feat: Major system improvements and production deployment
✨ New Features: - Added view_orders route with proper table display - Implemented CSV upload with preview workflow and date parsing - Added production WSGI server configuration with Gunicorn - Created comprehensive production management scripts 🔧 Bug Fixes: - Fixed upload_data route column mapping for actual CSV structure - Resolved print module database queries and template rendering - Fixed view orders navigation routing (was pointing to JSON API) - Corrected barcode display width constraints in print module - Added proper date format parsing for MySQL compatibility 🎨 UI/UX Improvements: - Updated view_orders template with theme-compliant styling - Hidden barcode text in print module preview for cleaner display - Enhanced CSV upload with two-step preview-then-save workflow - Improved error handling and debugging throughout upload process 🚀 Production Infrastructure: - Added Gunicorn WSGI server with proper configuration - Created systemd service for production deployment - Implemented production management scripts (start/stop/status) - Added comprehensive logging setup - Updated requirements.txt with production dependencies 📊 Database & Data: - Enhanced order_for_labels table compatibility - Fixed column mappings for real CSV data structure - Added proper date parsing and validation - Improved error handling with detailed debugging 🔧 Technical Debt: - Reorganized database setup documentation - Added proper error handling throughout upload workflow - Enhanced debugging capabilities for troubleshooting - Improved code organization and documentation
This commit is contained in:
@@ -82,15 +82,35 @@ table.view-orders-table.scan-table tbody tr:hover td {
|
||||
<h3>Upload Order Data for Labels</h3>
|
||||
{% endif %}
|
||||
<form method="POST" enctype="multipart/form-data" class="form-centered" id="csv-upload-form">
|
||||
<label for="csv_file">Choose CSV file:</label>
|
||||
{% if leftover_description %}
|
||||
<button type="submit" class="btn btn-danger" name="clear_table" value="1">Clear Table</button>
|
||||
{% elif not orders %}
|
||||
<input type="file" name="csv_file" accept=".csv" required><br>
|
||||
<button type="submit" class="btn">Upload & Review</button>
|
||||
{% if show_preview %}
|
||||
<!-- Show preview controls -->
|
||||
<input type="hidden" name="action" value="save">
|
||||
<label style="font-weight: bold;">Preview of: {{ filename }}</label><br>
|
||||
<p style="color: #666; font-size: 14px; margin: 10px 0;">
|
||||
Showing first 10 rows. Review the data below and click "Save to Database" to confirm.
|
||||
</p>
|
||||
<button type="submit" class="btn" style="background-color: #28a745;">Save to Database</button>
|
||||
<a href="{{ url_for('main.upload_data') }}" class="btn" style="background-color: #6c757d; margin-left: 10px;">Cancel</a>
|
||||
{% else %}
|
||||
<label style="font-weight: bold;">Selected file: {{ session['csv_filename'] if session['csv_filename'] else 'Unknown' }}</label><br>
|
||||
<button type="button" class="btn" onclick="showPopupAndSubmit()">Upload to Database</button>
|
||||
<!-- Show file upload -->
|
||||
<input type="hidden" name="action" value="preview">
|
||||
<label for="file">Choose CSV file:</label>
|
||||
<input type="file" name="file" accept=".csv" required><br>
|
||||
<button type="submit" class="btn">Upload & Preview</button>
|
||||
|
||||
<!-- CSV Format Information -->
|
||||
<div style="margin-top: 20px; padding: 15px; background-color: var(--app-card-bg, #2a3441); border-radius: 5px; border-left: 4px solid var(--app-accent-color, #007bff); color: var(--app-text-color, #ffffff);">
|
||||
<h5 style="margin-top: 0; color: var(--app-accent-color, #007bff);">Expected CSV Format</h5>
|
||||
<p style="margin-bottom: 10px; color: var(--app-text-color, #ffffff);">Your CSV file should contain columns such as:</p>
|
||||
<ul style="margin-bottom: 10px; color: var(--app-text-color, #ffffff);">
|
||||
<li><strong>order_number</strong> - The order/production number</li>
|
||||
<li><strong>quantity</strong> - Number of items</li>
|
||||
<li><strong>warehouse_location</strong> - Storage location</li>
|
||||
</ul>
|
||||
<p style="color: var(--app-secondary-text, #b8c5d1); font-size: 14px; margin-bottom: 0;">
|
||||
Column names are case-insensitive and can have variations like "Order Number", "Quantity", "Location", etc.
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</form>
|
||||
|
||||
@@ -124,108 +144,45 @@ table.view-orders-table.scan-table tbody tr:hover td {
|
||||
</div>
|
||||
|
||||
<!-- Preview Table Card (expandable height, scrollable) -->
|
||||
<div class="card scan-table-card{% if leftover_description %} leftover-table-card{% endif %}" style="margin-bottom: 24px; max-height: 480px; overflow-y: auto;">
|
||||
{% if leftover_description %}
|
||||
<h3>Left over orders</h3>
|
||||
<div class="card scan-table-card" style="margin-bottom: 24px; max-height: 480px; overflow-y: auto;">
|
||||
{% if show_preview %}
|
||||
<h3>CSV Data Preview - {{ filename }}</h3>
|
||||
<table class="scan-table">
|
||||
<thead>
|
||||
<tr>
|
||||
{% for header in headers %}
|
||||
<th>{{ header }}</th>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if preview_data %}
|
||||
{% for row in preview_data %}
|
||||
<tr>
|
||||
{% for header in headers %}
|
||||
<td>{{ row.get(header, '') }}</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<tr><td colspan="{{ headers|length }}" style="text-align:center;">No data to preview</td></tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<h3>Preview Table</h3>
|
||||
<h3>CSV Data Preview</h3>
|
||||
<table class="scan-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Upload a CSV file to see preview</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td style="text-align:center; padding: 40px;">No CSV file uploaded yet. Use the form above to upload and preview your data.</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
<table class="scan-table view-orders-table{% if leftover_description %} leftover-table{% endif %}">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Comanda<br>Productie</th>
|
||||
<th>Cod<br>Articol</th>
|
||||
<th>Descr. Com.<br>Prod</th>
|
||||
<th>Cantitate</th>
|
||||
<th>Data<br>Livrare</th>
|
||||
<th>Dimensiune</th>
|
||||
<th>Com.Achiz.<br>Client</th>
|
||||
<th>Nr.<br>Linie</th>
|
||||
<th>Customer<br>Name</th>
|
||||
<th>Customer<br>Art. Nr.</th>
|
||||
<th>Open<br>Order</th>
|
||||
<th>Line</th>
|
||||
<th>Printed</th>
|
||||
<th>Created</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if orders %}
|
||||
{% for order in orders %}
|
||||
{% if order and (order.get('comanda_productie', '') or order.get('descr_com_prod', '')) %}
|
||||
<tr>
|
||||
<td>{{ order.get('id', '') }}</td>
|
||||
<td><strong>{{ order.get('comanda_productie', '') }}</strong></td>
|
||||
<td>{{ order.get('cod_articol', '-') }}</td>
|
||||
<td>{{ order.get('descr_com_prod', '') }}</td>
|
||||
<td style="text-align: right; font-weight: 600;">{{ order.get('cantitate', '') }}</td>
|
||||
<td style="text-align: center;">{{ order.get('data_livrare', '') }}</td>
|
||||
<td style="text-align: center;">{{ order.get('dimensiune', '-') }}</td>
|
||||
<td>{{ order.get('com_achiz_client', '-') }}</td>
|
||||
<td style="text-align: right;">{{ order.get('nr_linie_com_client', '-') }}</td>
|
||||
<td>{{ order.get('customer_name', '-') }}</td>
|
||||
<td>{{ order.get('customer_article_number', '-') }}</td>
|
||||
<td>{{ order.get('open_for_order', '-') }}</td>
|
||||
<td style="text-align: right;">{{ order.get('line_number', '-') }}</td>
|
||||
<td style="text-align: center;">
|
||||
{% if order.get('printed_labels', 0) == 1 %}
|
||||
<span style="color: #28a745; font-weight: bold;">✓ Yes</span>
|
||||
{% else %}
|
||||
<span style="color: #dc3545;">✗ No</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td style="font-size: 11px; color: #6c757d;">{{ order.get('created_at', '-') }}</td>
|
||||
</tr>
|
||||
{% if order.error_message %}
|
||||
<tr>
|
||||
<td colspan="15" style="color: #dc3545; font-size: 12px; background: #fff3f3;">
|
||||
<strong>Error:</strong> {{ order.error_message }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<tr><td colspan="15" style="text-align:center;">No CSV file uploaded yet.</td></tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{% if validation_errors or validation_warnings %}
|
||||
{% if not leftover_description %}
|
||||
<div class="card" style="margin-bottom: 24px;">
|
||||
<h4>Validation Results</h4>
|
||||
{% if validation_errors %}
|
||||
<div style="color: #dc3545; margin-bottom: 16px;">
|
||||
<strong>Errors found:</strong>
|
||||
<ul>
|
||||
{% for error in validation_errors %}
|
||||
<li>{{ error }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if validation_warnings %}
|
||||
<div style="color: #ffc107;">
|
||||
<strong>Warnings:</strong>
|
||||
<ul>
|
||||
{% for warning in validation_warnings %}
|
||||
<li>{{ warning }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if report %}
|
||||
<div class="card" style="margin-bottom: 24px;">
|
||||
<h4>Import Report</h4>
|
||||
<p>{{ report }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
Reference in New Issue
Block a user