mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 17:43:12 +00:00
155 lines
6.6 KiB
C#
155 lines
6.6 KiB
C#
using Data.SeaHavenIndustries;
|
|
using Data.SeaHavenIndustries.Enums;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using SeaHaven.DataServices.Interfaces;
|
|
using SeaHaven.DataServices.Models;
|
|
|
|
namespace SeaHaven.DataServices.Implementation
|
|
{
|
|
public class ServicesRegistryDataService : IServicesRegistryDataService
|
|
{
|
|
private readonly ApplicationDbContext _context;
|
|
|
|
public ServicesRegistryDataService(ApplicationDbContext context)
|
|
{
|
|
_context = context;
|
|
}
|
|
|
|
public async Task<IReadOnlyList<ServiceRegistryRow>> GetServiceRowsAsync(bool? isActive, WorkOrderType? workOrderType, CancellationToken cancellationToken)
|
|
{
|
|
var query = _context.Services
|
|
.AsNoTracking()
|
|
.Where(s => s.IsDeleted != true);
|
|
|
|
if (isActive.HasValue)
|
|
query = query.Where(s => s.IsActive == isActive.Value);
|
|
|
|
if (workOrderType.HasValue)
|
|
query = query.Where(s => s.SupportedWorkOrderTypes.Any(t => t.WorkOrderType == workOrderType.Value));
|
|
|
|
var rows = await query
|
|
.OrderBy(s => s.Name)
|
|
.Select(s => new ServiceRegistryRow
|
|
{
|
|
Id = s.Id,
|
|
Name = s.Name,
|
|
Trade = s.Trade,
|
|
IconKey = s.IconKey,
|
|
RequiresCompletionDocument = s.RequiresCompletionDocument,
|
|
IsActive = s.IsActive,
|
|
CompletionDocTemplateId = s.CompletionDocTemplateId,
|
|
CompletionDocTemplateName = s.CompletionDocTemplate != null ? s.CompletionDocTemplate.Name : null,
|
|
SupportedWorkOrderTypes = s.SupportedWorkOrderTypes.Select(t => t.WorkOrderType).ToList()
|
|
})
|
|
.ToListAsync(cancellationToken);
|
|
return rows;
|
|
}
|
|
|
|
public async Task<ServiceRegistryRow?> GetServiceRowByIdAsync(int id, CancellationToken cancellationToken)
|
|
{
|
|
return await _context.Services.AsNoTracking()
|
|
.Where(s => s.Id == id && s.IsDeleted != true)
|
|
.Select(s => new ServiceRegistryRow
|
|
{
|
|
Id = s.Id,
|
|
Name = s.Name,
|
|
Trade = s.Trade,
|
|
IconKey = s.IconKey,
|
|
RequiresCompletionDocument = s.RequiresCompletionDocument,
|
|
IsActive = s.IsActive,
|
|
CompletionDocTemplateId = s.CompletionDocTemplateId,
|
|
CompletionDocTemplateName = s.CompletionDocTemplate != null ? s.CompletionDocTemplate.Name : null,
|
|
SupportedWorkOrderTypes = s.SupportedWorkOrderTypes.Select(t => t.WorkOrderType).ToList()
|
|
})
|
|
.FirstOrDefaultAsync(cancellationToken);
|
|
}
|
|
|
|
public async Task<Service?> GetServiceForUpdateAsync(int id, CancellationToken cancellationToken)
|
|
{
|
|
return await _context.Services
|
|
.Include(s => s.SupportedWorkOrderTypes)
|
|
.FirstOrDefaultAsync(s => s.Id == id && s.IsDeleted != true, cancellationToken);
|
|
}
|
|
|
|
public async Task<bool> NormalizedNameExistsAsync(string normalizedName, int? excludeServiceId, CancellationToken cancellationToken)
|
|
{
|
|
return await _context.Services
|
|
.AnyAsync(s => s.IsDeleted != true
|
|
&& s.NormalizedName == normalizedName
|
|
&& (excludeServiceId == null || s.Id != excludeServiceId),
|
|
cancellationToken);
|
|
}
|
|
|
|
public async Task<LinkedTemplateSummary?> GetActiveTemplateSummaryAsync(int templateId, CancellationToken cancellationToken)
|
|
{
|
|
return await _context.CompletionDocTemplates
|
|
.Where(t => t.Id == templateId && t.IsActive && t.IsDeleted != true)
|
|
.Select(t => new LinkedTemplateSummary { Id = t.Id, Name = t.Name })
|
|
.FirstOrDefaultAsync(cancellationToken);
|
|
}
|
|
|
|
public async Task<Service> AddServiceAsync(Service service, CancellationToken cancellationToken)
|
|
{
|
|
await _context.Services.AddAsync(service, cancellationToken);
|
|
try
|
|
{
|
|
await _context.SaveChangesAsync(cancellationToken);
|
|
}
|
|
catch (DbUpdateException ex) when (IsUniqueNameViolation(ex))
|
|
{
|
|
throw new ServicesRegistryDuplicateNameException(ex);
|
|
}
|
|
|
|
return service;
|
|
}
|
|
|
|
public async Task SaveServiceAsync(Service service, IReadOnlyCollection<WorkOrderType> supportedWorkOrderTypes, CancellationToken cancellationToken)
|
|
{
|
|
var desired = supportedWorkOrderTypes.Distinct().ToList();
|
|
var current = service.SupportedWorkOrderTypes ?? new List<ServiceWorkOrderType>();
|
|
|
|
var stale = current.Where(t => !desired.Contains(t.WorkOrderType)).ToList();
|
|
_context.ServiceWorkOrderTypes.RemoveRange(stale);
|
|
|
|
var existingTypes = current.Select(t => t.WorkOrderType).ToHashSet();
|
|
foreach (var type in desired.Where(t => !existingTypes.Contains(t)))
|
|
{
|
|
_context.ServiceWorkOrderTypes.Add(new ServiceWorkOrderType
|
|
{
|
|
ServiceId = service.Id,
|
|
WorkOrderType = type
|
|
});
|
|
}
|
|
|
|
try
|
|
{
|
|
await _context.SaveChangesAsync(cancellationToken);
|
|
}
|
|
catch (DbUpdateException ex) when (IsUniqueNameViolation(ex))
|
|
{
|
|
throw new ServicesRegistryDuplicateNameException(ex);
|
|
}
|
|
}
|
|
|
|
public async Task<bool> DeactivateServiceAsync(int id, CancellationToken cancellationToken)
|
|
{
|
|
var service = await _context.Services
|
|
.FirstOrDefaultAsync(s => s.Id == id && s.IsDeleted != true, cancellationToken);
|
|
if (service == null)
|
|
return false;
|
|
|
|
service.IsActive = false;
|
|
await _context.SaveChangesAsync(cancellationToken);
|
|
return true;
|
|
}
|
|
|
|
private static bool IsUniqueNameViolation(DbUpdateException exception)
|
|
{
|
|
var message = exception.InnerException?.Message ?? exception.Message;
|
|
return message.Contains("IX_Services_NormalizedName", StringComparison.OrdinalIgnoreCase)
|
|
|| message.Contains("NormalizedName", StringComparison.OrdinalIgnoreCase)
|
|
&& (message.Contains("duplicate", StringComparison.OrdinalIgnoreCase)
|
|
|| message.Contains("unique", StringComparison.OrdinalIgnoreCase));
|
|
}
|
|
}
|
|
}
|