- 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>
- 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>
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>
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
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>
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
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
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>
- 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>
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>
- 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>
- 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>
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>
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>
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>
/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>
- /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>
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>
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>
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>
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>