mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 18:53:12 +00:00
* fix(migrations): make Phase6 completion slide-over migration idempotent Use IF EXISTS / IF COL_LENGTH guards and explicit EF migration metadata so partial environments can apply Phase 6 safely. * feat(locations): add sites options endpoint and vendor contactName Expose GET /api/locations/sites for the WO create wizard and include vendor contactName on dropdown responses. * feat(work-orders): add structured service notes POC and vendor fields Persist primary/extra services, service notes, free-text POC, and tech/vendor notes on create/patch/board/detail instead of embedding them in description. * fix(work-orders): make stacked tip build for CI quality gates * fix(work-orders): align stacked services with CI build * fix(work-orders): keep FlagColor out of structured-notes slice 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. --------- Co-authored-by: Arthur Bassi <arthur.winiarski.ranger@outlook.com>
95 lines
3.6 KiB
C#
95 lines
3.6 KiB
C#
using Data.SeaHavenIndustries;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using SeaHaven.DataServices.Helpers;
|
|
using SeaHaven.DataServices.Interfaces;
|
|
|
|
namespace SeaHaven.DataServices.Implementation
|
|
{
|
|
public class WorkOrderDetailDataService : IWorkOrderDetailDataService
|
|
{
|
|
private readonly ApplicationDbContext _context;
|
|
|
|
public WorkOrderDetailDataService(ApplicationDbContext context)
|
|
{
|
|
_context = context;
|
|
}
|
|
|
|
public Task<bool> ExistsAsync(int workOrderId)
|
|
=> WorkOrderBoardQueryFilters.ApplyBaseScope(_context.workOrders.AsNoTracking())
|
|
.AnyAsync(w => w.Id == workOrderId);
|
|
|
|
public async Task<WorkOrderDetailExtendedFields?> GetExtendedFieldsAsync(int workOrderId)
|
|
{
|
|
return await WorkOrderBoardQueryFilters.ApplyBaseScope(_context.workOrders.AsNoTracking())
|
|
.Where(w => w.Id == workOrderId)
|
|
.Select(w => new WorkOrderDetailExtendedFields(
|
|
w.Description,
|
|
w.Trade,
|
|
w.Problem,
|
|
w.SubTrade,
|
|
w.OriginalWeek,
|
|
w.OriginalDate,
|
|
w.CompletedDate,
|
|
w.SignOffName,
|
|
w.SignOffAttachment,
|
|
w.SignOffSignature,
|
|
w.ExtraServices,
|
|
w.ServiceNotes,
|
|
w.PrimaryDispatch != null && w.PrimaryDispatch.VendorNotes != null
|
|
? w.PrimaryDispatch.VendorNotes
|
|
: w.VendorNotes))
|
|
.FirstOrDefaultAsync();
|
|
}
|
|
|
|
public async Task<IReadOnlyList<Comments>> GetCommentsAsync(int workOrderId)
|
|
{
|
|
return await _context.Comments
|
|
.AsNoTracking()
|
|
.Where(c => c.WorkerOrderId == workOrderId && c.IsDeleted != true)
|
|
.OrderByDescending(c => c.CreatedDate)
|
|
.ToListAsync();
|
|
}
|
|
|
|
public async Task<IReadOnlyList<WorkOrderAuditLog>> GetAuditLogsAsync(int workOrderId, int? limit = null)
|
|
{
|
|
var query = _context.WorkOrderAuditLogs
|
|
.AsNoTracking()
|
|
.Where(a => a.WorkOrderId == workOrderId)
|
|
.OrderByDescending(a => a.CreatedAt);
|
|
|
|
if (limit.HasValue)
|
|
return await query.Take(limit.Value).ToListAsync();
|
|
|
|
return await query.ToListAsync();
|
|
}
|
|
|
|
public async Task<IReadOnlyList<WorkOrderAttachments>> GetAttachmentsAsync(int workOrderId)
|
|
{
|
|
return await _context.workOrderAttachments
|
|
.AsNoTracking()
|
|
.Where(a => a.WorkorderId == workOrderId && a.IsDeleted != true)
|
|
.OrderByDescending(a => a.CreatedDate)
|
|
.ToListAsync();
|
|
}
|
|
|
|
public async Task<IReadOnlyList<DispatchSignoffRow>> GetDispatchSignoffsAsync(int workOrderId)
|
|
{
|
|
return await _context.DispatchSignoffs
|
|
.AsNoTracking()
|
|
.Where(s => s.Dispatch != null && s.Dispatch.WorkOrderId == workOrderId && s.IsDeleted != true)
|
|
.OrderByDescending(s => s.SignedAt)
|
|
.Select(s => new DispatchSignoffRow(
|
|
s.DispatchId,
|
|
s.SignoffType,
|
|
s.Name,
|
|
s.SignedAt))
|
|
.ToListAsync();
|
|
}
|
|
|
|
public async Task<WorkOrder?> GetWorkOrderForMediaAsync(int workOrderId)
|
|
{
|
|
return await WorkOrderBoardQueryFilters.ApplyBaseScope(_context.workOrders.AsNoTracking())
|
|
.FirstOrDefaultAsync(w => w.Id == workOrderId);
|
|
}
|
|
}
|
|
}
|