shoc-backend/SeaHaven.DataServices/Implementation/WorkOrderBoardDataService.cs

222 lines
9.2 KiB
C#

using Data.SeaHavenIndustries;
using Data.SeaHavenIndustries.Enums;
using Microsoft.EntityFrameworkCore;
using SeaHaven.DataServices.Interfaces;
namespace SeaHaven.DataServices.Implementation
{
public class WorkOrderBoardDataService : IWorkOrderBoardDataService
{
private readonly ApplicationDbContext _context;
public WorkOrderBoardDataService(ApplicationDbContext context)
{
_context = context;
}
public async Task<WorkOrderBoardQueryResult> GetBoardRowsAsync(WorkOrderBoardQuery query)
{
var weekStartDate = query.WeekStart.ToDateTime(TimeOnly.MinValue);
var weekEndDate = query.WeekEnd.ToDateTime(TimeOnly.MinValue);
var baseQuery = _context.workOrders
.AsNoTracking()
.Where(w => w.istemplate != true && (w.IsDeleted != true || w.IsDeleted == null));
baseQuery = ApplyDispatcherFilter(baseQuery, query);
baseQuery = ApplyTypeFilter(baseQuery, query);
var scheduledBase = baseQuery.Where(w =>
(w.ScheduledDate != null
&& w.ScheduledDate.Value.Date >= weekStartDate.Date
&& w.ScheduledDate.Value.Date <= weekEndDate.Date)
|| (w.ScheduleWeekOnly == true && w.TargetWeek == query.WeekStart));
var unscheduledBase = baseQuery.Where(w =>
w.ScheduledDate == null && !IsTerminalExpression(w));
var scheduledTotal = await scheduledBase.CountAsync();
if (!string.IsNullOrWhiteSpace(query.Search))
{
scheduledBase = ApplySearchFilter(scheduledBase, query.Search);
unscheduledBase = ApplySearchFilter(unscheduledBase, query.Search);
}
var scheduledRows = await ProjectRows(scheduledBase, isUnscheduled: false);
var unscheduledRows = await ProjectRows(unscheduledBase, isUnscheduled: true);
return new WorkOrderBoardQueryResult(scheduledRows, unscheduledRows, scheduledTotal);
}
public async Task<IReadOnlyList<DispatcherLookupRow>> GetDispatcherLookupsAsync()
{
return await _context.Users
.AsNoTracking()
.Where(u => u.IsDeleted != true)
.OrderBy(u => u.FirstName)
.ThenBy(u => u.LastName)
.Select(u => new DispatcherLookupRow(
u.Id,
u.FirstName ?? "",
u.LastName,
u.Initials,
u.Color))
.ToListAsync();
}
private static IQueryable<WorkOrder> ApplyDispatcherFilter(IQueryable<WorkOrder> query, WorkOrderBoardQuery boardQuery)
{
if (boardQuery.MyWorkOrders && !string.IsNullOrEmpty(boardQuery.CurrentUserId))
return query.Where(w => w.AssignTo == boardQuery.CurrentUserId);
if (boardQuery.Dispatchers == null || boardQuery.Dispatchers.Count == 0)
return query;
var ids = boardQuery.Dispatchers
.Where(d => d != "__unassigned__")
.ToList();
var includeUnassigned = boardQuery.Dispatchers.Contains("__unassigned__");
if (includeUnassigned && ids.Count == 0)
return query.Where(w => w.AssignTo == null || w.AssignTo == "");
if (includeUnassigned && ids.Count > 0)
{
return query.Where(w =>
w.AssignTo == null || w.AssignTo == "" || ids.Contains(w.AssignTo));
}
return query.Where(w => w.AssignTo != null && ids.Contains(w.AssignTo));
}
private static IQueryable<WorkOrder> ApplyTypeFilter(IQueryable<WorkOrder> query, WorkOrderBoardQuery boardQuery)
{
if (boardQuery.Types == null || boardQuery.Types.Count == 0)
return query;
return query.Where(w => w.WorkOrderType != null && boardQuery.Types.Contains(w.WorkOrderType.Value));
}
private static IQueryable<WorkOrder> ApplySearchFilter(IQueryable<WorkOrder> query, string search)
{
var s = search.Trim().ToLower();
return query.Where(w =>
(w.SiteCode ?? "").ToLower().Contains(s)
|| (w.InternalWONumber ?? "").ToLower().Contains(s)
|| (w.WorkerOrderNumber ?? "").ToLower().Contains(s)
|| (w.Locations != null && (w.Locations.Name ?? "").ToLower().Contains(s))
|| (w.AssignToUser != null && ((w.AssignToUser.FirstName ?? "") + " " + (w.AssignToUser.LastName ?? "")).ToLower().Contains(s))
|| (w.Trade ?? "").ToLower().Contains(s)
|| (w.Problem ?? "").ToLower().Contains(s)
|| (w.PrimaryDispatch != null && w.PrimaryDispatch.Vendor != null && (w.PrimaryDispatch.Vendor.CompanyName ?? "").ToLower().Contains(s))
|| (w.Status ?? "").ToLower().Contains(s));
}
private static System.Linq.Expressions.Expression<Func<WorkOrder, bool>> IsTerminalExpression(WorkOrder w)
=> w => w.LifecycleStatus == LifecycleStatus.Complete
|| w.LifecycleStatus == LifecycleStatus.Canceled
|| w.LifecycleStatus == LifecycleStatus.Closed;
private async Task<IReadOnlyList<WorkOrderBoardRawRow>> ProjectRows(
IQueryable<WorkOrder> query,
bool isUnscheduled)
{
var rows = await query
.Include(w => w.AssignToUser)
.Include(w => w.Locations)
.Include(w => w.PrimaryDispatch!)
.ThenInclude(d => d!.Vendor)
.Include(w => w.WorkOrderContacts!)
.ThenInclude(c => c.POC)
.OrderBy(w => w.ScheduledDate)
.ThenBy(w => w.InternalWONumber)
.Select(w => new
{
w.Id,
w.InternalWONumber,
w.RescheduleCount,
w.CarriedOver,
w.WorkOrderType,
w.SiteCode,
LocationName = w.Locations != null ? w.Locations.Name : null,
Poc = w.WorkOrderContacts!
.OrderBy(c => c.Id)
.Select(c => new
{
Name = c.POC != null
? ((c.POC.FirstName ?? "") + " " + (c.POC.LastName ?? "")).Trim()
: null,
c.POC!.PhoneNumber,
c.Notes
})
.FirstOrDefault(),
w.LifecycleStatus,
w.LegacyStatus,
w.Status,
w.AssignTo,
w.AssignToUser!.FirstName,
w.AssignToUser!.LastName,
w.AssignToUser!.Initials,
w.AssignToUser!.Color,
w.DueDate,
w.ScheduledDate,
w.ScheduledStart,
w.ScheduledEnd,
w.TargetWeek,
w.ScheduleWeekOnly,
VendorId = w.PrimaryDispatch != null ? (int?)w.PrimaryDispatch.VendorId : null,
VendorName = w.PrimaryDispatch != null && w.PrimaryDispatch.Vendor != null
? w.PrimaryDispatch.Vendor.CompanyName
: null,
TechName = w.PrimaryDispatch != null && w.PrimaryDispatch.Vendor != null
? w.PrimaryDispatch.Vendor.ContactName
: null,
TechPhone = w.PrimaryDispatch != null && w.PrimaryDispatch.Vendor != null
? w.PrimaryDispatch.Vendor.Phone
: null,
DispatchApptDate = w.PrimaryDispatch != null ? w.PrimaryDispatch.ScheduledDate : null,
w.Trade,
w.Problem,
w.DocStatus,
w.RowVersion
})
.ToListAsync();
return rows.Select(w => new WorkOrderBoardRawRow(
w.Id,
w.InternalWONumber,
w.RescheduleCount,
w.CarriedOver,
w.WorkOrderType,
w.SiteCode,
w.LocationName,
w.Poc?.Name,
w.Poc?.PhoneNumber,
w.Poc?.Notes,
w.LifecycleStatus,
w.LegacyStatus ?? w.Status,
w.AssignTo,
w.FirstName,
w.LastName,
w.Initials,
w.Color,
w.DueDate,
w.ScheduledDate,
w.ScheduledStart,
w.ScheduledEnd,
w.TargetWeek,
w.ScheduleWeekOnly,
w.VendorId,
w.VendorName,
w.TechName,
w.TechPhone,
w.DispatchApptDate,
w.Trade ?? w.Problem,
w.Problem,
w.DocStatus,
w.RowVersion,
isUnscheduled)).ToList();
}
}
}