Commit graph

152 commits

Author SHA1 Message Date
e31014d45c docs: document the issue-to-deploy pipeline, staging, and test DB
- App/README.md: add FORGEJO_*/NEXT_PUBLIC_ENV_LABEL env vars and an
  'Operations & Automation' section pointing to automation/README.md.
- App/CLAUDE.md: complete the env var list (AZURE_AD_*, FORGEJO_*, GST_SERVICE_URL,
  NEXT_PUBLIC_ENV_LABEL) and note the prod-mirror test DB used by autofix/staging.
- .env.example: document NEXT_PUBLIC_ENV_LABEL.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 12:07:55 +05:30
b592358db0 feat(app): env-gated banner (EnvBanner) for non-prod environments
Renders a thin fixed banner only when NEXT_PUBLIC_ENV_LABEL is set; production
leaves it unset so nothing shows. Used to mark the staging instance.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 11:56:34 +05:30
080dafb473 feat(automation): add triage phase to issue watcher
Portal issues now file with only the 'portal' label. The watcher runs two phases:
  1. Triage — Claude reads each untriaged 'portal' issue (analysis only), posts a
     requirements-breakdown comment, and routes it to 'claude-queue' (auto-fixable)
     or 'interactive' (needs human steering).
  2. Fix — unchanged; processes 'claude-queue' issues into PRs.

The triage breakdown is posted without the bot marker so the fix stage reads it
back as refined requirements.

PS 5.1 fixes found while validating:
  - Send API bodies as UTF-8 bytes (Invoke-RestMethod mangled non-ASCII, e.g. the
    em-dash in Claude's breakdown, so Forgejo rejected the JSON)
  - Build the labels array body by hand (ConvertTo-Json unwraps a single-element
    array to a scalar, which Forgejo rejects)
  - Triage output via two plain files (label + markdown) instead of one JSON blob
    (embedded-newline markdown broke ConvertFrom-Json)
  - Read triage files as UTF-8; additive label POST + a guard so Set-IssueLabels
    can never wipe an issue's labels

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 04:20:21 +05:30
64634ccb5e Merge branch 'master' into claude/issue-9 2026-06-18 22:34:18 +00:00
Claude (auto-fix)
9adc93e54a fix(receipt): upsert Receipt record on repeat confirmations with notes
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
2026-06-19 04:01:26 +05:30
Claude (auto-fix)
d7be141589 fix(export): include optional line item description in PDF and XLSX exports
The POLineItem model has both a required `name` and an optional `description`
field. The export was only rendering `name` (with description as a fallback),
dropping the optional description entirely when a name was present.

- PDF: renders description in smaller italic text below the item name
- XLSX: appends description on a new line within the cell (wrapText enabled)
- Row height in XLSX now accounts for the extra line when description exists

Fixes #8

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 03:43:49 +05:30
600f637de2 Merge pull request 'fix: Closed PO list filters are wrong for manager and submitter' (#21) from claude/issue-6 into master
Reviewed-on: #21
2026-06-18 22:10:25 +00:00
Claude (auto-fix)
5d3b45a3a4 fix(po-detail): show approval date as PO date on detail screen
The PO date field was only displayed when a submitter explicitly set it.
For approved POs without an explicit date, the approval date is now shown.
Precedence: submitter-set poDate → approvedAt → createdAt (matches the
export route which already used this logic).

Fixes #5
2026-06-19 03:39:19 +05:30
Claude (auto-fix)
a37ca068c2 fix(my-orders): correct closed PO filters for manager and submitter
Managers and superusers were silently filtered to only their own
submitted POs because submitterId: userId was applied unconditionally.
Submitters were also shown MGR_APPROVED, SENT_FOR_PAYMENT,
PAID_DELIVERED and REJECTED orders alongside CLOSED ones.

Fix: managers/superusers see all CLOSED POs (no submitterId filter);
submitters see only their own CLOSED POs.

Fixes #6
2026-06-19 03:34:21 +05:30
Claude (auto-fix)
66f2e133b1 fix(inventory): add items to inventory on PO approval, not on closure
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>
2026-06-19 03:15:56 +05:30
Claude (auto-fix)
25d1164d34 feat(po): allow submitter to set an optional PO date
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>
2026-06-16 13:06:12 +05:30
e1340b9d1e chore(perm): manager permissions fix 2 2026-06-15 12:00:49 +05:30
a88f27431e chore{perm}: Allow managers to confirm receipt 2026-06-15 11:49:14 +05:30
8b6d4e8ea6 feat(automation): issue-to-deploy pipeline — Report Issue button, Claude watcher, tag-triggered deploy
- Report Issue button in portal header files a Forgejo issue (portal + claude-queue labels)
- Windows scheduled watcher runs headless Claude Code on queued issues and opens a PR
- .forgejo/workflows/deploy.yml deploys v* release tags via the pms1 host runner (pm2 restart ppms)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 16:39:43 +05:30
add0f3c19c feat(payments): compulsory payment date when Accounts records payment
- 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>
2026-06-10 08:59:25 +05:30
eb402e03ef fix(profile+vendors): profile reachable for all roles incl SSO; submitter vendor creation
Profile (fixes Safari/SSO no-password redirect):
- User lookup falls back to email when JWT id is stale (SSO users)
- generateDownloadUrl wrapped in try/catch so storage never crashes the page
- Signature gate now uses approve_po permission (approvers only)
- SSO/no-password users see a Set Password form (current-password field hidden)

Vendors:
- New create_vendor permission for all PO roles incl. submitters
- Submitters create UNVERIFIED vendors (no Vendor ID); simple form mode
- verifyVendor action + Verify menu item (manage_vendors)
- Vendors auto-verify when a PO closes with them (receipt confirm + import)
- Add Vendor button on /inventory/vendors

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 18:53:33 +05:30
b5a5097ab5 feat(sidebar): add Sites to Administration section for admin
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 08:49:58 +05:30
025b932f70 feat(sidebar): no Purchasing section for admin; Cost Centres in Administration
PURCHASING_MGMT roles narrowed to MANAGER only, so the entire Purchasing
section disappears for ADMIN (they never needed the /inventory/ browse links).
Cost Centres (/admin/vessels) added to the top of ADMIN_ITEMS.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 08:46:19 +05:30
2c912caedb fix(searchable-select): reposition portal on scroll/resize
Adds scroll (capture) and resize listeners so the fixed-position dropdown
tracks its trigger as the page scrolls.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 06:49:49 +05:30
2057fc2d8d seed(prod): add 3 companies (PMS, HNR, DEI) with full GST/contact details
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 06:42:58 +05:30
6351eaa5e9 feat(items): separate editable/read-only detail pages, same as vendors
/admin/products/[id]   requires manage_products, shows Edit + Toggle
/inventory/items/[id]  accessible to all, cart only, no edit controls

ProductsTable gains detailBase prop so both list pages link correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 06:28:37 +05:30
478f1d1f9c refactor(items): canonical detail route is /inventory/items/[id]
- /inventory/items uses same ProductsTable as /admin/products
- canManage driven by manage_products permission on both pages
- /inventory/items/[id] is the canonical detail page (same content,
  breadcrumb back to /inventory/items)
- /admin/products/[id] redirects to /inventory/items/[id]
- All ProductsTable name links point to /inventory/items/[id]
- Old items-table.tsx (cart-based browse) retired in favour of shared table

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 06:24:46 +05:30
2c364f95e5 feat(products): name is also editable
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 06:18:47 +05:30
7b498a91f8 feat(products): code is editable on edit, name is locked
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 06:18:09 +05:30
80fa1ea63c fix(products): canManage no longer requires ADMIN role
Any user with manage_products permission (including MANAGER)
can now edit, deactivate, and delete products.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 06:17:06 +05:30
982a114eb5 feat(products): edit support on /admin/products; Purchasing Items -> /inventory/items
- updateProduct server action (name + description, code locked)
- EditProductButton dialog in product-form.tsx
- Edit entry wired into ProductActionsMenu
- Sidebar Purchasing Items for Manager/Admin now points to /inventory/items (cart view)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 06:14:15 +05:30
9bbc97b9bd feat(sidebar): add Items (/admin/products) to Administration for Manager
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 06:10:42 +05:30
734f96107f feat(import): upsert ProductVendorPrice from imported PO line items
For each line item with a price and a resolved vendor, upsert a
ProductVendorPrice record (productId + vendorId → price). This keeps
the per-vendor price list in the item catalogue up to date from imports.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 06:07:59 +05:30
0d6df57a88 fix(sidebar): purchasing Vendors links to /inventory, admin to /admin
No mirroring: the two vendor links serve different purposes.
Purchasing -> /inventory/vendors (site selector, distance sort)
Administration -> /admin/vendors (CRUD registry)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 03:08:25 +05:30
cc9c7b7e1f feat(sidebar): add Vendors to Purchasing section for Manager/Admin
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 03:01:48 +05:30
e3851a1799 feat(sidebar+vessels): Purchasing section, split Administration, Cost Centre rename
Sidebar:
- Inventory section renamed to Purchasing
- Manager gets separate Administration section for Vendors only
- Admin gets full Administration (Vendors + Users + Accounting Codes + Companies)
- Sites hidden from Manager when NEXT_PUBLIC_INVENTORY_ENABLED=false
- Cost Centres replaces Vessels in the Purchasing nav link

Admin vessel pages:
- All headings, titles, dialogs, breadcrumbs: Vessels -> Cost Centre
- Error messages updated accordingly

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 02:53:33 +05:30
b2402a7e22 seed(prod): trim SITES to geocoded entries only; update admin email
Removes the 3 Lakshadweep island sites (PMSK/LACD/THKM/KVRT/THNK) that had
no address or coordinates, keeping only the 4 fully-specified sites:
  HOFC  Head Office Mumbai  (19.0449, 73.0758)
  HLDA  Haldia Port         (22.0286, 88.0780)
  KCHI  Kochi               (10.0261, 76.2193)
  PTNA  Patna               (25.6097, 85.1376)

Also updates admin upsert email to admin@pelagiamarine.com.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 02:44:37 +05:30
d4bee878e5 seed(prod): add 4 sites with addresses and geocoordinates
New / updated sites:
- HOFC  Head Office Mumbai   19.0449, 73.0758  Kharghar, Navi Mumbai
- HLDA  Haldia Port          22.0286, 88.0780  Haldia Dock Complex, WB
- KCHI  Kochi                10.0261, 76.2193  LNG Terminal, Puthuvype
- PTNA  Patna                25.6097, 85.1376  Gaighat, Gulzarbagh

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 02:42:38 +05:30
ccc93d40f3 fix(po-number): floor at 9000, imported POs keep original PO number
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 02:33:42 +05:30
6763a60421 fix(export): widen columns and increase row heights to prevent cell cutoff
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 02:29:33 +05:30
ce24539640 fix(line-items): portal dropdown to escape overflow, hide scrollbar
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 02:23:39 +05:30
a9c125c21c fix(searchable-select): compact mode dropdown positioning and group labels
- Compact dropdown is now right-anchored at fixed 380px width so it
  extends leftward from the trigger and doesn't overflow the table edge
- Group headers in compact mode show only the sub-category (strip the
  top-level breadcrumb before the arrow) and are single-line truncated

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 02:19:32 +05:30
fc6f3146d4 fix(permissions): add manage_vessels_accounts to MANAGER role
MANAGER had the Vessels link in the sidebar but lacked the permission,
causing a redirect to dashboard on click.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 02:14:36 +05:30
6a3b371acc fix(po-number): FY format changed to 2024-25 style
PO numbers now end with e.g. PMS/HNR1/200/2025-26

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 01:57:48 +05:30
56b0490229 feat: structured PO numbers, import closed, auto-vendor/product, company code, inventory flag
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 01:56:33 +05:30
4cb927cbd0 feat(companies): add invoiceEmail field separate from contact email
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 01:32:17 +05:30
e308d86e93 feat: Companies — multi-company PO support with admin CRUD and export integration
Schema:
- New Company model (name, gstNumber, address, telephone, mobile, email, invoiceAddress, isActive)
- PurchaseOrder.companyId FK (optional, SET NULL on company delete)
- Migration: 20260530000003_add_company

Admin:
- /admin/companies page with full CRUD (create, edit, deactivate, delete)
- Companies table shows name, GST, contact details, status
- Companies link added to Admin section of sidebar (Briefcase icon)

PO forms (new / edit / import / manager-edit):
- Company dropdown appears at the top of Order Information when companies exist
- Pre-populated with first active company; selection persisted to DB via companyId

Import form:
- parseSheet() now extracts companyName from Excel row 1 (col A)
- Import preview auto-matches detected company name against known companies
- Shows detected name as a hint; user can override before saving

Export (PDF + XLSX):
- Company constants (CO_NAME, CO_ADDR, CO_TEL, INV_ADDR, INV_GST) are now
  derived from the linked Company record when present, falling back to the
  original Pelagia Marine hardcoded defaults when no company is set

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 19:31:34 +05:30
b43d44b59a fix(seed+tests): correct vessel/cost-centre names, update unit tests
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>
2026-05-30 18:50:23 +05:30
280966a369 refactor: revert cost centre to vessels only, remove vessel-site link
Cost Centre on PO forms now shows only Vessels (plain vesselId field).
Sites are a separate concept and not selectable as cost centres.

- PurchaseOrder.vesselId is required again (NOT NULL restored)
- Vessel.siteId and vessel->site relation removed from schema
- DB migration: drops Vessel.siteId column, restores PO.vesselId NOT NULL
- All PO forms (new/edit/import/manager-edit): plain vessel <select> with
  code-prefixed labels (e.g. "HNR1 — HNR 1")
- History, approvals, dashboard, my-orders, payments: back to vesselId
  filter params and po.vessel.name display
- Admin vessels: removed Site column and site-assignment dropdown
- Admin sites detail page: removed "Assigned Vessels" section
- Sites table: removed Vessels count column (no longer linked)
- seed-prod.ts and seed.ts: vessels created without siteId
- SearchableSelect accounting code picker retained from previous commit

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 18:14:24 +05:30
565f9d5833 feat: searchable accounting code picker + cost centres grouped by site
Accounting Code search (new/edit/import/manager-edit PO forms):
- New SearchableSelect component (components/ui/searchable-select.tsx):
  type-to-filter by code or name, results grouped by sub-category with
  sticky headers, highlighted selected item, clear button, Escape/outside-click
  to dismiss
- Replaces the plain <select> for the main Accounting Code field on all PO forms
- LineItemsEditor per-row account column also uses SearchableSelect (compact size)
  when multi-account mode is active

Cost Centre dropdown reorganised by site:
- New type CostCentreGroup replaces flat CostCentreOption
- Each site becomes an <optgroup> label (unselectable); the site itself is the
  first selectable option inside ("Haldia (Site)"), followed by its vessels
- Vessels with no site assigned appear under an "Unassigned Vessels" group
- Shared helpers buildCostCentreGroups() and buildAccountGroups() in
  lib/cost-centre-groups.ts — used by all four PO form pages

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 17:54:43 +05:30
0e3a79ecd4 feat: production seed script for Pelagia Marine (pnpm db:seed:prod)
Idempotent seed with real company data:
- 14 users (SSO/no-password): Accounts, Managers, Technical, Manning
- 7 sites: Head Office (HOFC), PMS Kochi, Laccadives, Haldia,
  Thilakkam, Kavaratti, Thinnakara
- 10 vessels assigned to their respective sites:
  HNR1-4, Champion, Hanunam, Sejal, Sejal 2, GD 3000, Thilakkam
- Full accounting code hierarchy (Rev. 01/251227) — 300+ codes across
  7 top categories via two-pass upsert to wire parent links

Run with: pnpm db:seed:prod

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 04:26:38 +05:30
a1b77d8b00 feat(vessels): editable custom code when creating a vessel
- Add Vessel dialog now shows an editable Code field pre-filled with the
  next auto-generated code (e.g. SITE-004) — user can change it freely
- Edit Vessel dialog keeps the code read-only (changing codes on existing
  data would break PO references)
- createVessel action: uses submitted code if provided, auto-generates if
  left blank, and validates uniqueness before saving

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 04:14:03 +05:30
0d17672ea9 feat(accounts): hierarchical accounting codes with 6-digit format and category tree
- Account model gains parentId (self-referential, 3 levels: TopCategory → SubCategory → Item)
- DB migration: adds parentId FK column to Account table
- Code format changed from PREFIX-NNN to 6-digit numeric (e.g. 100101)
- Seeded all 300+ accounting codes from the official chart (Rev. 01/251227) across
  7 top categories: Capital Expenses, Business Development, Office Admin, Project
  Expenses, Manning, Technical, Bunker/Lubes
- Admin Accounting Code page: collapsible tree view (top category > sub-category > items),
  inline search, Add/Edit dialogs with parent selector and 6-digit code field
- All PO forms (new, edit, import, manager-edit): accounting code dropdown now shows
  only leaf items grouped in <optgroup> by sub-category, labelled "TopCat › SubCat"
- Seed data updated: old flat account codes replaced by mapped leaf codes from new hierarchy

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 03:27:31 +05:30
cc7251e6b7 feat: Cost Centre covers vessels and sites, vessel codes, Accounting Code rename, vessel-site assignment
- Undo Vessel→Cost Centre rename in admin (admin shows "Vessel Management" again)
- Sidebar: "Cost Centres"→"Vessels", "Accounts"→"Accounting Codes"
- PO forms (new/edit/import/manager-edit) now show both Vessels (with code) and Sites in the
  Cost Centre dropdown, encoded as v:<id> / s:<id> via a costCentreRef field
- vesselId on PurchaseOrder is now nullable; siteId is set when a site is the cost centre
- History, approvals, dashboard, my-orders, payments display vessel.name ?? site.name as Cost Centre
- History and approvals cost centre filters use costCentreRef URL param supporting both types
- Admin vessel form: adds Site assignment dropdown
- Admin accounts: renamed to "Accounting Code" throughout (pages, forms, sidebar)
- PO detail and exports: "Account" label renamed to "Accounting Code"
- Site detail: "Assigned Vessels (Cost Centres)" heading; vessel detail breadcrumb fixed
- Create PO links from vessel/site detail use ?costCentreRef= param
- Export routes handle costCentreRef filter param (with legacy vesselId fallback)
- DB migration: ALTER TABLE PurchaseOrder ALTER COLUMN vesselId DROP NOT NULL
- CLAUDE.md updated with Cost Centre Model documentation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 03:04:29 +05:30
3f3e1e6423 feat(admin): confirm activate/deactivate via modal popup across all tables
Replace immediate server action calls with ConfirmDialog modals for
activate/deactivate on all 6 admin tables (users, vendors, vessels,
sites, accounts, products). Delete already used DeleteConfirmDialog;
this adds the same pattern for reversible toggle actions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 03:07:04 +05:30