From 87938e74595c33c4c619560f03e879a7b8c082ce Mon Sep 17 00:00:00 2001 From: Scheianu Ionut Date: Sun, 14 Sep 2025 20:03:04 +0300 Subject: [PATCH] added report styles --- py_app/app/__pycache__/routes.cpython-312.pyc | Bin 44446 -> 47935 bytes py_app/app/routes.py | 67 +++++++++ py_app/app/static/script.js | 139 +++++++++++++++++- py_app/app/static/style.css | 33 +++-- py_app/app/templates/quality.html | 4 + 5 files changed, 228 insertions(+), 15 deletions(-) diff --git a/py_app/app/__pycache__/routes.cpython-312.pyc b/py_app/app/__pycache__/routes.cpython-312.pyc index fea81f1bbc0f060e077c334edf0da02aad42b3f9..31ec46bc1b1330cd3860c52cfe9870066e501462 100644 GIT binary patch delta 2833 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 BP=o*g delta 1113 zcmYL{eQZ-z6u|GjulL5a-B`O;S8;*0IOxp8jxB-=q>F%jYy{2hnz*3yIzVPg?weLg zp_4y!LnX>FAsK0xj6~)pWb@%y_=6CWE$a3MW@g1D7$r-DXc)2)SYq^?F2h!hELt^qx*+Xj+Fe`A_m;{?Uq|cz|j3>dD=M5%s|#iJIse0Fz!Pm zdCI;Yzak8gtbvIaKM3*Uj2S_9u;Av&YiVKD9$bZ?T<6mU%Af2bZ63q#G&dHiJ^g>R zWFvUYN*H}uU5gH_J{WRI+rZ!jG51*eWzJg z4Dm$^XXa+?tf;dk|C>RJw2|cI7F=R$p>1KxI5VF;;ydblzkl&J#Z&A}BhFGhyxqRq z{!u9p!@-orE%+sM0RA}I!kZzQspdZD$n10N#D=;DMc5D5GZw!Nv921Y)@ZT(C?L}8 zhh2RNzV7n4{zAjMIHGknlk4x`*QK-`c@Ac6Gbtl#$4VQcaK#_;$XA^9p5dBI%973eRU&4ZM?du zm8tPH-q?Eggp|k=&aF$(F&QXob*agqw^g|(>m>2IXapTooQh2;MeGj8)*4gwocKvz zOUhbeu%|5UG4d-yakp{RE#n@0=6J8c=b`IFt-OcR@36l*5pX-g zTs!O^dv6J`z~I|#gPKR5o&%XXChjum$%Xt9uT(gqRz#x|Fb|h=tN0w;%pI1cXx(og z=o?oqF9ndeCScPimy{22Mu0r~v3d~khJe1aSyhhsr+~(RtaB;iZGlMvxG~VHmZ3T? zpy$)$yaIfK%T*;B76d#scq&+hXyM0}>(wZKcJ51b?&*B_m5zj^SEBtNapuk-S7Ah5 z1NVn2g4e*NVLva27ltqLC%`+>=2}B3^^19jM~=zuh-Eha z{5)4pWZem0*p+e@VjWD|;A$r0b0l`dTNfUc&m*q0&s=Ed8TwagI=tD=e)Bi~7h2^o00000 diff --git a/py_app/app/routes.py b/py_app/app/routes.py index ebe4726..69cd6f6 100644 --- a/py_app/app/routes.py +++ b/py_app/app/routes.py @@ -576,6 +576,73 @@ def generate_report(): "date": selected_date } + elif report == "9": # Date Range Quality Defects Report + print(f"DEBUG: Processing Date Range Quality Defects Report") + + # Get date range from request parameters + start_date = request.args.get('start_date') + end_date = request.args.get('end_date') + + print(f"DEBUG: Date range quality defects requested - Start: {start_date}, End: {end_date}") + + if not start_date or not end_date: + data["error"] = "Both start date and end date are required for date range quality defects report." + conn.close() + return jsonify(data) + + try: + # Validate date format + from datetime import datetime + datetime.strptime(start_date, '%Y-%m-%d') + datetime.strptime(end_date, '%Y-%m-%d') + + # Check what dates are available in the database within the range + cursor.execute(""" + SELECT DISTINCT date + FROM scan1_orders + WHERE date >= ? AND date <= ? AND quality_code != 0 + ORDER BY date DESC + """, (start_date, end_date)) + existing_dates = cursor.fetchall() + print(f"DEBUG: Available dates with quality defects in range: {existing_dates}") + + # Query for quality defects in the date range + cursor.execute(""" + SELECT Id, operator_code, CP_full_code, OC1_code, OC2_code, quality_code, date, time, approved_quantity, rejected_quantity + FROM scan1_orders + WHERE date >= ? AND date <= ? AND quality_code != 0 + ORDER BY date DESC, quality_code DESC, time DESC + """, (start_date, end_date)) + rows = cursor.fetchall() + print(f"DEBUG: Date range quality defects query found {len(rows)} rows from {start_date} to {end_date}") + + data["headers"] = ["Id", "Operator Code", "CP Full Code", "OC1 Code", "OC2 Code", "Quality Code", "Date", "Time", "Approved Quantity", "Rejected Quantity"] + data["rows"] = [[format_cell_data(cell) for cell in row] for row in rows] + + # Add helpful message if no data found + if len(rows) == 0: + data["message"] = f"No quality defects found between {start_date} and {end_date}. This could mean no scanning was performed in this date range or all items passed quality control." + else: + # Add summary for quality defects in date range + total_defective_items = len(rows) + total_rejected_qty = sum(row[9] for row in rows if row[9] is not None) + unique_quality_codes = len(set(row[5] for row in rows if row[5] != 0)) + unique_dates = len(set(row[6] for row in rows)) + + data["defects_summary"] = { + "total_defective_items": total_defective_items, + "total_rejected_quantity": total_rejected_qty, + "unique_defect_types": unique_quality_codes, + "date_range": f"{start_date} to {end_date}", + "days_with_defects": unique_dates + } + + except ValueError: + data["error"] = "Invalid date format. Please use YYYY-MM-DD format." + except Exception as e: + print(f"DEBUG: Error in date range quality defects report: {e}") + data["error"] = f"Error processing date range quality defects report: {e}" + conn.close() except mariadb.Error as e: print(f"Error fetching custom date report: {e}") diff --git a/py_app/app/static/script.js b/py_app/app/static/script.js index ad31c39..11800c8 100644 --- a/py_app/app/static/script.js +++ b/py_app/app/static/script.js @@ -118,7 +118,7 @@ document.addEventListener('DOMContentLoaded', () => { reportButtons.forEach((button) => { button.addEventListener('click', () => { // Skip buttons that have their own handlers - if (button.id === 'select-day-report' || button.id === 'date-range-report' || button.id === 'select-day-defects-report') { + if (button.id === 'select-day-report' || button.id === 'date-range-report' || button.id === 'select-day-defects-report' || button.id === 'date-range-defects-report') { return; } @@ -744,9 +744,13 @@ document.addEventListener('DOMContentLoaded', () => { // ===== DATE RANGE MODAL FUNCTIONALITY ===== const dateRangeReportBtn = document.getElementById('date-range-report'); + const dateRangeDefectsBtn = document.getElementById('date-range-defects-report'); const dateRangeModal = document.getElementById('date-range-modal'); const closeDateRange = document.getElementById('close-date-range'); const cancelDateRange = document.getElementById('cancel-date-range'); + + // Track which date range report type was requested + let currentDateRangeReportType = 'standard'; // 'standard' or 'defects' const confirmDateRange = document.getElementById('confirm-date-range'); const startDateInput = document.getElementById('start-date'); const endDateInput = document.getElementById('end-date'); @@ -755,6 +759,7 @@ document.addEventListener('DOMContentLoaded', () => { // Open date range modal dateRangeReportBtn.addEventListener('click', () => { console.log('DEBUG: Date Range Report button clicked!'); + currentDateRangeReportType = 'standard'; // Set default dates (last 7 days to today) const today = new Date(); @@ -773,6 +778,30 @@ document.addEventListener('DOMContentLoaded', () => { validateDateRange(); // Enable/disable confirm button based on inputs }); + // Add handler for date range defects report + if (dateRangeDefectsBtn) { + dateRangeDefectsBtn.addEventListener('click', () => { + console.log('DEBUG: Date Range Quality Defects Report button clicked!'); + currentDateRangeReportType = 'defects'; + + // Set default dates (last 7 days to today) + const today = new Date(); + const weekAgo = new Date(); + weekAgo.setDate(today.getDate() - 6); // Last 7 days including today + + const todayStr = formatDateForInput(today); + const weekAgoStr = formatDateForInput(weekAgo); + + startDateInput.value = weekAgoStr; + endDateInput.value = todayStr; + + console.log(`DEBUG: Default date range for defects report set to ${weekAgoStr} - ${todayStr}`); + + dateRangeModal.style.display = 'block'; + validateDateRange(); // Enable/disable confirm button based on inputs + }); + } + // Close modal functions function closeDateRangeModal() { dateRangeModal.style.display = 'none'; @@ -822,11 +851,15 @@ document.addEventListener('DOMContentLoaded', () => { const startDate = startDateInput.value; const endDate = endDateInput.value; - console.log(`DEBUG: Generating date range report from ${startDate} to ${endDate}`); + console.log(`DEBUG: Generating ${currentDateRangeReportType} date range report from ${startDate} to ${endDate}`); closeDateRangeModal(); - // Fetch report data for the selected date range - fetchDateRangeReport(startDate, endDate); + // Fetch report data for the selected date range based on report type + if (currentDateRangeReportType === 'defects') { + fetchDateRangeDefectsReport(startDate, endDate); + } else { + fetchDateRangeReport(startDate, endDate); + } }); } @@ -931,4 +964,102 @@ document.addEventListener('DOMContentLoaded', () => { localPopulateTable({ headers: [], rows: [] }); }); } + + // Function to fetch date range quality defects report + function fetchDateRangeDefectsReport(startDate, endDate) { + console.log(`DEBUG: Fetching date range quality defects report from ${startDate} to ${endDate}`); + + // Get elements directly to avoid scope issues + const reportTitleElement = document.getElementById('report-title'); + const reportTableElement = document.getElementById('report-table'); + + if (!reportTitleElement) { + console.error('ERROR: report-title element not found!'); + return; + } + + reportTitleElement.textContent = `Loading quality defects report for ${startDate} to ${endDate}...`; + + // Local function to populate table to avoid scope issues + function localPopulateTable(data) { + const tableHead = reportTableElement.querySelector('thead tr'); + const tableBody = reportTableElement.querySelector('tbody'); + + // Clear existing table content + tableHead.innerHTML = ''; + tableBody.innerHTML = ''; + + if (data.headers && data.rows && data.rows.length > 0) { + // Populate table headers + data.headers.forEach((header) => { + const th = document.createElement('th'); + th.textContent = header; + tableHead.appendChild(th); + }); + + // Populate table rows + data.rows.forEach((row) => { + const tr = document.createElement('tr'); + row.forEach((cell, index) => { + const td = document.createElement('td'); + td.textContent = cell; + tr.appendChild(td); + }); + tableBody.appendChild(tr); + }); + } else { + // Handle no data scenarios + const tr = document.createElement('tr'); + const td = document.createElement('td'); + td.colSpan = 10; // Span all columns + td.textContent = 'No quality defects found for the selected date range.'; + td.style.textAlign = 'center'; + tr.appendChild(td); + tableBody.appendChild(tr); + } + } + + const url = `/generate_report?report=9&start_date=${startDate}&end_date=${endDate}`; + console.log(`DEBUG: Making date range defects request to URL: ${url}`); + + fetch(url) + .then(response => { + console.log(`DEBUG: Response status: ${response.status}`); + return response.json(); + }) + .then(data => { + console.log('DEBUG: Date range defects response data:', data); + + if (data.error) { + reportTitleElement.textContent = `Error: ${data.error}`; + localPopulateTable({ headers: [], rows: [] }); + } else if (data.message) { + reportTitleElement.textContent = data.message; + localPopulateTable({ headers: [], rows: [] }); + } else if (data.rows && data.rows.length === 0) { + reportTitleElement.textContent = `No quality defects found for ${startDate} to ${endDate}`; + localPopulateTable(data); + } else { + const recordCount = data.rows ? data.rows.length : 0; + let titleText = `Quality Defects Report: ${startDate} to ${endDate} (${recordCount} defective items)`; + + // Add defects summary info if available + if (data.defects_summary) { + const summary = data.defects_summary; + titleText += ` | Rejected Qty: ${summary.total_rejected_quantity || 0}, Defect Types: ${summary.unique_defect_types || 0}`; + if (summary.days_with_defects) { + titleText += `, Days: ${summary.days_with_defects}`; + } + } + + reportTitleElement.textContent = titleText; + localPopulateTable(data); + } + }) + .catch(error => { + console.error('Error fetching date range defects report:', error); + reportTitleElement.textContent = 'Error loading date range quality defects report'; + localPopulateTable({ headers: [], rows: [] }); + }); + } }); \ No newline at end of file diff --git a/py_app/app/static/style.css b/py_app/app/static/style.css index c7b71ba..4d8179b 100644 --- a/py_app/app/static/style.css +++ b/py_app/app/static/style.css @@ -693,26 +693,30 @@ body.dark-mode .export-description { } /* Specific styles for Quality Reports Card ONLY */ +.report-form-card { + padding: 15px; /* Reduced padding for more compact card */ +} + .report-form-card .form-centered { display: grid; grid-template-columns: 2fr 1fr; - gap: 15px; + gap: 10px; /* Reduced gap between columns */ align-items: center; - padding: 6px 0; /* Reduced vertical padding */ + padding: 0; /* No vertical padding for maximum compactness */ } .report-form-card .form-centered .report-description { margin: 0; - padding-right: 10px; - font-size: 0.85em; /* Smaller text for quality reports */ - line-height: 1.3; + padding-right: 5px; /* Reduced padding */ + font-size: 0.82em; /* Slightly smaller text */ + line-height: 1.2; /* Tighter line spacing */ } .report-form-card .form-centered .btn { margin: 0; white-space: nowrap; - font-size: 0.8em; /* Smaller button text for quality reports */ - padding: 8px 12px; /* Adjust padding for smaller text */ + font-size: 0.78em; /* Smaller button text */ + padding: 6px 10px; /* Reduced button padding for compactness */ } /* Keep original form-centered styles for other pages */ @@ -764,20 +768,27 @@ body.dark-mode .export-description { /* Responsive design for Quality Reports Card only */ @media (max-width: 768px) { + .report-form-card { + padding: 10px; /* Even more compact on mobile */ + } + .report-form-card .form-centered { grid-template-columns: 1fr; - gap: 10px; + gap: 5px; /* Reduced gap on mobile */ text-align: center; + padding: 0; /* No vertical padding on mobile */ } .report-form-card .form-centered .report-description { padding-right: 0; - margin-bottom: 5px; - font-size: 0.8em; /* Even smaller on mobile */ + margin-bottom: 2px; /* Very tight spacing */ + font-size: 0.78em; /* Smaller text on mobile */ + line-height: 1.1; /* Tighter line spacing on mobile */ } .report-form-card .form-centered .btn { - font-size: 0.75em; /* Smaller buttons on mobile */ + font-size: 0.72em; /* Smaller buttons on mobile */ + padding: 4px 8px; /* Reduced button padding on mobile */ } } diff --git a/py_app/app/templates/quality.html b/py_app/app/templates/quality.html index 426cecd..fd25d82 100644 --- a/py_app/app/templates/quality.html +++ b/py_app/app/templates/quality.html @@ -32,6 +32,10 @@ +
+ + +