Commit graph

33 commits

Author SHA1 Message Date
Alexandre Brandizzi
e09ef061d1 Merge remote-tracking branch 'origin/main' into feat/ab/sh-385-invite-registration
# Conflicts:
#	Api.SeaHavenIndustries/Controllers/TeamMemberController.cs
2026-09-25 12:45:03 -03:00
Alexandre Brandizzi
c0ae8479ce feat(team-members): invite registration with emailed code confirmation (SH-385) 2026-09-25 11:49:10 -03:00
Alexandre Brandizzi
c3865e56ac Sites API: site code uniqueness, soft delete with role check, open work orders, site notes
- 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
2026-09-25 11:19:29 -03:00
Alexandre Brandizzi
4872fe5ba1 feat(locations): manage ordered site contacts 2026-09-15 19:03:54 -03:00
Arthur Bassi
4e4bb0ca90 fix(locations): reject unparseable accountId and forward cancellation
Blank accountId stays optional; nonblank parse failures return 400. Account lookup uses ExistsActiveAsync with the request token.
2026-08-26 14:18:38 -03:00
Arthur Bassi
2e56ec7678 fix(work-orders): keep location account server-owned and forward create cancellation
Stop client writes from changing Locations.AccountId, make the SH-221 migration discoverable, and thread the board-create CancellationToken through lookup and persistence.
2026-08-26 10:00:02 -03:00
Arthur Bassi
61923b2a7d feat(work-orders): stamp board create account from location
Org-wide create no longer depends on customer name. POST /workorders/board requires locationId and stamps WorkOrder.AccountId from Location.AccountId.
2026-08-26 09:12:48 -03:00
Alexandre Brandizzi
7a0856ddf7 feat(vendors): confirm-to-deactivate with open work orders (SH-254)
SH-44 and SH-82 both left "blocks, or requires explicit confirmation" to
be decided with the team, and the implementation took the blocking
branch. SH-254 settles it the other way: the approved design offers
"Deactivate anyway" beside the list of open work orders.

Deactivation with open work orders is now permitted, but only when the
caller says it has shown them: ConfirmOpenWorkOrders on the update DTO
and a confirmOpenWorkOrders query parameter on the delete route. Absent
the flag the existing guard still throws, so nothing deactivates by
accident and no caller loses the check by omission.

confirmOpenWorkOrders is a required parameter on DeleteVendorAsync
rather than an optional one, so every call site states its intent.
2026-08-19 13:31:16 -03:00
Arthur Bassi
1edcf479ae fix(work-orders): apply account scope across create and reads [SH-221]
Stamp WorkOrder.AccountId on all create paths and filter board/list/search/detail by server-derived account claims so scoped callers cannot cross accounts.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-11 10:45:37 -03:00
Arthur Bassi
ea2dedf579 !fix(work-orders): fail-closed media account scope with org_scope claim [SH-221] 2026-08-06 10:26:04 -03:00
Alexandre Brandizzi
7d245eb717
refactor: enforce backend boundaries and optimize dispatch (#30)
* refactor(api): enforce service and data-service boundaries

* refactor(api): complete feature service boundaries

* refactor(identity): enforce service and data boundaries

* refactor(vendors): enforce service and data boundaries

* refactor(workorders): enforce service and data boundaries

* refactor(backend): enforce architecture and optimize dispatch

* style(backend): format changed architecture files

* fix(architecture): address backend review follow-ups

* fix(backend): sanitize exception disclosure in changed API endpoints

Replace raw exception-message disclosure (ex.Message) returned to API
callers with a stable sanitized public message plus correlated structured
internal logging, across the endpoints changed in this PR.

- Add SanitizedErrors helper: logs the original exception at Error with a
  generated correlation id and returns a stable public message referencing
  it so support can trace without exposing internals.
- Inject ILogger<T> into the 14 changed controllers and route every
  ex.Message/dbex.Message disclosure through the helper, preserving status
  codes, response shapes, and business data (e.g. OpenWorkOrders).
- Leave FluentValidation (vex.Errors) and existing fixed-message catches
  untouched; out-of-scope controllers (Account/Contact/Employee/Asset/
  PMSchedule) are unchanged.
- Add focused tests proving internal exception text is not returned and
  that Error logging carrying the original exception is invoked.

* fix(architecture): abstract job run state access

* style: format board update service

* test: use collection assertion idiom
2026-07-24 17:35:34 -03:00
Alexandre Brandizzi
4863d1fdaf feat(vendors): complete operations roadmap backend 2026-07-23 19:18:06 -03:00
Alexandre Brandizzi
8cf49afc2c feat(vendors): complete core vendor workflows 2026-07-23 17:02:40 -03:00
Alexandre Brandizzi
1162c68596
feat(vendors): add directory filters and details API (#25)
* feat(vendors): add directory filters and details API

* fix(vendors): preserve omitted status

* fix(vendors): align facet filtering

* fix(vendors): address directory review findings
2026-07-23 15:55:47 +00:00
Adam Moussa
1f3972ae49
Add calendar/events backend API (#8)
* Align EntityFrameworkCore.SqlServer and Tools to 8.0.8

* Add calendar/events backend API

Cherry-picked from main-backup (19994ef); scratch notes file removed.

* Require authentication on CalendarController

Security review found [Authorize] commented out, leaving all 6 calendar
endpoints anonymous. Enforce auth to match the API convention (17/23
controllers).

* Add CalendarController unit tests (xUnit + EF InMemory)
2026-06-22 18:46:46 -04:00
npalOmega
59385cf5b1 backend changes 2026-05-14 11:00:12 -05:00
npalOmega
5e4d9894e9 backend architectural template 2026-05-06 10:49:33 -05:00
Adam Moussa
81472bf729 Add dispatch sign-offs with signature capture
- DispatchSignoff model (DispatchId, SignoffType, Name, Signature base64, SignatureMethod, SignedAt)
- AddDispatchSignoff endpoint — one per type per dispatch, validates no duplicate
- GetDispatchById includes signoffs in response
- Migration for DispatchSignoffs table
2026-04-17 15:51:20 -04:00
Adam Moussa
3a25fa8559 Add dispatch checklist items with template support
- DispatchChecklistItem model (DispatchId, WorkOrderId, ItemText, IsCompleted, CompletedBy, CompletedAt)
- DispatchToVendor copies template items when TaskListTemplateId provided
- Supports custom checklist items alongside template items
- UpdateChecklistItem endpoint to toggle completion with user name
- AddChecklistItem endpoint for ad-hoc items
- GetDispatchById includes checklist items in response
- Migration for DispatchChecklistItems table
2026-04-17 15:28:52 -04:00
Adam Moussa
be190836a4 Add multi-WO dispatch support with junction table
- DispatchWorkOrder junction table for 1:N dispatch-to-WO relationship
- Make Dispatch.WorkOrderId nullable (backward compat)
- Add AcceptToken and AcknowledgedAt to Dispatch model
- Dispatch_DTO accepts WorkOrderIds array
- DispatchToVendor creates junction rows, email lists all WOs in table
- GetDispatches queries both junction table and direct FK
- GetDispatchById includes workOrders list from junction table
- Migration with DispatchWorkOrder table
2026-04-17 15:16:28 -04:00
Adam Moussa
1f4bd12cd7 Add Task List Templates with CRUD controller
- TaskListTemplate and TaskListTemplateItem models
- TaskListTemplateController: list, get by ID, create with items, update (replace items), soft delete
- Migration for new tables
2026-04-17 14:57:18 -04:00
Adam Moussa
63f76e9b2c Add dispatch detail modal backend + vendor reply sync
- Add DispatchNumber and CompletedDate to Dispatch model
- Add DispatchId to Comments for per-dispatch vendor threads
- GetDispatchById endpoint with vendor communication thread
- UpdateDispatch endpoint for status, NTE, dates, description
- AddDispatchComment endpoint — saves comment + sends email to vendor with sender name
- BackfillDispatchNumbers endpoint for existing dispatches
- SyncVendorReplies endpoint — pulls from DynamoDB VendorReplies table
- Fix reply-to address to include dispatch number
- Include sender name in dispatch and comment emails
2026-04-17 14:01:03 -04:00
Adam Moussa
ee69a1863a Add vendor scheduled date to dispatch workflow
- Add ScheduledDate field to Dispatch model and DTO
- Save scheduled date when dispatching to vendor
- Include ScheduledDate in dispatch response projections
2026-04-17 11:47:00 -04:00
Adam Moussa
d24c4643f5 Add vendor dispatch workflow backend
- Create Vendor model with company info, trade specialties, active flag
- Create Dispatch model (doubles as Vendor PO) with PO number, NTE, status, reply-to address
- VendorController: CRUD, paginated list, dropdown endpoint with trade filtering
- DispatchToVendor endpoint: multi-vendor dispatch, auto-generated PO numbers (VPO-00001),
  HTML email with full WO details via SendGrid, reply-to wo-{number}@int.seahaven.com
- GetDispatches endpoint for listing dispatches by WO
- Include dispatches in GetWorkorderById response
- SendMessage.SendDispatchEmail with reply-to support
- Audit log entry for each dispatch
2026-04-17 11:37:35 -04:00
Adam Moussa
05b36ef7dd Add configurable dropdowns, new WO fields, and seed data
- Create DropdownOption model with Category, Value, ParentValue for Trade/SubTrade/Problem
- Add DropdownOptionsController with CRUD + ByCategory endpoint with parent filtering
- Add Problem, Trade, SubTrade, VendorNTE, ScheduledDate, CompletedDate, Source to WorkOrder
- Update EditWorkorder_DTO and GetWorkorderById with new fields
- Audit log tracks changes to all new fields
- Seed default Trades (10), SubTrades (20), and Problems (11) on startup
2026-04-17 10:40:38 -04:00
Adam Moussa
be70c84add Make Comments_DTO fields nullable for JSON endpoint compatibility
- Text, UserId, CreatedDate are set server-side, not required from client
2026-04-16 18:24:04 -04:00
Adam Moussa
e1f57d3fb2 Add comment types, audit logging, and WorkOrderAuditLog table
- Add CommentType field to Comments (customer, vendor, internal)
- Add Status field to EditWorkorder_DTO
- Create WorkOrderAuditLog model tracking field-level changes
- Log all field changes on work order edit and status change
- Include commentType and auditLog in GetWorkorderById response
- Set CommentType=customer on synced comments from DynamoDB
- Add BackfillCommentTypes endpoint for existing data
2026-04-16 18:09:57 -04:00
Adam Moussa
93fa76a5aa Handle string-to-int AccountId conversion in Location DTOs
- Frontend sends accountId as empty string when not set
- Change DTO AccountId to string with GetAccountId() parser
- Prevents JSON deserialization error on empty/non-numeric values
2026-04-16 17:15:28 -04:00
Adam Moussa
534f97d6f1 Add LocationController with full CRUD and extended model
- Extend Locations model with Address, City, State, ZipCode, Phone, Contact, ContactEmail, Status, AccountId
- Update Location DTOs to match new fields
- Create LocationController with paged list, get by ID, create, update, delete
- Support both REST-style routes (/api/Location/{id}) and legacy query routes (/api/Location/DeleteLocation?id=)
- Add migration for new Location columns
2026-04-16 17:09:59 -04:00
npalOmega
a9fc4b8701 fix 2026-03-30 06:49:40 -05:00
npalOmega
cd78c93fa8 fix 2026-01-21 16:24:54 -06:00
npalOmega
9c78cd96fa added new controllers 2026-01-21 15:41:19 -06:00
69b9e69f00 Initial commit 2024-09-28 14:58:36 -04:00