updated structure in the table view
This commit is contained in:
@@ -471,3 +471,24 @@
|
|||||||
192.168.0.132 - - [25/Oct/2025:11:57:37 +0300] "GET / HTTP/1.1" 200 1627 "-" "-" 46568
|
192.168.0.132 - - [25/Oct/2025:11:57:37 +0300] "GET / HTTP/1.1" 200 1627 "-" "-" 46568
|
||||||
192.168.0.132 - - [25/Oct/2025:12:15:43 +0300] "GET / HTTP/1.1" 200 1627 "-" "-" 47085
|
192.168.0.132 - - [25/Oct/2025:12:15:43 +0300] "GET / HTTP/1.1" 200 1627 "-" "-" 47085
|
||||||
192.168.0.132 - - [26/Oct/2025:09:28:48 +0200] "GET /robots.txt HTTP/1.1" 404 207 "http://quality.moto-adv.com/robots.txt" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36; compatible; OAI-SearchBot/1.0; robots.txt; +https://openai.com/searchbot" 2129
|
192.168.0.132 - - [26/Oct/2025:09:28:48 +0200] "GET /robots.txt HTTP/1.1" 404 207 "http://quality.moto-adv.com/robots.txt" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36; compatible; OAI-SearchBot/1.0; robots.txt; +https://openai.com/searchbot" 2129
|
||||||
|
192.168.0.132 - - [26/Oct/2025:15:05:56 +0200] "GET / HTTP/1.1" 200 1627 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 1703
|
||||||
|
192.168.0.132 - - [26/Oct/2025:15:05:56 +0200] "GET //wp-includes/wlwmanifest.xml HTTP/1.1" 404 207 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 1929
|
||||||
|
192.168.0.132 - - [26/Oct/2025:15:05:56 +0200] "GET //xmlrpc.php?rsd HTTP/1.1" 404 207 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 1466
|
||||||
|
192.168.0.132 - - [26/Oct/2025:15:05:57 +0200] "GET / HTTP/1.1" 200 1627 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 1741
|
||||||
|
192.168.0.132 - - [26/Oct/2025:15:05:57 +0200] "GET //blog/wp-includes/wlwmanifest.xml HTTP/1.1" 404 207 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 1441
|
||||||
|
192.168.0.132 - - [26/Oct/2025:15:05:57 +0200] "GET //web/wp-includes/wlwmanifest.xml HTTP/1.1" 404 207 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 1362
|
||||||
|
192.168.0.132 - - [26/Oct/2025:15:05:57 +0200] "GET //wordpress/wp-includes/wlwmanifest.xml HTTP/1.1" 404 207 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 1372
|
||||||
|
192.168.0.132 - - [26/Oct/2025:15:05:57 +0200] "GET //website/wp-includes/wlwmanifest.xml HTTP/1.1" 404 207 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 2574
|
||||||
|
192.168.0.132 - - [26/Oct/2025:15:05:58 +0200] "GET //wp/wp-includes/wlwmanifest.xml HTTP/1.1" 404 207 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 2042
|
||||||
|
192.168.0.132 - - [26/Oct/2025:15:05:58 +0200] "GET //news/wp-includes/wlwmanifest.xml HTTP/1.1" 404 207 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 1445
|
||||||
|
192.168.0.132 - - [26/Oct/2025:15:05:58 +0200] "GET //2018/wp-includes/wlwmanifest.xml HTTP/1.1" 404 207 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 1362
|
||||||
|
192.168.0.132 - - [26/Oct/2025:15:05:58 +0200] "GET //2019/wp-includes/wlwmanifest.xml HTTP/1.1" 404 207 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 1347
|
||||||
|
192.168.0.132 - - [26/Oct/2025:15:05:58 +0200] "GET //shop/wp-includes/wlwmanifest.xml HTTP/1.1" 404 207 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 1358
|
||||||
|
192.168.0.132 - - [26/Oct/2025:15:05:59 +0200] "GET //wp1/wp-includes/wlwmanifest.xml HTTP/1.1" 404 207 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 1448
|
||||||
|
192.168.0.132 - - [26/Oct/2025:15:05:59 +0200] "GET //test/wp-includes/wlwmanifest.xml HTTP/1.1" 404 207 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 1419
|
||||||
|
192.168.0.132 - - [26/Oct/2025:15:05:59 +0200] "GET //media/wp-includes/wlwmanifest.xml HTTP/1.1" 404 207 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 1365
|
||||||
|
192.168.0.132 - - [26/Oct/2025:15:05:59 +0200] "GET //wp2/wp-includes/wlwmanifest.xml HTTP/1.1" 404 207 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 1365
|
||||||
|
192.168.0.132 - - [26/Oct/2025:15:06:00 +0200] "GET //site/wp-includes/wlwmanifest.xml HTTP/1.1" 404 207 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 1385
|
||||||
|
192.168.0.132 - - [26/Oct/2025:15:06:00 +0200] "GET //cms/wp-includes/wlwmanifest.xml HTTP/1.1" 404 207 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 1375
|
||||||
|
192.168.0.132 - - [26/Oct/2025:15:06:00 +0200] "GET //sito/wp-includes/wlwmanifest.xml HTTP/1.1" 404 207 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" 1433
|
||||||
|
192.168.0.132 - - [26/Oct/2025:17:11:18 +0200] "GET / HTTP/1.1" 200 1627 "http://172.67.151.21:80/" "-" 1691
|
||||||
|
|||||||
@@ -906,8 +906,8 @@ def api_get_production_data():
|
|||||||
params = []
|
params = []
|
||||||
|
|
||||||
if search:
|
if search:
|
||||||
where_conditions.append("(production_order LIKE %s OR customer_code LIKE %s OR article_code LIKE %s)")
|
where_conditions.append("(production_order LIKE %s OR open_for_order_line LIKE %s OR client_order_line LIKE %s OR customer_code LIKE %s OR article_code LIKE %s)")
|
||||||
params.extend([f"%{search}%", f"%{search}%", f"%{search}%"])
|
params.extend([f"%{search}%", f"%{search}%", f"%{search}%", f"%{search}%", f"%{search}%"])
|
||||||
|
|
||||||
if filter_status:
|
if filter_status:
|
||||||
where_conditions.append("production_status = %s")
|
where_conditions.append("production_status = %s")
|
||||||
@@ -927,10 +927,10 @@ def api_get_production_data():
|
|||||||
# Get paginated data
|
# Get paginated data
|
||||||
offset = (page - 1) * per_page
|
offset = (page - 1) * per_page
|
||||||
data_query = f"""
|
data_query = f"""
|
||||||
SELECT id, production_order, customer_code, customer_name, client_order,
|
SELECT id, production_order, open_for_order_line, client_order_line,
|
||||||
article_code, article_description, quantity_requested, delivery_date,
|
customer_code, customer_name, article_code, article_description,
|
||||||
production_status, end_of_quilting, end_of_sewing, machine_code,
|
quantity_requested, delivery_date, production_status,
|
||||||
data_planificare
|
end_of_quilting, end_of_sewing, machine_code, data_planificare
|
||||||
FROM dm_production_orders {where_clause}
|
FROM dm_production_orders {where_clause}
|
||||||
ORDER BY data_planificare DESC, production_order
|
ORDER BY data_planificare DESC, production_order
|
||||||
LIMIT %s OFFSET %s
|
LIMIT %s OFFSET %s
|
||||||
@@ -942,18 +942,19 @@ def api_get_production_data():
|
|||||||
records.append({
|
records.append({
|
||||||
'id': row[0],
|
'id': row[0],
|
||||||
'production_order': row[1],
|
'production_order': row[1],
|
||||||
'customer_code': row[2],
|
'open_for_order_line': row[2],
|
||||||
'customer_name': row[3],
|
'client_order_line': row[3],
|
||||||
'client_order': row[4],
|
'customer_code': row[4],
|
||||||
'article_code': row[5],
|
'customer_name': row[5],
|
||||||
'article_description': row[6],
|
'article_code': row[6],
|
||||||
'quantity_requested': row[7],
|
'article_description': row[7],
|
||||||
'delivery_date': str(row[8]) if row[8] else None,
|
'quantity_requested': row[8],
|
||||||
'production_status': row[9],
|
'delivery_date': str(row[9]) if row[9] else None,
|
||||||
'end_of_quilting': str(row[10]) if row[10] else None,
|
'production_status': row[10],
|
||||||
'end_of_sewing': str(row[11]) if row[11] else None,
|
'end_of_quilting': str(row[11]) if row[11] else None,
|
||||||
'machine_code': row[12],
|
'end_of_sewing': str(row[12]) if row[12] else None,
|
||||||
'data_planificare': str(row[13]) if row[13] else None
|
'machine_code': row[13],
|
||||||
|
'data_planificare': str(row[14]) if row[14] else None
|
||||||
})
|
})
|
||||||
|
|
||||||
dm_db.disconnect()
|
dm_db.disconnect()
|
||||||
@@ -986,7 +987,8 @@ def api_update_production_data(record_id):
|
|||||||
|
|
||||||
update_query = """
|
update_query = """
|
||||||
UPDATE dm_production_orders SET
|
UPDATE dm_production_orders SET
|
||||||
customer_code = %s, customer_name = %s, client_order = %s,
|
open_for_order_line = %s, client_order_line = %s,
|
||||||
|
customer_code = %s, customer_name = %s,
|
||||||
article_code = %s, article_description = %s, quantity_requested = %s,
|
article_code = %s, article_description = %s, quantity_requested = %s,
|
||||||
delivery_date = %s, production_status = %s, machine_code = %s,
|
delivery_date = %s, production_status = %s, machine_code = %s,
|
||||||
updated_at = CURRENT_TIMESTAMP
|
updated_at = CURRENT_TIMESTAMP
|
||||||
@@ -994,9 +996,10 @@ def api_update_production_data(record_id):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
cursor.execute(update_query, (
|
cursor.execute(update_query, (
|
||||||
|
data.get('open_for_order_line'),
|
||||||
|
data.get('client_order_line'),
|
||||||
data.get('customer_code'),
|
data.get('customer_code'),
|
||||||
data.get('customer_name'),
|
data.get('customer_name'),
|
||||||
data.get('client_order'),
|
|
||||||
data.get('article_code'),
|
data.get('article_code'),
|
||||||
data.get('article_description'),
|
data.get('article_description'),
|
||||||
data.get('quantity_requested'),
|
data.get('quantity_requested'),
|
||||||
@@ -1014,3 +1017,105 @@ def api_update_production_data(record_id):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error updating production data: {e}")
|
print(f"Error updating production data: {e}")
|
||||||
return jsonify({'error': str(e)}), 500
|
return jsonify({'error': str(e)}), 500
|
||||||
|
|
||||||
|
|
||||||
|
@daily_mirror_bp.route('/api/tune/production_data/<int:record_id>', methods=['DELETE'])
|
||||||
|
def api_delete_production_data(record_id):
|
||||||
|
"""API endpoint to delete a production record"""
|
||||||
|
access_check = check_daily_mirror_api_access()
|
||||||
|
if access_check:
|
||||||
|
return access_check
|
||||||
|
|
||||||
|
try:
|
||||||
|
dm_db = DailyMirrorDatabase()
|
||||||
|
dm_db.connect()
|
||||||
|
cursor = dm_db.connection.cursor()
|
||||||
|
|
||||||
|
# Delete the record
|
||||||
|
delete_query = "DELETE FROM dm_production_orders WHERE id = ?"
|
||||||
|
cursor.execute(delete_query, (record_id,))
|
||||||
|
|
||||||
|
if cursor.rowcount == 0:
|
||||||
|
dm_db.disconnect()
|
||||||
|
return jsonify({'error': 'Record not found'}), 404
|
||||||
|
|
||||||
|
dm_db.connection.commit()
|
||||||
|
dm_db.disconnect()
|
||||||
|
|
||||||
|
return jsonify({'success': True, 'message': 'Production record deleted successfully'})
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error deleting production data: {e}")
|
||||||
|
return jsonify({'error': str(e)}), 500
|
||||||
|
|
||||||
|
|
||||||
|
@daily_mirror_bp.route('/clear_production_orders', methods=['POST'])
|
||||||
|
def clear_production_orders():
|
||||||
|
"""Delete all rows from the Daily Mirror production orders table"""
|
||||||
|
# Check access
|
||||||
|
access_check = check_daily_mirror_api_access()
|
||||||
|
if access_check:
|
||||||
|
return access_check
|
||||||
|
|
||||||
|
try:
|
||||||
|
dm_db = DailyMirrorDatabase()
|
||||||
|
dm_db.connect()
|
||||||
|
result = dm_db.clear_production_orders()
|
||||||
|
dm_db.disconnect()
|
||||||
|
|
||||||
|
if result:
|
||||||
|
return jsonify({'success': True, 'message': 'All production orders deleted successfully.'})
|
||||||
|
else:
|
||||||
|
return jsonify({'success': False, 'message': 'Error deleting production orders.'}), 500
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error clearing production orders: {e}")
|
||||||
|
return jsonify({'error': str(e)}), 500
|
||||||
|
|
||||||
|
|
||||||
|
@daily_mirror_bp.route('/clear_orders', methods=['POST'])
|
||||||
|
def clear_orders():
|
||||||
|
"""Delete all rows from the Daily Mirror orders table"""
|
||||||
|
# Check access
|
||||||
|
access_check = check_daily_mirror_api_access()
|
||||||
|
if access_check:
|
||||||
|
return access_check
|
||||||
|
|
||||||
|
try:
|
||||||
|
dm_db = DailyMirrorDatabase()
|
||||||
|
dm_db.connect()
|
||||||
|
result = dm_db.clear_orders()
|
||||||
|
dm_db.disconnect()
|
||||||
|
|
||||||
|
if result:
|
||||||
|
return jsonify({'success': True, 'message': 'All orders deleted successfully.'})
|
||||||
|
else:
|
||||||
|
return jsonify({'success': False, 'message': 'Error deleting orders.'}), 500
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error clearing orders: {e}")
|
||||||
|
return jsonify({'error': str(e)}), 500
|
||||||
|
|
||||||
|
|
||||||
|
@daily_mirror_bp.route('/clear_delivery', methods=['POST'])
|
||||||
|
def clear_delivery():
|
||||||
|
"""Delete all rows from the Daily Mirror delivery table"""
|
||||||
|
# Check access
|
||||||
|
access_check = check_daily_mirror_api_access()
|
||||||
|
if access_check:
|
||||||
|
return access_check
|
||||||
|
|
||||||
|
try:
|
||||||
|
dm_db = DailyMirrorDatabase()
|
||||||
|
dm_db.connect()
|
||||||
|
result = dm_db.clear_delivery()
|
||||||
|
dm_db.disconnect()
|
||||||
|
|
||||||
|
if result:
|
||||||
|
return jsonify({'success': True, 'message': 'All delivery records deleted successfully.'})
|
||||||
|
else:
|
||||||
|
return jsonify({'success': False, 'message': 'Error deleting delivery records.'}), 500
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error clearing delivery records: {e}")
|
||||||
|
return jsonify({'error': str(e)}), 500
|
||||||
@@ -36,59 +36,83 @@ CREATE TABLE IF NOT EXISTS dm_orders (
|
|||||||
-- PRODUCTION DATA TABLES
|
-- PRODUCTION DATA TABLES
|
||||||
-- =============================================
|
-- =============================================
|
||||||
|
|
||||||
-- Production Orders Table (from Comenzi Productie)
|
-- Production Orders Table (from Comenzi Productie - Production orders Data sheet)
|
||||||
CREATE TABLE IF NOT EXISTS dm_production_orders (
|
CREATE TABLE IF NOT EXISTS dm_production_orders (
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
|
||||||
|
-- Primary Identifiers
|
||||||
production_order VARCHAR(50) UNIQUE NOT NULL,
|
production_order VARCHAR(50) UNIQUE NOT NULL,
|
||||||
order_id VARCHAR(50),
|
open_for_order_line VARCHAR(100), -- Concatenated: "Opened for Order" + "-" + "Linia"
|
||||||
|
client_order_line VARCHAR(100), -- Concatenated: "Com. Achiz. Client" + "-" + "Nr. linie com. client"
|
||||||
|
|
||||||
|
-- Customer Information
|
||||||
customer_code VARCHAR(50),
|
customer_code VARCHAR(50),
|
||||||
customer_name VARCHAR(255),
|
customer_name VARCHAR(255),
|
||||||
client_order VARCHAR(100),
|
|
||||||
article_code VARCHAR(50),
|
-- Article Information
|
||||||
|
article_code VARCHAR(100),
|
||||||
article_description TEXT,
|
article_description TEXT,
|
||||||
quantity_requested INT,
|
quantity_requested INT,
|
||||||
delivery_date DATE,
|
unit_of_measure VARCHAR(20),
|
||||||
production_status VARCHAR(50),
|
|
||||||
|
-- Dates
|
||||||
|
delivery_date DATE, -- SO Duedate
|
||||||
|
opening_date DATE, -- Data Deschiderii
|
||||||
|
closing_date DATE, -- Data Inchiderii
|
||||||
|
data_planificare DATE, -- Data Planific.
|
||||||
|
|
||||||
|
-- Production Status
|
||||||
|
production_status VARCHAR(50), -- Status (Inchis, etc.)
|
||||||
|
|
||||||
|
-- Machine Information
|
||||||
|
machine_code VARCHAR(50), -- Masina cusut
|
||||||
|
machine_type VARCHAR(50), -- Tip masina
|
||||||
|
machine_number VARCHAR(20), -- Machine Number
|
||||||
|
|
||||||
-- Production Timeline
|
-- Production Timeline
|
||||||
end_of_quilting DATETIME,
|
end_of_quilting DATE, -- End of Quilting
|
||||||
end_of_sewing DATETIME,
|
end_of_sewing DATE, -- End of Sewing
|
||||||
data_deschiderii DATE,
|
|
||||||
data_planificare DATE,
|
|
||||||
|
|
||||||
-- Quality Control Stages
|
-- Quality Control Phase T1 (Prepared)
|
||||||
t1_status DECIMAL(3,1),
|
phase_t1_prepared VARCHAR(50), -- Faza pregatit(T1)
|
||||||
t1_registration_date DATETIME,
|
t1_operator_name VARCHAR(100), -- Nume complet T1
|
||||||
t1_operator_name VARCHAR(100),
|
t1_registration_date DATETIME, -- Data inregistrare T1
|
||||||
t2_status DECIMAL(3,1),
|
|
||||||
t2_registration_date DATETIME,
|
|
||||||
t2_operator_name VARCHAR(100),
|
|
||||||
t3_status DECIMAL(3,1),
|
|
||||||
t3_registration_date DATETIME,
|
|
||||||
t3_operator_name VARCHAR(100),
|
|
||||||
|
|
||||||
-- Machine and Production Details
|
-- Quality Control Phase T2 (Cut/Quilted)
|
||||||
machine_code VARCHAR(50),
|
phase_t2_cut VARCHAR(50), -- Faza taiat/matlasat(T2)
|
||||||
machine_type VARCHAR(50),
|
t2_operator_name VARCHAR(100), -- Nume complet T2
|
||||||
machine_number VARCHAR(20),
|
t2_registration_date DATETIME, -- Data inregistrare T2
|
||||||
classification VARCHAR(100),
|
|
||||||
design_number INT,
|
|
||||||
needle_position INT,
|
|
||||||
total_norm_time DECIMAL(8,2),
|
|
||||||
model_lb2 VARCHAR(255),
|
|
||||||
|
|
||||||
|
-- Quality Control Phase T3 (Sewing)
|
||||||
|
phase_t3_sewing VARCHAR(50), -- Faza cusut(T3)
|
||||||
|
t3_operator_name VARCHAR(100), -- Nume complet T3
|
||||||
|
t3_registration_date DATETIME, -- Data inregistrare T3
|
||||||
|
|
||||||
|
-- Additional Information
|
||||||
|
design_number INT, -- Design number
|
||||||
|
classification VARCHAR(100), -- Clasificare
|
||||||
|
model_description VARCHAR(255), -- Descriere Model
|
||||||
|
model_lb2 VARCHAR(255), -- Model Lb2
|
||||||
|
needle_position DECIMAL(5,1), -- Needle Position
|
||||||
|
needle_row VARCHAR(50), -- Needle row
|
||||||
|
priority INT DEFAULT 0, -- Prioritate executie
|
||||||
|
|
||||||
|
-- Metadata
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
-- Indexes for Performance
|
||||||
INDEX idx_production_order (production_order),
|
INDEX idx_production_order (production_order),
|
||||||
INDEX idx_order_id (order_id),
|
INDEX idx_open_for_order_line (open_for_order_line),
|
||||||
|
INDEX idx_client_order_line (client_order_line),
|
||||||
INDEX idx_customer (customer_code),
|
INDEX idx_customer (customer_code),
|
||||||
INDEX idx_article (article_code),
|
INDEX idx_article (article_code),
|
||||||
INDEX idx_delivery_date (delivery_date),
|
INDEX idx_delivery_date (delivery_date),
|
||||||
INDEX idx_status (production_status),
|
INDEX idx_status (production_status),
|
||||||
INDEX idx_machine (machine_code),
|
INDEX idx_machine (machine_code),
|
||||||
INDEX idx_quilting_date (end_of_quilting),
|
INDEX idx_quilting_date (end_of_quilting),
|
||||||
INDEX idx_sewing_date (end_of_sewing)
|
INDEX idx_sewing_date (end_of_sewing),
|
||||||
|
INDEX idx_data_planificare (data_planificare)
|
||||||
);
|
);
|
||||||
|
|
||||||
-- =============================================
|
-- =============================================
|
||||||
|
|||||||
@@ -94,50 +94,52 @@ class DailyMirrorDatabase:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def import_production_data(self, file_path):
|
def import_production_data(self, file_path):
|
||||||
"""Import production data from Excel file (Comenzi Productie format)"""
|
"""Import production data from Excel file (Production orders Data sheet OR DataSheet)"""
|
||||||
try:
|
try:
|
||||||
# The correct data is in the first sheet (DataSheet)
|
# Read from "Production orders Data" sheet (new format) or "DataSheet" (old format)
|
||||||
df = None
|
df = None
|
||||||
sheet_used = None
|
sheet_used = None
|
||||||
|
|
||||||
# Get available sheets
|
# Try different engines (openpyxl for .xlsx, pyxlsb for .xlsb)
|
||||||
excel_file = pd.ExcelFile(file_path)
|
engines_to_try = ['openpyxl', 'pyxlsb']
|
||||||
|
|
||||||
|
# Try different sheet names (new format first, then old format)
|
||||||
|
sheet_names_to_try = ['Production orders Data', 'DataSheet']
|
||||||
|
|
||||||
|
for engine in engines_to_try:
|
||||||
|
if df is not None:
|
||||||
|
break
|
||||||
|
|
||||||
|
try:
|
||||||
|
logger.info(f"Trying to read Excel file with engine: {engine}")
|
||||||
|
excel_file = pd.ExcelFile(file_path, engine=engine)
|
||||||
logger.info(f"Available sheets: {excel_file.sheet_names}")
|
logger.info(f"Available sheets: {excel_file.sheet_names}")
|
||||||
|
|
||||||
# Try DataSheet first (where the actual production data is), then fallback options
|
# Try each sheet name
|
||||||
sheet_attempts = [
|
for sheet_name in sheet_names_to_try:
|
||||||
('DataSheet', 'openpyxl'),
|
if sheet_name in excel_file.sheet_names:
|
||||||
('DataSheet', 'xlrd'),
|
|
||||||
(0, 'openpyxl'),
|
|
||||||
(0, 'xlrd'),
|
|
||||||
('Sheet1', 'openpyxl'), # fallback to Sheet1 if DataSheet fails
|
|
||||||
(1, 'openpyxl')
|
|
||||||
]
|
|
||||||
|
|
||||||
for sheet_name, engine in sheet_attempts:
|
|
||||||
try:
|
try:
|
||||||
logger.info(f"Trying to read sheet '{sheet_name}' with engine '{engine}'")
|
logger.info(f"Reading sheet '{sheet_name}'")
|
||||||
df = pd.read_excel(file_path, sheet_name=sheet_name, engine=engine, header=0)
|
df = pd.read_excel(file_path, sheet_name=sheet_name, engine=engine, header=0)
|
||||||
sheet_used = f"{sheet_name} (engine: {engine})"
|
sheet_used = f"{sheet_name} (engine: {engine})"
|
||||||
logger.info(f"Successfully read from sheet: {sheet_used}")
|
logger.info(f"Successfully read from sheet: {sheet_used}")
|
||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as sheet_error:
|
||||||
logger.warning(f"Failed to read sheet {sheet_name} with {engine}: {e}")
|
logger.warning(f"Failed to read sheet '{sheet_name}': {sheet_error}")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# If all engines fail on DataSheet, try a different approach
|
if df is not None:
|
||||||
if df is None:
|
break
|
||||||
try:
|
|
||||||
logger.info("Trying alternative method: reading without specifying engine")
|
|
||||||
df = pd.read_excel(file_path, sheet_name='DataSheet')
|
|
||||||
sheet_used = "DataSheet (default engine)"
|
|
||||||
logger.info("Successfully read with default engine")
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Failed with default engine: {e}")
|
logger.warning(f"Failed with engine {engine}: {e}")
|
||||||
raise Exception("Could not read the DataSheet from the Excel file. The file may be corrupted.")
|
continue
|
||||||
|
|
||||||
|
if df is None:
|
||||||
|
raise Exception("Could not read Excel file. Please ensure it has a 'Production orders Data' or 'DataSheet' sheet.")
|
||||||
|
|
||||||
logger.info(f"Loaded production data from {sheet_used}: {len(df)} rows, {len(df.columns)} columns")
|
logger.info(f"Loaded production data from {sheet_used}: {len(df)} rows, {len(df.columns)} columns")
|
||||||
logger.info(f"Available columns: {list(df.columns)}")
|
logger.info(f"First 5 column names: {list(df.columns)[:5]}")
|
||||||
|
|
||||||
cursor = self.connection.cursor()
|
cursor = self.connection.cursor()
|
||||||
success_count = 0
|
success_count = 0
|
||||||
@@ -145,60 +147,116 @@ class DailyMirrorDatabase:
|
|||||||
updated_count = 0
|
updated_count = 0
|
||||||
error_count = 0
|
error_count = 0
|
||||||
|
|
||||||
# Prepare insert statement
|
# Prepare insert statement with new schema
|
||||||
insert_sql = """
|
insert_sql = """
|
||||||
INSERT INTO dm_production_orders (
|
INSERT INTO dm_production_orders (
|
||||||
production_order, customer_code, client_order, article_code,
|
production_order, open_for_order_line, client_order_line,
|
||||||
article_description, quantity_requested, delivery_date, production_status,
|
customer_code, customer_name, article_code, article_description,
|
||||||
end_of_quilting, end_of_sewing, t1_status, t1_registration_date, t1_operator_name,
|
quantity_requested, unit_of_measure, delivery_date, opening_date,
|
||||||
t2_status, t2_registration_date, t2_operator_name, t3_status, t3_registration_date,
|
closing_date, data_planificare, production_status,
|
||||||
t3_operator_name, machine_code, machine_type, classification, total_norm_time,
|
machine_code, machine_type, machine_number,
|
||||||
data_deschiderii, model_lb2, data_planificare, machine_number, design_number, needle_position
|
end_of_quilting, end_of_sewing,
|
||||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
phase_t1_prepared, t1_operator_name, t1_registration_date,
|
||||||
|
phase_t2_cut, t2_operator_name, t2_registration_date,
|
||||||
|
phase_t3_sewing, t3_operator_name, t3_registration_date,
|
||||||
|
design_number, classification, model_description, model_lb2,
|
||||||
|
needle_position, needle_row, priority
|
||||||
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
ON DUPLICATE KEY UPDATE
|
ON DUPLICATE KEY UPDATE
|
||||||
|
open_for_order_line = VALUES(open_for_order_line),
|
||||||
|
client_order_line = VALUES(client_order_line),
|
||||||
customer_code = VALUES(customer_code),
|
customer_code = VALUES(customer_code),
|
||||||
client_order = VALUES(client_order),
|
customer_name = VALUES(customer_name),
|
||||||
article_code = VALUES(article_code),
|
article_code = VALUES(article_code),
|
||||||
article_description = VALUES(article_description),
|
article_description = VALUES(article_description),
|
||||||
quantity_requested = VALUES(quantity_requested),
|
quantity_requested = VALUES(quantity_requested),
|
||||||
delivery_date = VALUES(delivery_date),
|
delivery_date = VALUES(delivery_date),
|
||||||
production_status = VALUES(production_status),
|
production_status = VALUES(production_status),
|
||||||
|
machine_code = VALUES(machine_code),
|
||||||
|
end_of_quilting = VALUES(end_of_quilting),
|
||||||
|
end_of_sewing = VALUES(end_of_sewing),
|
||||||
|
phase_t1_prepared = VALUES(phase_t1_prepared),
|
||||||
|
t1_operator_name = VALUES(t1_operator_name),
|
||||||
|
t1_registration_date = VALUES(t1_registration_date),
|
||||||
|
phase_t2_cut = VALUES(phase_t2_cut),
|
||||||
|
t2_operator_name = VALUES(t2_operator_name),
|
||||||
|
t2_registration_date = VALUES(t2_registration_date),
|
||||||
|
phase_t3_sewing = VALUES(phase_t3_sewing),
|
||||||
|
t3_operator_name = VALUES(t3_operator_name),
|
||||||
|
t3_registration_date = VALUES(t3_registration_date),
|
||||||
updated_at = CURRENT_TIMESTAMP
|
updated_at = CURRENT_TIMESTAMP
|
||||||
"""
|
"""
|
||||||
|
|
||||||
for index, row in df.iterrows():
|
for index, row in df.iterrows():
|
||||||
try:
|
try:
|
||||||
|
# Create concatenated fields with dash separator
|
||||||
|
opened_for_order = str(row.get('Opened for Order', '')).strip() if pd.notna(row.get('Opened for Order')) else ''
|
||||||
|
linia = str(row.get('Linia', '')).strip() if pd.notna(row.get('Linia')) else ''
|
||||||
|
open_for_order_line = f"{opened_for_order}-{linia}" if opened_for_order and linia else ''
|
||||||
|
|
||||||
|
com_achiz_client = str(row.get('Com. Achiz. Client', '')).strip() if pd.notna(row.get('Com. Achiz. Client')) else ''
|
||||||
|
nr_linie_com_client = str(row.get('Nr. linie com. client', '')).strip() if pd.notna(row.get('Nr. linie com. client')) else ''
|
||||||
|
client_order_line = f"{com_achiz_client}-{nr_linie_com_client}" if com_achiz_client and nr_linie_com_client else ''
|
||||||
|
|
||||||
|
# Helper function to safely get numeric values
|
||||||
|
def safe_int(value, default=None):
|
||||||
|
if pd.isna(value) or value == '':
|
||||||
|
return default
|
||||||
|
try:
|
||||||
|
return int(float(value))
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
return default
|
||||||
|
|
||||||
|
def safe_float(value, default=None):
|
||||||
|
if pd.isna(value) or value == '':
|
||||||
|
return default
|
||||||
|
try:
|
||||||
|
return float(value)
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
return default
|
||||||
|
|
||||||
|
def safe_str(value, default=''):
|
||||||
|
if pd.isna(value):
|
||||||
|
return default
|
||||||
|
return str(value).strip()
|
||||||
|
|
||||||
# Prepare data tuple
|
# Prepare data tuple
|
||||||
data = (
|
data = (
|
||||||
row.get('Comanda Productie', ''),
|
safe_str(row.get('Comanda Productie')), # production_order
|
||||||
row.get('Customer', ''),
|
open_for_order_line, # open_for_order_line (concatenated)
|
||||||
row.get('Comanda client', ''),
|
client_order_line, # client_order_line (concatenated)
|
||||||
row.get('Cod Articol', ''),
|
safe_str(row.get('Cod. Client')), # customer_code
|
||||||
row.get('Descriere', ''),
|
safe_str(row.get('Customer Name')), # customer_name
|
||||||
row.get('Cantitate ceruta', 0),
|
safe_str(row.get('Cod Articol')), # article_code
|
||||||
self._parse_date(row.get('Delivery date')),
|
safe_str(row.get('Descr. Articol.1')), # article_description
|
||||||
row.get('Status', ''),
|
safe_int(row.get('Cantitate Com. Prod.'), 0), # quantity_requested
|
||||||
self._parse_datetime(row.get('End of Quilting')),
|
safe_str(row.get('U.M.')), # unit_of_measure
|
||||||
self._parse_datetime(row.get('End of sewing')),
|
self._parse_date(row.get('SO Duedate')), # delivery_date
|
||||||
row.get('T1', 0),
|
self._parse_date(row.get('Data Deschiderii')), # opening_date
|
||||||
self._parse_datetime(row.get('Data inregistrare T1')),
|
self._parse_date(row.get('Data Inchiderii')), # closing_date
|
||||||
row.get('Numele Complet T1', ''),
|
self._parse_date(row.get('Data Planific.')), # data_planificare
|
||||||
row.get('T2', 0),
|
safe_str(row.get('Status')), # production_status
|
||||||
self._parse_datetime(row.get('Data inregistrare T2')),
|
safe_str(row.get('Masina cusut')), # machine_code
|
||||||
row.get('Numele Complet T2', ''),
|
safe_str(row.get('Tip masina')), # machine_type
|
||||||
row.get('T3', 0),
|
safe_str(row.get('Machine Number')), # machine_number
|
||||||
self._parse_datetime(row.get('Data inregistrare T3')),
|
self._parse_date(row.get('End of Quilting')), # end_of_quilting
|
||||||
row.get('Numele Complet T3', ''),
|
self._parse_date(row.get('End of Sewing')), # end_of_sewing
|
||||||
row.get('Masina Cusut ', ''),
|
safe_str(row.get('T2')), # phase_t1_prepared (using T2 column)
|
||||||
row.get('Tip Masina', ''),
|
safe_str(row.get('Nume complet T2')), # t1_operator_name
|
||||||
row.get('Clasificare', ''),
|
self._parse_datetime(row.get('Data inregistrare T2')), # t1_registration_date
|
||||||
row.get('Timp normat total', 0),
|
safe_str(row.get('T1')), # phase_t2_cut (using T1 column)
|
||||||
self._parse_date(row.get('Data Deschiderii')),
|
safe_str(row.get('Nume complet T1')), # t2_operator_name
|
||||||
row.get('Model Lb2', ''),
|
self._parse_datetime(row.get('Data inregistrare T1')), # t2_registration_date
|
||||||
self._parse_date(row.get('Data Planific.')),
|
safe_str(row.get('T3')), # phase_t3_sewing (using T3 column)
|
||||||
row.get('Numar masina', ''),
|
safe_str(row.get('Nume complet T3')), # t3_operator_name
|
||||||
row.get('Design nr', 0),
|
self._parse_datetime(row.get('Data inregistrare T3')), # t3_registration_date
|
||||||
row.get('Needle position', 0)
|
safe_int(row.get('Design number')), # design_number
|
||||||
|
safe_str(row.get('Clasificare')), # classification
|
||||||
|
safe_str(row.get('Descriere Model')), # model_description
|
||||||
|
safe_str(row.get('Model Lb2')), # model_lb2
|
||||||
|
safe_float(row.get('Needle Position')), # needle_position
|
||||||
|
safe_str(row.get('Needle row')), # needle_row
|
||||||
|
safe_int(row.get('Prioritate executie'), 0) # priority
|
||||||
)
|
)
|
||||||
|
|
||||||
cursor.execute(insert_sql, data)
|
cursor.execute(insert_sql, data)
|
||||||
@@ -217,11 +275,17 @@ class DailyMirrorDatabase:
|
|||||||
|
|
||||||
except Exception as row_error:
|
except Exception as row_error:
|
||||||
logger.warning(f"Error processing row {index}: {row_error}")
|
logger.warning(f"Error processing row {index}: {row_error}")
|
||||||
|
# Log first few values of problematic row
|
||||||
|
try:
|
||||||
|
row_sample = {k: v for k, v in list(row.items())[:5]}
|
||||||
|
logger.warning(f"Row data sample: {row_sample}")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
error_count += 1
|
error_count += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self.connection.commit()
|
self.connection.commit()
|
||||||
logger.info(f"Production data import completed: {success_count} successful, {error_count} failed")
|
logger.info(f"Production data import completed: {success_count} successful ({created_count} created, {updated_count} updated), {error_count} failed")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'success_count': success_count,
|
'success_count': success_count,
|
||||||
@@ -233,6 +297,8 @@ class DailyMirrorDatabase:
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error importing production data: {e}")
|
logger.error(f"Error importing production data: {e}")
|
||||||
|
import traceback
|
||||||
|
logger.error(traceback.format_exc())
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def import_orders_data(self, file_path):
|
def import_orders_data(self, file_path):
|
||||||
@@ -688,6 +754,30 @@ class DailyMirrorDatabase:
|
|||||||
logger.error(f"Error deleting production orders: {e}")
|
logger.error(f"Error deleting production orders: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def clear_orders(self):
|
||||||
|
"""Delete all rows from the Daily Mirror orders table"""
|
||||||
|
try:
|
||||||
|
cursor = self.connection.cursor()
|
||||||
|
cursor.execute("DELETE FROM dm_orders")
|
||||||
|
self.connection.commit()
|
||||||
|
logger.info("All orders deleted from dm_orders table.")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error deleting orders: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def clear_delivery(self):
|
||||||
|
"""Delete all rows from the Daily Mirror delivery table"""
|
||||||
|
try:
|
||||||
|
cursor = self.connection.cursor()
|
||||||
|
cursor.execute("DELETE FROM dm_deliveries")
|
||||||
|
self.connection.commit()
|
||||||
|
logger.info("All delivery records deleted from dm_deliveries table.")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error deleting delivery records: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
def _parse_date(self, date_value):
|
def _parse_date(self, date_value):
|
||||||
"""Parse date with better null handling"""
|
"""Parse date with better null handling"""
|
||||||
if pd.isna(date_value) or date_value == 'nan' or date_value is None or date_value == '':
|
if pd.isna(date_value) or date_value == 'nan' or date_value is None or date_value == '':
|
||||||
|
|||||||
@@ -1,6 +1,41 @@
|
|||||||
/* Daily Mirror Tune Pages - Modal Styles */
|
/* Daily Mirror Tune Pages - Modal Styles */
|
||||||
/* Fixes for editable modals across tune/production, tune/orders, and tune/delivery pages */
|
/* Fixes for editable modals across tune/production, tune/orders, and tune/delivery pages */
|
||||||
|
|
||||||
|
/* Force modal width to be extra large (20% wider than standard 1200px) */
|
||||||
|
#editModal .modal-dialog {
|
||||||
|
max-width: 1440px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modal footer button spacing and sizing */
|
||||||
|
#editModal .modal-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editModal .modal-footer .btn {
|
||||||
|
min-width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editModal .modal-footer .btn-danger {
|
||||||
|
min-width: 150px;
|
||||||
|
background-color: #dc3545 !important;
|
||||||
|
border-color: #dc3545 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editModal .modal-footer .btn-danger:hover {
|
||||||
|
background-color: #bb2d3b !important;
|
||||||
|
border-color: #b02a37 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editModal .modal-footer .btn-primary {
|
||||||
|
min-width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editModal .modal-footer .btn-secondary {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Force Bootstrap modal to have proper z-index */
|
/* Force Bootstrap modal to have proper z-index */
|
||||||
#editModal.modal {
|
#editModal.modal {
|
||||||
z-index: 9999 !important;
|
z-index: 9999 !important;
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
{% block title %}Build Database - Daily Mirror{% endblock %}
|
{% block title %}Build Database - Daily Mirror{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_css %}
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='daily_mirror_tune.css') }}">
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<!-- Page Header -->
|
<!-- Page Header -->
|
||||||
@@ -205,6 +209,43 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
/* Additional modal fixes specific to this page */
|
||||||
|
#uploadResultModal {
|
||||||
|
z-index: 10000 !important;
|
||||||
|
pointer-events: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#uploadResultModal .modal-dialog {
|
||||||
|
pointer-events: auto !important;
|
||||||
|
z-index: 10001 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#uploadResultModal .modal-content {
|
||||||
|
pointer-events: auto !important;
|
||||||
|
background-color: white !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#uploadResultModal .modal-backdrop {
|
||||||
|
z-index: 9998 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#uploadResultModal .btn-close,
|
||||||
|
#uploadResultModal .modal-footer button {
|
||||||
|
pointer-events: auto !important;
|
||||||
|
cursor: pointer !important;
|
||||||
|
opacity: 1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure modal can be dismissed */
|
||||||
|
.modal-backdrop.show {
|
||||||
|
pointer-events: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark mode modal fixes */
|
||||||
|
body.dark-mode #uploadResultModal .modal-content {
|
||||||
|
background-color: #2d3748 !important;
|
||||||
|
}
|
||||||
|
|
||||||
.accordion-button:not(.collapsed) {
|
.accordion-button:not(.collapsed) {
|
||||||
background-color: #e7f3ff;
|
background-color: #e7f3ff;
|
||||||
color: #0066cc;
|
color: #0066cc;
|
||||||
|
|||||||
@@ -87,6 +87,11 @@
|
|||||||
</h5>
|
</h5>
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<span id="recordsInfo" class="text-muted me-3"></span>
|
<span id="recordsInfo" class="text-muted me-3"></span>
|
||||||
|
{% if session.get('role') == 'superadmin' %}
|
||||||
|
<button class="btn btn-danger btn-sm me-2" onclick="clearAllDelivery()" id="clearAllBtn">
|
||||||
|
<i class="fas fa-trash-alt"></i> Clear All Delivery
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
<button class="btn btn-success btn-sm" onclick="saveAllChanges()">
|
<button class="btn btn-success btn-sm" onclick="saveAllChanges()">
|
||||||
<i class="fas fa-save"></i> Save All Changes
|
<i class="fas fa-save"></i> Save All Changes
|
||||||
</button>
|
</button>
|
||||||
@@ -499,5 +504,46 @@ function saveRecord() {
|
|||||||
function saveAllChanges() {
|
function saveAllChanges() {
|
||||||
alert('Save All Changes functionality will be implemented for bulk operations.');
|
alert('Save All Changes functionality will be implemented for bulk operations.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clearAllDelivery() {
|
||||||
|
if (!confirm('⚠️ WARNING: This will permanently delete ALL delivery records from the database!\n\nAre you absolutely sure you want to continue?')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second confirmation for safety
|
||||||
|
if (!confirm('This action CANNOT be undone! All delivery data will be lost.\n\nClick OK to proceed with deletion.')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const clearBtn = document.getElementById('clearAllBtn');
|
||||||
|
const originalText = clearBtn.innerHTML;
|
||||||
|
clearBtn.disabled = true;
|
||||||
|
clearBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Deleting...';
|
||||||
|
|
||||||
|
fetch('/daily_mirror/clear_delivery', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
alert('✅ ' + data.message);
|
||||||
|
// Reload the page to show empty table
|
||||||
|
loadDeliveryData(1);
|
||||||
|
} else {
|
||||||
|
alert('❌ Error: ' + (data.message || 'Failed to clear delivery records'));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
alert('❌ Error clearing delivery records: ' + error.message);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
clearBtn.disabled = false;
|
||||||
|
clearBtn.innerHTML = originalText;
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -87,6 +87,11 @@
|
|||||||
</h5>
|
</h5>
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<span id="recordsInfo" class="text-muted me-3"></span>
|
<span id="recordsInfo" class="text-muted me-3"></span>
|
||||||
|
{% if session.get('role') == 'superadmin' %}
|
||||||
|
<button class="btn btn-danger btn-sm me-2" onclick="clearAllOrders()" id="clearAllBtn">
|
||||||
|
<i class="fas fa-trash-alt"></i> Clear All Orders
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
<button class="btn btn-success btn-sm" onclick="saveAllChanges()">
|
<button class="btn btn-success btn-sm" onclick="saveAllChanges()">
|
||||||
<i class="fas fa-save"></i> Save All Changes
|
<i class="fas fa-save"></i> Save All Changes
|
||||||
</button>
|
</button>
|
||||||
@@ -518,5 +523,46 @@ function saveRecord() {
|
|||||||
function saveAllChanges() {
|
function saveAllChanges() {
|
||||||
alert('Save All Changes functionality will be implemented for bulk operations.');
|
alert('Save All Changes functionality will be implemented for bulk operations.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clearAllOrders() {
|
||||||
|
if (!confirm('⚠️ WARNING: This will permanently delete ALL customer orders from the database!\n\nAre you absolutely sure you want to continue?')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second confirmation for safety
|
||||||
|
if (!confirm('This action CANNOT be undone! All customer order data will be lost.\n\nClick OK to proceed with deletion.')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const clearBtn = document.getElementById('clearAllBtn');
|
||||||
|
const originalText = clearBtn.innerHTML;
|
||||||
|
clearBtn.disabled = true;
|
||||||
|
clearBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Deleting...';
|
||||||
|
|
||||||
|
fetch('/daily_mirror/clear_orders', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
alert('✅ ' + data.message);
|
||||||
|
// Reload the page to show empty table
|
||||||
|
loadOrdersData(1);
|
||||||
|
} else {
|
||||||
|
alert('❌ Error: ' + (data.message || 'Failed to clear orders'));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
alert('❌ Error clearing orders: ' + error.message);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
clearBtn.disabled = false;
|
||||||
|
clearBtn.innerHTML = originalText;
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -4,6 +4,47 @@
|
|||||||
|
|
||||||
{% block extra_css %}
|
{% block extra_css %}
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/daily_mirror_tune.css') }}">
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/daily_mirror_tune.css') }}">
|
||||||
|
<style>
|
||||||
|
/* Force modal width - using viewport width for maximum responsiveness */
|
||||||
|
.modal#editModal .modal-dialog {
|
||||||
|
max-width: 95vw !important;
|
||||||
|
width: 95vw !important;
|
||||||
|
margin: 1.75rem auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal#editModal .modal-dialog.modal-xl {
|
||||||
|
max-width: 95vw !important;
|
||||||
|
width: 95vw !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Override ALL Bootstrap media queries */
|
||||||
|
@media (min-width: 576px) {
|
||||||
|
.modal#editModal .modal-dialog {
|
||||||
|
max-width: 95vw !important;
|
||||||
|
width: 95vw !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 992px) {
|
||||||
|
.modal#editModal .modal-dialog {
|
||||||
|
max-width: 95vw !important;
|
||||||
|
width: 95vw !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
.modal#editModal .modal-dialog,
|
||||||
|
.modal#editModal .modal-dialog.modal-xl {
|
||||||
|
max-width: 95vw !important;
|
||||||
|
width: 95vw !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure pointer events work */
|
||||||
|
.modal#editModal .modal-dialog {
|
||||||
|
pointer-events: auto !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
@@ -90,6 +131,11 @@
|
|||||||
</h5>
|
</h5>
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<span id="recordsInfo" class="text-muted me-3"></span>
|
<span id="recordsInfo" class="text-muted me-3"></span>
|
||||||
|
{% if session.get('role') == 'superadmin' %}
|
||||||
|
<button class="btn btn-danger btn-sm me-2" onclick="clearAllProductionOrders()" id="clearAllBtn">
|
||||||
|
<i class="fas fa-trash-alt"></i> Clear All Orders
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
<button class="btn btn-success btn-sm" onclick="saveAllChanges()">
|
<button class="btn btn-success btn-sm" onclick="saveAllChanges()">
|
||||||
<i class="fas fa-save"></i> Save All Changes
|
<i class="fas fa-save"></i> Save All Changes
|
||||||
</button>
|
</button>
|
||||||
@@ -101,8 +147,9 @@
|
|||||||
<thead class="table-dark">
|
<thead class="table-dark">
|
||||||
<tr>
|
<tr>
|
||||||
<th>Production Order</th>
|
<th>Production Order</th>
|
||||||
|
<th>Opened for Order</th>
|
||||||
|
<th>Client Order-Line</th>
|
||||||
<th>Customer</th>
|
<th>Customer</th>
|
||||||
<th>Client Order</th>
|
|
||||||
<th>Article Code</th>
|
<th>Article Code</th>
|
||||||
<th>Description</th>
|
<th>Description</th>
|
||||||
<th>Quantity</th>
|
<th>Quantity</th>
|
||||||
@@ -147,7 +194,7 @@
|
|||||||
|
|
||||||
<!-- Edit Modal -->
|
<!-- Edit Modal -->
|
||||||
<div class="modal fade" id="editModal" tabindex="-1" aria-labelledby="editModalLabel" aria-hidden="true" data-bs-backdrop="true" data-bs-keyboard="true">
|
<div class="modal fade" id="editModal" tabindex="-1" aria-labelledby="editModalLabel" aria-hidden="true" data-bs-backdrop="true" data-bs-keyboard="true">
|
||||||
<div class="modal-dialog modal-lg modal-dialog-scrollable">
|
<div class="modal-dialog modal-xl modal-dialog-scrollable" style="max-width: 95vw !important; width: 95vw !important;">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title" id="editModalLabel">Edit Production Order</h5>
|
<h5 class="modal-title" id="editModalLabel">Edit Production Order</h5>
|
||||||
@@ -157,50 +204,59 @@
|
|||||||
<form id="editForm">
|
<form id="editForm">
|
||||||
<input type="hidden" id="editRecordId">
|
<input type="hidden" id="editRecordId">
|
||||||
|
|
||||||
<div class="row">
|
<!-- Production Order (Full Width) -->
|
||||||
<div class="col-md-6 mb-3">
|
<div class="row mb-3">
|
||||||
<label for="editProductionOrder" class="form-label">Production Order</label>
|
<div class="col-12">
|
||||||
<input type="text" class="form-control" id="editProductionOrder" readonly>
|
<label for="editProductionOrder" class="form-label fw-bold">Production Order</label>
|
||||||
</div>
|
<input type="text" class="form-control form-control-lg" id="editProductionOrder" readonly>
|
||||||
<div class="col-md-6 mb-3">
|
|
||||||
<label for="editCustomerCode" class="form-label">Customer Code</label>
|
|
||||||
<input type="text" class="form-control" id="editCustomerCode">
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<hr class="my-3">
|
||||||
<div class="col-md-6 mb-3">
|
|
||||||
<label for="editCustomerName" class="form-label">Customer Name</label>
|
|
||||||
<input type="text" class="form-control" id="editCustomerName">
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6 mb-3">
|
|
||||||
<label for="editClientOrder" class="form-label">Client Order</label>
|
|
||||||
<input type="text" class="form-control" id="editClientOrder">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<!-- Three Column Layout -->
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6 mb-3">
|
<!-- Column 1 -->
|
||||||
<label for="editArticleCode" class="form-label">Article Code</label>
|
<div class="col-md-4">
|
||||||
<input type="text" class="form-control" id="editArticleCode">
|
<div class="mb-3">
|
||||||
</div>
|
<label for="editOpenForOrderLine" class="form-label">Opened for Order-Line</label>
|
||||||
<div class="col-md-6 mb-3">
|
<input type="text" class="form-control" id="editOpenForOrderLine" readonly>
|
||||||
<label for="editQuantity" class="form-label">Quantity</label>
|
|
||||||
<input type="number" class="form-control" id="editQuantity">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="editDescription" class="form-label">Article Description</label>
|
<label for="editCustomerCode" class="form-label">Customer Code</label>
|
||||||
<textarea class="form-control" id="editDescription" rows="2"></textarea>
|
<input type="text" class="form-control" id="editCustomerCode">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="mb-3">
|
||||||
<div class="col-md-6 mb-3">
|
<label for="editArticleCode" class="form-label">Article Code</label>
|
||||||
|
<input type="text" class="form-control" id="editArticleCode" readonly>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
<label for="editDeliveryDate" class="form-label">Delivery Date</label>
|
<label for="editDeliveryDate" class="form-label">Delivery Date</label>
|
||||||
<input type="date" class="form-control" id="editDeliveryDate">
|
<input type="date" class="form-control" id="editDeliveryDate">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 mb-3">
|
</div>
|
||||||
|
|
||||||
|
<!-- Column 2 -->
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="editClientOrderLine" class="form-label">Client Order-Line</label>
|
||||||
|
<input type="text" class="form-control" id="editClientOrderLine" readonly>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="editCustomerName" class="form-label">Customer Name</label>
|
||||||
|
<input type="text" class="form-control" id="editCustomerName">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="editQuantity" class="form-label">Quantity</label>
|
||||||
|
<input type="number" class="form-control" id="editQuantity">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
<label for="editStatus" class="form-label">Production Status</label>
|
<label for="editStatus" class="form-label">Production Status</label>
|
||||||
<select class="form-control" id="editStatus">
|
<select class="form-control" id="editStatus">
|
||||||
<option value="PENDING">Pending</option>
|
<option value="PENDING">Pending</option>
|
||||||
@@ -211,21 +267,35 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Column 3 -->
|
||||||
|
<div class="col-md-4">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="editMachine" class="form-label">Machine Code</label>
|
<label for="editMachine" class="form-label">Machine Code</label>
|
||||||
<input type="text" class="form-control" id="editMachine">
|
<input type="text" class="form-control" id="editMachine">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="editDescription" class="form-label">Article Description</label>
|
||||||
|
<textarea class="form-control" id="editDescription" rows="6"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer d-flex justify-content-between">
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
<button type="button" class="btn btn-danger" onclick="deleteRecord()" style="min-width: 150px;">
|
||||||
<button type="button" class="btn btn-primary" onclick="saveRecord()">
|
<i class="fas fa-trash"></i> Delete Record
|
||||||
|
</button>
|
||||||
|
<div>
|
||||||
|
<button type="button" class="btn btn-secondary me-2" data-bs-dismiss="modal" style="min-width: 100px;">Cancel</button>
|
||||||
|
<button type="button" class="btn btn-primary" onclick="saveRecord()" style="min-width: 150px;">
|
||||||
<i class="fas fa-save"></i> Save Changes
|
<i class="fas fa-save"></i> Save Changes
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
let currentPage = 1;
|
let currentPage = 1;
|
||||||
@@ -300,8 +370,9 @@ function renderTable(data) {
|
|||||||
tbody.innerHTML = data.records.map((record, index) => `
|
tbody.innerHTML = data.records.map((record, index) => `
|
||||||
<tr id="row-${record.id}">
|
<tr id="row-${record.id}">
|
||||||
<td><strong>${record.production_order}</strong></td>
|
<td><strong>${record.production_order}</strong></td>
|
||||||
|
<td>${record.open_for_order_line || ''}</td>
|
||||||
|
<td>${record.client_order_line || ''}</td>
|
||||||
<td>${record.customer_code}<br><small class="text-muted">${record.customer_name || ''}</small></td>
|
<td>${record.customer_code}<br><small class="text-muted">${record.customer_name || ''}</small></td>
|
||||||
<td>${record.client_order || ''}</td>
|
|
||||||
<td>${record.article_code || ''}</td>
|
<td>${record.article_code || ''}</td>
|
||||||
<td><small>${record.article_description || ''}</small></td>
|
<td><small>${record.article_description || ''}</small></td>
|
||||||
<td>${record.quantity_requested || ''}</td>
|
<td>${record.quantity_requested || ''}</td>
|
||||||
@@ -371,9 +442,10 @@ function editRecord(recordId) {
|
|||||||
// Populate the edit form
|
// Populate the edit form
|
||||||
document.getElementById('editRecordId').value = record.id;
|
document.getElementById('editRecordId').value = record.id;
|
||||||
document.getElementById('editProductionOrder').value = record.production_order;
|
document.getElementById('editProductionOrder').value = record.production_order;
|
||||||
|
document.getElementById('editOpenForOrderLine').value = record.open_for_order_line || '';
|
||||||
|
document.getElementById('editClientOrderLine').value = record.client_order_line || '';
|
||||||
document.getElementById('editCustomerCode').value = record.customer_code || '';
|
document.getElementById('editCustomerCode').value = record.customer_code || '';
|
||||||
document.getElementById('editCustomerName').value = record.customer_name || '';
|
document.getElementById('editCustomerName').value = record.customer_name || '';
|
||||||
document.getElementById('editClientOrder').value = record.client_order || '';
|
|
||||||
document.getElementById('editArticleCode').value = record.article_code || '';
|
document.getElementById('editArticleCode').value = record.article_code || '';
|
||||||
document.getElementById('editDescription').value = record.article_description || '';
|
document.getElementById('editDescription').value = record.article_description || '';
|
||||||
document.getElementById('editQuantity').value = record.quantity_requested || '';
|
document.getElementById('editQuantity').value = record.quantity_requested || '';
|
||||||
@@ -382,8 +454,8 @@ function editRecord(recordId) {
|
|||||||
document.getElementById('editMachine').value = record.machine_code || '';
|
document.getElementById('editMachine').value = record.machine_code || '';
|
||||||
|
|
||||||
// Explicitly enable all editable fields
|
// Explicitly enable all editable fields
|
||||||
const editableFields = ['editCustomerCode', 'editCustomerName', 'editClientOrder',
|
const editableFields = ['editCustomerCode',
|
||||||
'editArticleCode', 'editDescription', 'editQuantity',
|
'editCustomerName', 'editDescription', 'editQuantity',
|
||||||
'editDeliveryDate', 'editStatus', 'editMachine'];
|
'editDeliveryDate', 'editStatus', 'editMachine'];
|
||||||
editableFields.forEach(fieldId => {
|
editableFields.forEach(fieldId => {
|
||||||
const field = document.getElementById(fieldId);
|
const field = document.getElementById(fieldId);
|
||||||
@@ -403,6 +475,7 @@ function editRecord(recordId) {
|
|||||||
|
|
||||||
// Show the modal with proper configuration
|
// Show the modal with proper configuration
|
||||||
const modalElement = document.getElementById('editModal');
|
const modalElement = document.getElementById('editModal');
|
||||||
|
const modalDialog = modalElement.querySelector('.modal-dialog');
|
||||||
|
|
||||||
// Remove any existing modal instances to prevent conflicts
|
// Remove any existing modal instances to prevent conflicts
|
||||||
const existingModal = bootstrap.Modal.getInstance(modalElement);
|
const existingModal = bootstrap.Modal.getInstance(modalElement);
|
||||||
@@ -416,8 +489,27 @@ function editRecord(recordId) {
|
|||||||
focus: true
|
focus: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Show the modal first
|
||||||
modal.show();
|
modal.show();
|
||||||
|
|
||||||
|
// Force the modal dialog width AFTER modal is shown - using 95% of viewport width
|
||||||
|
setTimeout(() => {
|
||||||
|
if (modalDialog) {
|
||||||
|
console.log('Applying width after modal shown');
|
||||||
|
modalDialog.style.setProperty('max-width', '95vw', 'important');
|
||||||
|
modalDialog.style.setProperty('width', '95vw', 'important');
|
||||||
|
modalDialog.style.setProperty('margin', '1.75rem auto', 'important');
|
||||||
|
|
||||||
|
// Also apply to modal content for good measure
|
||||||
|
const modalContent = modalDialog.querySelector('.modal-content');
|
||||||
|
if (modalContent) {
|
||||||
|
modalContent.style.setProperty('width', '100%', 'important');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Modal dialog computed width:', window.getComputedStyle(modalDialog).width);
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
|
||||||
// Ensure form inputs are focusable and interactive after modal is shown
|
// Ensure form inputs are focusable and interactive after modal is shown
|
||||||
modalElement.addEventListener('shown.bs.modal', function () {
|
modalElement.addEventListener('shown.bs.modal', function () {
|
||||||
// Re-enable all fields after modal animation completes
|
// Re-enable all fields after modal animation completes
|
||||||
@@ -445,9 +537,10 @@ function saveRecord() {
|
|||||||
const recordId = document.getElementById('editRecordId').value;
|
const recordId = document.getElementById('editRecordId').value;
|
||||||
|
|
||||||
const formData = {
|
const formData = {
|
||||||
|
open_for_order_line: document.getElementById('editOpenForOrderLine').value,
|
||||||
|
client_order_line: document.getElementById('editClientOrderLine').value,
|
||||||
customer_code: document.getElementById('editCustomerCode').value,
|
customer_code: document.getElementById('editCustomerCode').value,
|
||||||
customer_name: document.getElementById('editCustomerName').value,
|
customer_name: document.getElementById('editCustomerName').value,
|
||||||
client_order: document.getElementById('editClientOrder').value,
|
|
||||||
article_code: document.getElementById('editArticleCode').value,
|
article_code: document.getElementById('editArticleCode').value,
|
||||||
article_description: document.getElementById('editDescription').value,
|
article_description: document.getElementById('editDescription').value,
|
||||||
quantity_requested: parseInt(document.getElementById('editQuantity').value) || 0,
|
quantity_requested: parseInt(document.getElementById('editQuantity').value) || 0,
|
||||||
@@ -482,6 +575,39 @@ function saveRecord() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function deleteRecord() {
|
||||||
|
const recordId = document.getElementById('editRecordId').value;
|
||||||
|
const productionOrder = document.getElementById('editProductionOrder').value;
|
||||||
|
|
||||||
|
if (!confirm(`⚠️ Are you sure you want to delete production order "${productionOrder}"?\n\nThis action cannot be undone.`)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(`/daily_mirror/api/tune/production_data/${recordId}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.error) {
|
||||||
|
throw new Error(data.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close modal and reload data
|
||||||
|
const modal = bootstrap.Modal.getInstance(document.getElementById('editModal'));
|
||||||
|
modal.hide();
|
||||||
|
|
||||||
|
alert('Record deleted successfully!');
|
||||||
|
loadProductionData(currentPage);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error deleting record:', error);
|
||||||
|
alert('Error deleting record: ' + error.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function clearFilters() {
|
function clearFilters() {
|
||||||
document.getElementById('searchInput').value = '';
|
document.getElementById('searchInput').value = '';
|
||||||
document.getElementById('statusFilter').value = '';
|
document.getElementById('statusFilter').value = '';
|
||||||
@@ -493,6 +619,47 @@ function saveAllChanges() {
|
|||||||
alert('Bulk save functionality will be implemented in a future update!');
|
alert('Bulk save functionality will be implemented in a future update!');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clearAllProductionOrders() {
|
||||||
|
if (!confirm('⚠️ WARNING: This will permanently delete ALL production orders from the database!\n\nAre you absolutely sure you want to continue?')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second confirmation for safety
|
||||||
|
if (!confirm('This action CANNOT be undone! All production order data will be lost.\n\nClick OK to proceed with deletion.')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const clearBtn = document.getElementById('clearAllBtn');
|
||||||
|
const originalText = clearBtn.innerHTML;
|
||||||
|
clearBtn.disabled = true;
|
||||||
|
clearBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Deleting...';
|
||||||
|
|
||||||
|
fetch('/daily_mirror/clear_production_orders', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
alert('✅ ' + data.message);
|
||||||
|
// Reload the page to show empty table
|
||||||
|
loadProductionData(1);
|
||||||
|
} else {
|
||||||
|
alert('❌ Error: ' + (data.message || 'Failed to clear production orders'));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
alert('❌ Error clearing production orders: ' + error.message);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
clearBtn.disabled = false;
|
||||||
|
clearBtn.innerHTML = originalText;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Add event listeners for real-time filtering
|
// Add event listeners for real-time filtering
|
||||||
document.getElementById('searchInput').addEventListener('input', function() {
|
document.getElementById('searchInput').addEventListener('input', function() {
|
||||||
clearTimeout(this.searchTimeout);
|
clearTimeout(this.searchTimeout);
|
||||||
|
|||||||
Reference in New Issue
Block a user