# ScanLook - Inventory Management System **Barcode-based inventory counting system designed for food production facilities** Replace 5 days of manual year-end physical inventory with a weekend project. Track variances, location errors, phantom lots, and ghost inventory in real-time. --- ## 🚀 Quick Start ### 1. Install Dependencies ```bash pip install flask werkzeug --break-system-packages ``` ### 2. Initialize Database ```bash cd /path/to/scanlook python database/init_db.py ``` This creates the database with default users: - **Owner**: `owner` / `owner123` - **Admin**: `admin` / `admin123` - **Staff**: `staff1` / `staff123` - **Staff**: `staff2` / `staff123` ### 3. Run Application ```bash python app.py ``` Access at: **http://localhost:5000** --- ## 📱 Accessing from Scanner Devices For Zebra MC9300 scanners or tablets on the same network: 1. Find your server's IP address: ```bash hostname -I ``` 2. On scanner device, open browser and navigate to: ``` http://YOUR_SERVER_IP:5000 ``` 3. Scanner trigger acts as Enter key (keyboard wedge mode) --- ## 🏗️ Modular Architecture ScanLook uses a modular system designed to grow into a full WMS. Modules can be enabled/disabled per user. ### Current Modules: - **Counts** - Cycle Counts and Physical Inventory ### Planned Modules: - Shipping - Receiving - Transfers - Production ### Module Access - Admins assign modules to users via User Management - Users only see modules they have access to on the home screen - Route guards prevent URL bypassing --- ## 👥 User Roles ### Owner (Level 1) - Super admin privileges - Manage all users (admins and staff) - Access to all modules - View all sessions across branches ### Admin (Level 2) - Create count sessions - Upload MASTER baseline (morning snapshot) - Upload CURRENT baseline (refresh anytime) - View real-time dashboard - Export variance reports - Manage staff users and module assignments ### Staff/Counter (Level 3) - Access assigned modules only - Select active count session - Scan locations and lots - Enter weights - Edit/delete their own scans - View their progress --- ## 🔄 Core Workflow (Counts Module) ### Phase 1: Session Setup (Admin) 1. **Log in as admin** 2. **Navigate to Admin Console** 3. **Create new count session**: - Session name: "January 17, 2026 - Daily Cycle Count" - Type: Cycle Count OR Full Physical Inventory 4. **Upload MASTER baseline** CSV from NetSuite: - Format: `Item, Description, Lot Number, Location, Bin Number, On Hand` 5. Session status: **Active** 6. Counters can now begin ### Phase 2: Counting (Staff) 1. **Log in as staff** 2. **Select Counts module** from home screen 3. **Select active session** 4. **Start a new bin** - scan or enter bin number 5. **Scan lot barcode** 6. System checks lot against MASTER baseline: - ✅ **MATCH**: Expected here, location correct - ⚠️ **WRONG LOCATION**: Lot exists but system says different location - ❌ **GHOST LOT**: Not in system at all - 🔵 **DUPLICATE**: Lot already scanned (same or different location) 7. **Enter weight** 8. Save → returns to scan input (autofocus) 9. Repeat for all lots in bin 10. Click **"Finish Location"** to finalize ### Phase 3: Admin Monitoring **Real-Time Dashboard Shows:** - Total locations & completion percentage - Active counters with current location - Variance summary (matches, wrong locations, missing, ghost lots) **Optional CURRENT Baseline Refresh:** - Admin uploads new CSV from NetSuite - System recalculates CURRENT status for all scans - Shows what changed in system after count - Proves count was correct, lot moved later --- ## 📊 CSV Import Format **Required columns:** ```csv Item,Description,Lot Number,Location,Bin Number,On Hand 100001,Beef MDM,20260108-132620-PO25146,Wisconsin G & H,R903B,2030 100001,Beef MDM,20260108-132700-PO25146,Wisconsin G & H,R903B,2030 100001,Beef MDM,20260106-150649-PO24949,Wisconsin G & H,R905C,2065 ``` **Column Descriptions:** - **Item**: SKU or item number - **Description**: Product description - **Lot Number**: Unique lot identifier - **Location**: Warehouse location name - **Bin Number**: Specific bin/rack location code - **On Hand**: Current quantity in pounds --- ## 🎯 Key Features ### Dual Baseline System **MASTER Baseline**: - Uploaded once at session start (e.g., 6:00 AM) - Never changes during session - What counters validate against - Represents "what should have been there when we started" **CURRENT Baseline** (Global): - Admin can refresh unlimited times - Shared across all sessions - Only affects admin dashboard/reporting - Counters never see it - Shows "where is it in the system NOW" - Identifies movement after count ### Variance Detection - **Perfect Match**: Right location, weight within tolerance - **Weight Variance**: Right location, weight differs (calculates %) - **Wrong Location**: Lot exists but scanned in different location - **Ghost Lot**: Scanned but not in baseline at all - **Missing/Phantom**: In baseline but not found during count ### Duplicate Detection - **Status 00**: First scan of lot (no duplicate) - **Status 01**: Duplicate in same location by same user - **Status 03**: Found in different location - **Status 04**: Both same location duplicate AND different location ### Count Types **Cycle Count:** - Shows expected lots for the bin - Staff can see what should be there - Good for regular inventory checks **Full Physical Inventory:** - Blind count (no expected list shown) - Staff only sees what they've scanned - Missing lots determined after finalization ### Real-Time Dashboard - Active sessions with progress stats - Location completion tracking - Variance counts updating live - Dual view (MASTER vs CURRENT) after refresh ### Audit Trail - Every scan timestamped with user - Soft deletes tracked - Edits tracked with modified timestamp - Session archival (archived sessions are read-only) --- ## 🗂️ Database Schema ### Core Tables: - **Users**: Authentication and role management - **Modules**: Available system modules - **UserModules**: Per-user module access - **CountSessions**: Count session metadata - **BaselineInventory_Master**: Session-specific baseline (immutable) - **BaselineInventory_Current**: Global refreshable baseline - **LocationCounts**: Bin-by-bin progress tracking - **ScanEntries**: Every lot scan with status tracking - **MissingLots**: Expected lots not found after finalization ### Key Relationships: - Users → UserModules → Modules (many-to-many) - CountSessions → BaselineInventory_Master (one-to-many) - CountSessions → LocationCounts → ScanEntries (hierarchical) --- ## 🔧 Technology Stack - **Backend**: Python 3.13 + Flask - **Database**: SQLite (auto-initializes on first run) - **Frontend**: HTML5 + CSS3 + Vanilla JavaScript - **Templates**: Jinja2 - **Icons**: Font Awesome 6.5 - **Deployment**: Docker (Linux) --- ## 📂 Project Structure ``` scanlook/ ├── app.py # Main Flask application & routes ├── db.py # Database helper functions ├── utils.py # Decorators (login_required, role_required) ├── blueprints/ │ ├── counting.py # Counts module routes │ ├── sessions.py # Session management routes │ ├── users.py # User management routes │ ├── data_imports.py # CSV upload routes │ └── admin_locations.py # Admin location management ├── database/ │ ├── init_db.py # Database initialization & schema │ └── scanlook.db # SQLite database (created at runtime) ├── static/ │ ├── css/ │ │ ├── style.css # Base/desktop styles │ │ ├── mobile.css # Mobile overrides (360-767px) │ │ └── scanner.css # MC9300 scanner overrides (<360px) │ ├── js/ │ │ └── main.js # Client-side JavaScript │ ├── manifest.json # PWA manifest │ └── sw.js # Service worker └── templates/ ├── base.html # Base template with navbar ├── login.html # Login page ├── home.html # Module selection (landing page) ├── admin_dashboard.html ├── staff_dashboard.html ├── manage_users.html ├── create_session.html ├── session_detail.html ├── my_counts.html └── count_location.html ``` --- ## 🎨 Design Philosophy **Desktop-First, Multi-Device Optimized:** - High contrast dark theme for warehouse lighting - Large touch targets (44px minimum) - Autofocus on scan inputs - Scanner trigger = Enter key - Visual feedback with color-coded statuses - Minimal typing required **CSS Architecture:** - `style.css` - Base/desktop styles (768px+) - `mobile.css` - Phone overrides (360-767px) - `scanner.css` - MC9300 scanner overrides (<360px) **Color Coding:** - ✅ Green (`--color-success`): Perfect match - ⚠️ Yellow (`--color-warning`): Wrong location / Expected - ❌ Red (`--color-danger`): Missing or ghost lot - 🔵 Blue (`--color-duplicate`): Duplicate scan - 🟠 Orange (`--color-orange`): Weight variance --- ## 🐳 Docker Deployment ```bash # Build docker build -t scanlook . # Run (preserves database between updates) docker run -d \ -p 5000:5000 \ -v /path/to/data:/app/database \ -e SCANLOOK_SECRET_KEY=your-secret-key \ scanlook ``` **Important:** Only `/app/database` is volume-mounted to preserve data between container updates. --- ## 🔐 Security Considerations - Passwords hashed with Werkzeug - Session management via Flask sessions - SQL injection prevention (parameterized queries) - Role-based access control - Module-based access control with route guards - Soft deletes preserve audit trail --- ## 🎯 Success Metrics **Current State (Year-End Physical):** - Duration: 5 days - Data entry: Manual, error-prone - Variance resolution: Weeks later **Target State (with ScanLook):** - Duration: 1 weekend (2 days max) - Data entry: Zero (all scanned) - Variance resolution: Real-time flagging - Accuracy: 99%+ (no handwriting errors) - Time savings: 60%+ --- ## 💡 Future Enhancements - Additional WMS modules (Shipping, Receiving, Transfers, Production) - Multi-branch support - Direct NetSuite API integration - Photo capture for variance proof - Barcode generation for location labels - Native mobile apps - Offline mode with sync --- ## 📝 Version History - **v0.12.0** - Modular architecture with user-based module access - **v0.11.x** - CSS refactoring, multi-device support, duplicate detection - **v0.10.x** - Global CURRENT baseline, session archival - **v0.9.x** - Core counting workflow, dual baseline system --- ## 🔧 Support This is a custom internal tool. Contact your system administrator for support. **Built with ❤️ for efficient inventory management** *Inspired by BomLook from the FoxPro days* 🚀