Files
quality_app-v2/documentation/SCANFG_ORDERS_BOX_TRACKING.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

10 KiB

scanfg_orders Table - Box Tracking Implementation

Last Updated: January 28, 2026
Status: Active and Deployed


📋 Table Overview

The scanfg_orders table has been enhanced to support scanned goods box tracking functionality. It records all finished goods (FG) quality scans with integration to the box/location warehouse system.

Current Status

  • Total Records: 0
  • Table Size: Configured and ready
  • New Box Tracking Columns: Added and functional

📊 Complete Column Structure

# Column Name Data Type Null Key Default Purpose
1 Id INT(11) NO PRI auto_increment Primary key - unique scan record ID
2 operator_code VARCHAR(50) YES MUL NULL Quality operator ID/code
3 CP_full_code VARCHAR(50) YES MUL NULL Complete CP (production order) code
4 OC1_code VARCHAR(50) YES - NULL Order code 1 (optional component)
5 OC2_code VARCHAR(50) YES - NULL Order code 2 (optional component)
6 quality_code VARCHAR(10) YES - NULL Defect/Quality classification code
7 date DATE YES MUL NULL Scan date
8 time TIME YES - NULL Scan time
9 approved_quantity INT(11) YES - 0 Count of approved units
10 rejected_quantity INT(11) YES - 0 Count of rejected units
11 box_id BIGINT(20) YES MUL NULL 🆕 FK to boxes_crates table
12 location_id BIGINT(20) YES MUL NULL 🆕 FK to warehouse_locations table
13 created_at TIMESTAMP YES - CURRENT_TIMESTAMP Record creation timestamp

🆕 NEW BOX TRACKING COLUMNS

Column 1: box_id

box_id BIGINT(20) NULL, 
FOREIGN KEY (box_id) REFERENCES boxes_crates(id) ON DELETE SET NULL,
INDEX idx_box_id (box_id)

Purpose: Links each scanned order to a specific box in the warehouse system

Relationship:

  • Many scanfg_orders → One boxes_crates record
  • Enables tracking which box contains which CP codes
  • Allows retrieval of all scans for a specific box

Usage Example:

-- Find all scans in a specific box
SELECT * FROM scanfg_orders 
WHERE box_id = 5 
ORDER BY created_at DESC;

-- Join with box details
SELECT s.*, b.box_number, b.status 
FROM scanfg_orders s
JOIN boxes_crates b ON s.box_id = b.id
WHERE b.box_number = '00000001';

Column 2: location_id

location_id BIGINT(20) NULL,
FOREIGN KEY (location_id) REFERENCES warehouse_locations(id) ON DELETE SET NULL,
INDEX idx_location_id (location_id)

Purpose: Tracks the warehouse location where the scanned goods are stored

Relationship:

  • Many scanfg_orders → One warehouse_locations record
  • Enables location-based inventory queries
  • Supports warehouse zone tracking (FG_INCOMING, TRUCK_LOADING, etc.)

Usage Example:

-- Find all scans in FG_INCOMING location
SELECT s.*, l.location_code 
FROM scanfg_orders s
JOIN warehouse_locations l ON s.location_id = l.id
WHERE l.location_code = 'FG_INCOMING';

-- Count approvals by location
SELECT l.location_code, COUNT(*) as total_scans
FROM scanfg_orders s
JOIN warehouse_locations l ON s.location_id = l.id
GROUP BY l.location_code;

🔗 Foreign Key Relationships

scanfg_orders → boxes_crates

scanfg_orders.box_id → boxes_crates.id
  • Cardinality: Many-to-One
  • Delete Action: SET NULL (orphaned scans remain)
  • Purpose: Track which box contains the scanned CP codes

scanfg_orders → warehouse_locations

scanfg_orders.location_id → warehouse_locations.id
  • Cardinality: Many-to-One
  • Delete Action: SET NULL (location deleted, scans preserved)
  • Purpose: Track warehouse location of the scanned goods

boxes_crates (Contains CP codes)

CREATE TABLE boxes_crates (
  id BIGINT PK,
  box_number VARCHAR(20) UNIQUE,
  status ENUM('open','closed'),
  location_id BIGINT FK,
  created_at TIMESTAMP,
  created_by INT FK
)

box_contents (Maps CP codes to boxes)

CREATE TABLE box_contents (
  id BIGINT PK,
  box_id BIGINT FK  boxes_crates.id,
  cp_code VARCHAR(50),
  quantity INT,
  added_at TIMESTAMP
)

warehouse_locations (Storage zones)

CREATE TABLE warehouse_locations (
  id BIGINT PK,
  location_code VARCHAR(12) UNIQUE,
  size INT,
  description VARCHAR(250),
  created_at TIMESTAMP
)

cp_location_history (Audit trail)

CREATE TABLE cp_location_history (
  id BIGINT PK,
  cp_code VARCHAR(50),
  box_id BIGINT FK,
  from_location_id BIGINT FK,
  to_location_id BIGINT FK,
  moved_by INT FK,
  moved_at TIMESTAMP
)

🔍 Sample Query Patterns

Get All Scans with Box and Location Info

SELECT 
  s.Id as scan_id,
  s.operator_code,
  s.CP_full_code,
  b.box_number,
  b.status,
  l.location_code,
  s.quality_code,
  s.approved_quantity,
  s.rejected_quantity,
  s.date,
  s.time
FROM scanfg_orders s
LEFT JOIN boxes_crates b ON s.box_id = b.id
LEFT JOIN warehouse_locations l ON s.location_id = l.id
ORDER BY s.created_at DESC;

Track Box Contents via Scans

SELECT 
  b.box_number,
  COUNT(DISTINCT s.CP_full_code) as unique_cp_codes,
  SUM(s.approved_quantity) as total_approved,
  SUM(s.rejected_quantity) as total_rejected,
  l.location_code
FROM scanfg_orders s
JOIN boxes_crates b ON s.box_id = b.id
JOIN warehouse_locations l ON s.location_id = l.id
GROUP BY b.id, l.location_code
ORDER BY b.box_number;

Find Scans Without Box Assignment

SELECT *
FROM scanfg_orders
WHERE box_id IS NULL
ORDER BY created_at DESC
LIMIT 10;

Historical Location Tracking for a Scan

SELECT 
  s.*,
  h.from_location_id,
  h.to_location_id,
  lf.location_code as from_location,
  lt.location_code as to_location,
  h.moved_at
FROM scanfg_orders s
LEFT JOIN cp_location_history h ON s.CP_full_code = h.cp_code
LEFT JOIN warehouse_locations lf ON h.from_location_id = lf.id
LEFT JOIN warehouse_locations lt ON h.to_location_id = lt.id
WHERE s.Id = ?
ORDER BY h.moved_at DESC;

💾 Data Statistics

Metric Value
Total Records 0
Records with box_id 0
Records with location_id 0
Indexed Columns Id, operator_code, CP_full_code, date, box_id, location_id
Storage Engine InnoDB
Charset utf8mb4

🔐 Indexes

Index Name Columns Type Purpose
PRIMARY Id Unique Record identification
idx_operator operator_code Regular Find scans by operator
idx_cp_code CP_full_code Regular Find scans by CP code
idx_date date Regular Find scans by date range
idx_box_id box_id Regular Find scans in specific box
idx_location_id location_id Regular Find scans by location

📝 Table Creation SQL

CREATE TABLE IF NOT EXISTS scanfg_orders (
    id INT AUTO_INCREMENT PRIMARY KEY,
    operator_code VARCHAR(50),
    CP_full_code VARCHAR(50),
    OC1_code VARCHAR(50),
    OC2_code VARCHAR(50),
    quality_code VARCHAR(10),
    date DATE,
    time TIME,
    approved_quantity INT DEFAULT 0,
    rejected_quantity INT DEFAULT 0,
    box_id BIGINT,                          -- NEW: Links to boxes_crates
    location_id BIGINT,                     -- NEW: Links to warehouse_locations
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    -- Foreign Keys
    FOREIGN KEY (box_id) REFERENCES boxes_crates(id) ON DELETE SET NULL,
    FOREIGN KEY (location_id) REFERENCES warehouse_locations(id) ON DELETE SET NULL,
    
    -- Indexes
    INDEX idx_operator (operator_code),
    INDEX idx_cp_code (CP_full_code),
    INDEX idx_date (date),
    INDEX idx_box_id (box_id),
    INDEX idx_location_id (location_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

🎯 Features Enabled by Box Tracking Columns

1. Box-Based Inventory Tracking

  • Know exactly which scanned CP codes are in which box
  • Track box status (open/closed) with scan completion
  • Generate box contents reports

2. Location-Based Inventory

  • Locate all scans in a specific warehouse zone
  • Generate location usage reports
  • Track goods movement through warehouse

3. Scan-to-Box Assignment

  • Operator can assign scan to a box during FG scan entry
  • Supports quick box label printing workflow
  • Enables just-in-time box creation

4. Quality Report by Location

  • Analyze approval/rejection rates by warehouse location
  • Generate performance metrics by zone
  • Identify quality patterns by location

5. Audit Trail Integration

  • cp_location_history tracks box movements
  • Combined with scanfg_orders, full traceability available
  • Supports root cause analysis for quality issues

Implementation Checklist

  • box_id column added to scanfg_orders
  • location_id column added to scanfg_orders
  • Foreign key constraints established
  • Indexes created for query performance
  • Table structure verified in database
  • Documentation created
  • Backend routes updated to populate box_id on scan
  • Backend routes updated to populate location_id on scan
  • Frontend form updated to select box during scan entry
  • Test scans with box assignment
  • Verify box_contents table reflects scanned items

🚀 Next Steps

  1. Update FG Scan Route - Modify /fg_scan route to capture and store box_id
  2. Update Frontend Form - Add box selection dropdown to scan entry form
  3. Create Box Assignment Logic - Auto-link scans to selected box
  4. Test Box Tracking - Verify data flow end-to-end
  5. Create Reports - Build box inventory and location reports


🔧 Maintenance Notes

Backup Considerations

  • Include scanfg_orders in daily backups
  • Maintain referential integrity with boxes_crates
  • Archive old scans periodically

Performance Tuning

  • For 100,000+ records, consider partitioning by date
  • Monitor index usage on date, box_id, location_id
  • Vacuum/optimize table after large delete operations

Data Consistency

  • Ensure box_id is valid before insert (FK constraint enforces this)
  • Handle orphaned scans gracefully (FK SET NULL allows this)
  • Regular integrity checks: CHECK TABLE scanfg_orders;