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

398 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
<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:
```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
<!-- 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**
```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
<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**
```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