Commit graph

23 commits

Author SHA1 Message Date
Arthur Bassi
2f4b783615 fix(uplifts): open evidence by work-order access and keep every file
Auto-approved evidence was hidden because download checked the approval tier. Viewers of the work order can open it, and a request can store more than one scanned document.
2026-09-28 16:24:26 -03:00
Arthur Bassi
31dd2d5dcd merge(main): keep uplift evidence on the current work-order routes
The route contract keeps the poc endpoint from main and the uplift evidence routes from this branch. Create still passes the scanned evidence document through the locked mutation.
2026-09-28 15:56:45 -03:00
Alexandre Brandizzi
e941e055b7 Merge remote-tracking branch 'origin/main' into fix/ab/sh-407-cancel-wo-cancels-uplift 2026-09-25 19:49:50 -03:00
Alexandre Brandizzi
a32471d4c0 Serialize sync cancels and vendor uplift requests on the work order lock
The legacy ingest batch holds the per-work-order lock, taken in id order,
for every work order it may cancel until the batch commits. A vendor
uplift request now runs under the same lock. Uplift creation on both
routes refuses a work order cancelled by either lifecycle or status text,
so a request can neither slip past a cancel nor land after one.
2026-09-25 19:37:08 -03:00
Alexandre Brandizzi
99499c3281 Cancel pending uplifts when the CRM cancels a work order
The webhook and reconciliation saves now stage the same pending-uplift
cancellation, with its own sync audit row, as the board cancel. The rule
and the write live in one data-layer helper so the paths cannot drift.
2026-09-25 18:48:44 -03:00
Alexandre Brandizzi
185c84dd8c fix(uplifts): refuse admin revoke of an auto-approved uplift
An admin revoke overturns a human decision, so admins may revoke only
admin-approved uplifts. The work-order revoke path let an admin revoke an
auto-approved uplift they had requested themselves. Both revoke endpoints
now refuse it; dispatchers keep revoking their own auto-approved uplifts.
2026-09-25 18:07:33 -03:00
Alexandre Brandizzi
beb091fcc8 Merge remote-tracking branch 'origin/main' into lane/sh-327
# Conflicts:
#	Api.SeaHavenIndustries.Tests/WorkOrderUpliftControllerTests.cs
2026-09-24 23:00:18 -03:00
Alexandre Brandizzi
cc7cda4818 Merge remote-tracking branch 'origin/main' into lane/sh-327 2026-09-24 22:28:15 -03:00
Alexandre Brandizzi
24ad21d7f2 Merge remote-tracking branch 'origin/main' into lane/sh-387 2026-09-24 22:25:54 -03:00
Alexandre Brandizzi
89376e99e4 fix(uplifts): resolve work-order uplifts through owned dispatches (SH-393)
Board create left the new primary dispatch with no WorkOrderId, so uplifts
created on those work orders were written to a dispatch the work order's
uplift reads never resolve: not listed, allowance never consumed, queue WO
number blank. The same orphan made ApptDate/vendor patches fail with
"A primary dispatch is required".

- Board create backfills Dispatch.WorkOrderId after the first save.
- Uplift create resolves its dispatch through the read-side scope
  (non-deleted, owned or linked); otherwise the stable
  "no primary dispatch" error.
- Data-only migration assigns existing orphaned primaries to the single
  work order naming them primary; idempotent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 21:22:13 -03:00
Arthur Bassi
31d4352a23 fix(work-orders): accept a scanned uplift evidence file (SH-388)
Dispatchers can attach one evidence file, and create links it only
after that document has passed scanning.
2026-09-24 14:34:07 -03:00
Alexandre Brandizzi
8af9ad076f fix: map concurrent uplift inserts to conflict 2026-09-23 01:26:15 -03:00
Alexandre Brandizzi
0b39d92723 Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	SeaHavenIndustries.Tests/WorkOrderUpliftServiceTests.cs
2026-09-23 00:57:01 -03:00
Alexandre Brandizzi
ff6a5945f1 fix(uplifts): honor current permissions and denial contract 2026-09-22 23:24:17 -03:00
Alexandre Brandizzi
9156107e72 fix(uplifts): enforce request permission at service boundary 2026-09-22 23:09:47 -03:00
Alexandre Brandizzi
5c5c01b2e8 fix(uplifts): attribute audit to requested work order
Use the operation work order when staging uplift audit logs so a dispatch linked through DispatchWorkOrders cannot write the event to its primary work order. Add coverage for the cross-work-order fallback case.
2026-09-22 21:29:35 -03:00
Alexandre Brandizzi
d282799127 Fix SH-387 uplift creation without primary dispatch 2026-09-22 16:44:31 -03:00
arthur.bassi
8c44fa746e merge origin/feature/sh-196-wo-uplifts 2026-08-18 17:44:40 -03:00
Alexandre Brandizzi
2327097d5e fix(work-orders): symmetric NTE release, terminal guard, serialized cancel (SH-196)
Three contract gaps found reviewing the frontend consumer:

- Revoking an auto-approved uplift never restored the dispatch NTE. Create
  raises NTE for both auto-approved and approved requests, but revoke restored
  it only for Approved, so the allowance was freed while the NTE stayed raised
  and every create -> auto-approve -> revoke cycle compounded the inflation.
  Revoke now compensates for NoApprovalRequired symmetrically.
- Revoke and cancel had no work-order lifecycle check, so a direct API call
  could still mutate uplifts on a Completed or Canceled work order; the board
  dialog's read-only state is UX only. Both now reject terminal work orders in
  the service.
- WorkOrderBoardCancelService read the pending-uplift list outside any gate, so
  an in-flight create could commit after that read and leave a pending uplift on
  a Canceled work order. The cancel flow now runs inside the same per-work-order
  gate as create, so the pending read, withdrawal and status audit serialize
  against it.
2026-08-18 17:41:14 -03:00
arthur.bassi
5ea5a1d702 fix(work-orders): restore NTE on auto-approved revoke and serialize cancel 2026-08-18 17:39:11 -03:00
arthur.bassi
aeface594a fix(work-orders): serialize uplift create and atomic cancel (SH-196) 2026-08-18 10:20:05 -03:00
arthur.bassi
4c15669aff fix(work-orders): enforce SH-196 cumulative allowance and one pending per WO
Auto-approval now uses the WO-scoped $500/$5,000 Emergency cap instead of dispatch NTE, rejects a second open request across dispatches, and cancelling a WO withdraws pending uplifts with audit.
2026-08-14 10:36:35 -03:00
arthur.bassi
b81cfbb005 feat(work-orders): WO-scoped uplift endpoints and board summary (SH-196)
Expose workorders/{id}/uplifts list/create/cancel/revoke for the SH-196 dialog, aggregate upliftSummary on board rows, and add service/controller regression tests.
2026-08-13 14:49:56 -03:00