The manager dashboard "Approved This Month" card only counted POs whose
current status is MGR_APPROVED, so approvals that had already moved on to
payment, delivery, or closure dropped out of the count. Managers could not
see what happened to the POs they approved this month.
- Count every PO whose `approvedAt` falls in the current month across all
post-approval statuses (MGR_APPROVED → ... → CLOSED). `approvedAt` is set
once at approval and persists, so it is the correct anchor.
- Introduce a shared `POST_APPROVAL_STATUSES` constant (includes the
previously-omitted PARTIALLY_CLOSED). This also fixes Total Approved Spend
and the vessel/monthly breakdowns, which were silently dropping
partially-received POs.
- Make the card a link into /history with an approval-date filter applied
(?approvedFrom=<startOfMonth>) so a click shows the full set with each PO's
current status, as requested.
- Add `approvedFrom`/`approvedTo` filtering to the history page, its filter
UI, and the reports export route so the deep-link and exports stay in sync.
Scope note: the count remains org-wide, consistent with every other card on
the manager dashboard.
Adds an integration test covering the moved-on case and the date window.
Fixes#32
All PO attachments are stored as PODocument rows whose lifecycle stage
(submission vs delivery) is encoded in the storageKey prefix. The PO
details screen previously listed them in a single flat "Attachments"
block, giving no indication of which were submission documents (invoice,
quotation) versus delivery receipts.
Add lib/attachments.ts to derive a user-facing group from the storageKey
prefix (submission / payment / delivery / other) and render each
non-empty group as a labelled subsection on the PO details screen, in
lifecycle order. Unknown prefixes fall back to an "Other" group so
nothing is ever hidden.
Fixes#10
Partial-receipt flows call confirmReceipt multiple times. The nested
`create` on the Receipt relation threw a unique-constraint error on the
second call when both confirmations supplied notes, preventing any
delivery from completing and blocking attachment uploads.
Changed to `upsert` so subsequent confirmations update the existing
Receipt row's notes instead of failing.
Adds integration tests covering full receipt, partial receipt, the
upsert scenario (two confirmations each with notes), and permission guards.
Fixes#9
Moves the ItemInventory upsert from confirmReceipt (CLOSED) to approvePo
(MGR_APPROVED) so site inventory is visible as soon as a purchase order
is manager-approved, without waiting for full closure.
- approvePo: fetch lineItems, upsert ItemInventory per site PO line item
that has a productId; revalidate the site admin path.
- confirmReceipt: remove the now-redundant inventory update block.
- Rename approvepo → approvePo for consistency (fixes import mismatch
in the existing integration test file).
- Add three integration test cases covering: site PO inventory increment,
line items without productId are skipped, vessel-only POs are untouched.
Fixes#7
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add an optional PO Date field to the create and edit PO forms.
Submitters can pick any date (back-dated or forward-dated). If left
blank, the exported PO document falls back to the approved date, then
to the creation date.
Changes:
- Prisma schema: add `poDate DateTime?` to PurchaseOrder
- Migration 20260616000000_add_po_date: ALTER TABLE to add the column
- createPoSchema: add optional `poDate` string field
- new-po-form, edit-po-form: add PO Date picker in Order Information
- create/edit actions: persist poDate to DB
- edit action resubmit snapshot: track poDate changes for manager diff
- po-detail: show PO Date in Order Details; include in resubmit diff banner
- export route: use poDate ?? approvedAt ?? createdAt as the date on
the exported PDF/XLSX document
- validations.test: fix pre-existing costCentreRef→vesselId mismatch
and add poDate test cases
Fixes#4
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New PurchaseOrder.paymentDate field (migration 20260531000002)
- Backfill: existing POs use paidAt, else the earliest payment action date
- Accounts must enter a payment date with the payment reference
- Date input pre-selected to today, max=today (no future dates)
- Validated server-side (required + not in future) in processPaymentSchema
- paymentDate stored on both full and partial payments; paidAt set from it
- Shown on PO detail (Payment Date) and payment history (prefers paymentDate)
- Integration tests updated; added future-date rejection test
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
seed-prod.ts:
- Correct vessel list: Head Office, PMS Kochi, CSD H&R 1/3/4, CSD Champion,
CSD Hanuman, Kavaratti, Laccadives, Thinnakara, Thillaakam, GD3000
- Add System Admin user (admin@pelagia.local / admin1234) via bcrypt
Unit tests:
- po-import-parser: assert on line item .name rather than .description
- po-line-items-editor: fix placeholder text assertions, add .name to
LineItemInput fixtures, add two new GST 0% calculation tests
- validations: add .name to line item fixtures; update createPoSchema
assertions to reference costCentreRef; mark description as optional
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PARTIALLY_CLOSED was missing from the open-filter so affected POs
disappeared from the submitter''s My Orders view entirely, making it
impossible to confirm remaining deliveries.
Also hardens confirmReceipt() against negative delivery quantities
and extends partial-receipt.spec.ts with US-8c/8d/8e covering the
full PARTIALLY_CLOSED revisit flow.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
parseFloat('0') is falsy in JS so `|| 0.18` silently discarded the user's
explicit 0% selection. Replaced with an explicit empty-string guard.
Adds e2e spec gst-rate.spec.ts covering all five GST rates (0/5/12/18/28%).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>