# Project plan — personal_laundry

Evidence date: 2026-10-07.

Source repository: `git@bitbucket.org:overdrive/personal_laundry.git`.

This plan describes what the repository contains. It does not decide what the product should become.

## Product

Personal Laundry is the operating system for a commercial laundry. Staff receive customer linen and garments as workloads (prelists), count them, pack them, seal them into bags, and dispatch deliveries. A desktop point-of-sale console runs the floor stations. A separate desktop admin application maintains customers, operators, prices, companies, settings, and reports. An ASP.NET website lets customer logins see pickups and invoices, and lets operators export deliveries to Pastel and use a mobile driver log.

Provenance: **Inferred** from the solution layout, station names, and in-repo notes in `.cursor/PROJECT_MEMORY.md`, `CHANGELOG.md`, and `scope/`. There is no product requirements document inside the source repository.

The git history starts at `aa4ab42` on 2024-04-15 ("Initial commit"). Assembly copyright on the POS project is 2012, and a conflicted project file is named for 2012-08-24. The product is older than this Git repository. Provenance: **Implemented** (`PersonalLaundry/PersonalLaundry/Properties/AssemblyInfo.cs`).

Two brands are visible in the POS console. The default header is Personal Laundry. When the selected company id is 2, the console shows Texcare branding instead. Provenance: **Implemented** (`ConsoleForm.SetCompanyHeaders`). Whether Texcare is a trading name, a second company, or a site is **Unknown / Requires Confirmation**. Company names themselves live in the `Companies` table and are not seeded in this repository.

## Related Silicon Ark sets

These are different checkouts. They are not this repository.

| Silicon Ark directory | Repository | What it is |
|---|---|---|
| `personal_laundry/` (this set) | `overdrive/personal_laundry` at `0b3d107` (2026-10-02) | Current operational system: POS, Admin, and PersonalWeb |
| `personal_laundry_20240415/` | `overdrive/personal_laundry_20240415` at `4af604f` (2024-03-19) | Earlier snapshot of the same kind of system, documented from that repo's `master` |
| `personal_laundry_website/` | `overdrive/personal_laundry_website` | Public WordPress site for www.personallaundry.co.za |
| `Personal Laundry/` | `overdrive/personal-laundry` | Empty Bitbucket repository. No commits |

Where the 2024 snapshot and this `main` disagree, this set follows `0b3d107`. The 2024 snapshot does not contain Holdback or the multi-prelist bag contract.

## Branch reality

Default branch is `main`. `origin/HEAD` points at `main`.

| Line | Tip | Date | What it is |
|---|---|---|---|
| `main` | `0b3d107` | 2026-10-02 | "Merged in Renier_Work (pull request #8)". 73 commits from `aa4ab42` (2024-04-15) |
| `origin/Renier_Work` | merged | 2026-10-02 | Merged by pull request #8. Tip subject on the merge: invoice items grouped by prelist |
| `origin/josh_work` | merged | several PRs | Merged by pull requests #1, #2, #4, #5, and #6 recorded in commit subjects |
| `origin/feature/holdback-phase1-open-prelist-finder` | merged | pull request #3 | Holdback Phase 1. Commit subjects on `main` include that work |
| `origin/DefectiveItemsFunctionality` | no unique commits | — | Every commit on this branch is already in `main`. `main` is ahead of it |

This documentation set is based on `main` at `0b3d107`.

The onboarding issue recorded a scan-host checkout at `1a568b4` (2025-08-07, "Bag Slips and Delivery Notes email work") and listed `repos/`, `sonar-project.properties`, and `sonarqube_scan.bat` at the root. Those three paths are not in `main` at `0b3d107`. `1a568b4` is an ancestor of `main`. Provenance of the missing root files: **Unknown** — they may have been untracked files on the scan host.

Which build is installed on the laundry floor is **Unknown / Requires Confirmation**. In-repo verification notes say a dual-version database test was SQL and a console harness only. No WinForms station was clicked during that UAT (`PersonalLaundry/documents/phase2-multi-prelist-verification.md`).

## Scope in the repository

In scope of what is implemented on `main`:

- POS console (`PersonalLaundry`) with counting, packing, bagging, dispatch, and holdback stations.
- Personal Admin (`PersonalAdmin`) for customers, operators, companies, price increases, reports, and settings.
- Shared data access (`Common`) via Entity Framework 6 against SQL Server database `PersonalLaundry`.
- ASP.NET Web Forms site (`PersonalWeb`) for customer pickups, invoices, bag labels, dispatch slips, Pastel export, and a mobile driver log.
- SQL change scripts under `Scripts/` and `Database/Scripts/`.
- A SQL Server Data Tools project `PLFunctions`.
- A pseudo thermal printer for development (`PseudoPosPrinter`) and a UI automation harness (`PosUiTests`).
- Vendored libraries: POS for .NET 1.14.1 MSI, Zen Barcode, and a Newtonsoft.Json source tree under `JSON/`.

Out of scope of this repository, or not present here:

- The Inteltag / RFID integration document dated 8 April 2025. `scope/IntelTag_MultiPrelist_What_Changed.md` says it updates that document. The document itself is not in the checkout.
- The website project `acme_v_2_1_3_html` referenced by `PersonalLaundry.sln` under `../AcmeTemplates/`. That folder is not in the checkout.
- Production hosting, the live SQL Server instance, and which till binaries are deployed. **Unknown / Requires Confirmation**.
- `PersonalFunctions` exists as a .NET Framework 4.0 project folder. It is not a project entry in `PersonalLaundry.sln`.

## System architecture

```text
POS console (ClickOnce, .NET Framework 4.8 WinForms)
Personal Admin (ClickOnce, .NET Framework 4.8 WinForms)
        |                              |
        +---- Common (Entity Framework 6) ----+
                              |
                    SQL Server: PersonalLaundry
                     stored procedures + views
                              |
        +---------------------+---------------------+
        |                                           |
PersonalWeb (ASP.NET Web Forms 4.8, IIS)     Inteltag / RFID
 pickups, invoices, Pastel export,           calls stored procedures
 mobile driver log                           (external; contract cited,
                                              document not in repo)
        |
Office 365 SMTP (count and condemned emails from the POS)
Pastel accounting (file export from the website, not an API)
Microsoft POS for .NET thermal printer (or PseudoPosPrinter in dev)
```

Major components:

| Component | Role | Evidence |
|---|---|---|
| `PersonalLaundry/PersonalLaundry` | Floor POS. Stations 01 counting through 05 holdback | Project and `Station_*` folders |
| `PersonalLaundry/PersonalAdmin` | Back-office WinForms | `ConsoleForm` menu |
| `PersonalLaundry/Common` | EF model, settings, shared types | `Common.csproj`, target v4.8 |
| `PersonalWeb` | Customer and operator website | `Global.asax` routes |
| `Scripts` | Procedures the POS and Inteltag depend on | SQL file headers |
| `PseudoPosPrinter` | On-screen `PosPrinter` service object | `PseudoPosPrinter/README.md` |

## Milestones visible in history

These are delivery points already in `main`, not a future roadmap.

| When | What landed | Evidence |
|---|---|---|
| 2012 (pre-git) | Original POS. Copyright and a conflicted copy filename | `AssemblyInfo.cs` |
| 2024-04-15 | Repository created and initial code imported | `aa4ab42`, `8dbaf76` |
| 2024-04 | Company headers; companies menu in admin | comments dated 20240326 / 20240416 |
| 2016 through 2025, retained in code | Count-recon and condemned emails; Pastel export notes | dated comments in counting and `Dispatch.aspx.cs` |
| 2026-03 | Order Reference Report; post-count edit (manager code, audit, sync invoice items) | `CHANGELOG.md`, `PROJECT_MEMORY.md` |
| 2026-07 / 2026-08 | Holdback Phase 1 (on-hand, LIFO allocate, Open Prelist Finder). Console label later moved to `v1.5.0.132` | `CHANGELOG.md`, `ConsoleForm.Designer.cs` |
| 2026-08 onward | Multi-bag / multi-prelist experiment that created delivery invoices, then removal of those invoices | `scope/Why_The_Delivery_Invoice_Exists.md`, `Scripts/Phase2_MultiPrelistBag.sql` |
| 2026-09-04 to 2026-09-08 | Documented cleanup and SQL UAT of multi-prelist bags without delivery invoices | `phase2-multi-prelist-verification.md` |
| 2026-10-02 | Tax invoice lines grouped by category; multi-prelist invoice print groups items by prelist section | commits `5ab28ee`, `bdfae9e` |

## Implementation plan that the repository itself states

The documents describe an install order for the current multi-prelist behaviour. Provenance: **Documented** in `phase2-multi-prelist-verification.md`.

1. Take a fresh production backup.
2. Run `Scripts/Phase2_CleanupRetainedDeliveryInvoices.sql` while pre-Phase-2 binaries are still in use.
3. Run `Scripts/Phase2_MultiPrelistBag.sql`.
4. Confirm a pre-Phase-2 till can still seal a one-prelist bag.
5. Copy `Common`, `PersonalLaundry`, and `PersonalWeb` till by till.

Whether that order has been applied to production is **Unknown / Requires Confirmation**. The recovery map says a local database was not production and that cleanup embeds production invoice ids from a 2026-08-31 backup (`phase2-recovery-map.md`).

Holdback Phase 1 is in the POS binaries on `main`. The holdback pseudocode's Phase 2 (link table `BagPrelistLink` and a delivery invoice per seal) was superseded. Current bagging does not create those objects. See the conflict note below.

Post-count RFID edits require three scripts before use: `UpdateWorkloadItem.sql`, `SyncInvoiceItemsFromWorkload.sql`, `CreatePostCountEditAudit.sql`, then an administrator must save the manager code. Provenance: **Documented** (`CHANGELOG.md`).

## Known dependencies

- Windows desktop, .NET Framework 4.8 for POS, Admin, Common, PersonalWeb, and PseudoPosPrinter.
- Visual Studio 2019-era solution (`VisualStudioVersion = 16.0`).
- SQL Server database `PersonalLaundry`. Entity Framework 6.4.4 is in `packages/`.
- Microsoft POS for .NET 1.14.1 for a physical receipt printer. The MSI is vendored at `Libraries/PosForDotNet-1.14.1.msi`.
- ClickOnce for POS and Admin updates. POS logo click checks for an update (`ConsoleForm.InstallUpdateSyncWithInfo`).
- IIS plus Web Deploy (`PersonalWeb.deploy.cmd`) for the website. The deploy readme expects `PersonalWeb.zip`, which is not in the checkout.
- Newtonsoft.Json 13.0.3.
- Microsoft Report Viewer (RDLC reports in Personal Admin).
- FlaUI.UIA3 4.0.0 for `PosUiTests` (net48, x86).
- Office 365 SMTP from the counting station. Credentials are hardcoded. See technical documentation. Do not copy them into new environments from memory; rotate them.
- Pastel, as a file the operator downloads. No Pastel API client is in the repository.
- Inteltag, as an external caller of stored procedures. `GetItemCostForReceiving.sql` says it is called when an item is scanned at count.

## Current project status

`main` contains a working description of:

- The historical single-prelist laundry flow (count, pack, bag, dispatch, print).
- Holdback Phase 1 on the console.
- Multi-prelist bags that share one dispatch for a single customer, without a second "delivery invoice" row.
- Web tax invoices grouped by Laundry / Linen / Food and Bev, with multi-prelist sections.
- Admin reports: Outstanding Order, Bag Recon, Order Reference.

Status of production data after the delivery-invoice cleanup is **Unknown / Requires Confirmation**.

## Conflicts inside the repository

Do not treat every markdown file as the current rule.

| Document | What it says | What `main` code and `Scripts/Phase2_MultiPrelistBag.sql` do |
|---|---|---|
| `.cursor/PROJECT_MEMORY.md` and `NewKnowledgeBase.md` | Phase 2 multi-prelist bagging is not in this build. `CreateDispatch` is one invoice per bag | The install script allows one or more invoices on a bag when they belong to one customer |
| `PersonalLaundry/documents/holdback-module-pseudocode.md` | Phase 2 uses `BagPrelistLink` and a delivery invoice | `Phase2_MultiPrelistBag.sql` states it does not create `IsDeliveryInvoice`, `BagPrelistLink`, `DispatchInvoiceLink`, or `GenerateDeliveryInvoicesForBagSeal` |
| `scope/Why_The_Delivery_Invoice_Exists.md` | Middle sections describe delivery invoices created at seal | The same file's closing section says delivery invoices are removed and must not be recreated |
| `scope/IntelTag_MultiPrelist_What_Changed.md` and `phase2-multi-prelist-verification.md` | One counting invoice per prelist. Bag contents come from `DispatchPackages`. `Dispatches.InvoiceId` is only a representative invoice | Matches `Scripts/CreateDispatch.sql` and `Scripts/Phase2_MultiPrelistBag.sql` |

The current contract for agents and for Inteltag is the IntelTag note plus `Phase2_MultiPrelistBag.sql`, not the holdback pseudocode's Phase 2 schema.

## Human confirmation still required

- Which SQL Server and which ClickOnce URL are production.
- Whether production still has delivery-invoice rows or has already been cleaned up.
- Whether Inteltag has been updated to the multi-prelist contract in `scope/IntelTag_MultiPrelist_What_Changed.md`.
- Whether customer names `S.S.W.F`, `Capital Mirage Hotel`, and `The Stack` are still the only customers who receive count emails directly.
- What `OperatorLoginId` 2 represents. Personal Admin's menu load replaces the signed-in operator with that id.
- Whether the `DefectiveItemsFunctionality` branch should be deleted. It has no commits that `main` lacks.
