# 02 — Existing Module Status

**Status legend**

- **Working**: code, API, UI and tests exist.
- **Partial**: some parts exist.
- **Missing**: nothing exists, or only a permission key.
- **Broken**: a defect was confirmed.
- **Not Verified**: present but could not be exercised in this audit.

> **About "tested".** Backend feature tests exist for every Working module, but they were **not executed** in this copy (see `01` §5). "Working" means the code, routes and UI are complete and covered by tests in the NH history. All backend modules are therefore *Not Verified at runtime* until the suite runs against `techpos_test`. Frontend unit tests **were** run: 1,685/1,687 passed, and the 2 failures were load timeouts.

Paths are relative to `backend/` (BE) or `frontend/` (FE).

---

## Summary table

| # | Module | Status | Key code | Tests (files) |
|---|---|---|---|---|
| 1 | POS sales / order entry | **Working** (restaurant-flavoured) | BE `app/Orders/*`, `Http/Controllers/Api/V1/Orders/*`; FE `src/pages/orders/CreateOrderPage.tsx` (`/pos`) | `tests/Feature/Orders` (23) |
| 2 | Orders list / detail / workflow | **Working** | BE `app/Orders/OrderWorkflow.php`, `OrderStatusTransitionGuard.php`; FE `OrdersListPage`, `OrderDetailPage` | Orders (23) |
| 3 | Discounts / price override | **Partial** | Service methods only (`OrderService::applyDiscount`, `overrideLinePrice`); **no route** | — |
| 4 | Refunds / returns | **Missing** | Permission `refunds.process` unused; only an automatic compensation refund in `app/Payments/OrderFinalizationCoordinator.php` | — |
| 5 | Void item / reopen | **Missing / Partial** | `orders.void_item` unused; `removeLine` pre-commit only; COMPLETED→CONFIRMED reopen exists | — |
| 6 | Cash drawer / register shift / Z-report | **Missing** | Permissions `cash_drawer.open`, `shifts.close` unused | — |
| 7 | Receipt printing | **Missing** | Printers are configuration only (`app/Printers`) | Printers (7) |
| 8 | Invoices (PDF) | **Working** | `app/Invoices/*`, `resources/views/invoices/pdf.blade.php`; tables `invoices`, `invoice_number_sequences` | (in Orders/Payments) |
| 9 | Payments: architecture, ledger, offline, payment links | **Working** | `app/Payments/*`; tables `payments`, `payment_events`, `payment_gateway_configs`, `order_payment_links` | Payments (6), Storefront payment (several) |
| 10 | Payment gateways: Bambora (Shift4), Moneris | **Partial / Not Verified** | `app/Payments/Providers/BamboraPaymentProvider.php`, `MonerisPaymentProvider.php`. Real HTTP code, labelled "SANDBOX ONLY in this phase". No webhooks, no card-present terminals | — |
| 11 | Payment reconciliation | **Partial** | `app/Console/Commands/ReconcilePaymentsCommand.php` exists but is **not scheduled** | — |
| 12 | Checkout quote / shipping zones | **Working** | `app/Checkout/CheckoutQuoteService.php`, `app/Shipping/*`; tables `checkout_quotes`, `shipping_zones`, `shipping_zone_cities`; FE `/settings/delivery` | Checkout (1), Shipping (1) |
| 13 | Tax classes | **Working** | `app/Menu/TaxClassService.php`, `ProductTaxResolver.php`; tables `tax_classes`, `tax_class_location_rates`; FE `/settings/tax` | Tax (1) |
| 14 | Products, categories, variants, SKU, pricing, media | **Working** | `app/Menu/*`; FE `src/pages/menu/*` | Menu (84 files, ~830 tests), Unit/Menu (3) |
| 15 | Catalogues (menus) | **Working** | `app/Menu/Catalogues/*`; FE `/menu/catalogues` | Menu |
| 16 | Menu CSV import | **Working** (CSV only; no SKU/barcode/stock columns) | `app/Menu/Import/*` | Menu (10 import files) |
| 17 | Combos / modifiers / kitchen routing | **Working**, restaurant-specific | `ComboService`, `ModifierService`, `*StationRoute*` | Menu |
| 18 | Inventory (quantity ledger) | **Working**, with 2 confirmed defects (see `03`) | `app/Inventory/*`; FE `src/pages/menu/Inventory*` | Inventory (17 files, ~185 tests) |
| 19 | Purchasing / suppliers / goods receiving | **Missing** | "Receiving" is only a `+qty` movement | — |
| 20 | Stock transfers | **Missing** | `transfer_in`/`transfer_out` exist only in the movement-type vocabulary | — |
| 21 | Stock reservations | **Missing** | No reserved quantity | — |
| 22 | Low / out-of-stock alerts | **Working** (reconcile sweep not scheduled by design) | `app/Inventory/Alerts/*`, `app/Jobs/DeliverInventoryStockAlert.php` | Inventory |
| 23 | Customer CRM | **Working** | `app/Customers/*` (13 tables); FE `src/pages/customers/*`, `/settings/customer-crm` | Customers (8) + e2e (3 specs) |
| 24 | Customer financial history | **Working** | `app/Customers/CustomerFinancialService.php` | Customers |
| 25 | Store credit / balances / loyalty | **Missing** | — | — |
| 26 | Users, roles, permissions, overrides | **Working** | `app/Authorization/*` (`PermissionCatalog.php`: 75 keys; `RoleTemplates.php`: 10 restaurant roles); FE `/management/roles` | Authorization (18), Roles (1) |
| 27 | Auth (login, PIN, activation, reset, manager approval) | **Working** (manager approval: issued but never consumed) | `app/Auth/*` | Auth (9), Pin (5) |
| 28 | Tenancy / multi-location | **Working** | `app/Tenancy/*`, `app/Access/*`, `app/Locations/*` | Tenancy (5), Locations (8) |
| 29 | Audit log (write) | **Working** | `app/Audit/*`, `audit_logs` (append-only trigger) | Audit (4) |
| 30 | Audit log viewer | **Missing** | `audit_logs.view` unused | — |
| 31 | Platform admin (super-admin / support sessions) | **Partial** | `app/Platform/*`; no tenant-admin console routes; tenants provisioned via `cacart:provision-tenant` | Platform (7) |
| 32 | Reports: sales / tax / payments / EOD | **Missing** | Only attendance reports (8 endpoints) and order fulfillment metrics | — |
| 33 | Dashboard | **Partial** | `api/v1/dashboard/*` (attendance summary, inventory alerts); FE `DashboardPage.tsx` partly "Coming soon" | — |
| 34 | Workforce (employees, schedules, time clock, kiosk, attendance intelligence) | **Working** | `app/Workforce/*` (121 files) | ~170 test files across Workforce/Attendance*/TimeClock/Scheduling |
| 35 | Timesheet approval / export | **Missing** | Permissions only | — |
| 36 | AI assistant | **Partial** | `app/AI/*`; only `FakeAiProvider` | AI (29) |
| 37 | KDS / printers / stations / channels | **Partial** (configuration only) | `app/Kds`, `app/Printers`, `app/Stations`, `app/Channels` | Kds (5), Printers (7), Stations (6), Channels (7) |
| 38 | Storefront API for WordPress | **Working** (backend side) | `app/Storefront/*`; 26 routes `api/v1/storefront/*` | Storefront (7 files, ~75 tests), Checkout (1) |
| 39 | WordPress connector plugin | **Missing locally / Not Verified** | See `04` | — |
| 40 | Background jobs, mail, scheduler | **Working** | `app/Jobs/*` (3 jobs), `app/Mail/*` (8 mailables), `routes/console.php` (1 schedule) | Mail (1) |
| 41 | Webhooks | **Partial** | Inbound: only the storefront payment-webhook relay. Outbound: **none** | Storefront |
| 42 | Realtime (Reverb / Echo) | **Missing** (installed, not wired) | No `ShouldBroadcast` events; FE `laravel-echo` unused | — |
| 43 | Offline POS (Dexie) | **Missing** (dependency only) | FE `dexie` unused | — |
| 44 | Repairs, devices, IPTV, phone plans | **Missing** | — | — |

## Confirmed defects (Broken)

These were verified by reading the code. No fix was applied.

1. **`not_configured` stock is blocked on reads but not at commit.**
   - `app/Inventory/InventoryAvailabilityResolver.php` blocks a variant that is mapped but has no stock row at the location.
   - But `app/Inventory/InventoryMovementService.php::lockStock()` (l.425–445) silently inserts a row with `on_hand=0` and `prevent_sale=false`, then deducts.
   - Result: a POS sale succeeds and drives stock negative, while the storefront and quote say "blocked".
2. **Archived inventory items still accept movements and consumption.** Item status is never checked in `applyManual`, `applyCount` or consumption, and `InventoryItemService::archive` does not revoke mappings.
3. **Online pre-capture stock check is a stub.** `app/Payments/OrderFinalizationCoordinator.php::stockAvailable()` always returns `true` (l.177–182). An out-of-stock online order is captured and then refunded by compensation, never declined.
4. **Variant SKU generation is not location-unique.** `app/Menu/Variants/VariantSkuGenerator.php` assumes no DB uniqueness, but unique indexes exist (`2026_10_25_100000`). A clash with another product's variant SKU fails the whole bulk operation with a 422.

## Stale documentation in code

Some docblocks still say code is "not wired to any live POS path", but it is wired:

- `InventoryMovementService.php:143`
- `InventoryDeductionService.php:18`
- `InventoryConsumptionResolver.php:10`
- `StorefrontCheckoutController.php:22,135` ("payment is a later phase")
- `routes/api.php:623` ("NO write routes exist yet")

Low risk, but misleading.

## Restaurant-specific concepts to retire or hide for TechTitans

- **Order types and kitchen workflow:**
  - `DINE_IN`/`TAKEOUT` order types;
  - `kitchen_status`, `SENT_TO_KITCHEN`, the production queue and calendar;
  - KDS;
  - preparation stations and kitchen routing.
- **Catalogue features:**
  - modifiers and combos (keep the code, hide the UI);
  - menu `setup/active` state;
  - daypart category windows;
  - food variant presets.
- **Inventory and roles:**
  - the `staff_meal` movement type;
  - role templates (Server, Host, Kitchen Manager/Staff);
  - permission names `restaurant.settings.manage`, `kitchen_stations.manage`, `menu.*`.
- **Frontend copy:** the `/menu/*` route prefix and the "Menu" navigation group.
