update views and orders
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,50 @@
|
|||||||
|
import mariadb
|
||||||
|
|
||||||
|
# Database connection credentials
|
||||||
|
DB_CONFIG = {
|
||||||
|
"user": "trasabilitate",
|
||||||
|
"password": "Initial01!",
|
||||||
|
"host": "localhost",
|
||||||
|
"database": "trasabilitate_database"
|
||||||
|
}
|
||||||
|
|
||||||
|
def recreate_order_for_labels_table():
|
||||||
|
conn = mariadb.connect(**DB_CONFIG)
|
||||||
|
cursor = conn.cursor()
|
||||||
|
print("Connected to the database successfully!")
|
||||||
|
|
||||||
|
# Drop the table if it exists
|
||||||
|
cursor.execute("DROP TABLE IF EXISTS order_for_labels")
|
||||||
|
print("Dropped existing 'order_for_labels' table.")
|
||||||
|
|
||||||
|
# Create the table with the new unique constraint
|
||||||
|
create_table_sql = """
|
||||||
|
CREATE TABLE order_for_labels (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT 'Unique identifier',
|
||||||
|
comanda_productie VARCHAR(15) NOT NULL UNIQUE COMMENT 'Production Order (unique)',
|
||||||
|
cod_articol VARCHAR(15) COMMENT 'Article Code',
|
||||||
|
descr_com_prod VARCHAR(50) NOT NULL COMMENT 'Production Order Description',
|
||||||
|
cantitate INT(3) NOT NULL COMMENT 'Quantity',
|
||||||
|
data_livrare DATE COMMENT 'Delivery date',
|
||||||
|
dimensiune VARCHAR(20) COMMENT 'Dimensions',
|
||||||
|
com_achiz_client VARCHAR(25) COMMENT 'Client Purchase Order',
|
||||||
|
nr_linie_com_client INT(3) COMMENT 'Client Order Line Number',
|
||||||
|
customer_name VARCHAR(50) COMMENT 'Customer Name',
|
||||||
|
customer_article_number VARCHAR(25) COMMENT 'Customer Article Number',
|
||||||
|
open_for_order VARCHAR(25) COMMENT 'Open for Order Status',
|
||||||
|
line_number INT(3) COMMENT 'Line Number',
|
||||||
|
printed_labels TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Boolean flag: 0=labels not printed, 1=labels printed',
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT 'Record creation timestamp',
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'Record update timestamp'
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Table for storing order information for label generation';
|
||||||
|
"""
|
||||||
|
cursor.execute(create_table_sql)
|
||||||
|
print("Created new 'order_for_labels' table with unique comanda_productie.")
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
cursor.close()
|
||||||
|
conn.close()
|
||||||
|
print("Done.")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
recreate_order_for_labels_table()
|
||||||
@@ -7,6 +7,7 @@ import mariadb
|
|||||||
from flask import current_app, request, render_template, session, redirect, url_for, flash
|
from flask import current_app, request, render_template, session, redirect, url_for, flash
|
||||||
import csv
|
import csv
|
||||||
import os
|
import os
|
||||||
|
import json
|
||||||
import tempfile
|
import tempfile
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
@@ -236,6 +237,24 @@ def process_csv_file(file_path):
|
|||||||
return orders_data, all_errors, all_warnings
|
return orders_data, all_errors, all_warnings
|
||||||
|
|
||||||
def upload_orders_handler():
|
def upload_orders_handler():
|
||||||
|
# Handle clear table POST
|
||||||
|
if request.method == 'POST' and request.form.get('clear_table') == '1':
|
||||||
|
session.pop('orders_csv_data', None)
|
||||||
|
session.pop('csv_filename', None)
|
||||||
|
session.pop('orders_csv_filepath', None)
|
||||||
|
session.pop('orders_validation_errors', None)
|
||||||
|
session.pop('orders_validation_warnings', None)
|
||||||
|
session.pop('leftover_orders', None)
|
||||||
|
session.pop('leftover_description', None)
|
||||||
|
# Remove the leftovers JSON file if it exists
|
||||||
|
leftovers_path = os.path.join(current_app.root_path, 'static', 'leftover_orders.json')
|
||||||
|
try:
|
||||||
|
if os.path.exists(leftovers_path):
|
||||||
|
os.remove(leftovers_path)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
flash('Leftover orders have been cleared.', 'info')
|
||||||
|
return redirect(url_for('main.view_orders'))
|
||||||
"""
|
"""
|
||||||
Main handler for the upload orders functionality
|
Main handler for the upload orders functionality
|
||||||
Handles both CSV upload/preview and database insertion
|
Handles both CSV upload/preview and database insertion
|
||||||
@@ -295,12 +314,28 @@ def upload_orders_handler():
|
|||||||
success_count += 1
|
success_count += 1
|
||||||
else:
|
else:
|
||||||
failed_count += 1
|
failed_count += 1
|
||||||
failed_orders.append(f"{order.get('comanda_productie', 'Unknown')}: {message}")
|
order_with_error = order.copy()
|
||||||
|
order_with_error['error_message'] = message
|
||||||
|
failed_orders.append(order_with_error)
|
||||||
|
|
||||||
|
# Save leftovers to static/leftover_orders.json if any
|
||||||
|
if failed_orders:
|
||||||
|
static_folder = os.path.join(current_app.root_path, 'static')
|
||||||
|
os.makedirs(static_folder, exist_ok=True)
|
||||||
|
leftovers_path = os.path.join(static_folder, 'leftover_orders.json')
|
||||||
|
with open(leftovers_path, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(failed_orders, f, ensure_ascii=False, indent=2)
|
||||||
|
|
||||||
# Create report
|
# Create report
|
||||||
report = f"✅ Successfully imported {success_count} orders."
|
report = f"✅ Successfully imported {success_count} orders."
|
||||||
if failed_count > 0:
|
if failed_count > 0:
|
||||||
report += f" ❌ {failed_count} orders failed to import."
|
report += f" ❌ {failed_count} orders failed to import."
|
||||||
|
leftover_description = (
|
||||||
|
"These orders were not uploaded to the database because they already exist. "
|
||||||
|
"Check your order list or modify them in the database."
|
||||||
|
)
|
||||||
|
session['leftover_orders'] = failed_orders
|
||||||
|
session['leftover_description'] = leftover_description
|
||||||
for failure in failed_orders[:5]: # Show first 5 failures
|
for failure in failed_orders[:5]: # Show first 5 failures
|
||||||
report += f"<br>• {failure}"
|
report += f"<br>• {failure}"
|
||||||
if len(failed_orders) > 5:
|
if len(failed_orders) > 5:
|
||||||
@@ -313,10 +348,30 @@ def upload_orders_handler():
|
|||||||
session.pop('orders_csv_filepath', None)
|
session.pop('orders_csv_filepath', None)
|
||||||
session.pop('orders_validation_errors', None)
|
session.pop('orders_validation_errors', None)
|
||||||
session.pop('orders_validation_warnings', None)
|
session.pop('orders_validation_warnings', None)
|
||||||
|
session.pop('leftover_orders', None)
|
||||||
|
session.pop('leftover_description', None)
|
||||||
|
|
||||||
flash(report, "success" if failed_count == 0 else "warning")
|
flash(report, "success" if failed_count == 0 else "warning")
|
||||||
|
if failed_count > 0:
|
||||||
return redirect(url_for('main.view_orders'))
|
# Show leftover orders on the upload_orders page
|
||||||
|
# Try to reload leftovers from JSON if available
|
||||||
|
leftovers_path = os.path.join(current_app.root_path, 'static', 'leftover_orders.json')
|
||||||
|
orders_data = session.get('leftover_orders', [])
|
||||||
|
try:
|
||||||
|
if os.path.exists(leftovers_path):
|
||||||
|
with open(leftovers_path, 'r', encoding='utf-8') as f:
|
||||||
|
orders_data = json.load(f)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
leftover_description = session.get('leftover_description', '')
|
||||||
|
return render_template('upload_orders.html',
|
||||||
|
orders=orders_data,
|
||||||
|
leftover_description=leftover_description,
|
||||||
|
validation_errors=validation_errors,
|
||||||
|
validation_warnings=validation_warnings,
|
||||||
|
report=report)
|
||||||
|
else:
|
||||||
|
return redirect(url_for('main.view_orders'))
|
||||||
|
|
||||||
# Load data from session if available
|
# Load data from session if available
|
||||||
elif 'orders_csv_data' in session:
|
elif 'orders_csv_data' in session:
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
{% block head %}
|
{% block head %}
|
||||||
<style>
|
<style>
|
||||||
/* COMPLETE OVERRIDE FOR UPLOAD ORDERS TABLE - Maximum Specificity */
|
/* VIEW ORDERS TABLE - Specific styling (copied from view_orders.html) */
|
||||||
table.upload-orders-table.scan-table {
|
table.view-orders-table.scan-table {
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
border-spacing: 0 !important;
|
border-spacing: 0 !important;
|
||||||
border-collapse: collapse !important;
|
border-collapse: collapse !important;
|
||||||
@@ -12,24 +12,8 @@ table.upload-orders-table.scan-table {
|
|||||||
table-layout: fixed !important;
|
table-layout: fixed !important;
|
||||||
font-size: 11px !important;
|
font-size: 11px !important;
|
||||||
}
|
}
|
||||||
|
table.view-orders-table.scan-table thead th {
|
||||||
/* REMOVE ALL SPACING AROUND THE TABLE CARD */
|
height: 85px !important;
|
||||||
.scan-table-card {
|
|
||||||
padding: 15px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scan-table-card h3 {
|
|
||||||
margin: 0 0 15px 0 !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scan-table-card > * {
|
|
||||||
margin-top: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* HEADER STYLES - Ultra specific to prevent overrides */
|
|
||||||
table.upload-orders-table.scan-table thead th {
|
|
||||||
height: 200px !important;
|
|
||||||
min-height: 85px !important;
|
min-height: 85px !important;
|
||||||
max-height: 85px !important;
|
max-height: 85px !important;
|
||||||
vertical-align: middle !important;
|
vertical-align: middle !important;
|
||||||
@@ -49,9 +33,7 @@ table.upload-orders-table.scan-table thead th {
|
|||||||
text-overflow: clip !important;
|
text-overflow: clip !important;
|
||||||
position: relative !important;
|
position: relative !important;
|
||||||
}
|
}
|
||||||
|
table.view-orders-table.scan-table tbody td {
|
||||||
/* BODY CELL STYLES */
|
|
||||||
table.upload-orders-table.scan-table tbody td {
|
|
||||||
padding: 4px 2px !important;
|
padding: 4px 2px !important;
|
||||||
font-size: 10px !important;
|
font-size: 10px !important;
|
||||||
text-align: center !important;
|
text-align: center !important;
|
||||||
@@ -61,72 +43,30 @@ table.upload-orders-table.scan-table tbody td {
|
|||||||
text-overflow: ellipsis !important;
|
text-overflow: ellipsis !important;
|
||||||
vertical-align: middle !important;
|
vertical-align: middle !important;
|
||||||
}
|
}
|
||||||
|
table.view-orders-table.scan-table td:nth-child(1) { width: 50px !important; }
|
||||||
/* SPECIFIC COLUMN WIDTHS - Ultra specific selectors */
|
table.view-orders-table.scan-table td:nth-child(2) { width: 80px !important; }
|
||||||
table.upload-orders-table.scan-table th:nth-child(1),
|
table.view-orders-table.scan-table td:nth-child(3) { width: 80px !important; }
|
||||||
table.upload-orders-table.scan-table td:nth-child(1) { width: 45px !important; } /* Comanda Productie */
|
table.view-orders-table.scan-table td:nth-child(4) { width: 150px !important; }
|
||||||
|
table.view-orders-table.scan-table td:nth-child(5) { width: 70px !important; }
|
||||||
table.upload-orders-table.scan-table th:nth-child(2),
|
table.view-orders-table.scan-table td:nth-child(6) { width: 80px !important; }
|
||||||
table.upload-orders-table.scan-table td:nth-child(2) { width: 65px !important; } /* Cod Articol */
|
table.view-orders-table.scan-table td:nth-child(7) { width: 75px !important; }
|
||||||
|
table.view-orders-table.scan-table td:nth-child(8) { width: 90px !important; }
|
||||||
table.upload-orders-table.scan-table th:nth-child(3),
|
table.view-orders-table.scan-table td:nth-child(9) { width: 70px !important; }
|
||||||
table.upload-orders-table.scan-table td:nth-child(3) { width: 110px !important; } /* Descr. Com. Prod */
|
table.view-orders-table.scan-table td:nth-child(10) { width: 100px !important; }
|
||||||
|
table.view-orders-table.scan-table td:nth-child(11) { width: 90px !important; }
|
||||||
table.upload-orders-table.scan-table th:nth-child(4),
|
table.view-orders-table.scan-table td:nth-child(12) { width: 70px !important; }
|
||||||
table.upload-orders-table.scan-table td:nth-child(4) { width: 55px !important; text-align: right !important; } /* Cantitate */
|
table.view-orders-table.scan-table td:nth-child(13) { width: 50px !important; }
|
||||||
|
table.view-orders-table.scan-table td:nth-child(14) { width: 70px !important; }
|
||||||
table.upload-orders-table.scan-table th:nth-child(5),
|
table.view-orders-table.scan-table td:nth-child(15) { width: 100px !important; }
|
||||||
table.upload-orders-table.scan-table td:nth-child(5) { width: 70px !important; } /* Data Livrare */
|
table.view-orders-table.scan-table tbody tr:hover td {
|
||||||
|
|
||||||
table.upload-orders-table.scan-table th:nth-child(6),
|
|
||||||
table.upload-orders-table.scan-table td:nth-child(6) { width: 75px !important; } /* Dimensiune */
|
|
||||||
|
|
||||||
table.upload-orders-table.scan-table th:nth-child(8),
|
|
||||||
table.upload-orders-table.scan-table td:nth-child(8) { width: 80px !important; } /* Nr. Linie com. Client */
|
|
||||||
|
|
||||||
table.upload-orders-table.scan-table th:nth-child(9),
|
|
||||||
table.upload-orders-table.scan-table td:nth-child(9) { width: 90px !important; } /* Customer Name */
|
|
||||||
|
|
||||||
table.upload-orders-table.scan-table th:nth-child(10),
|
|
||||||
table.upload-orders-table.scan-table td:nth-child(10) { width: 85px !important; } /* Customer Article Number */
|
|
||||||
|
|
||||||
table.upload-orders-table.scan-table th:nth-child(11),
|
|
||||||
table.upload-orders-table.scan-table td:nth-child(11) { width: 60px !important; } /* Open for order */
|
|
||||||
|
|
||||||
table.upload-orders-table.scan-table th:nth-child(12),
|
|
||||||
table.upload-orders-table.scan-table td:nth-child(12) { width: 40px !important; } /* Line */
|
|
||||||
|
|
||||||
/* HOVER EFFECTS */
|
|
||||||
table.upload-orders-table.scan-table tbody tr:hover td {
|
|
||||||
background-color: #f8f9fa !important;
|
background-color: #f8f9fa !important;
|
||||||
}
|
}
|
||||||
|
.report-table-card h3 {
|
||||||
/* REMOVE EMPTY ROWS */
|
margin: 0 0 15px 0 !important;
|
||||||
table.upload-orders-table.scan-table tbody tr:empty {
|
padding: 0 !important;
|
||||||
display: none !important;
|
|
||||||
}
|
}
|
||||||
|
.report-table-card {
|
||||||
table.upload-orders-table.scan-table tbody tr td:empty:only-child {
|
padding: 15px !important;
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.upload-orders-table.scan-table tbody tr:has(td:empty:only-child) {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hide rows that contain only a single empty cell */
|
|
||||||
table.upload-orders-table.scan-table tbody tr:has(td[colspan]:empty) {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* REMOVE UNWANTED SPACING IN PREVIEW CARD */
|
|
||||||
.scan-table-card h3 {
|
|
||||||
margin-bottom: 10px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scan-table-card .scan-table {
|
|
||||||
margin-top: 0 !important;
|
|
||||||
margin-bottom: 0 !important;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -135,15 +75,22 @@ table.upload-orders-table.scan-table tbody tr:has(td[colspan]:empty) {
|
|||||||
<div class="scan-container">
|
<div class="scan-container">
|
||||||
<!-- Upload Orders Card (first, fixed position) -->
|
<!-- Upload Orders Card (first, fixed position) -->
|
||||||
<div class="card scan-form-card" style="margin-bottom: 24px;">
|
<div class="card scan-form-card" style="margin-bottom: 24px;">
|
||||||
<h3>Upload Order Data for Labels</h3>
|
{% if leftover_description %}
|
||||||
|
<h3>Left over orders</h3>
|
||||||
|
<div style="color: #dc3545; font-weight: bold; margin-bottom: 10px;">{{ leftover_description }}</div>
|
||||||
|
{% else %}
|
||||||
|
<h3>Upload Order Data for Labels</h3>
|
||||||
|
{% endif %}
|
||||||
<form method="POST" enctype="multipart/form-data" class="form-centered" id="csv-upload-form">
|
<form method="POST" enctype="multipart/form-data" class="form-centered" id="csv-upload-form">
|
||||||
<label for="csv_file">Choose CSV file:</label>
|
<label for="csv_file">Choose CSV file:</label>
|
||||||
{% if not orders %}
|
{% 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>
|
<input type="file" name="csv_file" accept=".csv" required><br>
|
||||||
<button type="submit" class="btn">Upload & Preview</button>
|
<button type="submit" class="btn">Upload & Review</button>
|
||||||
{% else %}
|
{% else %}
|
||||||
<label style="font-weight: bold;">Selected file: {{ session['csv_filename'] if session['csv_filename'] else 'Unknown' }}</label><br>
|
<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()">Save to Database</button>
|
<button type="button" class="btn" onclick="showPopupAndSubmit()">Upload to Database</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
@@ -177,11 +124,16 @@ table.upload-orders-table.scan-table tbody tr:has(td[colspan]:empty) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Preview Table Card (expandable height, scrollable) -->
|
<!-- Preview Table Card (expandable height, scrollable) -->
|
||||||
<div class="card scan-table-card" style="margin-bottom: 24px; max-height: 480px; overflow-y: auto;">
|
<div class="card scan-table-card{% if leftover_description %} leftover-table-card{% endif %}" style="margin-bottom: 24px; max-height: 480px; overflow-y: auto;">
|
||||||
<h3>Preview Table</h3>
|
{% if leftover_description %}
|
||||||
<table class="scan-table upload-orders-table">
|
<h3>Left over orders</h3>
|
||||||
|
{% else %}
|
||||||
|
<h3>Preview Table</h3>
|
||||||
|
{% endif %}
|
||||||
|
<table class="scan-table view-orders-table{% if leftover_description %} leftover-table{% endif %}">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
<th>Comanda<br>Productie</th>
|
<th>Comanda<br>Productie</th>
|
||||||
<th>Cod<br>Articol</th>
|
<th>Cod<br>Articol</th>
|
||||||
<th>Descr. Com.<br>Prod</th>
|
<th>Descr. Com.<br>Prod</th>
|
||||||
@@ -189,11 +141,13 @@ table.upload-orders-table.scan-table tbody tr:has(td[colspan]:empty) {
|
|||||||
<th>Data<br>Livrare</th>
|
<th>Data<br>Livrare</th>
|
||||||
<th>Dimensiune</th>
|
<th>Dimensiune</th>
|
||||||
<th>Com.Achiz.<br>Client</th>
|
<th>Com.Achiz.<br>Client</th>
|
||||||
<th>Nr. Linie com.<br>Client</th>
|
<th>Nr.<br>Linie</th>
|
||||||
<th>Customer<br>Name</th>
|
<th>Customer<br>Name</th>
|
||||||
<th>Customer Article<br>Number</th>
|
<th>Customer<br>Art. Nr.</th>
|
||||||
<th>Open for<br>order</th>
|
<th>Open<br>Order</th>
|
||||||
<th>Line</th>
|
<th>Line</th>
|
||||||
|
<th>Printed</th>
|
||||||
|
<th>Created</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -201,62 +155,77 @@ table.upload-orders-table.scan-table tbody tr:has(td[colspan]:empty) {
|
|||||||
{% for order in orders %}
|
{% for order in orders %}
|
||||||
{% if order and (order.get('comanda_productie', '') or order.get('descr_com_prod', '')) %}
|
{% if order and (order.get('comanda_productie', '') or order.get('descr_com_prod', '')) %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ order.get('comanda_productie', '') }}</td>
|
<td>{{ order.get('id', '') }}</td>
|
||||||
<td>{{ order.get('cod_articol', '') }}</td>
|
<td><strong>{{ order.get('comanda_productie', '') }}</strong></td>
|
||||||
|
<td>{{ order.get('cod_articol', '-') }}</td>
|
||||||
<td>{{ order.get('descr_com_prod', '') }}</td>
|
<td>{{ order.get('descr_com_prod', '') }}</td>
|
||||||
<td>{{ order.get('cantitate', '') }}</td>
|
<td style="text-align: right; font-weight: 600;">{{ order.get('cantitate', '') }}</td>
|
||||||
<td>{{ order.get('data_livrare', '') }}</td>
|
<td style="text-align: center;">{{ order.get('data_livrare', '') }}</td>
|
||||||
<td>{{ order.get('dimensiune', '') }}</td>
|
<td style="text-align: center;">{{ order.get('dimensiune', '-') }}</td>
|
||||||
<td>{{ order.get('com_achiz_client', '') }}</td>
|
<td>{{ order.get('com_achiz_client', '-') }}</td>
|
||||||
<td>{{ order.get('nr_linie_com_client', '') }}</td>
|
<td style="text-align: right;">{{ order.get('nr_linie_com_client', '-') }}</td>
|
||||||
<td>{{ order.get('customer_name', '') }}</td>
|
<td>{{ order.get('customer_name', '-') }}</td>
|
||||||
<td>{{ order.get('customer_article_number', '') }}</td>
|
<td>{{ order.get('customer_article_number', '-') }}</td>
|
||||||
<td>{{ order.get('open_for_order', '') }}</td>
|
<td>{{ order.get('open_for_order', '-') }}</td>
|
||||||
<td>{{ order.get('line_number', '') }}</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>
|
</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 %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<tr><td colspan="12" style="text-align:center;">No CSV file uploaded yet.</td></tr>
|
<tr><td colspan="15" style="text-align:center;">No CSV file uploaded yet.</td></tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if validation_errors or validation_warnings %}
|
{% if validation_errors or validation_warnings %}
|
||||||
<div class="card" style="margin-bottom: 24px;">
|
{% if not leftover_description %}
|
||||||
<h4>Validation Results</h4>
|
<div class="card" style="margin-bottom: 24px;">
|
||||||
|
<h4>Validation Results</h4>
|
||||||
{% if validation_errors %}
|
{% if validation_errors %}
|
||||||
<div style="color: #dc3545; margin-bottom: 16px;">
|
<div style="color: #dc3545; margin-bottom: 16px;">
|
||||||
<strong>Errors found:</strong>
|
<strong>Errors found:</strong>
|
||||||
<ul>
|
<ul>
|
||||||
{% for error in validation_errors %}
|
{% for error in validation_errors %}
|
||||||
<li>{{ error }}</li>
|
<li>{{ error }}</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</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>
|
</div>
|
||||||
{% endif %}
|
{% 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>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if report %}
|
|
||||||
<div class="card" style="margin-bottom: 24px;">
|
|
||||||
<h4>Import Report</h4>
|
|
||||||
<p>{{ report }}</p>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -341,4 +310,16 @@ table.upload-orders-table.scan-table tbody tr:has(td[colspan]:empty) {
|
|||||||
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
|
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
<style>
|
||||||
|
/* Special style for leftover orders table to match preview table height and appearance */
|
||||||
|
.leftover-table-card {
|
||||||
|
max-height: 480px !important;
|
||||||
|
overflow-y: auto !important;
|
||||||
|
border: 2px solid #dc3545 !important;
|
||||||
|
background: #fff6f6 !important;
|
||||||
|
}
|
||||||
|
.leftover-table thead th, .leftover-table td {
|
||||||
|
background: #fff6f6 !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -120,7 +120,7 @@ table.view-orders-table.scan-table td:nth-child(15) { width: 100px !important; }
|
|||||||
<div class="form-centered last-buttons">
|
<div class="form-centered last-buttons">
|
||||||
<label class="export-description">Export orders as:</label>
|
<label class="export-description">Export orders as:</label>
|
||||||
<div class="button-row">
|
<div class="button-row">
|
||||||
<button class="btn export-btn" onclick="window.print()">Print Orders</button>
|
<button class="btn export-btn" onclick="location.href='/print_module'">Print Orders</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user