# MASTER_INTEGRATION.md — Habib Cables ERP

How the components communicate. Read this before any change that crosses a boundary.

## Component dependency graph

```
                    ┌─────────────────────────────┐
                    │        erp-web-core          │
                    │  (Blade UI + controllers)    │
                    │  Inventory · Purchasing ·    │
                    │  Manufacturing · WMS · QC    │
                    └───────┬─────────────┬────────┘
                            │ events      │ writes
              GRNPosted /   │             │  Item, ItemVariation,
              IGPProcessed  ▼             ▼  Stock*, Warehouse*
                    ┌───────────────┐   ┌──────────────────────┐
                    │ accounting-   │   │  Shared domain models │
                    │ ledger        │◄──┤  (single source of    │
                    │ (double-entry)│   │   truth)              │
                    └───────────────┘   └───────┬──────────────┘
                                                │
                    ┌───────────────┐           │
                    │ shop-pos-api  │◄──────────┤ Shop* models,
                    │ (retail POS)  │           │ ShopProductStock
                    └───────┬───────┘           │
                            │ pull/push (Sanctum token, JSON)
                            ▼
                    ┌───────────────────────────┐
                    │  desktop-sync-api          │
                    │  api/desktop/* endpoints   │
                    └───────────────────────────┘
                            ▲
                            │ HTTP (offline-tolerant, queued client-side)
                    ┌───────────────┐
                    │ Windows       │
                    │ desktop client│  (separate app, consumes this API)
                    └───────────────┘
```

## 1. Event-driven ledger integration (erp-web-core → accounting-ledger)
- Events: `App\Events\GRNPosted` (carries a `Grn`), `App\Events\IGPProcessed`.
- Listeners: `App\Listeners\ProcessGRNPosted`, `App\Listeners\ProcessIGP`.
- Contract: posting a GRN / processing an IGP must produce **balanced** double-entry
  `AccountTransaction` rows against the `ChartOfAccount` hierarchy and the correct `CostCenter`.
- **Rule:** if you change what a GRN/IGP means financially, update the listener AND
  `TestDualLedgerIntegration` / `TestChartOfAccountsIntegration`.

## 2. Desktop sync protocol (desktop-sync-api ↔ Windows client)
Base prefix: `api/desktop/*` (CSRF-exempt per `bootstrap/app.php`). Auth via Sanctum token issued
after `authenticate`, gated further by license.

**Auth & license**
- `GET  api/desktop/check-license`  → `LicenseAPIController@checkLicense`
- `POST api/desktop/authenticate`   → issues the Sanctum token
- `GET  api/desktop/app-launch`     → `SyncAPIController@appLaunchSync` (bootstrap payload)

**Pull (server → client)** `PullController` — e.g. `user-info`, `employee-info`, `product-updates`,
`products` (+ `products/mark-synced`), `customers`/`contacts`, `customer-account-updates`,
`product-stock`, `server-changes`, `invoices`, `invoice-items`, `invoice-return-items`.

**Push (client → server)** `PushController` — e.g. `new-products`, `product-updates`, `products`,
`new-customers`, `customer-edits`, `customer-account-updates`, `stock-entries`, `invoices`,
`invoice-items`, `invoice-returns`, `invoice-return-items`, `goods-receipts`, `goods-receipt-items`,
`contacts`, `stocks`, `contact-account-transactions`, `return-invoices`, `expense-categories`.

**Attachments** `AttachmentSyncController` — `POST attachments/upload`, `GET attachments/download`.

**Contract rules**
- Sync uses a **mark-synced** acknowledgement pattern (`markSynced`, `pullServerChanges`) — the
  client pulls changes, applies them, then acknowledges. Preserve this handshake.
- Every new syncable field must be added to **both** the matching Push and Pull payloads, and the
  desktop client's expectations, or clients diverge.
- Desktop clients are **offline-tolerant**: they queue locally and replay. Endpoints must be
  idempotent / conflict-aware — do not assume single delivery.

## 3. Shop POS integration (shop-pos-api ↔ shared inventory & ledger)
- Shop domain: `Shop`, `ShopProduct`, `ShopProductPrice`, `ShopProductStock`, `ShopStock`,
  `ShopContact`, `ShopInvoice(+Item)`, `ShopInvoiceReturn(+Item)`, `ShopGoodsReceipt(+Item)`,
  `ShopExpenseCategory`, `ShopContactAccountTransaction`.
- POS sales/receipts adjust `ShopProductStock` and post to the shop-level ledger
  (`ShopContactAccountTransaction`).
- Web API surface: `GET api/v1/shop/dashboard` (`Api\ShopApiController@getDashboardData`),
  factory POS `POST api/v1/factory-pos/store`, and payments
  (`get-references`, `process-payment`, `process-receipt`) — all on the `web` (session) middleware.
- **Rule:** shop stock and central inventory are related but distinct tables. Know which you are
  writing to; do not conflate `ShopProductStock` with `WarehouseCurrentStock`/`StockBalance`.

## 4. Shared domain models (the true cross-cutting contract)
Changes to these ripple across components — grep for every usage first:
`Item`, `ItemVariation`, `ItemCategory`, `Uom`, `Contact`, `Warehouse`, `StockLedger`,
`StockMovement`, `StockBalance`, `WarehouseCurrentStock`, `ChartOfAccount`, `Account`,
`AccountTransaction`, `CostCenter`.

## 5. Cross-component change checklist
1. Which components read/write the model or contract you're touching?
2. Update every side (web write + sync payload + POS view + ledger listener) in one PR.
3. Add/adjust an integration test (`Test*` command or Pest feature test).
4. Round-trip test the sync and re-run the ledger balance check.
