Gas Reporting
Water Usage
Wash Compliance
Manuals & Guides
System documentation for leadership and management. Not visible to technicians.
System Purpose
The Inventory Management System tracks stock levels, deliveries, usage, and reorder workflows for Richter's Lawn Care (RLC) and GreenX (GX). It solves three problems:
- Visibility — managers see real-time stock status (in-stock / low / out) across departments (Lawn, Tree, Pest, Fleet, General)
- Accountability — every movement is logged as a transaction, creating a full audit trail
- Compliance — weekly physical counts are tracked per company, with automated compliance checks and escalation tasks
Design Philosophy: Reference Model
TEOD (Truck End-of-Day) forms log what technicians used in the field, but this data is reference only. It does not change stock levels. The source of truth for inventory quantities is the weekly physical count submitted by managers.
This is intentional. Field usage data is approximate (generic labels like "Lawn Fertilizer (bags)" with no SKU). Actual stock is confirmed by a human walking the warehouse.
Data Flow
TEOD Form Submit
└─→ logInventoryUsage()
└─→ inventory_transactions (type = 'usage_reference', prev/new qty = 0)
└─→ Reference only. Does NOT update current_quantity.
Weekly Physical Count
└─→ POST /api/inventory/count
├─→ inventory_counts (count header record)
├─→ inventory_count_items (per-item counted vs. previous quantity)
├─→ inventory_transactions (type = 'count', records difference)
└─→ UPDATE inventory_items.current_quantity = counted value ← SOURCE OF TRUTH
Vendor Delivery (via PO Receive)
└─→ POST /api/inventory/purchase-orders/:id/receive
├─→ UPDATE purchase_order_items.quantity_received
├─→ UPDATE inventory_items.current_quantity += received
├─→ inventory_transactions (type = 'delivery')
└─→ PO status → 'partial' or 'complete'
Vendor Delivery (direct, no PO)
└─→ POST /api/inventory/deliveries
├─→ inventory_deliveries + inventory_delivery_items
├─→ UPDATE inventory_items.current_quantity += received
├─→ inventory_transactions (type = 'delivery')
└─→ Auto-resolves open low-stock tasks if stock exceeds threshold
Manual Transaction
└─→ POST /api/inventory/transactions
├─→ inventory_transactions (type = 'use', 'receive', 'adjust', or 'return')
└─→ UPDATE inventory_items.current_quantity ← direct update
Key Tables
| Table | Purpose |
|---|---|
inventory_items |
Master item catalog. Fields: id, company, department, sku, name, unit, current_quantity, reorder_threshold, reorder_quantity, cost_per_unit, supplier, vendor_id, storage_location, is_active, requires_count, image_url, last_count_date, last_count_by. Stock status is computed: out_of_stock (qty ≤ 0), low_stock (qty ≤ threshold), ok (above threshold). |
inventory_transactions |
All movements. Fields: id, item_id, transaction_type, quantity, previous_quantity, new_quantity, employee_id, employee_name, notes, source_form, source_submission_id, company, created_at. Types: delivery, usage_reference, count, use, receive, adjust, return. |
inventory_counts |
Physical count header records. Fields: id, company, department, manager_id, manager_name, submission_date, notes, source (local_form or submission_form), created_at. |
inventory_count_items |
Per-item detail for a count. Fields: id, count_id, item_id, previous_quantity, counted_quantity, difference (or system_quantity/variance in detail view). |
purchase_orders |
PO management. Fields: id, po_number (auto: PO-YYYY-NNNN), vendor_id, status, company, expected_date, order_date, received_date, subtotal, tax, shipping, total, notes, created_by, created_by_name. Statuses: draft → submitted → partial → complete (also cancelled). |
purchase_order_items |
PO line items. Fields: id, po_id, item_id, quantity_ordered, quantity_received, unit_cost, line_total, notes. |
reorder_requests |
Restock and new-item requests. Fields: id, request_type (restock or new_item), item_id, item_name, item_description, quantity, urgency (normal/high/critical/low), status (pending/approved/rejected/po_created), company, department, suggested_vendor_id, estimated_cost, reason, notes, requested_by, requested_by_name, approved_by, rejected_by, rejection_reason, po_id. |
vendors |
Vendor directory. Fields: id, name, code, contact_name, email, phone, address, website, payment_terms, notes, categories (JSON array), is_preferred, is_active. |
inventory_alerts |
Low-stock alert configuration per item. Fields: id, item_id, alert_type, threshold, notification_method, cooldown_hours, last_triggered_at, is_active. |
inventory_orders |
Auto-generated reorder records from low-stock detection during counts. Fields: id, item_id, requested_quantity, requested_by, requested_by_name, reason, status, task_id, company. |
inventory_deliveries |
Direct delivery records (non-PO). Fields: id, delivery_date, supplier, invoice_number, po_number, received_by, received_by_name, company, notes, total_items, total_cost. |
inventory_delivery_items |
Line items for direct deliveries. Fields: id, delivery_id, item_id, quantity_received, quantity_ordered, unit_cost, line_total, order_id. |
inventory_categories |
Department-based category taxonomy. Fields: department, name, sort_order, is_active. |
po_number_sequence |
Auto-increment sequence for PO numbering per year. |
Role Permissions Matrix
| Capability | Technician | Lead Tech | Manager | Office | Leadership/Owner |
|---|---|---|---|---|---|
| View inventory items | — | ✓ (own dept + General) | ✓ | ✓ (all) | ✓ (all) |
| View transactions | — | ✓ (own dept) | ✓ | ✓ | ✓ |
| Submit reorder request | — | ✓ | ✓ | ✓ | ✓ |
| Create inventory items | — | — | ✓ | ✓ | ✓ |
| Edit inventory items | — | — | ✓ | ✓ | ✓ |
| Soft-delete items | — | — | — | — | ✓ |
| Submit physical count | — | — | ✓ | — | ✓ |
| Edit count items | — | — | — | — | ✓ |
| Delete counts | — | — | — | — | ✓ |
| Create/submit POs | — | — | ✓ | ✓ | ✓ |
| Receive deliveries | — | — | ✓ | ✓ | ✓ |
| Cancel POs | — | — | ✓ | ✓ | ✓ |
| Delete POs | — | — | — | — | ✓ |
| Approve/reject reorder requests | — | — | — | — | ✓ |
| Manage vendors | — | — | ✓ | ✓ | ✓ |
| Delete vendors | — | — | ✓ | ✓ | ✓ |
| Upload item images (R2) | — | — | ✓ | ✓ | ✓ |
Department Visibility (RBAC)
Non-leadership users see inventory scoped to their department plus General:
- Lawn / Lawn Care → Lawn + General
- Tree / Tree Care → Tree + General
- Pest / Pest Control → Pest + General
- Fleet / Mechanic → Fleet + General
- Office / Admin / Leadership → all departments
Multi-Tenant Scoping
Items have a company field: RLC, GX, or BOTH. Non-leadership users are automatically filtered to their company. Leadership sees everything. The BOTH value means the item is shared across brands (e.g., common supplies).
Automated Behaviors
- Low-stock task creation — when a physical count puts an item at or below its reorder threshold, a task is auto-created and assigned to the company's manager with 48-hour due date
- Low-stock alert cooldown — alerts respect a cooldown period (default 24 hours) to avoid spam
- Compliance task auto-resolve — submitting a count auto-resolves any open
inventory_compliancetask for that company - Delivery auto-resolve — receiving a delivery that pushes stock above the reorder threshold auto-completes open low-stock tasks for that item
- Reorder → PO conversion — approving a restock request with a vendor auto-creates a draft PO with line items