Commit graph

189 commits

Author SHA1 Message Date
12e6d16061 feat(automation): test DB mirror + dev-server env for autofix verification
- automation/refresh-test-db.sh: daily pg_dump of prod (pelagia) into a throwaway
  mirror (pelagia_test) on pms1; cron at 03:30. ~10MB, refresh ~1s.
- Autofix clone ~/pelagia-autofix/App/.env points DATABASE_URL at pelagia_test in
  safe dev mode (no Resend/SSO secrets -> console email, local storage), port 3100.
- Fix prompt: Claude may run integration tests against the test DB and start a dev
  server on port 3100 ONLY; stop it by port (fuser -k 3100/tcp), never broad pkill
  (production also runs a next-server on 3000).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 04:49:15 +05:30
3e711a171c feat(automation): port issue watcher to bash for pms1 (cron, 24/7)
- automation/claude-issue-watcher.sh: Linux port of the watcher (curl + jq +
  flock). Same triage + fix phases. On Linux the PS 5.1 encoding/array quirks
  don't apply, so it's simpler.
- Auth preflight: no-ops until Claude Code is signed in on the host (or an
  ANTHROPIC_API_KEY is set), so cron can be enabled before sign-in.
- Runs on pms1 under cron every 10 min; Windows scheduled task is disabled so the
  two machines don't race the Forgejo queue.
- .gitattributes pins *.sh to LF.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 04:32:06 +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
23e5243442 Merge pull request 'fix: Allow attachments (incl. delivery receipt) at delivery confirmation' (#25) from claude/issue-9 into master
Reviewed-on: #25
2026-06-18 22:34:37 +00:00
64634ccb5e Merge branch 'master' into claude/issue-9 2026-06-18 22:34:18 +00:00
69901ba079 Merge pull request 'fix: Exported PO must include line item optional description' (#23) from claude/issue-8 into master
Reviewed-on: #23
2026-06-18 22:32:27 +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
464475f62c Merge pull request 'fix: Approved POs should show approval date as the PO date (screen + export)' (#22) from claude/issue-5 into master
Reviewed-on: #22
2026-06-18 22:10:06 +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
b19ab695eb feat(automation): add manual run-watcher launcher for desktop shortcut
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 03:28:12 +05:30
5a7145e0cb Merge pull request 'fix: Add items to inventory on PO approval, not on closure' (#20) from claude/issue-7 into master
Reviewed-on: #20
2026-06-18 21:53:20 +00:00
06f8f91f1a Merge branch 'master' into claude/issue-7 2026-06-18 21:52:53 +00:00
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
f3557aca97 fix(automation): feed issue comments to Claude; fix PS 5.1 array-unroll bug
- Get-IssueCommentsBlock includes human issue comments in Claude's prompt so
  scope/repro added as comments is acted on (requested for delivery-dropdown #19)
- Critical: capture Api responses to a variable before filtering. Piping the
  Api function's array output straight into Where-Object collapses all issues
  into one object in PS 5.1, so the watcher tried to process #12/#8/#7 at once
- Bot status comments now carry an ASCII <!-- ppms-bot --> marker and are
  filtered out (incl. legacy emoji comments via stable ASCII phrase match) so
  they are never fed back as human input; script kept ASCII-only for ANSI load
- Harden numeric sort/select on issue numbers

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 03:13:34 +05:30
feb6fb745a Merge pull request 'fix: Submitter can set an optional PO date (back/forward-datable)' (#16) from claude/issue-4 into master
Reviewed-on: #16
2026-06-18 21:08:10 +00:00
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
c7a20381f4 Merge branch 'master' of https://git.tunnel.pelagiamarine.com/shad0w/pelagia-portal 2026-06-15 12:01:07 +05:30
e1340b9d1e chore(perm): manager permissions fix 2 2026-06-15 12:00:49 +05:30
8d6ca69edf Merge branch 'master' of https://git.pelagiamarine.com/shad0w/pelagia-portal 2026-06-15 11:58:39 +05:30
0c384d4f86 Merge branch 'master' of https://git.pelagiamarine.com/shad0w/pelagia-portal 2026-06-15 11:51:05 +05:30
a88f27431e chore{perm}: Allow managers to confirm receipt 2026-06-15 11:49:14 +05:30
7a4dab4fe8 Merge pull request 'fix: Add CHANGELOG.md documenting the automated pipeline' (#2) from claude/issue-1 into master
Reviewed-on: #2
2026-06-11 11:36:07 +00:00
cc62a9ddf6 docs(automation): note Forgejo 10 broken-PR quirk and close/reopen fix
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 17:05:52 +05:30
21ead95506 Merge branch 'master' into claude/issue-1 2026-06-11 11:26:26 +00:00
2a9d4f08fa fix(automation): ASCII log prefix to avoid console encoding garble
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 16:50:02 +05:30
Claude (auto-fix)
d4be4ed0de docs: add CHANGELOG.md documenting the automated issue-to-deploy pipeline
Fixes #1
2026-06-11 16:41:52 +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
4c6b9c670f chore(forgejo): add issue template 2026-06-11 16:04:22 +05:30
2a3fad3eb9 mockup(Reports): add graphs for reporting as mockup 2026-06-11 16:04:06 +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