2026-06-30 13:20:40 -03:00
|
|
|
|
using System.ComponentModel.DataAnnotations;
|
2024-09-28 14:58:36 -04:00
|
|
|
|
using System.ComponentModel.DataAnnotations.Schema;
|
2026-06-30 13:20:40 -03:00
|
|
|
|
using Data.SeaHavenIndustries.Enums;
|
2024-09-28 14:58:36 -04:00
|
|
|
|
|
|
|
|
|
|
namespace Data.SeaHavenIndustries
|
|
|
|
|
|
{
|
|
|
|
|
|
public class WorkOrder : FullAuditEntity
|
|
|
|
|
|
{
|
2026-06-30 13:20:40 -03:00
|
|
|
|
// --- Core slice ---
|
2026-04-16 18:42:58 -04:00
|
|
|
|
public string? InternalWONumber { get; set; }
|
Add DynamoDB sync bridge for workorder-ingest pipeline
- Add ExternalWorkOrderId, Customer, SiteCode, Building, Severity,
DateReported, ScheduledStart, SourceEmailS3Key to WorkOrder model
- Add Commenter, RecordType, ExternalCommentId to Comments model
- Add AWSSDK.DynamoDBv2 package
- Create SyncController with endpoints:
- POST /api/Sync/WorkOrders — scans DynamoDB WorkOrders table, upserts into SQL
- POST /api/Sync/Comments — scans DynamoDB WorkOrderComments, creates Comments
- POST /api/Sync/All — runs both
- Auto-creates Locations from site_code/building/address during sync
- Maps DynamoDB status values to SHOC status strings
- Maps severity to SHOC priority format (Sev N)
- Deduplicates on ExternalWorkOrderId / ExternalCommentId
2026-04-16 17:29:52 -04:00
|
|
|
|
public string? ExternalWorkOrderId { get; set; }
|
2026-07-24 21:03:50 -03:00
|
|
|
|
public DateTimeOffset? ExternalLastOccurredAt { get; set; }
|
2026-07-24 22:13:25 -03:00
|
|
|
|
[MaxLength(128)]
|
|
|
|
|
|
public string? ExternalSource { get; set; }
|
|
|
|
|
|
public DateTimeOffset? ExternalUpdatedAt { get; set; }
|
|
|
|
|
|
[MaxLength(64)]
|
|
|
|
|
|
public string? ExternalVersionHash { get; set; }
|
|
|
|
|
|
[MaxLength(450)]
|
|
|
|
|
|
public string? ExternalAssignedTo { get; set; }
|
|
|
|
|
|
[MaxLength(64)]
|
|
|
|
|
|
public string? ExternalRecordType { get; set; }
|
2024-09-28 14:58:36 -04:00
|
|
|
|
public string? WorkerOrderNumber { get; set; }
|
|
|
|
|
|
public string? WorkerOrderTitle { get; set; }
|
|
|
|
|
|
public string? Description { get; set; }
|
Add DynamoDB sync bridge for workorder-ingest pipeline
- Add ExternalWorkOrderId, Customer, SiteCode, Building, Severity,
DateReported, ScheduledStart, SourceEmailS3Key to WorkOrder model
- Add Commenter, RecordType, ExternalCommentId to Comments model
- Add AWSSDK.DynamoDBv2 package
- Create SyncController with endpoints:
- POST /api/Sync/WorkOrders — scans DynamoDB WorkOrders table, upserts into SQL
- POST /api/Sync/Comments — scans DynamoDB WorkOrderComments, creates Comments
- POST /api/Sync/All — runs both
- Auto-creates Locations from site_code/building/address during sync
- Maps DynamoDB status values to SHOC status strings
- Maps severity to SHOC priority format (Sev N)
- Deduplicates on ExternalWorkOrderId / ExternalCommentId
2026-04-16 17:29:52 -04:00
|
|
|
|
public string? Customer { get; set; }
|
2026-08-06 09:47:34 -03:00
|
|
|
|
/// <summary>CRM account (customer) boundary for server-derived media/tenant scope (SH-221).</summary>
|
|
|
|
|
|
public int? AccountId { get; set; }
|
|
|
|
|
|
[ForeignKey(nameof(AccountId))]
|
|
|
|
|
|
public virtual Accounts? Account { get; set; }
|
Add DynamoDB sync bridge for workorder-ingest pipeline
- Add ExternalWorkOrderId, Customer, SiteCode, Building, Severity,
DateReported, ScheduledStart, SourceEmailS3Key to WorkOrder model
- Add Commenter, RecordType, ExternalCommentId to Comments model
- Add AWSSDK.DynamoDBv2 package
- Create SyncController with endpoints:
- POST /api/Sync/WorkOrders — scans DynamoDB WorkOrders table, upserts into SQL
- POST /api/Sync/Comments — scans DynamoDB WorkOrderComments, creates Comments
- POST /api/Sync/All — runs both
- Auto-creates Locations from site_code/building/address during sync
- Maps DynamoDB status values to SHOC status strings
- Maps severity to SHOC priority format (Sev N)
- Deduplicates on ExternalWorkOrderId / ExternalCommentId
2026-04-16 17:29:52 -04:00
|
|
|
|
public string? SiteCode { get; set; }
|
|
|
|
|
|
public string? Building { get; set; }
|
|
|
|
|
|
public string? Severity { get; set; }
|
2026-06-30 13:20:40 -03:00
|
|
|
|
public DateTime? DueDate { get; set; }
|
|
|
|
|
|
public string? AssignTo { get; set; }
|
|
|
|
|
|
[ForeignKey(nameof(AssignTo))]
|
|
|
|
|
|
public virtual ApplicationUser? AssignToUser { get; set; }
|
|
|
|
|
|
public int? LocationId { get; set; }
|
|
|
|
|
|
[ForeignKey(nameof(LocationId))]
|
|
|
|
|
|
public virtual Locations? Locations { get; set; }
|
|
|
|
|
|
public LifecycleStatus? LifecycleStatus { get; set; }
|
|
|
|
|
|
public string? LegacyStatus { get; set; }
|
|
|
|
|
|
public WorkOrderType? WorkOrderType { get; set; }
|
|
|
|
|
|
/// <summary>SHOC board "Service" column (PM type label). Not Trade/Problem.</summary>
|
2026-07-23 19:18:06 -03:00
|
|
|
|
[MaxLength(128)]
|
2026-06-30 13:20:40 -03:00
|
|
|
|
public string? Service { get; set; }
|
|
|
|
|
|
public int? PrimaryDispatchId { get; set; }
|
|
|
|
|
|
[ForeignKey(nameof(PrimaryDispatchId))]
|
|
|
|
|
|
public virtual Dispatch? PrimaryDispatch { get; set; }
|
|
|
|
|
|
|
2026-07-17 10:37:23 -03:00
|
|
|
|
// --- Service & Notes / POC (structured create) ---
|
|
|
|
|
|
[MaxLength(200)]
|
|
|
|
|
|
public string? PocName { get; set; }
|
|
|
|
|
|
[MaxLength(50)]
|
|
|
|
|
|
public string? PocPhone { get; set; }
|
|
|
|
|
|
[MaxLength(2000)]
|
|
|
|
|
|
public string? PocNotes { get; set; }
|
|
|
|
|
|
/// <summary>JSON array of extra service labels beyond primary (Trade).</summary>
|
|
|
|
|
|
[MaxLength(2000)]
|
|
|
|
|
|
public string? ExtraServices { get; set; }
|
|
|
|
|
|
[MaxLength(4000)]
|
|
|
|
|
|
public string? ServiceNotes { get; set; }
|
|
|
|
|
|
/// <summary>Tech/crew phone when no primary dispatch; otherwise prefer Dispatch.TechPhone.</summary>
|
|
|
|
|
|
[MaxLength(50)]
|
|
|
|
|
|
public string? TechPhone { get; set; }
|
|
|
|
|
|
/// <summary>Vendor instructions when no primary dispatch; otherwise prefer Dispatch.VendorNotes.</summary>
|
|
|
|
|
|
[MaxLength(2000)]
|
|
|
|
|
|
public string? VendorNotes { get; set; }
|
|
|
|
|
|
|
2026-06-30 13:20:40 -03:00
|
|
|
|
// --- Scheduling slice ---
|
|
|
|
|
|
public DateTime? ScheduledDate { get; set; }
|
Add DynamoDB sync bridge for workorder-ingest pipeline
- Add ExternalWorkOrderId, Customer, SiteCode, Building, Severity,
DateReported, ScheduledStart, SourceEmailS3Key to WorkOrder model
- Add Commenter, RecordType, ExternalCommentId to Comments model
- Add AWSSDK.DynamoDBv2 package
- Create SyncController with endpoints:
- POST /api/Sync/WorkOrders — scans DynamoDB WorkOrders table, upserts into SQL
- POST /api/Sync/Comments — scans DynamoDB WorkOrderComments, creates Comments
- POST /api/Sync/All — runs both
- Auto-creates Locations from site_code/building/address during sync
- Maps DynamoDB status values to SHOC status strings
- Maps severity to SHOC priority format (Sev N)
- Deduplicates on ExternalWorkOrderId / ExternalCommentId
2026-04-16 17:29:52 -04:00
|
|
|
|
public DateTime? ScheduledStart { get; set; }
|
2026-06-30 13:20:40 -03:00
|
|
|
|
public DateTime? ScheduledEnd { get; set; }
|
|
|
|
|
|
public DateOnly? TargetWeek { get; set; }
|
|
|
|
|
|
public bool? ScheduleWeekOnly { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
// --- Tracking slice (set-once) ---
|
|
|
|
|
|
public DateOnly? OriginalWeek { get; set; }
|
|
|
|
|
|
public DateOnly? OriginalDate { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
// --- Analytics slice ---
|
|
|
|
|
|
public int RescheduleCount { get; set; }
|
|
|
|
|
|
public int CarriedOver { get; set; }
|
|
|
|
|
|
public OperationalFlags OperationalFlags { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
// --- Completion slice ---
|
|
|
|
|
|
public DocStatus? DocStatus { get; set; }
|
|
|
|
|
|
|
2026-07-21 09:42:10 -03:00
|
|
|
|
/// <summary>Board flag color (#RRGGBB from fixed palette). Null = no flag.</summary>
|
|
|
|
|
|
[MaxLength(7)]
|
|
|
|
|
|
public string? FlagColor { get; set; }
|
|
|
|
|
|
|
2026-06-30 13:20:40 -03:00
|
|
|
|
// --- Legacy SQL columns (drift reconciliation) ---
|
|
|
|
|
|
public string? AvettaTask { get; set; }
|
|
|
|
|
|
public DateOnly? AssignDate { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
// --- Legacy fields (retained for Blazor / coexistence) ---
|
|
|
|
|
|
public DateTime? DateReported { get; set; }
|
Add DynamoDB sync bridge for workorder-ingest pipeline
- Add ExternalWorkOrderId, Customer, SiteCode, Building, Severity,
DateReported, ScheduledStart, SourceEmailS3Key to WorkOrder model
- Add Commenter, RecordType, ExternalCommentId to Comments model
- Add AWSSDK.DynamoDBv2 package
- Create SyncController with endpoints:
- POST /api/Sync/WorkOrders — scans DynamoDB WorkOrders table, upserts into SQL
- POST /api/Sync/Comments — scans DynamoDB WorkOrderComments, creates Comments
- POST /api/Sync/All — runs both
- Auto-creates Locations from site_code/building/address during sync
- Maps DynamoDB status values to SHOC status strings
- Maps severity to SHOC priority format (Sev N)
- Deduplicates on ExternalWorkOrderId / ExternalCommentId
2026-04-16 17:29:52 -04:00
|
|
|
|
public string? SourceEmailS3Key { get; set; }
|
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
|
|
|
|
public string? Problem { get; set; }
|
|
|
|
|
|
public string? Trade { get; set; }
|
|
|
|
|
|
public string? SubTrade { get; set; }
|
|
|
|
|
|
public decimal? VendorNTE { get; set; }
|
|
|
|
|
|
public DateTime? CompletedDate { get; set; }
|
|
|
|
|
|
public string? Source { get; set; }
|
2024-09-28 14:58:36 -04:00
|
|
|
|
public bool? istemplate { get; set; }
|
|
|
|
|
|
public string? PO { get; set; }
|
|
|
|
|
|
public string? TT { get; set; }
|
|
|
|
|
|
public string? Priority { get; set; }
|
|
|
|
|
|
public string? Status { get; set; }
|
|
|
|
|
|
public string? Attachments { get; set; }
|
|
|
|
|
|
public string? BeforPhotoIssue { get; set; }
|
|
|
|
|
|
public string? BeforPhotoAttachment { get; set; }
|
|
|
|
|
|
public string? AfterPhotoIssue { get; set; }
|
|
|
|
|
|
public string? AfterPhotoAttachment { get; set; }
|
|
|
|
|
|
public string? SignOffName { get; set; }
|
|
|
|
|
|
public string? SignOffAttachment { get; set; }
|
|
|
|
|
|
public string? SignOffSignature { get; set; }
|
2026-06-30 13:20:40 -03:00
|
|
|
|
|
|
|
|
|
|
[Timestamp]
|
|
|
|
|
|
public byte[]? RowVersion { get; set; }
|
|
|
|
|
|
|
2024-09-28 14:58:36 -04:00
|
|
|
|
public ICollection<Comments>? Comments { get; set; }
|
|
|
|
|
|
public ICollection<Quotes>? Quotes { get; set; }
|
|
|
|
|
|
public ICollection<WorkOrderContacts>? WorkOrderContacts { get; set; }
|
|
|
|
|
|
public ICollection<WorkOrderAttachments>? workOrderAttachments { get; set; }
|
|
|
|
|
|
public ICollection<WorkOrderCategories>? WorkOrderCategories { get; set; }
|
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
|
|
|
|
public ICollection<Dispatch>? Dispatches { get; set; }
|
2026-06-30 13:20:40 -03:00
|
|
|
|
public ICollection<WorkOrderFieldLock>? FieldLocks { get; set; }
|
2024-09-28 14:58:36 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|