# 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* 🚀
