diff --git a/py_app/app/__pycache__/routes.cpython-312.pyc b/py_app/app/__pycache__/routes.cpython-312.pyc index fea81f1..31ec46b 100644 Binary files a/py_app/app/__pycache__/routes.cpython-312.pyc and b/py_app/app/__pycache__/routes.cpython-312.pyc differ 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 @@ +
+ + +