From d0a90483b39a6e4c1ac3d68a44f1db0b2949ddf8 Mon Sep 17 00:00:00 2001 From: Alexandre Brandizzi Date: Fri, 21 Aug 2026 09:32:58 -0300 Subject: [PATCH 1/2] fix(vendors): show canonical list contact data --- .../VendorDataServiceTests.cs | 103 ++++++++++++++++++ .../Implementation/VendorDataService.cs | 14 ++- 2 files changed, 114 insertions(+), 3 deletions(-) diff --git a/Api.SeaHavenIndustries.Tests/VendorDataServiceTests.cs b/Api.SeaHavenIndustries.Tests/VendorDataServiceTests.cs index 650c911..2bed953 100644 --- a/Api.SeaHavenIndustries.Tests/VendorDataServiceTests.cs +++ b/Api.SeaHavenIndustries.Tests/VendorDataServiceTests.cs @@ -364,6 +364,109 @@ public class VendorDataServiceTests items.Should().Contain(i => i.ContactName == "No Company Tech" && i.VendorId != null); } + [Fact] + public async Task GetDirectoryPagedAsync_UsesCanonicalCompanyLocationAndEmailFallback() + { + await using var context = NewContext(); + var company = new VendorCompany + { + Name = "Canonical Co", + NormalizedName = "canonical co", + Email = "dispatch@canonical.example", + City = "Chicago", + State = "IL" + }; + context.VendorCompanies.Add(company); + context.Vendors.AddRange( + new Vendor + { + CompanyName = "Canonical Co", + ContactName = "Company Fallback", + Email = " ", + City = "Stale City", + State = "TX", + IsActive = true, + IsDeleted = false, + Company = company + }, + new Vendor + { + CompanyName = "Canonical Co", + ContactName = "Technician Email", + Email = "technician@canonical.example", + IsActive = true, + IsDeleted = false, + Company = company + }, + new Vendor + { + CompanyName = "Legacy Co", + ContactName = "Unlinked Technician", + Email = "legacy@example.com", + City = "Austin", + State = "TX", + IsActive = true, + IsDeleted = false, + CompanyId = null + }); + await context.SaveChangesAsync(); + + var service = new VendorDataService(context); + var (items, totalCount) = await service.GetDirectoryPagedAsync(1, 50, isActive: true); + + totalCount.Should().Be(3); + var companyFallback = items.Single(i => i.ContactName == "Company Fallback"); + companyFallback.Email.Should().Be("dispatch@canonical.example"); + companyFallback.City.Should().Be("Chicago"); + companyFallback.State.Should().Be("IL"); + + var technicianEmail = items.Single(i => i.ContactName == "Technician Email"); + technicianEmail.Email.Should().Be("technician@canonical.example"); + technicianEmail.City.Should().Be("Chicago"); + technicianEmail.State.Should().Be("IL"); + + var legacy = items.Single(i => i.ContactName == "Unlinked Technician"); + legacy.Email.Should().Be("legacy@example.com"); + legacy.City.Should().Be("Austin"); + legacy.State.Should().Be("TX"); + } + + [Fact] + public async Task GetDirectoryPagedAsync_SearchAndLocationFilterUseCanonicalCompanyLocation() + { + await using var context = NewContext(); + var company = new VendorCompany + { + Name = "Searchable Co", + NormalizedName = "searchable co", + City = "Chicago", + State = "IL" + }; + context.VendorCompanies.Add(company); + context.Vendors.Add(new Vendor + { + CompanyName = "Searchable Co", + ContactName = "Pat", + City = null, + State = null, + IsActive = true, + IsDeleted = false, + Company = company + }); + await context.SaveChangesAsync(); + + var service = new VendorDataService(context); + var search = await service.GetDirectoryPagedAsync(1, 50, search: "chicago", isActive: true); + var location = await service.GetDirectoryPagedAsync( + 1, + 50, + isActive: true, + locations: new[] { "Chicago, IL" }); + + search.Items.Should().ContainSingle(i => i.ContactName == "Pat"); + location.Items.Should().ContainSingle(i => i.ContactName == "Pat"); + } + [Theory] [InlineData("trade")] [InlineData("location")] diff --git a/SeaHaven.DataServices/Implementation/VendorDataService.cs b/SeaHaven.DataServices/Implementation/VendorDataService.cs index 01a5be6..81f77ba 100644 --- a/SeaHaven.DataServices/Implementation/VendorDataService.cs +++ b/SeaHaven.DataServices/Implementation/VendorDataService.cs @@ -191,13 +191,21 @@ namespace SeaHaven.DataServices.Implementation CompanyId = v.CompanyId ?? 0, CompanyName = v.CompanyName, ContactName = v.ContactName, - Email = v.Email, + Email = v.Email != null && v.Email.Trim() != "" + ? v.Email + : v.Company != null + ? v.Company.Email + : v.Email, Phone = v.Phone, CompanyPhone = v.CompanyPhone, PreferredContact = v.PreferredContact, Address = v.Address, - City = v.City, - State = v.State, + City = v.Company != null && v.Company.City != null && v.Company.City.Trim() != "" + ? v.Company.City + : v.City, + State = v.Company != null && v.Company.State != null && v.Company.State.Trim() != "" + ? v.Company.State + : v.State, Zip = v.Zip, TradeSpecialties = v.TradeSpecialties, GoogleMapsUrl = v.GoogleMapsUrl, From 9c3da9b5e3e3150214f1fd0a264ca8fc96c4211b Mon Sep 17 00:00:00 2001 From: Alexandre Brandizzi Date: Fri, 21 Aug 2026 09:40:51 -0300 Subject: [PATCH 2/2] fix(vendors): keep location fallback atomic --- .../VendorDataServiceTests.cs | 17 +++++++++++------ .../Implementation/VendorDataService.cs | 8 ++++++-- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/Api.SeaHavenIndustries.Tests/VendorDataServiceTests.cs b/Api.SeaHavenIndustries.Tests/VendorDataServiceTests.cs index 2bed953..a7d91f1 100644 --- a/Api.SeaHavenIndustries.Tests/VendorDataServiceTests.cs +++ b/Api.SeaHavenIndustries.Tests/VendorDataServiceTests.cs @@ -440,15 +440,15 @@ public class VendorDataServiceTests Name = "Searchable Co", NormalizedName = "searchable co", City = "Chicago", - State = "IL" + State = null }; context.VendorCompanies.Add(company); context.Vendors.Add(new Vendor { CompanyName = "Searchable Co", ContactName = "Pat", - City = null, - State = null, + City = "Stale City", + State = "TX", IsActive = true, IsDeleted = false, Company = company @@ -461,10 +461,15 @@ public class VendorDataServiceTests 1, 50, isActive: true, - locations: new[] { "Chicago, IL" }); + locations: new[] { "Chicago" }); - search.Items.Should().ContainSingle(i => i.ContactName == "Pat"); - location.Items.Should().ContainSingle(i => i.ContactName == "Pat"); + var searchRow = search.Items.Should().ContainSingle(i => i.ContactName == "Pat").Subject; + searchRow.City.Should().Be("Chicago"); + searchRow.State.Should().BeNull(); + + var locationRow = location.Items.Should().ContainSingle(i => i.ContactName == "Pat").Subject; + locationRow.City.Should().Be("Chicago"); + locationRow.State.Should().BeNull(); } [Theory] diff --git a/SeaHaven.DataServices/Implementation/VendorDataService.cs b/SeaHaven.DataServices/Implementation/VendorDataService.cs index 81f77ba..dc09d71 100644 --- a/SeaHaven.DataServices/Implementation/VendorDataService.cs +++ b/SeaHaven.DataServices/Implementation/VendorDataService.cs @@ -200,10 +200,14 @@ namespace SeaHaven.DataServices.Implementation CompanyPhone = v.CompanyPhone, PreferredContact = v.PreferredContact, Address = v.Address, - City = v.Company != null && v.Company.City != null && v.Company.City.Trim() != "" + City = v.Company != null && + ((v.Company.City != null && v.Company.City.Trim() != "") || + (v.Company.State != null && v.Company.State.Trim() != "")) ? v.Company.City : v.City, - State = v.Company != null && v.Company.State != null && v.Company.State.Trim() != "" + State = v.Company != null && + ((v.Company.City != null && v.Company.City.Trim() != "") || + (v.Company.State != null && v.Company.State.Trim() != "")) ? v.Company.State : v.State, Zip = v.Zip,