# Project plan — kb-online (Kohler Box)

Evidence date: 2026-10-11.

Source repository: `git@bitbucket.org:overdrive/kb-online.git`.

Inspected default branch: `main` at `5aa7141` (2026-09-17, rachelmogano, "added Kayla Koopman to job card printing"). `origin/HEAD` points at `main`. A shallow history of 13 commits was fetched, from 2026-05-18 through 2026-09-17. The scan-host path `~/projects/sonar_scan/repos/kb-online` was not on this machine. The tree below was read from that git revision.

This plan describes what the repository contains. It does not decide what the product should become. There was no prior Silicon Ark folder for this repository, and the source tree has no README or product requirements document.

## Product

**Kohler Box** is the name used on the public host, on estimate PDFs, and on the production spreadsheet.

| String | Where | Provenance |
|---|---|---|
| `www.kb-online.co.za` | `login.php` redirects `www.overdrive.co.za` here. `system.php` rewrites a bare `kb-online.co.za` host to `www.kb-online.co.za` | **Implemented** |
| Kohler Box | Estimate PDF body in `Order::GenerateKohlerBoxEstimatePDF` | **Implemented** |
| Kohlerbox Production Order | First cell of the production-order worksheet in `Order::GenerateOrder` | **Implemented** |
| kohlerbox | Sublime project `kohlerbox.sublime-project`. Staff addresses in the job-card reprint allowlist use `@kohlerbox.com` | **Implemented** |
| KB Number | Order-list column alias for `strOrderNumber` | **Implemented** |

The page title and header brand come from `sysSettings` keys `Title` and `Brand`, loaded at startup. Those values are not in the repository. **Unknown / Requires Confirmation:** the exact browser title and logo text stored in production.

The product is an internal system for a box manufacturer. Staff record customers and box specifications, move a job from enquiry through estimation and quote into a production order, print a factory spreadsheet (job card), schedule deliveries, and flag deliveries that still need an invoice number. Pricing, annual price increases, and customer price-list emails are part of the same application.

There is no written statement of company, industry, or product goals in the repository. The box-making purpose is **Inferred** from boards, styles, crease specifications, sheet size, area, weight, production orders, and inspection tracking.

## Branch reality

| Line | Tip | Date | What it is |
|---|---|---|---|
| `main` (default; `origin/HEAD`) | `5aa7141` | 2026-09-17 | Only branch present after fetch |

No other remote branch was returned by this fetch. History before the 2026-05-18 initial commit is not in this repository. Comments inside PHP files refer to work from 2010 through 2019 (login facility, SMS, production-order layout, Hetzner move). Those comments describe an older system that was committed here as a snapshot. Provenance of the pre-2026 comments: **Implemented** as comments. Whether that older system is the same production database is **Unknown / Requires Confirmation**.

History on `main`, compressed:

| Date | Commit | What the message says |
|---|---|---|
| 2026-05-18 | `d10c321` | Initial commit |
| 2026-06-02 | `399fb86` | initial code commit |
| 2026-06-02 | `4f47d62` | missing folders from init commit |
| 2026-06-03 | `fecf0b1` | php upgrade |
| 2026-06-03 | `5f3b4a6` | added export date and time |
| 2026-06-05 | `6a901e3` | Confirm Order no longer forces status back to `Order: New` |
| 2026-06-30 | `58d96bf`, `5979a27`, `971007f` | Security changes and password-field cleanup |
| 2026-08-07 | `2bcf33f` | Reverted OTP changes |
| 2026-08-07 | `75ca321` | Reply-To on order, enquiry, and estimation emails |
| 2026-09-17 | `5aa7141` | Kayla Koopman added to job-card printing |

## Objectives (inferred from the implementation, not from a written plan)

- Let signed-in staff capture customers, contacts, and box products.
- Move one `tblOrder` row through enquiry, estimation, quote, and production order.
- Email the estimator, the salesperson, and the customer contact at the hand-off points.
- Produce a Kohler Box estimate PDF and a production-order spreadsheet with an inspection sheet.
- Record deliveries and surface deliveries that have a date and no invoice number.
- Maintain product prices, including an annual increase and a personalised customer price list.
- Restrict menus and actions by security group stored in MySQL.

## Scope

### In scope of `main`

1. Nemo page shell: login, session, menu, toolbar, list, and detail screens.
2. Sales pipeline screens: `enquiry.php`, `estimation.php`, `pricing.estimate.php`, `quote.php`, `order.php`, `my.order.php`, `archive.php`.
3. Master data: customer, contact, contact log, product, board, style, descriptor, industry, sub-category, sales rep.
4. Pricing: product price matrix on an order, price-check from board cost times weight, annual increase upload, personalised price-list upload and email.
5. Documents: estimate PDF, signed-estimate upload, supporting-document upload, production-order spreadsheet, barcode image.
6. Reports: Daily Diary, Outstanding Production Orders, Dormant Customers.
7. Administration: users, own profile, security groups, settings, email templates, sent-email log, spreadsheet import (`data.import.php`).
8. Composer libraries `mpdf/mpdf` and `phpoffice/phpspreadsheet`, plus older copies under `mpdf/` and `PHPExcel/`.

### Out of scope of the repository

- The MySQL database, including menu rows, security-group names, the `ORDER_STATUS` setting, and email-template bodies other than the OTP insert script.
- The `.env` file. `system.php` loads it. It is not in the tree.
- Hosting, DNS, and TLS for `www.kb-online.co.za`. A 2016 comment says the live server moved to Hetzner. Current hosting is **Unknown / Requires Confirmation**.
- Automated tests, CI, and a deployment pipeline. None of those files are in the tree.

## System architecture

Browser requests hit a PHP page at the repository root. The page includes `system.php` through the Nemo classes. `system.php` loads `.env`, opens MySQL with `mysqli`, and copies every `sysSettings` row into `$SystemSettings`.

`Nemo` refuses the page when `$_SESSION["USER"]` is missing and redirects to `SessionExRedirect`. It then loads `sysSecurity` rows for the user's security group and blocks the script when `blnView` is not 1.

List and detail behaviour is not a separate API. Each screen is a PHP file that switches on `$_REQUEST["Action"]` and renders HTML through Nemo layouts. `ajaxfunctions.php` answers a few in-page calls (new customer, new product, calculated dimensions, printed-order flag).

Outbound mail uses PHP `mail()` from `NemoEmail`. PDF uses mPDF 8. Spreadsheets use PhpSpreadsheet. Files are written under paths taken from settings (`dir_quotes`, `dir_orders`, `dir_signed_estimates`, `dir_supporting_documents`).

```text
Browser
  -> login.php (MD5 password check)
  -> index.php (home message from settings)
  -> enquiry / estimation / quote / order / master-data pages
       -> Nemo list or OrderDetails
       -> tblOrder and related tables
       -> mail(), mPDF, PhpSpreadsheet, barcode.php
```

## Major components

| Component | Role |
|---|---|
| `_nemo.*.cls.php` | Framework: database reflection, lists, details, menu, email, reports |
| `includes/order.cls.php` | Pipeline lists, save, emails, estimate PDF, production spreadsheet |
| `_nemo.details.order.cls.php` | Shared order form, status buttons, on-screen instructions |
| `includes/product.cls.php` | Product list and price-increase processing |
| `includes/customer.cls.php` | Customer list and Mailchimp CSV |
| `system.php` | Host rewrite, `.env`, MySQL, settings load, session |
| `sysSettings` | Runtime configuration, including paths, SMTP display name, and `ORDER_STATUS` |
| `tblOrder` | One row for enquiry, estimation, quote, and order. Views filter on `strStatus` |

## Milestones

No project plan or milestone list is in the repository. The only dated plan is the commit history above. Comments record earlier milestones that are not commits in this git history: SMS helper (2010-12-20), production-order sheet changes (2016), Hetzner move (2016-08-29), Hetzner credential reset (2017-11-02), PHP 8 property fixes (comment dated 2022-08-29, commit `fecf0b1` on 2026-06-03).

## Known dependencies

- PHP with `mysqli`, `mail`, GD (`barcode.php` uses `imagecreate`), and `eval` used by the dimension calculator. The 2026-06-03 commit message says "php upgrade". The exact PHP version on the server is **Unknown / Requires Confirmation**.
- MySQL or MariaDB. Views in comments are `DEFINER=root@localhost`. Engine and version are **Unknown / Requires Confirmation**.
- Composer packages: `mpdf/mpdf` ^8.2, `phpoffice/phpspreadsheet` ^1.29.
- jQuery 1.8.2 from the Google Ajax CDN, and jQuery UI 1.8.6 shipped under `js/`.
- PHP `mail()` and settings `SMTP Send As` and `SMTP BCC`. No SMTP library is required by `NemoEmail::Send`.
- Optional SMS gateway `http://www.mymobileapi.com/api5/http5.aspx`. `SendSMS` is defined and is not called from any other file in this tree.
- Accounting: a Pastel account code is stored on the customer. No Pastel API client is in the tree.
- Mailchimp: customer export builds a CSV. No Mailchimp API client is in the tree.

## Current project status

**Implemented** and committed on `main` as of 2026-09-17. The repository is a working snapshot of a long-lived internal application, not a greenfield codebase. Active change since the June 2026 import is security, email reply routing, and the job-card reprint allowlist.

OTP files (`login2fa.php`, `includes/security.cls.php`, `database/tblMailAuthCodes.sql`, `database/emailtemplate.sql`) are in the tree. Commit `2bcf33f` says OTP changes were reverted. `login.php` still signs the user in after an MD5 match and does not redirect to `login2fa.php`. Treat two-factor login as present code that the current login path does not use.

## Human confirmation

- Production database name, host, and whether it matches the views and tables named in code.
- Full `ORDER_STATUS` list and the display names of security groups 1, 2, 4, 6, and 7.
- Whether `www.kb-online.co.za` is still the live host, and where it is hosted now.
- Whether the job-card email allowlist is still the intended access rule.
- Whether the OTP scripts should stay, be wired back in, or be removed.
- Whether `SendSMS`, Mailchimp CSV, and the Pastel account code are still used in the business.
