# Old App FG Scan Box Assignment Workflow Reference ## Overview The old app (`/srv/quality_app/py_app/app/templates/fg_scan.html`) implements a sophisticated **two-stage scanning and box assignment workflow** that provides users with options to either create new boxes or assign scans to existing boxes. ## Workflow Trigger **When does the modal appear?** - User fills in all scan fields (Operator Code, CP Code, OC1, OC2, Defect Code) - User scans defect code (3 digits) - The checkbox **"Enable Scan to Boxes"** must be ENABLED - Defect code must be **'000'** (good quality only) **Code Reference (Lines 730-750):** ```javascript if (scanToBoxesEnabled && this.value === '000') { console.log('Auto-submit: Scan-to-boxes enabled, calling submitScanWithBoxAssignment'); submitScanWithBoxAssignment(); // <-- Triggers modal instead of normal form submit } else { console.log('Auto-submit: Normal form submission'); form.submit(); // <-- Normal database insert, page reloads } ``` ## Step-by-Step Workflow ### Step 1: Scan Entry & Validation **File: fg_scan.html, Lines 1-400** User interface with scan input form: ```html
``` **Key validation rules:** - Operator code: Must start with `OP` - CP code: Must start with `CP` - OC1 code: Must start with `OC` - OC2 code: Must start with `OC` - Defect code: Must be 3 digits (000-999) ### Step 2: Form Submission - POST to Database **File: fg_scan.html, Lines 25-65** Before showing modal, the scan is saved to database: ```javascript async function submitScanWithBoxAssignment() { const form = document.getElementById('fg-scan-form'); const formData = new FormData(form); try { const response = await fetch(window.location.href, { method: 'POST', headers: { 'X-Requested-With': 'XMLHttpRequest' }, body: formData // <-- Posts all scan data to database }); if (response.ok) { currentCpCode = formData.get('cp_code'); const defectCode = formData.get('defect_code') || '000'; // ✅ Scan saved to database showNotification('✅ Scan recorded successfully!', 'success'); // Only show modal if quality code is 000 if (defectCode === '000' || defectCode === '0') { console.log('Should show box modal'); showBoxModal(currentCpCode); // <-- MODAL APPEARS HERE } } } catch (error) { console.error('Error:', error); } } ``` ### Step 3: Modal Presentation **File: fg_scan.html, Lines 1150-1250** Modal HTML structure: ```html ``` ## Three User Choices in Modal ### Choice 1: Create New Box (Green Button) **Code: Lines 1005-1095** ```javascript document.getElementById('quick-box-create-btn').addEventListener('click', async function() { this.disabled = true; this.textContent = 'Creating box...'; try { // Step 1: Create box in database const createResponse = await fetch('/warehouse/create_box', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({}) }); const result = await createResponse.json(); if (result.success && result.box_number) { const boxNumber = result.box_number; // Step 2: Generate PDF label const formData = new FormData(); formData.append('box_number', boxNumber); const pdfResponse = await fetch('/generate_box_label_pdf', { method: 'POST', body: formData }); // Step 3: Print label using QZ Tray const config = window.qz.configs.create(printer, { scaleContent: false, rasterize: false, size: { width: 80, height: 50 }, units: 'mm', margins: { top: 0, right: 0, bottom: 0, left: 0 } }); const printData = [{ type: 'pdf', format: 'base64', data: pdfBase64 }]; await window.qz.print(config, printData); showNotification(`✅ Box ${boxNumber} created and label printed!`, 'success'); // Step 4: Focus input to scan the newly created box document.getElementById('scan-box-input').value = ''; document.getElementById('scan-box-input').focus(); document.getElementById('scan-box-input').placeholder = 'Scan the printed label now...'; } } catch (error) { console.error('Error creating box:', error); showNotification('❌ Error creating box: ' + error.message, 'error'); } }); ``` **Process:** 1. ✅ Create empty box in database via `/warehouse/create_box` endpoint 2. ✅ Generate PDF label via `/generate_box_label_pdf` endpoint 3. ✅ Print label immediately using QZ Tray (thermal printer) 4. ✅ Focus input field to scan the newly printed label 5. ✅ Modal stays open for box assignment ### Choice 2: Scan Existing Box (Assign Button - Blue) **Code: Lines 1100-1120** ```javascript document.getElementById('assign-to-box-btn').addEventListener('click', async function() { const boxNumber = document.getElementById('scan-box-input').value.trim(); if (!boxNumber) { showNotification('âš ī¸ Please scan or enter a box number', 'warning'); return; } try { await assignCpToBox(boxNumber); // POST to /warehouse/assign_cp_to_box showNotification(`✅ CP ${currentCpCode} assigned to box ${boxNumber}`, 'success'); setTimeout(() => closeBoxModal(), 1000); } catch (error) { showNotification('❌ Error: ' + error.message, 'error'); } }); async function assignCpToBox(boxNumber) { const response = await fetch('/warehouse/assign_cp_to_box', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ box_number: boxNumber, cp_code: currentCpCode }) }); if (!response.ok) { const error = await response.json(); throw new Error(error.error || 'Failed to assign CP to box'); } return await response.json(); } ``` **Process:** 1. User scans existing box number (or enters manually) 2. Click "Assign to Box" button 3. POST to `/warehouse/assign_cp_to_box` with: - `box_number`: The scanned/entered box ID - `cp_code`: The current CP code from the scan 4. ✅ CP assigned to box in database 5. Modal closes and page reloads 6. Ready for next scan ### Choice 3: Skip (Gray Button) **Code: Lines 1110-1115** ```javascript ``` **Process:** 1. User clicks "Skip" 2. Modal closes via `closeBoxModal()` 3. Page reloads 4. Scan is already in database (saved in Step 2) 5. No box assignment for this scan 6. Ready for next scan ## Toggle Checkbox - Enable/Disable Feature **Code: Lines 310-360** ```javascript const toggleElement = document.getElementById('scan-to-boxes-toggle'); if (toggleElement) { toggleElement.checked = scanToBoxesEnabled; toggleElement.addEventListener('change', function() { scanToBoxesEnabled = this.checked; localStorage.setItem('scan_to_boxes_enabled', this.checked); // Connect or disconnect QZ Tray based on toggle state if (scanToBoxesEnabled) { // Connect to printer for label printing window.qz.websocket.connect().then(() => { showNotification('✅ QZ Tray connected for box label printing', 'success'); }); } else { // Disconnect printer connection window.qz.websocket.disconnect().then(() => { showNotification('â„šī¸ QZ Tray disconnected', 'info'); }); } }); } ``` **Behavior:** - When **CHECKED**: Modal appears after good quality scans (defect code 000) - When **UNCHECKED**: Normal database insert, no modal, page auto-reloads - Preference saved to browser localStorage for persistence ## Database Endpoints Required For this workflow to function, the backend must have these endpoints: 1. **POST `/warehouse/create_box`** - Creates empty box in `boxes_crates` table - Returns: `{ success: true, box_number: "BOX-12345" }` 2. **POST `/warehouse/assign_cp_to_box`** - Creates record linking CP to box (likely in `box_contents` table) - Accepts: `{ box_number: "BOX-12345", cp_code: "CP-123456" }` - Returns: `{ success: true, message: "..." }` 3. **POST `/generate_box_label_pdf`** - Generates PDF label for box number - Accepts: `FormData` with `box_number` - Returns: PDF blob 4. **POST `/fg_scan` (or current page)** - Original form POST - Inserts scan record with all fields - Returns: JSON response for AJAX handling ## Key Features to Implement in Quality App V2 ### 1. Toggle Checkbox (Already Have) ✅ Present in quality_app-v2 fg_scan.html ### 2. Modal Structure (Need to Review/Update) The modal should include: - Current CP code display - Option 1: Create box + print label - Option 2: Scan/enter existing box - Option 3: Skip assignment - Close button ### 3. QZ Tray Integration (Already Have) ✅ PDF printing capability already implemented ### 4. Database Endpoints (CRITICAL) Need to verify these exist in quality_app-v2: - [ ] `/warehouse/create_box` - Create empty box - [ ] `/warehouse/assign_cp_to_box` - Link CP to box - [ ] `/generate_box_label_pdf` - PDF label generation ### 5. Database Tables (VERIFIED ✅) All required tables now in init_db.py: - ✅ `boxes_crates` - Box master records - ✅ `box_contents` - CP to box assignments - ✅ `scanfg_orders` - Scan records (with location_id, box_id columns) ## HTML Form Flow Comparison ### Old App (`/srv/quality_app`) 1. Checkbox enabled → Defect code 000 → Modal appears 2. User has 3 choices (Create/Scan/Skip) 3. Create box → Print label → Scan it → Assign 4. OR Scan existing box → Assign 5. OR Skip ### New App (`/srv/quality_app-v2`) **CURRENT STATE:** Likely same structure, needs verification - [ ] Check if modal exists in current templates - [ ] Verify all three choice buttons present - [ ] Verify QZ Tray integration working - [ ] Verify backend endpoints exist ## Testing Checklist - [ ] Checkbox toggles feature on/off - [ ] Checkbox persists in localStorage - [ ] QZ Tray connects when checkbox enabled - [ ] Defect code 000 triggers modal - [ ] Other defect codes skip modal - [ ] "Create Box" button creates box + prints label - [ ] "Assign to Box" button assigns CP to existing box - [ ] "Skip" button closes modal, reload page - [ ] Modal has CP code displayed - [ ] Modal can be closed by X button - [ ] Modal can be closed by clicking outside ## File Reference - **Old App HTML:** `/srv/quality_app/py_app/app/templates/fg_scan.html` (1242 lines) - **Key JS Functions:** Lines 15-120 (submitScanWithBoxAssignment, showBoxModal, assignCpToBox) - **Modal HTML:** Lines 1150-1250 - **Toggle Code:** Lines 310-360 ## Next Steps 1. Review new app's fg_scan.html for same structure 2. Verify backend endpoints exist for box operations 3. Test the entire workflow (especially QZ Tray printing) 4. Update if needed to match old app's three-choice model