Commit graph

195 commits

Author SHA1 Message Date
1a290ea2f7
Merge remote-tracking branch 'origin/dev' into HEAD 2026-09-17 12:50:09 -04:00
Adam Moussa
1f905fc7dd
Merge branch 'dev' into feat/ab/sh-329-account-owner 2026-09-17 12:36:26 -04:00
Alexandre Brandizzi
679822733a
Merge branch 'dev' into feat/ab/sh-210-uplift-decisions 2026-09-17 12:44:12 -03:00
Alexandre Brandizzi
f4860a3dd9
Merge branch 'dev' into feat/ab/sh-348-region-filter 2026-09-17 12:36:15 -03:00
Adam Moussa
ef371b5917
Merge branch 'dev' into feat/ab/sh-210-uplift-decisions 2026-09-17 11:35:00 -04:00
Alexandre Brandizzi
1eadb82f28
Merge branch 'dev' into feat/ab/sh-210-uplift-decisions 2026-09-17 12:30:20 -03:00
Alexandre Brandizzi
564bd70301 fix(dashboard): scope Trend by picker and admit Scheduler to dispatcher picker
ResolveDispatcherScope now admits the Scheduler role, which owns the
viewAllDispatchersOnDashboard permission, so it can load Stats, Workload,
Performance, Regions and Trend instead of being denied.

GetTrendAsync now resolves scope via the shared ResolveDispatcherScope so a
picker DispatcherId selection scopes Trend consistently with the other
endpoints and unauthorized roles fail closed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-17 03:37:36 -03:00
Alexandre Brandizzi
5c93e4ecec Merge remote-tracking branch 'origin/dev' into feat/ab/sh-348-region-filter
# Conflicts:
#	SeaHaven.Services/Helpers/DashboardRegions.cs
2026-09-17 02:20:44 -03:00
Alexandre Brandizzi
f564e1b112 Merge remote-tracking branch 'origin/dev' into feat/ab/sh-347-dashboard-contract
# Conflicts:
#	Api.SeaHavenIndustries.Tests/DashboardServiceTests.cs
2026-09-17 02:18:22 -03:00
Alexandre Brandizzi
daf3ed9210 fix(team-members): map duplicate-email race to conflict error (SH-325)
CreateAsync checks FindByEmailAsync and then inserts, so two concurrent
creates with the same email can both pass the check and hit the unique
user-name index. That DbUpdateException was unhandled and surfaced as a
500. Catch it at the CreateAsync call and return the existing
"Email is already in use." message, matching the check-then-insert
converge pattern already used by SetOverrideCoreAsync.
2026-09-17 01:40:40 -03:00
Adam Moussa
7d728d9101
Merge branch 'dev' into feat/ab/sh-187-service-picker 2026-09-17 00:20:59 -04:00
Alexandre Brandizzi
2e983b1f6a
Merge branch 'dev' into feat/ab/sh-303-services-registry 2026-09-17 01:12:07 -03:00
Alexandre Brandizzi
bd98ea5629 merge: carry approval queue contract fields into decisions 2026-09-16 22:32:35 -03:00
Alexandre Brandizzi
e0e45d5ed3 feat(uplifts): expose approval queue contract fields (SH-208) 2026-09-16 22:32:23 -03:00
Alexandre Brandizzi
65b04687bc fix(work-orders): honor edited service labels 2026-09-16 22:30:32 -03:00
Alexandre Brandizzi
b3e9a2eec3 fix(services): allow admins to reactivate services 2026-09-16 22:30:32 -03:00
Alexandre Brandizzi
8acc580c5b
Merge branch 'dev' into feat/ab/sh-353-dashboard-kpis-stacked 2026-09-16 21:56:23 -03:00
Alexandre Brandizzi
db8470fbf9 chore(team-members): sync with dev (SH-325) 2026-09-16 21:52:44 -03:00
Alexandre Brandizzi
dca8d898cb feat(dashboard): add scoped metrics contract (SH-347) 2026-09-16 21:37:17 -03:00
Alexandre Brandizzi
738c9eaf45 feat(work-orders): add region filtering (SH-348) 2026-09-16 21:27:05 -03:00
Adam Moussa
f6bd779fe0
Merge branch 'dev' into feat/ab/sh-353-dashboard-kpis-stacked 2026-09-16 20:00:32 -04:00
Adam Moussa
e7e196caba
Merge branch 'dev' into feat/ab/sh-329-account-owner 2026-09-16 20:00:18 -04:00
Alexandre Brandizzi
9bf45d65ff
Merge branch 'dev' into feat/ab/sh-330-sites-list 2026-09-16 20:58:16 -03:00
Alexandre Brandizzi
660ebac628 feat(locations): support site registry queries (SH-330) 2026-09-16 20:45:15 -03:00
Alexandre Brandizzi
21b7083160
Merge branch 'dev' into feat/ab/sh-328-permission-overrides 2026-09-16 20:44:20 -03:00
Alexandre Brandizzi
fed45f423e
Merge branch 'dev' into feat/ab/sh-350-dashboard-trend 2026-09-16 20:26:23 -03:00
Alexandre Brandizzi
d366f319e9 feat(uplifts): add approval decision actions (SH-210) 2026-09-16 20:11:26 -03:00
Alexandre Brandizzi
3cb1e3e3f3 feat(uplifts): add approval queue read contract (SH-207) 2026-09-16 20:03:35 -03:00
Alexandre Brandizzi
5877f7817f fix(dashboard): bucket trend by calendar ScheduledDate (SH-350)
ScheduledDate is persisted as a midnight calendar value (board create writes
request.ScheduledDate.Value.Date; board patch writes the parsed .Date into a
datetime2 column with no offset). GetTrendAsync treated it as a UTC instant and
converted to America/New_York, so midnight became 19:00/20:00 the previous day
and every board-scheduled work order fell into the prior bucket: a job scheduled
today read as yesterday and overdue, and the Today bucket showed zero.

Bucket by DateOnly.FromDateTime(scheduled.Date) with no conversion, matching
DashboardMetrics and WorkOrderDerivedFields, so Trend and Stats agree on the
same rows. Rewrite the daily and yearly trend tests to assert calendar-date
classification (the removed conversion had encoded the shift into their
expectations) and add a regression test that a midnight-today work order stays
in the Today bucket and is not overdue.
2026-09-16 19:57:09 -03:00
Alexandre Brandizzi
7947e2e77d feat(dashboard): expose KPI counts (SH-353) 2026-09-16 19:23:53 -03:00
Alexandre Brandizzi
fc5c7d5ca4 feat(team-members): support pending member creation (SH-325) 2026-09-16 19:14:36 -03:00
Alexandre Brandizzi
9d7efa34a6 feat(dashboard): add trend metrics (SH-350) 2026-09-16 18:42:26 -03:00
Alexandre Brandizzi
ca4d4833ff feat(permissions): protect configured account owner (SH-329) 2026-09-16 18:26:20 -03:00
Alexandre Brandizzi
3358ea5058 feat(dashboard): add vendor insights (SH-349) 2026-09-16 18:10:42 -03:00
Alexandre Brandizzi
d4afcced87 feat(dashboard): add regional work order metrics (SH-348) 2026-09-16 18:03:38 -03:00
Alexandre Brandizzi
33f517620b feat(work-orders): link service selections to registry 2026-09-16 18:02:57 -03:00
Alexandre Brandizzi
441735d39d feat(permissions): expose team member permission overrides (SH-328) 2026-09-16 18:02:02 -03:00
Alexandre Brandizzi
0194748e3b feat(dashboard): add dispatcher performance (SH-347) 2026-09-16 17:58:08 -03:00
Alexandre Brandizzi
d6c3cd2e24 feat(permissions): add team member permission policy foundation (SH-327) 2026-09-16 17:48:37 -03:00
Alexandre Brandizzi
9b39d0e5ec feat(dashboard): add dispatcher workload (SH-346) 2026-09-16 17:43:49 -03:00
Alexandre Brandizzi
dec8b15278 fix(services): translate duplicate name races 2026-09-16 17:31:21 -03:00
Alexandre Brandizzi
a2e749c72d feat(dashboard): add core dashboard metrics (SH-343) 2026-09-16 17:28:21 -03:00
Alexandre Brandizzi
45f98e8154 Merge remote-tracking branch 'origin/dev' into feat/ab/sh-303-services-registry
# Conflicts:
#	Data.SeaHavenIndustries/Auth/ApplicationDbContext.cs
2026-09-16 17:15:38 -03:00
Alexandre Brandizzi
efd13b6f60 fix(dashboard): scope stats to authenticated accounts (SH-336) 2026-09-16 17:12:03 -03:00
Alexandre Brandizzi
06f9450485 feat(services): add global services registry 2026-09-16 17:07:59 -03:00
Alexandre Brandizzi
3047c2ba59
Merge branch 'dev' into feat/ab/sh-278-vendor-area 2026-09-16 17:00:27 -03:00
Alexandre Brandizzi
4b772c8db3
fix(work-orders): keep SH placeholder WO numbers and block downgrades (#123)
Some checks are pending
Validate and deploy / Validate deployable source bundle (push) Waiting to run
Validate and deploy / Deploy shoc-backend-dev through Terraform (push) Blocked by required conditions
Validate and deploy / Deploy shoc-backend-staging to Elastic Beanstalk (push) Blocked by required conditions
SH-320: the WO number normalizer stripped every non-digit, so a manually
entered SH placeholder (e.g. SH00001) was saved as 00000000001 on both
create and patch. Keep the SH prefix, and reject replacing a saved real
APM number with an SH placeholder.
2026-09-16 15:01:10 -03:00
Alexandre Brandizzi
caba84ea08
fix(work-orders): reject forged automatic lifecycle statuses on board patch (SH-357, SH-358) (#120)
Incomplete and Scheduled are derived by the server. A direct lifecycleStatus
PATCH may only restate the status derivation already produced; any other
request to move a work order into an automatic state returns the stable
AutomaticLifecycleStatus validation error and leaves status and audit untouched.
2026-09-16 14:41:23 -03:00
Alexandre Brandizzi
8515676f4d feat(vendors): add admin-assigned vendor company Area
Seed an organization-wide Area catalogue (East, Central, West, California)
with stable ids, add a nullable AreaId to VendorCompany, allow only Admins
to change it through the roster endpoints, expose areas facet metadata and
an areas[n] company-directory filter with the __unassigned__ sentinel.
2026-09-16 11:34:45 -03:00
Alexandre Brandizzi
4872fe5ba1 feat(locations): manage ordered site contacts 2026-09-15 19:03:54 -03:00