- Delete /inventory/items/[id] — items expand inline in the list - Move SiteSelect from deleted [id] folder to components/inventory/site-select - Fix admin product detail page import to use new shared path - Fix items-table: Fragment key prop, restore Link import, plain text item names - Fix vendor-items-table: remove broken link to deleted item detail page Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
13 KiB
13 KiB
Pelagia Portal — Build Progress
Last updated: 2026-05-05
Legend: ✅ Complete · ⚠️ Partial (works but incomplete) · ❌ Not started
Infrastructure & Config
| Item | Status | Notes |
|---|---|---|
| Next.js 15 App Router project | ✅ | Turbopack dev, strict TS |
| Tailwind CSS v4 + design tokens | ✅ | Colour palette matches spec |
| Prisma schema — all models | ✅ | Product, gstRate, piQuotationNo/Date, requisitionNo/Date, placeOfDelivery, tcDelivery/tcDispatch/tcInspection/tcTransitInsurance/tcPaymentTerms/tcOthers, address/gstin/contactMobile on Vendor — all migrated (latest: structured_tc_fields) |
| Database seed script | ✅ | 5 users, 3 vessels, 3 accounts, 3 vendors, 3 sample POs, 4 products |
| Dev / production environment split | ✅ | NODE_ENV gates R2 vs local storage, Resend vs console log |
.env.example + .env / .env.local docs |
✅ | README covers full setup |
| README with dev + prod setup guide | ✅ | |
| CI/CD (GitHub Actions) | ❌ | No workflow files yet |
Authentication & Authorisation
| Item | Status | Notes |
|---|---|---|
| Login page (credentials) | ✅ | Email + password, bcrypt hash |
| NextAuth.js v5 session | ✅ | Database sessions, role in JWT |
| Auth middleware (route protection) | ✅ | Redirects unauthenticated to /login |
Role permissions matrix (lib/permissions.ts) |
✅ | All 7 roles; manage_products added for Admin |
| SSO / Azure AD login | ❌ | Open question — credentials only for v1 |
PO State Machine (lib/po-state-machine.ts)
| Item | Status | Notes |
|---|---|---|
| All 10 statuses defined | ✅ | |
| All transitions with role guards | ✅ | |
canPerformAction, getAvailableActions helpers |
✅ | |
requiresNote helper |
✅ | |
| Unit tests | ✅ | tests/unit/po-state-machine.test.ts |
Email Notifications (lib/notifier.ts)
| Item | Status | Notes |
|---|---|---|
| Notifier module (Resend in prod, console in dev) | ✅ | |
| Email templates (all 7 events) | ✅ | React Email components in /emails/ |
| Notify on PO submitted | ✅ | Notifies managers + submitter (confirmation) |
| Notify on PO approved / rejected / edits requested | ✅ | Per notification matrix |
| Notify on vendor ID requested / provided | ✅ | |
| Notify on payment processed | ✅ | Notifies managers + accounts on processing; submitter + managers on confirmed |
| Notify on receipt confirmed | ✅ | Notifies managers + accounts |
File Storage (lib/storage.ts)
| Item | Status | Notes |
|---|---|---|
Dev local storage (/api/files/dev/[...key]) |
✅ | Auth-gated, path-traversal protected |
| Prod Cloudflare R2 presigned URLs | ✅ | Upload + download URL generation |
Sign API (/api/files/sign) |
✅ | Returns { uploadUrl, key } |
| File upload UI on New PO form | ✅ | FileUploader component + uploadAndLinkFiles utility; PO created first, then files signed+uploaded+linked |
| File upload UI on Receipt form | ✅ | Same pattern, type "receipt" |
| Document download links on PO detail | ✅ | PoDetail made async; generateDownloadUrl called server-side; filenames are clickable links |
Pages & Server Actions
Login
| Item | Status |
|---|---|
| Login page + credentials form | ✅ |
Dashboard
| Item | Status | Notes |
|---|---|---|
| Submitter dashboard (stat cards + New PO CTA) | ✅ | Recent orders table; link to My Orders |
| Manager dashboard (stat cards) | ✅ | |
| Manager dashboard — approved POs listing | ✅ | Recent approved/in-progress POs table with vessel, status, amount |
| Manager dashboard — spend by vessel breakdown | ✅ | Recharts bar chart (top 5 vessels) |
| Manager spend-by-vessel bar chart | ✅ | SpendCharts component using Recharts |
| Manager spend-by-month bar chart | ✅ | Last 12 months, bar chart |
| Accounts dashboard (stat cards) | ✅ | |
| Auditor / Admin / generic dashboard | ✅ | Single total-count card |
New PO
| Item | Status | Notes |
|---|---|---|
| Form (title, vessel, account, vendor, project code, date) | ✅ | |
| Line items — UoM dropdown (15 options) | ✅ | Replaces free-text unit field |
| Line items — Size field | ✅ | Optional free-text |
| Line items — GST rate per item (0 / 5 / 12 / 18 / 28%) | ✅ | Default 18%; taxable / GST / grand-total breakdown shown live in editor |
| PI / Quotation No. + Date | ✅ | Separate section on form |
| Vessel / Office Requisition No. + Date | ✅ | Separate section on form |
| Place of Delivery | ✅ | Pre-filled with company delivery address; editable |
| Terms & Conditions — structured fields | ✅ | Fixed line 1 (read-only); separate inputs for Delivery, Dispatch Instructions, Inspection, Transit Insurance, Payment Terms, Others (multiline); all pre-filled with defaults |
| Currency defaults to INR | ✅ | Changed from USD → INR throughout |
| Save as draft | ✅ | |
| Submit for approval (→ MGR_REVIEW) | ✅ | |
| Document file upload | ✅ | Drag-and-drop + click; signed upload after PO creation |
PO Detail (/po/[id])
| Item | Status | Notes |
|---|---|---|
| Full detail view (info, vendor, line items, activity trail) | ✅ | |
| New fields displayed (PI/Quotation, Requisition, Delivery, Approved By) | ✅ | |
| Line items with GST breakdown (taxable / GST / grand total) | ✅ | |
| Vendor detail (address, GSTIN, contact name + mobile + email) | ✅ | |
| Terms & Conditions block (structured display) | ✅ | Fixed line 1 always shown; each labeled field (Delivery, Dispatch, etc.) on its own line |
| Export PDF button | ✅ | /api/po/[id]/export?format=pdf — auto-triggers print dialog; matches Sample_PO layout |
| Export XLSX button | ✅ | /api/po/[id]/export?format=xlsx — SheetJS; matches Sample_PO column layout |
| Confirm Receipt CTA (PAID_DELIVERED state) | ✅ | |
| Document download links | ✅ | Clickable links with server-generated presigned/dev URLs |
| Edit PO link (DRAFT / EDITS_REQUESTED) | ✅ |
PO Edit (/po/[id]/edit)
| Item | Status | Notes |
|---|---|---|
| Edit page | ✅ | Pre-populated form including all new fields |
| Update draft action | ✅ | |
| Resubmit after edits | ✅ | Shows manager note banner + Resubmit button |
Vendor ID Flow
| Item | Status | Notes |
|---|---|---|
| Request vendor ID action (manager) | ✅ | Sets status to VENDOR_ID_PENDING |
| Provide vendor ID UI (submitter / manager) | ✅ | Inline form on PO detail for VENDOR_ID_PENDING |
| Provide vendor ID server action | ✅ | Transitions back to MGR_REVIEW, notifies managers |
Approvals
| Item | Status | Notes |
|---|---|---|
| Approval queue list | ✅ | |
| PO detail + decision view | ✅ | |
| Approve / Approve+Note actions | ✅ | |
| Reject action | ✅ | |
| Request edits action | ✅ | |
| Request vendor ID action | ✅ | |
| Manager edit line items (amber edit mode) | ✅ | Saves original snapshot to POAction; diff shown with strike-through |
| Search / filter (PO number, vessel, submitter, date) | ✅ | URL search params; ApprovalsSearch client component |
Payments
| Item | Status | Notes |
|---|---|---|
| Payment queue list (MGR_APPROVED + SENT_FOR_PAYMENT) | ✅ | |
| Start payment processing (MGR_APPROVED → SENT_FOR_PAYMENT) | ✅ | Step 1 |
| Confirm payment sent with ref (SENT_FOR_PAYMENT → PAID_DELIVERED) | ✅ | Step 2 — auto-updates Product.lastPrice for linked line items |
My Orders (/my-orders)
| Item | Status | Notes |
|---|---|---|
| My Orders page — all POs with open/past grouping | ✅ | Links to individual PO detail; shows manager note inline |
Receipt Confirmation
| Item | Status | Notes |
|---|---|---|
| Notes + file receipt confirmation | ✅ | Closes PO to CLOSED; optional file attachment via FileUploader |
History
| Item | Status | Notes |
|---|---|---|
| All-POs list (latest 200 by default) | ✅ | |
| CSV export | ✅ | Respects active filters |
| PDF export (bulk) | ✅ | Print-optimised HTML page (/api/reports/export?format=pdf); auto-triggers browser print dialog |
| Date range filter | ✅ | URL search params; HistoryFilters client component |
| Vessel / status filters | ✅ | Same component |
Admin — User Management
| Item | Status | Notes |
|---|---|---|
| User list | ✅ | |
| Add user form + action | ✅ | AdminDialog modal; bcrypt password hash |
| Edit user form + action | ✅ | Optional password change |
| Deactivate / reactivate user | ✅ | Cannot deactivate own account |
Admin — Vendor Management
| Item | Status | Notes |
|---|---|---|
| Vendor list | ✅ | |
| Add vendor form + action | ✅ | AdminDialog modal; sets isVerified if vendorId provided |
| Edit vendor form + action | ✅ | Includes address, GSTIN, contact mobile |
| Deactivate / reactivate vendor | ✅ |
Admin — Vessel Management
| Item | Status | Notes |
|---|---|---|
| Vessel list page | ✅ | /admin/vessels |
| Add vessel form + action | ✅ | IMO number uniqueness check |
| Edit vessel form + action | ✅ | |
| Deactivate / reactivate vessel | ✅ |
Admin — Account Management
| Item | Status | Notes |
|---|---|---|
| Account list page | ✅ | /admin/accounts |
| Add account form + action | ✅ | Code uniqueness check |
| Edit account form + action | ✅ | |
| Deactivate / reactivate account | ✅ |
Admin — Product Catalogue (/admin/products)
| Item | Status | Notes |
|---|---|---|
| Product list (code, name, last price, last vendor) | ✅ | Last price/vendor read-only — auto-populated on payment |
| Create product action | ✅ | Code must be unique |
| Toggle active/inactive action | ✅ | |
| Add product form (UI) | ✅ | AdminDialog modal wired to existing createProduct action |
Type Safety
| Item | Status | Notes |
|---|---|---|
Discriminated union narrowing in approval-actions.tsx |
✅ | Typed as { ok: true } | { error: string } | undefined, checked with "error" in result |
Union narrowing in receipt-form.tsx |
✅ | |
Union narrowing in new-po-form.tsx |
✅ | |
Buffer type in api/files/dev/route.ts |
✅ | Cast to Uint8Array |
| New PO fields in Prisma types | ⚠️ | Migration applied; Prisma client types stale — resolve by restarting dev server and running pnpm db:generate |
Testing
| Item | Status | Notes |
|---|---|---|
| Unit: state machine | ✅ | tests/unit/po-state-machine.test.ts — 21 tests |
| Unit: permissions | ✅ | tests/unit/permissions.test.ts — 11 tests |
| Unit: utility functions | ✅ | tests/unit/utils.test.ts — 17 tests (formatCurrency INR, formatDate, generatePoNumber, status labels/variants) |
| Unit: Zod validation schemas | ✅ | tests/unit/validations.test.ts — 24 tests (createPoSchema, lineItemSchema, TC fields, defaults) |
| Component: PoStatusBadge | ✅ | tests/unit/po-status-badge.test.tsx — 17 tests (all 10 statuses) |
| Component: LineItemsEditor | ✅ | tests/unit/po-line-items-editor.test.tsx — 20 tests (add/remove rows, GST calc, totals, read-only, diff mode) |
| Integration: PO creation (S-01, S-02, S-03) | ✅ | tests/integration/create-po.test.ts — 9 tests; uses real DB + mocked auth/notifier |
| Integration: Approval actions (M-02, M-03, M-04, S-06, S-07) | ✅ | tests/integration/approval-actions.test.ts — 14 tests |
| Integration: Payment actions (A-01, A-02) | ✅ | tests/integration/payment-actions.test.ts — 8 tests |
| E2E: authentication flow | ✅ | tests/e2e/auth.spec.ts — 6 tests |
| E2E: submitter journey (S-01 to S-08) | ✅ | tests/e2e/submitter-journey.spec.ts — 8 tests |
| E2E: manager approvals (M-01 to M-04) | ✅ | tests/e2e/manager-approvals.spec.ts — 9 tests |
| E2E: accounts payment (A-01, A-02) | ✅ | tests/e2e/accounts-payment.spec.ts — 6 tests |
| E2E: PO export (PDF + XLSX) | ✅ | tests/e2e/po-export.spec.ts — 8 tests (buttons, endpoints, content, auth) |
| Accessibility (axe-core + Playwright) | ❌ | Not yet written |
Summary
| Category | Total items tracked | ✅ Done | ⚠️ Partial | ❌ Pending |
|---|---|---|---|---|
| Infrastructure | 8 | 7 | 0 | 1 |
| Auth & Permissions | 5 | 4 | 0 | 1 |
| State Machine | 5 | 5 | 0 | 0 |
| Email Notifications | 7 | 7 | 0 | 0 |
| File Storage | 6 | 6 | 0 | 0 |
| Pages & Actions | 83 | 83 | 0 | 0 |
| Type Safety | 5 | 4 | 1 | 0 |
| Testing | 15 | 14 | 0 | 1 |
| Total | 134 | 130 (97%) | 1 (1%) | 3 (2%) |
Remaining Items
- Prisma client regeneration — restart dev server, then
pnpm db:generate(DLL was locked during the last generate; migration is fully applied, no data loss) - CI/CD — GitHub Actions workflow: lint, type-check, test, build on PR; deploy on merge
- Accessibility tests — axe-core + Playwright
- SSO / Azure AD — credentials-only for v1; open question for v2
Not in Spec (deferred)
- SSO / Azure AD login
- Discount field on PO
- Account Group / Account Code hierarchy (codes currently flat)
- Cost centre vs vessel distinction (currently same entity)
- Vendor deactivation cascade — warn if vendor has open POs
- Approval queue — show VENDOR_ID_PENDING alongside MGR_REVIEW
- Vendor required before approval can be granted (currently advisory only)