- Reject duplicate site codes per client (case-insensitive); site code is immutable once set
- Delete tombstones the site and requires the DeleteSites permission (Admin, Scheduler)
- GET /api/locations/{id}/open-work-orders returns the open count and ids
- PATCH /api/locations/{id}/contact-info saves contacts and notes from the work-order Site dialog
- Add nullable Locations.Notes, used as the site-level POC notes fallback
Overdue (8) is a dispatcher-assigned type, separate from the derived
past-due overlay. It takes no severity, resolves services and
completion-doc templates from the PM catalog, and filters as its own
type. The past-due flag now narrows a type filter instead of widening it,
and the dashboard breakdown partitions by stored type.
The legacy create paths (WorkOrderDTOs, SyncService, the Blazor
WorkorderService) still write Status without LifecycleStatus. The board
status filter only matched LifecycleStatus. So an open unassigned row of
that kind was left out of the Unassigned tile and its drill-down list,
even though the Open tile in the same response counted it.
ApplyStatusFilter now reads a row with no LifecycleStatus by its legacy
status (LegacyStatus ?? Status), using the Phase0 backfill rules: known
text maps as LifecycleStatusMapper does, and anything else, blank
included, counts as Incomplete. The tile and /board/search share the
predicate, so the count still matches the list it opens.
Work-order requests store the requested increase in RequestedNTE; vendor
portal requests store the requested NTE total. The queue Delta, the
pending and approved exposure totals, the work-order uplift list, the
board summary and the notification Delta now all read one definition
(UpliftAmount) that honours both meanings and translates to SQL.
Approving a work-order request now adds its increase to the dispatch NTE
instead of replacing the NTE with the increase; vendor requests still end
at their requested total.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Unassigned drill-down opens the board with no range, which searches
2000-01-01..2099-12-31 plus undated work. The All time count had no
bounds, so a work order dated outside that window was counted but not
listed. The count now uses the same window.
An explicit date range let every undated, non-terminal work order through,
so Unassigned plus a range still returned all ~1,780 unassigned rows. The
range now matches Schedule On, or the Target Week for week-only rows
(overlap), the same date the weekly board groups by. Undated rows are added
only when the caller sends includeDateless, which the client uses for
searches with no range selected and for the Unassigned queue.
Editing a work order's POC never reached the backend: no update path wrote
PocName/PocPhone/PocNotes, so the optimistic UI edit was lost on refetch and
the completion freeze captured the Site contact instead of the manual value,
and nothing was audited.
- Add tenant-scoped PATCH api/workorders/{id}/poc via new WorkOrderPocService
+ WorkOrderPocDataService: persists the override, stages FieldChanged audit
entries (which also write field locks so sync never overwrites a manual POC),
and enforces row-version concurrency and terminal-status read-only rules.
- Lock semantics (SH-190): a manual POC away from the Site's live contacts is
stored WO-level; an edit equal to a live Site contact (or blanking name+phone)
stores nothing so the WO follows the Site. PocCustomized exposes the state.
- Board projection, completion freeze and create now share one Site-contact
fallback (first non-deleted contact by SiteContactOrder) so a never-overridden
WO keeps following the Site, including at create when the wizard prefills it.
- Route contract baseline gains PATCH {id:int}/poc.
Break collection initializer entries onto one line each in
WorkOrderBoardRegions and WorkOrderBoardSearchTests so the changed-file
formatting gate (dotnet format --verify-no-changes) passes.
Expose workorders/{id}/uplifts list/create/cancel/revoke for the SH-196 dialog, aggregate upliftSummary on board rows, and add service/controller regression tests.
Add set-once IsAddOn with server cutoff at create, board DTO exposure, legacy type-7 backfill, and Types=AddOn search compat. Aligns with FE PR #61 frozen contract.
Past Due must track the deadline (Due Date), not Schedule On. Keep dueDate and scheduledDate PATCH mutations independent so rescheduling alone does not clear Past Due.
Map board PendingUpliftCount through WorkOrderDetailService.MapInfo and ignore soft-deleted dispatches in the aggregate so SH-188 gating is authoritative for board/search/detail.
Expose completedDate on PATCH /workorders/{id}/board so CompDoc can leave legacy EditWorkorder. Allow optional media category on upload, PATCH category afterward, and enforce JPG/PNG/MP4/MOV allowlist (SH-116).
* feat(work-orders): enrich board search overdue filters and 0-based paging
* fix(work-orders): align stacked services with CI build
* fix(tests): pass userDataService in comment service unit test
* fix(work-orders): use dedicated overdue query flag
Stop treating WorkOrderType.Other as an overdue sentinel. Board and advanced search now accept overdue=true while types=Other filters real Other rows; combining both uses OR.
* test(work-orders): cover overdue date/status boundary and Other type-filter
Lock the PR #23 overdue regression boundary through the public advanced
search service. Prove overdue filtering is driven by past-due date plus
non-terminal status, not by the WorkOrderType.Other sentinel:
- Other + future/not-completed excluded from overdue
- past-due + Scheduled included; past-due + Completed/Canceled excluded
- types=[PM, Other] keeps real Other rows and does not pull past-due rows
- assert 0-based paging (Page=0) is preserved alongside overdue/type filters
---------
Co-authored-by: Arthur Bassi <arthur.winiarski.ranger@outlook.com>
Co-authored-by: Alexandre Brandizzi <alex_brandizzi@hotmail.com>
Brings in dev's Phase 5 (PR #17) + vendor PRs (#25/#28/#29) atop the
Phase 6/7 + flagColor base (PR #22). Preserves dev Phase 1-5 behavior and
PR #22 Phase 6/7 + flagColor behavior.
Conflict resolutions (16 files):
- Migrations Phase4_SearchIndexes/.Designer + Phase5_DomainEvents/.Designer:
take dev (Phase4 incl. SQL Server SiteCode/InternalWONumber index-compat
shrink fix; Phase5 identical). ModelSnapshot union: Vendor CompanyId index
+ Phase7 ServiceNotes/ExternalWorkOrderId index.
- ApplicationDbContext: keep dev SiteCode/InternalWONumber MaxLength (Phase1-5
+ unguarded model test) + HEAD CompletionDocTemplate/ExternalWorkOrderId.
- WorkOrderAuditService: unify on dev async staging API; convert Phase6
CompletionService 2 call sites to await StageFieldChangedAsync (drops
HEAD sync duplicate; only callers, no test refs).
- Hosted services: take HEAD (retry-on-failure, coherent with Phase7
WorkOrderJobRunStateAccessor/OpsHealth). Program.cs keeps dev vendor DI
(ClamAV/VendorDocumentScanWorker/ArgumentExceptionFilter) + HEAD Phase7.
- WorkOrderController: keep HEAD Phase6/7 service params + dev doc comment.
- VendorController/WorkOrderBoardCreateService/QueryFilters/appsettings:
union / dev-correct.
- WorkOrderBoardUpdateServiceTests: union of HEAD (Phase6/7+flagColor) and
dev (Phase1-5) test methods.
Verified WorkOrderType.Other (enum 99) is a legit category, not an overdue
sentinel; overdue uses dedicated OperationalFlags.PastDue + IsPastDue, and
'Overdue' is rejected as a WorkOrderType (no PR #23 import needed).
Removed dev duplicate Api.Options.WorkOrderJobRunState (HEAD defines it in
Services.Implementation alongside the Accessor; Services cannot reference Api).
Merge origin/dev (vendor roadmap PRs #28/#29, phases 1-3 PRs #13-15)
into work-orders-phase-4. Conflict in WorkOrderController.cs resolved by
keeping both the Phase 4 board/search endpoint and the dev-side XML doc
comment on GetDispatcherLookups (both additions at the same site).
Migration timestamps remain monotonic and non-overlapping. Phase 4 global
advanced search, search index migrations, and the cross-platform LocalDB
test guard are preserved alongside the merged vendor roadmap and phases 1-3.
Validation (Docker .NET 8 SDK): build 0 errors; 191 tests pass across
all three test projects (64 + 18 + 109).
Harden contextual search on the weekly board and expose paginated cross-week GET /board/search with date presets, FE filter params, SQL indexes, and unit tests.
Restore FlagColor model/API/tests here after the parent structured-notes PR dropped them, so this PR remains the coherent home for the FlagColor column and palette.
Remove FlagColor model/API/tests from this PR so schema and EF model stay aligned with the structured-fields migration. FlagColor remains in the follow-on PR that adds its migration.
Document myWorkOrders overriding dispatchers, weekend dayGroup null contract, and that dispatcher lookups currently return all users. Map service ArgumentException to 400 for consistency.
Persist primary/extra services, service notes, free-text POC, and
tech/vendor notes on create/patch/board/detail instead of embedding
them in description.
Harden contextual search on the weekly board and expose paginated cross-week GET /board/search with date presets, FE filter params, SQL indexes, and unit tests.