Phase 3: AR/AP aging buckets, PO seeder, Bills vendor fix

- Bills.cs: replace aceHardware/fastenal lookups with grainger/harbor/localSupply
  to match Phase 1 vendor renames; update all vendor invoice number prefixes
- Bills.cs: add 3 AP aging-bucket bills (30-60, 61-90, 90+ days overdue) so all
  four AP aging buckets are populated for report demos
- Invoices.cs: add 3 more overdue invoices (31-60, 61-90, 90+ day AR buckets)
  alongside the existing 21-day overdue; total now 29 invoices
- New SeedDataService.PurchaseOrders.cs: 7 POs — 3 Received (historical), 2
  Submitted (in-flight), 2 Draft (pending approval); links to inventory items
  where available
- SeedDataService.cs: wire SeedPurchaseOrdersAsync after Vendors seeder
- Remove.cs: add PO + POItem cleanup inside Bills removal block (two-step ID
  fetch to avoid nested LINQ translation issues)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 22:29:31 -04:00
parent 584664e7c8
commit dbd39a9fe5
5 changed files with 359 additions and 25 deletions
@@ -342,6 +342,34 @@ public partial class SeedDataService
}
}
// --- Purchase Orders (removed alongside bills — tightly coupled in demo workflows) ---
if (options.Bills)
{
var poIds = await _context.Set<Core.Entities.PurchaseOrder>()
.IgnoreQueryFilters()
.Where(p => p.CompanyId == companyId)
.Select(p => p.Id)
.ToListAsync();
if (poIds.Any())
{
var poItems = await _context.Set<Core.Entities.PurchaseOrderItem>()
.IgnoreQueryFilters()
.Where(i => poIds.Contains(i.PurchaseOrderId))
.ToListAsync();
if (poItems.Any()) _context.Set<Core.Entities.PurchaseOrderItem>().RemoveRange(poItems);
var pos = await _context.Set<Core.Entities.PurchaseOrder>()
.IgnoreQueryFilters()
.Where(p => poIds.Contains(p.Id))
.ToListAsync();
_context.Set<Core.Entities.PurchaseOrder>().RemoveRange(pos);
totalRemoved += pos.Count;
details.Add($"✓ Removed {pos.Count} purchase order(s)");
await _context.SaveChangesAsync();
}
}
// --- Vendor Bills (all bills for the company) ---
if (options.Bills)
{