From d7239e4a041fee35b6ec7eb746e91f48337fcf38 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 3 Sep 2026 10:20:54 +0000 Subject: [PATCH] docs: drop client-name and assessment framing, present as a standalone project Removes every mention of the originating client's name and reframes the docs so the project reads as a standalone service rather than a graded submission: "assessment deliverable"/"assessment code"/"assessment workbook" become neutral descriptions, "submission scope"/"presentation scope" become "core scope"/"extended scope", QA_PREP.md's "Twenty Questions They Will Ask" becomes a design-rationale FAQ, and CONTRIBUTING.md's intro no longer frames the repo as an assessment submission. No code, tests, or application behavior changed -- doc wording and framing only. Also removes the now-unused backend/app/collections/images/ placeholder: real screenshots already live in docs/images/ and are wired into the root README, so the placeholder was dead weight pointing at an empty folder nobody was going to use. --- .github/pull_request_template.md | 2 +- CONTRIBUTING.md | 15 +++--- MASTER_PLAN.md | 45 +++++++++--------- QA_PREP.md | 14 +++--- README.md | 4 +- backend/app/collections/README.md | 49 ++++++++------------ backend/app/collections/docs/ARCHITECTURE.md | 6 +-- backend/app/collections/docs/DEVELOPMENT.md | 2 +- backend/app/collections/docs/RULES.md | 2 +- backend/app/collections/images/README.md | 15 ------ docs/CHANGELOG.md | 6 +-- postman/README.md | 2 +- 12 files changed, 68 insertions(+), 94 deletions(-) delete mode 100644 backend/app/collections/images/README.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 5644d41..362375a 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -2,7 +2,7 @@ ### What this adds -### Assessment requirement served +### Requirement served ### Docs updated diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 364588f..547b492 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,9 +1,8 @@ # Contributing -This is an assessment submission repo for Elevent Group (ERP Collection -Reporting Workflow) — not an open-source project accepting outside -contributions. This file documents the actual working conventions this -repo follows, for anyone reviewing or continuing the work. +This repo is not currently accepting outside contributions. This file +documents the actual working conventions it follows, for anyone reviewing +or continuing the work. ## Workflow @@ -31,7 +30,7 @@ anything under `backend/app/collections/`. ## Pull requests -Each PR follows the template: what it adds, which assessment requirement -it serves, which docs were updated, verification commands run, and known -gaps carried to the next phase. Self-review before merge; run -`/ponytail-review` on the diff first. +Each PR follows the template: what it adds, which requirement it serves, +which docs were updated, verification commands run, and known gaps carried +to the next phase. Self-review before merge; run `/ponytail-review` on the +diff first. diff --git a/MASTER_PLAN.md b/MASTER_PLAN.md index af726c9..0722008 100644 --- a/MASTER_PLAN.md +++ b/MASTER_PLAN.md @@ -1,6 +1,5 @@ -# ERP Collection Reporting Workflow: Master Plan v3 -Assessment for Elevent Group. Supersedes Blueprint v1 and v2. -Companion document: `QA_PREP.md` (the twenty questions this design answers). +# ERP Collection Reporting Workflow: Project Plan +Companion document: `QA_PREP.md` (a design-rationale FAQ this plan answers). --- ## 1. Goal, restated from the source of truth The email lists deliverables. The **README sheet inside the workbook** defines the @@ -16,18 +15,18 @@ Non-negotiables extracted from the workbook: | Payments after report date do not reduce the position | Date filter before aggregation | | **Do not silently delete problematic rows** | Every exclusion emits an exception row | | Blank Region derived from Region_Mapping via State | Enrichment step, never a blank output | -Graded on: business understanding, validation approach, exception handling, code -structure, responsible AI use, clarity of explanation. -**This is an MVP for a presentation, not a platform.** Optimise for what a -reviewer can see, click, and understand in fifteen minutes. +Design priorities: business understanding, validation approach, exception +handling, code structure, responsible AI use, clarity of explanation. +**This is an MVP for a walkthrough, not a platform.** Optimise for what +someone can see, click, and understand in fifteen minutes. --- -## 2. Two deadlines, two scopes -| Milestone | Deadline | Scope | -|---|---|---| -| **Submission** | 2 days | Phases 0 to 8. Code, README, working API, minimal UI | -| **Presentation** | Later, date TBC | Phases 9 to 13. They hand over a second workbook live | +## 2. Two phases of scope: core and extended +| Milestone | Scope | +|---|---| +| **Core** | Phases 0 to 8. Code, README, working API, minimal UI | +| **Extended** | Phases 9 to 13. Handling a second, differently-shaped workbook live | Design every phase so that stopping at the end of it still leaves a demoable -system. Never end a day mid-phase. +system. Never leave a phase half-finished. --- ## 3. The second-workbook problem At the presentation they will hand over a different file. Three ways that file @@ -58,7 +57,7 @@ after that is your diff, which is exactly what a reviewer wants to see. The frontend that was dead weight in v2 is now an asset, since a team needs to view results without reading logs. Keep it. ``` -backend/app/collections/ # the entire assessment service, one folder +backend/app/collections/ # the entire collections service, one folder __init__.py config.py # report date, thresholds, LLM settings contracts.py # CanonicalCustomer/Invoice/Payment/RegionMap @@ -102,10 +101,10 @@ backend/app/collections/ # the entire assessment service, one folder docs/ # see section 5 fixtures/ tests/ -frontend/src/routes/collections/ # the assessment UI +frontend/src/routes/collections/ # the collections UI runs.tsx run-detail.tsx exceptions.tsx summary.tsx upload.tsx mapping.tsx ``` -One folder, one concern, no assessment code leaking into the template's own +One folder, one concern, no collections code leaking into the template's own modules. A reviewer can `ls backend/app/collections` and see the whole design. Wire the router into the template's `app/api/main.py` with a single include line. That one-line touch is the only template file you modify. @@ -114,7 +113,7 @@ That one-line touch is the only template file you modify. Six files, strict ownership. A fact lives in exactly one file; others link to it. | File | Owns | Never contains | |---|---|---| -| `README.md` (service root) | **The assessment deliverable.** What it does, how to run, business rules, assumptions, AI tooling used, validation performed | Architecture internals, endpoint schemas | +| `README.md` (service root) | **The primary deliverable.** What it does, how to run, business rules, assumptions, AI tooling used, validation performed | Architecture internals, endpoint schemas | | `docs/ARCHITECTURE.md` | Components, data flow, why each decision was made, trade-offs, what breaks at scale | How to run, endpoint payloads | | `docs/API.md` | Every endpoint: method, path, params, response schema, status codes, error codes | Business rationale, setup | | `docs/RULES.md` | The exception rule catalogue. Single source of truth for E001 to E014 | Anything not a rule | @@ -241,7 +240,7 @@ One MR per phase. MR description template lives in ```markdown ## Phase N: ### What this adds -### Assessment requirement served +### Requirement served ### Docs updated - [ ] README.md - [ ] ARCHITECTURE.md - [ ] API.md - [ ] RULES.md - [ ] DEVELOPMENT.md - [ ] CHANGELOG.md @@ -259,13 +258,13 @@ SemVer, tagged on merge to `main`. | `v0.2.0` | Domain core | | `v0.3.0` | Validation | | ... | one minor per phase | -| `v1.0.0` | Submission-ready | +| `v1.0.0` | Core scope complete | | `v1.1.0`+ | Presentation hardening | `CHANGELOG.md` updated in the same MR, never retrofitted. --- ## 9. Phases Each phase: branch, build, docs, `/ponytail-review`, MR, tag, merge. -### Submission scope +### Core scope **Phase 0: Foundation** `v0.1.0` Clone template, init commit. Add `collections` package skeleton and docs skeleton. Docker Compose up with Postgres. Health endpoint returns green. @@ -303,13 +302,13 @@ Batched by rule code. Cause, impact, suggested fix, owner. `auto_fixable` hardcoded false. Guarded and cached. *Done when:* every exception row carries an explanation, and the explainer never invents an ID absent from its input. -**Phase 8: Frontend** `v0.9.0` then `v1.0.0` on submission +**Phase 8: Frontend** `v0.9.0` then `v1.0.0` on core-scope completion Five routes: runs list, run detail with timeline, exceptions table with filters, summary with block banner, upload. Template's shadcn/ui components throughout. *Done when:* someone who has never seen the terminal can upload a file and read every output. -**Submission cut line. Everything above ships in two days.** -### Presentation scope +**Core scope cut line — everything above is the core build.** +### Extended scope **Phase 9: Exports** `v1.1.0` CSV per report, PDF management pack. Download buttons on every view. **Phase 10: Multi-workbook** `v1.2.0` diff --git a/QA_PREP.md b/QA_PREP.md index 1a23aab..188aa79 100644 --- a/QA_PREP.md +++ b/QA_PREP.md @@ -1,8 +1,8 @@ -# Twenty Questions They Will Ask +# Design Rationale: Twenty Questions and Answers -Each entry: the question, the answer, and the design decision that makes the -answer true. If a design decision here is not in `MASTER_PLAN.md`, one of the two -documents is wrong. +Each entry: a question worth asking about this design, the answer, and the +design decision that makes the answer true. If a design decision here is not +in `MASTER_PLAN.md`, one of the two documents is wrong. --- @@ -204,9 +204,9 @@ with a different owner. **19. Why did you use the official FastAPI template rather than starting clean?** -It supplies the parts that are not being assessed and would otherwise consume the +It supplies the parts that aren't the point of this project and would otherwise consume the timeline: Postgres with SQLModel and Alembic, Docker Compose, auth, CI, and a -React frontend with shadcn/ui. All assessment code lives in one folder, +React frontend with shadcn/ui. All collections code lives in one folder, `app/collections`, with a single line wiring the router in. The initial commit is the unmodified template, so every subsequent commit is our own work and the diff is the deliverable. @@ -228,7 +228,7 @@ AR platforms and where E007 actually comes from. --- -## Two you should hope they ask +## Two worth hoping someone asks **How did you use AI to build this, not just inside it?** diff --git a/README.md b/README.md index 1e3a1c4..c159e77 100644 --- a/README.md +++ b/README.md @@ -89,9 +89,9 @@ for the full command reference. ## Repo layout ``` -backend/app/collections/ the entire assessment service — one folder, +backend/app/collections/ the entire collections service — one folder, one concern, see MASTER_PLAN.md section 4 -frontend/src/routes/collections/ the assessment UI +frontend/src/routes/collections/ the collections UI docs/CHANGELOG.md this project's own history MASTER_PLAN.md design and phase-by-phase build plan QA_PREP.md companion doc: the questions MASTER_PLAN.md answers diff --git a/backend/app/collections/README.md b/backend/app/collections/README.md index a43b124..3f4c3b3 100644 --- a/backend/app/collections/README.md +++ b/backend/app/collections/README.md @@ -1,15 +1,15 @@ # ERP Collection Reporting Workflow -The assessment deliverable for Elevent Group: an ERP collection -reporting service built on `fastapi/full-stack-fastapi-template`. This -file is the single source of truth for **what the service does, why it -is built this way, and how to run it**. Everything else — internals, -endpoints, the rule catalogue, local setup — is owned by one other file -each; see the map at the bottom rather than this file repeating them. - -Status: **submission scope (Phases 0-8) complete**, plus several -presentation-scope extras (file download, email, dashboard, full -rebrand) already pulled forward. See +An ERP collection reporting service built on +`fastapi/full-stack-fastapi-template`. This file is the single source +of truth for **what the service does, why it is built this way, and +how to run it**. Everything else — internals, endpoints, the rule +catalogue, local setup — is owned by one other file each; see the map +at the bottom rather than this file repeating them. + +Status: **core scope (Phases 0-8) complete**, plus several extended-scope +extras (file download, email, dashboard, full rebrand) already pulled +forward. See [`../../../docs/CHANGELOG.md`](../../../docs/CHANGELOG.md) for the exact, dated history of what shipped when. @@ -117,7 +117,7 @@ the exceptions, read the summary — from a browser. never left blank in the output. - **The control gate**: exception rows ÷ invoice count. Over 5%, the run is `BLOCKED`; at or under, it `PASSED`. The gate is never tuned - to pass — the given assessment file blocks at 47.2%, and that's the + to pass — the given sample file blocks at 47.2%, and that's the correct output for that file, not a bug to chase away. The full 14-rule exception catalogue — every condition, every dataset @@ -243,10 +243,10 @@ instead of raw JSON keeps a prompt small enough for a 4B-parameter model to handle its context window reliably, instead of truncating or losing structure on a large, verbose payload. It's wired and tested today, reserved for the schema-mapping role that reads a *renamed* -workbook (presentation-scope, not required for this submission) — -being honest about that is more useful to a reviewer than overstating -what's active. What's non-negotiable either way, submission or not, is -the boundary it's built under and never crosses: +workbook (extended scope, not yet part of the core build) — being +honest about that is more useful to a reviewer than overstating what's +active. What's non-negotiable either way is the boundary it's built +under and never crosses: ``` ALLOWED workbook -> anydoc -> markdown -> LLM context @@ -292,24 +292,15 @@ console errors throughout. ## Screenshots -`images/` in this folder holds the walkthrough screenshots referenced -below — upload, the run-detail timeline, an expanded exception, and the -management summary. Add them there under the filenames listed in -[`images/README.md`](images/README.md) and this section will render -them inline: - -``` -![Upload](images/upload.png) -![Run detail — blocked](images/run-detail-blocked.png) -![Exception expanded](images/exception-expanded.png) -![Summary](images/summary.png) -``` +Walkthrough screenshots — the dashboard, upload, the run-detail timeline +with its AI-written analysis, the exceptions list, and the mobile views — +live in the [root README](../../../README.md#screenshots). ## Technology used | Layer | Choice | Why | |---|---|---| -| API framework | FastAPI (unmodified `fastapi/full-stack-fastapi-template` base) | Supplies everything not being assessed — Postgres/SQLModel/Alembic, Docker Compose, CI, a React frontend — so every commit on top of the init commit is this project's own work, and the diff is the deliverable | +| API framework | FastAPI (unmodified `fastapi/full-stack-fastapi-template` base) | Supplies everything outside this project's own scope — Postgres/SQLModel/Alembic, Docker Compose, CI, a React frontend — so every commit on top of the init commit is this project's own work, and the diff is the deliverable | | Data model | SQLModel + Alembic | One ORM layer for both the Pydantic-style models and the SQL schema, with real migrations | | Money/dates | `Decimal` / `date`, never `float`/`datetime.now()` | Financial figures can't tolerate binary floating-point rounding, and a report date has to be reproducible, not clock-dependent | | Workbook parsing | `openpyxl` (no pandas) | Typed cell access straight into typed records — no second, looser dtype-inference path for money to travel through | @@ -333,5 +324,5 @@ rather than repeating it: | [`docs/DEVELOPMENT.md`](docs/DEVELOPMENT.md) | Local setup, every test/lint command, git workflow, and how this codebase was actually built with agent tooling | | [`docs/DEMO.md`](docs/DEMO.md) | The live presentation runbook | | [`../../../docs/CHANGELOG.md`](../../../docs/CHANGELOG.md) | The dated, phase-by-phase history of everything that shipped | -| [`../../../QA_PREP.md`](../../../QA_PREP.md) | Twenty rehearsed questions a reviewer is likely to ask, answered against this exact codebase | +| [`../../../QA_PREP.md`](../../../QA_PREP.md) | Twenty design-rationale questions and answers, grounded in this exact codebase | | [`../../../MASTER_PLAN.md`](../../../MASTER_PLAN.md) | The original design and phase plan this build followed | diff --git a/backend/app/collections/docs/ARCHITECTURE.md b/backend/app/collections/docs/ARCHITECTURE.md index 4c5f342..9e634fe 100644 --- a/backend/app/collections/docs/ARCHITECTURE.md +++ b/backend/app/collections/docs/ARCHITECTURE.md @@ -4,7 +4,7 @@ Owns: components, data flow, why each decision was made, trade-offs, what breaks at scale. Does not own: how to run anything (see `DEVELOPMENT.md`), endpoint payloads (see `API.md`). -Status: **Phase 8 complete -- submission scope (Phases 0-8) done.** Populated phase by phase as components land. +Status: **Phase 8 complete -- core scope (Phases 0-8) done.** Populated phase by phase as components land. ## Components @@ -143,7 +143,7 @@ itself. `control/gate.py`'s `evaluate_gate` is a pure function: invoice count in, `GateResult` out. It is deliberately never tuned to pass — `dataset_a_original.xlsx` blocks (47.2%), and that is the correct, -expected output for the given assessment file, not a bug to chase away. +expected output for the given sample file, not a bug to chase away. QA_PREP.md Q8 flags that the brief's wording, "exception records over invoice records," is ambiguous: one invoice can carry more than one @@ -358,7 +358,7 @@ path rather than an open-ended "would need more work." **Scheduler: in-process → Celery Beat / a Kubernetes CronJob.** `scheduler.py` is currently a stub for a single-process APScheduler job -(Phase 11, presentation scope). APScheduler works correctly with one +(Phase 11, extended scope). APScheduler works correctly with one worker process; the moment there is more than one (any real horizontal scale-out), two workers can both pick up the same trigger unless coordination is added. Celery Beat or a CronJob hitting the API is the diff --git a/backend/app/collections/docs/DEVELOPMENT.md b/backend/app/collections/docs/DEVELOPMENT.md index ca7fd3a..3b6a883 100644 --- a/backend/app/collections/docs/DEVELOPMENT.md +++ b/backend/app/collections/docs/DEVELOPMENT.md @@ -3,7 +3,7 @@ Owns: local setup, commands, git workflow, commit format, testing, release process. Does not own: business logic (see `README.md`). -Status: **Phase 8 complete — submission scope (Phases 0-8) done.** +Status: **Phase 8 complete — core scope (Phases 0-8) done.** ## Local setup diff --git a/backend/app/collections/docs/RULES.md b/backend/app/collections/docs/RULES.md index 297ea1a..85f68c6 100644 --- a/backend/app/collections/docs/RULES.md +++ b/backend/app/collections/docs/RULES.md @@ -192,7 +192,7 @@ needs investigation, not an automatic guess. `Invoice.invoice_amount`. **Fires on:** INV-1007 — invoice amount 88,000; PAY-2008 (30,000) + PAY-2028 (80,000) = 110,000, an overpayment of 22,000. -**Not on the assessment's required list** — added because the data +**Not on the original required list** — added because the data called for it (see QA_PREP.md Q5). **Excludes nothing further:** `compute_outstanding` already floors at zero, so no negative/credit figure leaks into the overdue report; this diff --git a/backend/app/collections/images/README.md b/backend/app/collections/images/README.md deleted file mode 100644 index 9257e38..0000000 --- a/backend/app/collections/images/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Screenshots - -Add screenshots here under these exact filenames and they render inline -in `../README.md` automatically — nothing else needs to change. - -| Filename | What to capture | -|---|---| -| `upload.png` | `/collections/upload` — the drag-and-drop dropzone | -| `run-detail-blocked.png` | `/collections/run-detail?runId=` for a `BLOCKED` run (dataset A) — the full colored stage timeline | -| `exception-expanded.png` | The exceptions panel with one card expanded, showing cause/impact/suggested fix/owner and the "Explained by" source badge | -| `summary.png` | `/collections/summary?runId=` — the block/pass banner, AI narrative, and region breakdown | - -PNG or JPG, no fixed size requirement — GitHub scales them to the -container width. This folder is otherwise empty on purpose; it's not -built or referenced by any code path, only by the README. diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 00e3fb1..7d3eb6d 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -72,7 +72,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.9.0] - 2026-08-31 -**Submission scope (MASTER_PLAN.md Phases 0-8) complete.** +**Core scope (MASTER_PLAN.md Phases 0-8) complete.** ### Added @@ -271,7 +271,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 amounts, invalid/missing GSTIN, payment-to-invoice customer mismatch, payment after report date, payment before invoice date, Cancelled/Credit Note status, duplicate source system reference, and overpayment (E014, - added beyond the assessment's required list). + added beyond the original required list). - `docs/RULES.md`: complete 14-rule catalogue, one entry per code, with condition, dataset A trigger, exclusion behavior, and rationale. - Test suite additions under `backend/app/collections/tests/` (65 new @@ -293,7 +293,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - `backend/app/collections/fixtures/dataset_a_original.xlsx`: the given - assessment workbook, committed as a reproducible fixture. + sample workbook, committed as a reproducible fixture. - `openpyxl` runtime dependency for reading xlsx workbooks with typed cells. - `contracts.py`: Decimal/date-typed canonical dataclasses (`CanonicalCustomer`, `CanonicalInvoice`, `CanonicalPayment`, `RegionMap`, `CanonicalDataset`). diff --git a/postman/README.md b/postman/README.md index 2399c86..8be5f35 100644 --- a/postman/README.md +++ b/postman/README.md @@ -18,7 +18,7 @@ API returns, every request and test script actually ran. 2. **Runs > Create Run - Dataset A (Blocks)** — click into the Body tab, click **Select File** next to `file`, choose `backend/app/collections/fixtures/dataset_a_original.xlsx` (or your - own copy of the assessment workbook). Send. The test script saves the + own copy of the sample workbook). Send. The test script saves the returned run's id into `{{run_id}}` automatically — nothing else to configure. 3. Open **Reports** folder, run every request top to bottom against that