mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-10-06 22:52:11 +00:00
Merge branch 'codex/vendor-core-completion-backend' into codex/vendor-roadmap-completion-backend
This commit is contained in:
commit
39829f7274
5 changed files with 209 additions and 31 deletions
|
|
@ -269,12 +269,12 @@ public class VendorDataServiceTests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void BuildOpenLinkedWorkOrdersQuery_TranslatesForSqlServerWithoutClientEvaluation()
|
public void BuildLinkedWorkOrdersQuery_TranslatesForSqlServerWithoutClientEvaluation()
|
||||||
{
|
{
|
||||||
using var context = NewSqlServerContext();
|
using var context = NewSqlServerContext();
|
||||||
var service = new VendorDataService(context);
|
var service = new VendorDataService(context);
|
||||||
|
|
||||||
var sql = service.BuildOpenLinkedWorkOrdersQuery(60).ToQueryString();
|
var sql = service.BuildLinkedWorkOrdersQuery(60).ToQueryString();
|
||||||
|
|
||||||
sql.Should().Contain("SELECT");
|
sql.Should().Contain("SELECT");
|
||||||
sql.Should().Contain("Dispatches");
|
sql.Should().Contain("Dispatches");
|
||||||
|
|
@ -283,7 +283,7 @@ public class VendorDataServiceTests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task GetOpenLinkedWorkOrdersAsync_DedupsToOneRecordPerWorkOrderAcrossDirectAndMultiLinks()
|
public async Task GetLinkedWorkOrdersAsync_DedupsToOneRecordPerWorkOrderAcrossDirectAndMultiLinks()
|
||||||
{
|
{
|
||||||
await using var context = NewContext();
|
await using var context = NewContext();
|
||||||
var vendor = new Vendor { Id = 60, CompanyName = "Linked Co", IsActive = true };
|
var vendor = new Vendor { Id = 60, CompanyName = "Linked Co", IsActive = true };
|
||||||
|
|
@ -315,7 +315,7 @@ public class VendorDataServiceTests
|
||||||
await context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
|
|
||||||
var service = new VendorDataService(context);
|
var service = new VendorDataService(context);
|
||||||
var result = await service.GetOpenLinkedWorkOrdersAsync(60);
|
var result = await service.GetLinkedWorkOrdersAsync(60);
|
||||||
|
|
||||||
result.Should().HaveCount(2);
|
result.Should().HaveCount(2);
|
||||||
result.Select(x => x.WorkOrderId).Should().BeEquivalentTo(new[] { 701, 702 });
|
result.Select(x => x.WorkOrderId).Should().BeEquivalentTo(new[] { 701, 702 });
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ public class VendorServiceTests
|
||||||
var existing = new Vendor { Id = 8, CompanyName = "Old", IsActive = true };
|
var existing = new Vendor { Id = 8, CompanyName = "Old", IsActive = true };
|
||||||
var data = new Mock<IVendorDataService>();
|
var data = new Mock<IVendorDataService>();
|
||||||
data.Setup(x => x.GetByIdAsync(8)).ReturnsAsync(existing);
|
data.Setup(x => x.GetByIdAsync(8)).ReturnsAsync(existing);
|
||||||
data.Setup(x => x.GetOpenLinkedWorkOrdersAsync(8)).ReturnsAsync(new List<LinkedWorkOrderInfo>());
|
data.Setup(x => x.GetLinkedWorkOrdersAsync(8)).ReturnsAsync(new List<LinkedWorkOrderInfo>());
|
||||||
data.Setup(x => x.UpdateAsync(existing)).Returns(Task.CompletedTask);
|
data.Setup(x => x.UpdateAsync(existing)).Returns(Task.CompletedTask);
|
||||||
|
|
||||||
var result = await NewService(data).UpdateVendorAsync(8, new UpdateVendorDTO
|
var result = await NewService(data).UpdateVendorAsync(8, new UpdateVendorDTO
|
||||||
|
|
@ -83,7 +83,7 @@ public class VendorServiceTests
|
||||||
var existing = new Vendor { Id = 9, CompanyName = "Keep History", IsActive = true };
|
var existing = new Vendor { Id = 9, CompanyName = "Keep History", IsActive = true };
|
||||||
var data = new Mock<IVendorDataService>();
|
var data = new Mock<IVendorDataService>();
|
||||||
data.Setup(x => x.GetByIdAsync(9)).ReturnsAsync(existing);
|
data.Setup(x => x.GetByIdAsync(9)).ReturnsAsync(existing);
|
||||||
data.Setup(x => x.GetOpenLinkedWorkOrdersAsync(9)).ReturnsAsync(new List<LinkedWorkOrderInfo>());
|
data.Setup(x => x.GetLinkedWorkOrdersAsync(9)).ReturnsAsync(new List<LinkedWorkOrderInfo>());
|
||||||
data.Setup(x => x.UpdateAsync(existing)).Returns(Task.CompletedTask);
|
data.Setup(x => x.UpdateAsync(existing)).Returns(Task.CompletedTask);
|
||||||
|
|
||||||
await NewService(data).DeleteVendorAsync(9, "42");
|
await NewService(data).DeleteVendorAsync(9, "42");
|
||||||
|
|
@ -221,7 +221,7 @@ public class VendorServiceTests
|
||||||
var existing = new Vendor { Id = 20, CompanyName = "Guarded", IsActive = true };
|
var existing = new Vendor { Id = 20, CompanyName = "Guarded", IsActive = true };
|
||||||
var data = new Mock<IVendorDataService>();
|
var data = new Mock<IVendorDataService>();
|
||||||
data.Setup(x => x.GetByIdAsync(20)).ReturnsAsync(existing);
|
data.Setup(x => x.GetByIdAsync(20)).ReturnsAsync(existing);
|
||||||
data.Setup(x => x.GetOpenLinkedWorkOrdersAsync(20))
|
data.Setup(x => x.GetLinkedWorkOrdersAsync(20))
|
||||||
.ReturnsAsync(new List<LinkedWorkOrderInfo>
|
.ReturnsAsync(new List<LinkedWorkOrderInfo>
|
||||||
{
|
{
|
||||||
new()
|
new()
|
||||||
|
|
@ -283,7 +283,7 @@ public class VendorServiceTests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CreateVendor_RejectsNonCanonicalPhoneAndInvalidPreferredContact()
|
public void CreateVendor_RejectsInvalidPhoneAndInvalidPreferredContact()
|
||||||
{
|
{
|
||||||
var validator = new CreateVendorValidation();
|
var validator = new CreateVendorValidation();
|
||||||
|
|
||||||
|
|
@ -300,6 +300,99 @@ public class VendorServiceTests
|
||||||
result.Errors.Should().Contain(e => e.PropertyName == nameof(CreateVendorDTO.PreferredContact));
|
result.Errors.Should().Contain(e => e.PropertyName == nameof(CreateVendorDTO.PreferredContact));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CreateVendor_NormalizesCommonNorthAmericanPhoneFormatsBeforeValidation()
|
||||||
|
{
|
||||||
|
var data = new Mock<IVendorDataService>();
|
||||||
|
Vendor? saved = null;
|
||||||
|
data.Setup(x => x.AddAsync(It.IsAny<Vendor>()))
|
||||||
|
.ReturnsAsync((Vendor vendor) =>
|
||||||
|
{
|
||||||
|
saved = vendor;
|
||||||
|
vendor.Id = 41;
|
||||||
|
return vendor;
|
||||||
|
});
|
||||||
|
|
||||||
|
await NewService(data).CreateVendorAsync(new CreateVendorDTO
|
||||||
|
{
|
||||||
|
Name = "Acme",
|
||||||
|
ContactName = "Riley",
|
||||||
|
Phone = "+1 312 555 0100"
|
||||||
|
}, "42");
|
||||||
|
|
||||||
|
saved!.Phone.Should().Be("(312) 555-0100");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UpdateVendor_RoutesCompanyOwnedFieldsToTheLinkedCompany()
|
||||||
|
{
|
||||||
|
var existing = new Vendor
|
||||||
|
{
|
||||||
|
Id = 42,
|
||||||
|
CompanyId = 77,
|
||||||
|
CompanyName = "Acme",
|
||||||
|
Address = "Old address",
|
||||||
|
IsActive = true
|
||||||
|
};
|
||||||
|
var company = new VendorCompany
|
||||||
|
{
|
||||||
|
Id = 77,
|
||||||
|
Name = "Acme",
|
||||||
|
NormalizedName = "acme",
|
||||||
|
Address = "Old address"
|
||||||
|
};
|
||||||
|
var data = new Mock<IVendorDataService>();
|
||||||
|
data.Setup(x => x.GetByIdAsync(42)).ReturnsAsync(existing);
|
||||||
|
data.Setup(x => x.GetCompanyByIdAsync(77)).ReturnsAsync(company);
|
||||||
|
data.Setup(x => x.UpdateCompanyAsync(company)).Returns(Task.CompletedTask);
|
||||||
|
data.Setup(x => x.UpdateAsync(existing)).Returns(Task.CompletedTask);
|
||||||
|
|
||||||
|
await NewService(data).UpdateVendorAsync(42, new UpdateVendorDTO
|
||||||
|
{
|
||||||
|
Name = "Acme Services",
|
||||||
|
Address = "200 New Street"
|
||||||
|
}, "42");
|
||||||
|
|
||||||
|
company.Name.Should().Be("Acme Services");
|
||||||
|
company.NormalizedName.Should().Be("acme services");
|
||||||
|
company.Address.Should().Be("200 New Street");
|
||||||
|
existing.Address.Should().Be("200 New Street");
|
||||||
|
data.Verify(x => x.UpdateCompanyAsync(company), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UpdateVendor_SparseCompanyDoesNotEraseExistingVendorFields()
|
||||||
|
{
|
||||||
|
var existing = new Vendor
|
||||||
|
{
|
||||||
|
Id = 43,
|
||||||
|
CompanyId = 77,
|
||||||
|
CompanyName = "Acme",
|
||||||
|
Address = "Keep this address",
|
||||||
|
CompanyPhone = "(312) 555-0199",
|
||||||
|
IsActive = true
|
||||||
|
};
|
||||||
|
var sparseCompany = new VendorCompany
|
||||||
|
{
|
||||||
|
Id = 77,
|
||||||
|
Name = "Acme",
|
||||||
|
NormalizedName = "acme"
|
||||||
|
};
|
||||||
|
var data = new Mock<IVendorDataService>();
|
||||||
|
data.Setup(x => x.GetByIdAsync(43)).ReturnsAsync(existing);
|
||||||
|
data.Setup(x => x.GetCompanyByIdAsync(77)).ReturnsAsync(sparseCompany);
|
||||||
|
data.Setup(x => x.UpdateCompanyAsync(sparseCompany)).Returns(Task.CompletedTask);
|
||||||
|
data.Setup(x => x.UpdateAsync(existing)).Returns(Task.CompletedTask);
|
||||||
|
|
||||||
|
await NewService(data).UpdateVendorAsync(43, new UpdateVendorDTO
|
||||||
|
{
|
||||||
|
Name = "Acme"
|
||||||
|
}, "42");
|
||||||
|
|
||||||
|
existing.Address.Should().Be("Keep this address");
|
||||||
|
existing.CompanyPhone.Should().Be("(312) 555-0199");
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void WorkOrderVendorUpdate_AcceptsCanonicalPhoneAndValidPreferredContact()
|
public void WorkOrderVendorUpdate_AcceptsCanonicalPhoneAndValidPreferredContact()
|
||||||
{
|
{
|
||||||
|
|
@ -383,6 +476,6 @@ public class VendorServiceTests
|
||||||
|
|
||||||
await act.Should().ThrowAsync<InvalidOperationException>()
|
await act.Should().ThrowAsync<InvalidOperationException>()
|
||||||
.WithMessage("*404*not found");
|
.WithMessage("*404*not found");
|
||||||
data.Verify(x => x.GetOpenLinkedWorkOrdersAsync(It.IsAny<int>()), Times.Never);
|
data.Verify(x => x.GetLinkedWorkOrdersAsync(It.IsAny<int>()), Times.Never);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -318,11 +318,30 @@ namespace SeaHaven.DataServices.Implementation
|
||||||
public async Task<VendorCompany> AddCompanyAsync(VendorCompany company)
|
public async Task<VendorCompany> AddCompanyAsync(VendorCompany company)
|
||||||
{
|
{
|
||||||
await _context.VendorCompanies.AddAsync(company);
|
await _context.VendorCompanies.AddAsync(company);
|
||||||
await _context.SaveChangesAsync();
|
try
|
||||||
return company;
|
{
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
return company;
|
||||||
|
}
|
||||||
|
catch (DbUpdateException)
|
||||||
|
{
|
||||||
|
_context.Entry(company).State = EntityState.Detached;
|
||||||
|
var existing = await _context.VendorCompanies
|
||||||
|
.AsNoTracking()
|
||||||
|
.SingleOrDefaultAsync(c => c.NormalizedName == company.NormalizedName);
|
||||||
|
if (existing != null)
|
||||||
|
return existing;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal IQueryable<LinkedWorkOrderInfo> BuildOpenLinkedWorkOrdersQuery(int vendorId)
|
public async Task UpdateCompanyAsync(VendorCompany company)
|
||||||
|
{
|
||||||
|
_context.VendorCompanies.Update(company);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal IQueryable<LinkedWorkOrderInfo> BuildLinkedWorkOrdersQuery(int vendorId)
|
||||||
{
|
{
|
||||||
var directLinks = _context.Dispatches
|
var directLinks = _context.Dispatches
|
||||||
.Where(d => d.VendorId == vendorId && d.WorkOrderId.HasValue)
|
.Where(d => d.VendorId == vendorId && d.WorkOrderId.HasValue)
|
||||||
|
|
@ -349,9 +368,9 @@ namespace SeaHaven.DataServices.Implementation
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<LinkedWorkOrderInfo>> GetOpenLinkedWorkOrdersAsync(int vendorId)
|
public async Task<List<LinkedWorkOrderInfo>> GetLinkedWorkOrdersAsync(int vendorId)
|
||||||
{
|
{
|
||||||
var raw = await BuildOpenLinkedWorkOrdersQuery(vendorId).ToListAsync();
|
var raw = await BuildLinkedWorkOrdersQuery(vendorId).ToListAsync();
|
||||||
return raw.DistinctBy(x => x.WorkOrderId).ToList();
|
return raw.DistinctBy(x => x.WorkOrderId).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,8 @@ namespace SeaHaven.DataServices.Interfaces
|
||||||
Task<VendorCompany?> GetCompanyByIdAsync(int id);
|
Task<VendorCompany?> GetCompanyByIdAsync(int id);
|
||||||
Task<VendorCompany?> GetCompanyByNormalizedNameAsync(string normalizedName);
|
Task<VendorCompany?> GetCompanyByNormalizedNameAsync(string normalizedName);
|
||||||
Task<VendorCompany> AddCompanyAsync(VendorCompany company);
|
Task<VendorCompany> AddCompanyAsync(VendorCompany company);
|
||||||
Task<List<LinkedWorkOrderInfo>> GetOpenLinkedWorkOrdersAsync(int vendorId);
|
Task UpdateCompanyAsync(VendorCompany company);
|
||||||
|
Task<List<LinkedWorkOrderInfo>> GetLinkedWorkOrdersAsync(int vendorId);
|
||||||
Task<bool> IsVendorAssignedToWorkOrderAsync(int vendorId, int workOrderId);
|
Task<bool> IsVendorAssignedToWorkOrderAsync(int vendorId, int workOrderId);
|
||||||
Task UpdateWithAuditLogsAsync(Vendor vendor, IReadOnlyCollection<VendorAuditLog> auditLogs);
|
Task UpdateWithAuditLogsAsync(Vendor vendor, IReadOnlyCollection<VendorAuditLog> auditLogs);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,7 @@ namespace SeaHaven.Services.Implementation
|
||||||
|
|
||||||
public async Task<VendorDTO> CreateVendorAsync(CreateVendorDTO dto, string userId)
|
public async Task<VendorDTO> CreateVendorAsync(CreateVendorDTO dto, string userId)
|
||||||
{
|
{
|
||||||
|
NormalizePhoneFields(dto);
|
||||||
var validationResult = await _createValidator.ValidateAsync(dto);
|
var validationResult = await _createValidator.ValidateAsync(dto);
|
||||||
if (!validationResult.IsValid)
|
if (!validationResult.IsValid)
|
||||||
{
|
{
|
||||||
|
|
@ -117,6 +118,7 @@ namespace SeaHaven.Services.Implementation
|
||||||
|
|
||||||
public async Task<VendorDTO> UpdateVendorAsync(int id, UpdateVendorDTO dto, string userId)
|
public async Task<VendorDTO> UpdateVendorAsync(int id, UpdateVendorDTO dto, string userId)
|
||||||
{
|
{
|
||||||
|
NormalizePhoneFields(dto);
|
||||||
var validationResult = await _updateValidator.ValidateAsync(dto);
|
var validationResult = await _updateValidator.ValidateAsync(dto);
|
||||||
if (!validationResult.IsValid)
|
if (!validationResult.IsValid)
|
||||||
{
|
{
|
||||||
|
|
@ -134,20 +136,18 @@ namespace SeaHaven.Services.Implementation
|
||||||
if (dto.ContactName != null) vendor.ContactName = dto.ContactName;
|
if (dto.ContactName != null) vendor.ContactName = dto.ContactName;
|
||||||
if (dto.Email != null) vendor.Email = dto.Email;
|
if (dto.Email != null) vendor.Email = dto.Email;
|
||||||
if (dto.Phone != null) vendor.Phone = VendorPhoneNormalizer.NormalizeToCanonical(dto.Phone);
|
if (dto.Phone != null) vendor.Phone = VendorPhoneNormalizer.NormalizeToCanonical(dto.Phone);
|
||||||
if (dto.CompanyPhone != null) vendor.CompanyPhone = VendorPhoneNormalizer.NormalizeToCanonical(dto.CompanyPhone);
|
|
||||||
if (dto.PreferredContact != null) vendor.PreferredContact = dto.PreferredContact;
|
if (dto.PreferredContact != null) vendor.PreferredContact = dto.PreferredContact;
|
||||||
if (dto.Address != null) vendor.Address = dto.Address;
|
|
||||||
if (dto.City != null) vendor.City = dto.City;
|
|
||||||
if (dto.State != null) vendor.State = dto.State;
|
|
||||||
if (dto.Zipcode != null) vendor.Zip = dto.Zipcode;
|
|
||||||
if (dto.TradeSpecialties != null) vendor.TradeSpecialties = dto.TradeSpecialties;
|
if (dto.TradeSpecialties != null) vendor.TradeSpecialties = dto.TradeSpecialties;
|
||||||
if (dto.GoogleMapsUrl != null) vendor.GoogleMapsUrl = dto.GoogleMapsUrl;
|
|
||||||
if (dto.Notes != null) vendor.Notes = dto.Notes;
|
if (dto.Notes != null) vendor.Notes = dto.Notes;
|
||||||
if (dto.IsActive.HasValue) vendor.IsActive = dto.IsActive.Value;
|
if (dto.IsActive.HasValue) vendor.IsActive = dto.IsActive.Value;
|
||||||
|
|
||||||
if (dto.CompanyId.HasValue || dto.Name != null)
|
if (dto.CompanyId.HasValue || dto.Name != null || HasCompanyFieldUpdate(dto))
|
||||||
{
|
{
|
||||||
var company = await ResolveCompanyAsync(dto.CompanyId, dto.Name, dto, userId);
|
var company = await ResolveCompanyAsync(
|
||||||
|
dto.CompanyId ?? vendor.CompanyId,
|
||||||
|
dto.Name ?? vendor.CompanyName,
|
||||||
|
dto,
|
||||||
|
userId);
|
||||||
vendor.CompanyId = company?.Id;
|
vendor.CompanyId = company?.Id;
|
||||||
ApplyCompanyFields(vendor, company);
|
ApplyCompanyFields(vendor, company);
|
||||||
}
|
}
|
||||||
|
|
@ -191,7 +191,7 @@ namespace SeaHaven.Services.Implementation
|
||||||
if (!await _vendorDataService.ExistsAsync(vendorId))
|
if (!await _vendorDataService.ExistsAsync(vendorId))
|
||||||
throw new InvalidOperationException($"Vendor with ID {vendorId} not found");
|
throw new InvalidOperationException($"Vendor with ID {vendorId} not found");
|
||||||
|
|
||||||
var linked = await _vendorDataService.GetOpenLinkedWorkOrdersAsync(vendorId);
|
var linked = await _vendorDataService.GetLinkedWorkOrdersAsync(vendorId);
|
||||||
var openWorkOrders = linked
|
var openWorkOrders = linked
|
||||||
.Where(wo => !IsTerminalWorkOrderStatus(wo.LifecycleStatus, wo.Status))
|
.Where(wo => !IsTerminalWorkOrderStatus(wo.LifecycleStatus, wo.Status))
|
||||||
.Select(MapToLinkedWorkOrderDTO)
|
.Select(MapToLinkedWorkOrderDTO)
|
||||||
|
|
@ -210,6 +210,7 @@ namespace SeaHaven.Services.Implementation
|
||||||
WorkOrderVendorUpdateDTO dto,
|
WorkOrderVendorUpdateDTO dto,
|
||||||
string userId)
|
string userId)
|
||||||
{
|
{
|
||||||
|
dto.Phone = VendorPhoneNormalizer.NormalizeToCanonical(dto.Phone);
|
||||||
var validationResult = await _workOrderUpdateValidator.ValidateAsync(dto);
|
var validationResult = await _workOrderUpdateValidator.ValidateAsync(dto);
|
||||||
if (!validationResult.IsValid)
|
if (!validationResult.IsValid)
|
||||||
{
|
{
|
||||||
|
|
@ -295,7 +296,11 @@ namespace SeaHaven.Services.Implementation
|
||||||
{
|
{
|
||||||
var byId = await _vendorDataService.GetCompanyByIdAsync(requestedCompanyId.Value);
|
var byId = await _vendorDataService.GetCompanyByIdAsync(requestedCompanyId.Value);
|
||||||
if (byId != null)
|
if (byId != null)
|
||||||
|
{
|
||||||
|
ApplyCompanyUpdates(byId, companyName, dto, userId);
|
||||||
|
await _vendorDataService.UpdateCompanyAsync(byId);
|
||||||
return byId;
|
return byId;
|
||||||
|
}
|
||||||
|
|
||||||
throw new ValidationException(new[]
|
throw new ValidationException(new[]
|
||||||
{
|
{
|
||||||
|
|
@ -311,7 +316,11 @@ namespace SeaHaven.Services.Implementation
|
||||||
var normalizedName = companyName.Trim().ToLowerInvariant();
|
var normalizedName = companyName.Trim().ToLowerInvariant();
|
||||||
var existing = await _vendorDataService.GetCompanyByNormalizedNameAsync(normalizedName);
|
var existing = await _vendorDataService.GetCompanyByNormalizedNameAsync(normalizedName);
|
||||||
if (existing != null)
|
if (existing != null)
|
||||||
|
{
|
||||||
|
ApplyCompanyUpdates(existing, companyName, dto, userId);
|
||||||
|
await _vendorDataService.UpdateCompanyAsync(existing);
|
||||||
return existing;
|
return existing;
|
||||||
|
}
|
||||||
|
|
||||||
string? companyPhone = null;
|
string? companyPhone = null;
|
||||||
string? email = null;
|
string? email = null;
|
||||||
|
|
@ -365,17 +374,73 @@ namespace SeaHaven.Services.Implementation
|
||||||
if (company == null)
|
if (company == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
vendor.CompanyPhone = company.CompanyPhone;
|
if (company.CompanyPhone != null) vendor.CompanyPhone = company.CompanyPhone;
|
||||||
vendor.Address = company.Address;
|
if (company.Address != null) vendor.Address = company.Address;
|
||||||
vendor.City = company.City;
|
if (company.City != null) vendor.City = company.City;
|
||||||
vendor.State = company.State;
|
if (company.State != null) vendor.State = company.State;
|
||||||
vendor.Zip = company.Zip;
|
if (company.Zip != null) vendor.Zip = company.Zip;
|
||||||
vendor.GoogleMapsUrl = company.GoogleMapsUrl;
|
if (company.GoogleMapsUrl != null) vendor.GoogleMapsUrl = company.GoogleMapsUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool HasCompanyFieldUpdate(UpdateVendorDTO dto) =>
|
||||||
|
dto.CompanyPhone != null ||
|
||||||
|
dto.Address != null ||
|
||||||
|
dto.City != null ||
|
||||||
|
dto.State != null ||
|
||||||
|
dto.Zipcode != null ||
|
||||||
|
dto.GoogleMapsUrl != null;
|
||||||
|
|
||||||
|
private static void ApplyCompanyUpdates(
|
||||||
|
VendorCompany company,
|
||||||
|
string? companyName,
|
||||||
|
object dto,
|
||||||
|
string userId)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(companyName))
|
||||||
|
{
|
||||||
|
company.Name = companyName.Trim();
|
||||||
|
company.NormalizedName = company.Name.ToLowerInvariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dto is CreateVendorDTO create)
|
||||||
|
{
|
||||||
|
if (create.CompanyPhone != null) company.CompanyPhone = create.CompanyPhone;
|
||||||
|
if (create.Address != null) company.Address = create.Address;
|
||||||
|
if (create.City != null) company.City = create.City;
|
||||||
|
if (create.State != null) company.State = create.State;
|
||||||
|
if (create.Zipcode != null) company.Zip = create.Zipcode;
|
||||||
|
if (create.GoogleMapsUrl != null) company.GoogleMapsUrl = create.GoogleMapsUrl;
|
||||||
|
}
|
||||||
|
else if (dto is UpdateVendorDTO update)
|
||||||
|
{
|
||||||
|
if (update.CompanyPhone != null) company.CompanyPhone = update.CompanyPhone;
|
||||||
|
if (update.Address != null) company.Address = update.Address;
|
||||||
|
if (update.City != null) company.City = update.City;
|
||||||
|
if (update.State != null) company.State = update.State;
|
||||||
|
if (update.Zipcode != null) company.Zip = update.Zipcode;
|
||||||
|
if (update.GoogleMapsUrl != null) company.GoogleMapsUrl = update.GoogleMapsUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
company.LastModificationTime = DateTime.UtcNow;
|
||||||
|
if (int.TryParse(userId, out int userIdInt))
|
||||||
|
company.LastModifierUserId = userIdInt;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void NormalizePhoneFields(CreateVendorDTO dto)
|
||||||
|
{
|
||||||
|
dto.Phone = VendorPhoneNormalizer.NormalizeToCanonical(dto.Phone);
|
||||||
|
dto.CompanyPhone = VendorPhoneNormalizer.NormalizeToCanonical(dto.CompanyPhone);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void NormalizePhoneFields(UpdateVendorDTO dto)
|
||||||
|
{
|
||||||
|
dto.Phone = VendorPhoneNormalizer.NormalizeToCanonical(dto.Phone);
|
||||||
|
dto.CompanyPhone = VendorPhoneNormalizer.NormalizeToCanonical(dto.CompanyPhone);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AssertNoOpenLinkedWorkOrdersAsync(int vendorId)
|
private async Task AssertNoOpenLinkedWorkOrdersAsync(int vendorId)
|
||||||
{
|
{
|
||||||
var linked = await _vendorDataService.GetOpenLinkedWorkOrdersAsync(vendorId);
|
var linked = await _vendorDataService.GetLinkedWorkOrdersAsync(vendorId);
|
||||||
var openWorkOrders = linked
|
var openWorkOrders = linked
|
||||||
.Where(wo => !IsTerminalWorkOrderStatus(wo.LifecycleStatus, wo.Status))
|
.Where(wo => !IsTerminalWorkOrderStatus(wo.LifecycleStatus, wo.Status))
|
||||||
.Select(MapToLinkedWorkOrderDTO)
|
.Select(MapToLinkedWorkOrderDTO)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue