Files
quality_app-v2/documentation/OLD_APP_BOX_WORKFLOW_REFERENCE.md
Quality App Developer b15cc93b9d FG Scan form validation improvements with warehouse module updates
- Fixed 3 JavaScript syntax errors in fg_scan.html (lines 951, 840-950, 1175-1215)
- Restored form field validation with proper null safety checks
- Re-enabled auto-advance between form fields
- Re-enabled CP code auto-complete with hyphen detection
- Updated validation error messages with clear format specifications and examples
- Added autocomplete='off' to all input fields
- Removed auto-prefix correction feature
- Updated warehouse routes and modules for box assignment workflow
- Added/improved database initialization scripts
- Updated requirements.txt dependencies

Format specifications implemented:
- Operator Code: OP + 2 digits (example: OP01, OP99)
- CP Code: CP + 8 digits + hyphen + 4 digits (example: CP00000000-0001)
- OC1/OC2 Codes: OC + 2 digits (example: OC01, OC99)
- Defect Code: 3 digits only
2026-01-30 10:50:06 +02:00

14 KiB
Raw Blame History

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):

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:

<label for="operator_code">Quality Operator Code:</label>
<label for="cp_code">CP Code:</label>
<label for="oc1_code">OC1 Code:</label>
<label for="oc2_code">OC2 Code:</label>
<label for="defect_code">Defect Code:</label>

<div style="margin-top: 20px; padding-top: 15px; border-top: 1px solid #ddd;">
    <label style="display: flex; align-items: center; justify-content: center; gap: 10px; cursor: pointer;">
        <span style="font-weight: bold;">Enable Scan to Boxes:</span>
        <input type="checkbox" id="scan-to-boxes-toggle" style="width: 20px; height: 20px; cursor: pointer;">
    </label>
</div>

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:

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:

<!-- Box Assignment Popup Modal -->
<div id="box-assignment-modal" class="box-modal" style="display: none;">
    <div class="box-modal-content">
        <div class="box-modal-header">
            <h3>Assign to Box</h3>
            <span class="box-modal-close" onclick="closeBoxModal()">&times;</span>
        </div>
        <div class="box-modal-body">
            <p>CP Code: <strong id="modal-cp-code"></strong></p>
            
            <!-- Option 1: Quick Box Creation -->
            <div style="margin: 20px 0; padding: 15px; background: #f0f8ff; border-radius: 5px;">
                <button type="button" id="quick-box-create-btn" class="btn" style="width: 100%; background: #28a745; color: white;">
                    📦 Quick Box Label Creation
                </button>
                <p style="font-size: 0.85em; color: #666; margin-top: 8px; text-align: center;">
                    Creates new box and prints label immediately
                </p>
            </div>
            
            <div style="text-align: center; margin: 15px 0; color: #999;">— OR —</div>
            
            <!-- Option 2: Scan Existing Box -->
            <div style="margin: 20px 0;">
                <label style="font-weight: bold;">Scan Box Number:</label>
                <input type="text" id="scan-box-input" placeholder="Scan or enter box number" 
                       style="width: 100%; padding: 8px; font-size: 1em; margin-top: 5px;">
                <p style="font-size: 0.85em; color: #666; margin-top: 5px;">
                    Scan an existing box label to assign this CP code to that box
                </p>
            </div>
            
            <div class="box-modal-buttons" style="margin-top: 20px;">
                <button type="button" class="btn" onclick="closeBoxModal()" style="background: #6c757d;">Skip</button>
                <button type="button" id="assign-to-box-btn" class="btn" style="background: #007bff;">Assign to Box</button>
            </div>
        </div>
    </div>
</div>

Three User Choices in Modal

Choice 1: Create New Box (Green Button)

Code: Lines 1005-1095

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

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

<button type="button" class="btn" onclick="closeBoxModal()" style="background: #6c757d;">Skip</button>

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

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