# Morbrick Construction Sales & Finance Platform

Implementation status, production gates, and residual integration risks are documented in [the 16 July 2026 implementation review](docs/implementation/review-16-Jul-2026/00-executive-overview.md).

A quote-to-cash sales and financial management system for Morbrick Systems Ltd — built for construction, engineering, and building materials sales, with full KRA eTIMS compliance.

Manages the complete lifecycle: **Lead → Quote → Approval → Invoice → Payment → Receipt**, with construction-specific pricing (materials, labour, transport, installation) and Kenyan tax compliance built in from day one.

---

## 1. Project Goals

- Replace manual/ad-hoc quoting with a structured, auditable quote-to-invoice workflow.
- Ensure every invoice is KRA eTIMS-compliant (OSCU) with no manual re-entry into the KRA portal.
- Support M-Pesa and standard payment methods with reconciliation.
- Run reliably on **standard shared hosting** — no VPS, no persistent background services required to operate day-to-day.
- Stay small and modular enough for a single developer to maintain, while leaving room to grow into inventory and procurement later without a rewrite.

---

## 2. Decisions Locked In

| Decision | Choice | Reason |
|---|---|---|
| Hosting | **Shared hosting (cPanel-style)** | Matches existing Morbrick/Brandlynk deployment pattern; lowest cost, fastest to deploy |
| Database | **MySQL 8** | No feature in this system needs Postgres; matches existing stack |
| eTIMS integration | **OSCU** (Online Sales Control Unit) | OSCU is KRA-hosted and accessed purely via API — no local server process to install or maintain. VSCU requires deploying and running a local Java package bound to a port (default 8088) on a machine you control, which shared hosting cannot support. OSCU is also KRA's recommended path for "always online" invoicing environments, which fits a web-hosted sales system. |
| Expected volume | **Low-to-moderate** (project-based quotes/invoices, not high-frequency retail transactions) | Keeps MySQL full-text search and database-driven queues sufficient for Phase 1 — no Redis/Meilisearch/Horizon dependency |

**Note on OSCU going forward:** if Morbrick later needs offline invoicing at a physical branch/yard with unreliable internet, VSCU can be added *in addition* to OSCU (KRA allows multiple solutions simultaneously) — but credit notes must be issued from the same solution as the original invoice, so invoice-origin rules would need to be defined per branch if that happens. Not needed for Phase 1.

---

## 3. Tech Stack

**Backend**
- Laravel 11 (PHP 8.2/8.3)
- MySQL 8
- Database queue driver (`QUEUE_CONNECTION=database`) — no Redis/Horizon required
- Laravel Sanctum (session-based auth)
- Laravel's built-in scheduler (`schedule:run` via cron) for queue processing and eTIMS retry jobs

**Frontend**
- Blade + Livewire 3 + Alpine.js
- Tailwind CSS 3
- Chart.js — dashboard charts
- Flatpickr — date pickers
- TomSelect — searchable dropdowns

**PWA**
- Responsive Tailwind layout (desktop/tablet/mobile)
- Optional web manifest for offline quote viewing (read-only cache, no offline write-back needed for Phase 1)

**Key Packages**

| Package | Purpose |
|---|---|
| `spatie/laravel-permission` | Roles & permissions (RBAC) |
| `spatie/laravel-activitylog` | Audit trail on quotes, invoices, payments |
| `spatie/laravel-medialibrary` | Attachments, product images |
| `barryvdh/laravel-dompdf` | Quote / invoice / receipt PDF generation |
| `maatwebsite/excel` | Report exports |
| `simplesoftwareio/simple-qrcode` | eTIMS QR code on invoices |
| `intervention/image` | Image handling for catalog/product photos |

**Explicitly not used in Phase 1:** Laravel Octane, Horizon, Reverb, Meilisearch, Redis. Each requires a persistent process shared hosting doesn't reliably support. Can be added later as a discrete upgrade if Morbrick moves to a VPS.

---

## 4. Architecture

**Style:** Modular monolith. Not DDD/CQRS/event-driven — that level of ceremony isn't earned yet at this scale, and can be introduced later if/when Inventory, Procurement, and Project Costing are added and modules genuinely need decoupling.

**Structure:**
```
app/
├── Modules/
│   ├── CRM/            # Customers, contacts, branches
│   ├── Catalog/         # Products, categories, pricing
│   ├── Quotes/          # Quotation engine (core module)
│   ├── Invoicing/       # Invoices, credit/debit notes
│   ├── Etims/            # OSCU integration, offline/retry queue
│   ├── Payments/        # Payment recording, M-Pesa Daraja
│   ├── Receipts/        # Receipt generation
│   └── Reports/         # Sales, VAT, aging reports
├── Services/            # Cross-module business logic (e.g. QuoteToInvoiceService)
└── Http/Livewire/       # Livewire components per module
```

Each module owns its own models, Livewire components, and a thin service class. Repository pattern is used **only** in the eTIMS module, where the OSCU implementation is likely to change as KRA specifications evolve — everywhere else, Eloquent models are used directly to avoid unnecessary abstraction.

---

## 5. Core Modules

### 5.1 CRM (lightweight)
Customers, contacts, branches, notes. Enough to support quoting and invoicing — not a full pipeline/deal-stage CRM unless requested later.

### 5.2 Product Catalog & Pricing
- Products, categories, units, brands
- Customer-specific price lists
- Bulk/tiered discounts
- VAT handling
- Construction-specific line items: transport cost, labour cost, installation charges

### 5.3 Quotation Module (core)
```
Draft → Review → Approval → Sent → Customer Accepted → Convert to Invoice → Invoice Paid → Receipt Generated → Closed
```
- Auto-numbering, version history
- PDF generation
- Email and WhatsApp send
- Expiry dates, approval workflow, notes, attachments

### 5.3a Bill of Materials Module
- Structured project/floor/work sections with catalog-linked or custom priced lines
- Automatic subtotal, VAT, and total calculation with construction units
- Draft, independent review/approval, branded PDF, and formatted Excel export
- Private supporting documents, duplication, ownership controls, and conversion of approved BOMs into draft quotations

### 5.4 Invoice Module
- Generated directly from an accepted quote
- Partial invoicing
- Credit notes, debit notes, proforma invoices, recurring invoices
- Every invoice routes through the eTIMS module before being marked final

### 5.5 KRA eTIMS Module (OSCU)
```
Generate Invoice → Validate → Submit to OSCU (KRA API) → Receive Signed Response → Store QR Code → Attach QR to PDF → Sync Status
```
- All submissions go through a database-queued job (`SubmitInvoiceToOscuJob`), so a temporary internet blip on shared hosting doesn't block invoice creation — it queues and retries.
- Failed transmissions, retry count, and sync status are logged in `etims_requests` / `etims_responses` tables for audit purposes.
- Repository pattern wraps the OSCU client so the KRA API integration can be swapped/updated without touching the rest of the Invoicing module.

### 5.6 Payments & Receipts
- Cash, bank, cheque, M-Pesa (Daraja), card
- Partial payments and reconciliation
- Auto-generated receipts with QR code, company logo, PDF export, email delivery

### 5.7 Reports
Sales, VAT, customer statements, aging reports, quote-conversion rate — Blade/Livewire views with Chart.js, exportable via `maatwebsite/excel`.

---

## 6. Database (Core Tables)

```
users, roles, permissions
customers, contacts, branches
products, categories, price_lists
bills_of_materials, bill_of_material_sections, bill_of_material_items, bill_of_material_approvals
quotes, quote_items, quote_approvals
invoices, invoice_items, credit_notes, debit_notes
receipts, payments, payment_methods
etims_requests, etims_responses
activity_logs
settings
```

---

## 7. User Roles

- **Super Admin (1 active account):** full operational, audit, and user-administration access.
- **Approver (up to 2 active accounts):** full operational and approval access, excluding administration and security audit events.
- **Quote Creator (up to 2 active accounts):** customer and catalog management plus creation, editing, export, and submission of their own BOMs and quotations.

Public registration is disabled. The Super Admin provisions all accounts, and inactive accounts do not consume a role slot. See [the access-control matrix](docs/security/access-control-matrix.md).

---

## 8. Security

- Laravel Sanctum for session-based authentication
- `spatie/laravel-permission` for role-based access control
- `spatie/laravel-activitylog` for a full audit trail — important given eTIMS compliance
- Standard Laravel hardening: CSRF protection, rate limiting, encrypted sensitive fields, signed URLs for shareable quote/invoice links

---

## 9. Environment Setup

**Requirements**
- PHP 8.2 or 8.3
- MySQL 8
- Composer
- Cron access (for Laravel scheduler — required to run `schedule:run` every minute)

**Install**
```bash
composer install
cp .env.example .env
php artisan key:generate
php artisan migrate --seed
```

**.env essentials**
```
DB_CONNECTION=mysql
QUEUE_CONNECTION=database
ETIMS_MODE=oscu
ETIMS_SANDBOX_URL=<KRA OSCU sandbox endpoint>
ETIMS_PRODUCTION_URL=<KRA OSCU production endpoint>
MPESA_ENV=sandbox
MPESA_CONSUMER_KEY=
MPESA_CONSUMER_SECRET=
MPESA_SHORTCODE=
```

**Cron entry (required for queues and eTIMS retries)**
```
* * * * * php /path-to-project/artisan schedule:run >> /dev/null 2>&1
```

---

## 10. Roadmap

1. **Phase 1 — Foundation:** Auth, roles, company profile, customers, product/service catalog.
2. **Phase 2 — Sales:** Quotation engine, approvals, PDF/email/WhatsApp send.
3. **Phase 3 — Finance:** Invoicing, payments (M-Pesa Daraja), receipts, customer statements.
4. **Phase 4 — Compliance:** OSCU sandbox testing, certification, production rollout.
5. **Phase 5 — Operations:** Inventory, procurement, dashboards/analytics — reassess Redis/Horizon/Meilisearch here if hosting has since moved to a VPS.
6. **Phase 6 — Enterprise:** Customer portal, PWA offline write support, workflow automation.

---

## 11. Known Constraints (by design)

- No real-time features (no Reverb) — dashboard/data updates via polling or page refresh.
- No background worker daemon assumed — queue jobs run via cron-triggered scheduler, not Horizon.
- Search is MySQL full-text, not Meilisearch — fine at current expected catalog/customer volume; revisit if that changes materially.
- Single eTIMS solution (OSCU) for Phase 1 — VSCU addition is a future, branch-specific decision, not a Phase 1 gap.
