Phase 4: Past appointments + AI prediction demo data
- Appointments: add ~25 past appointments (last 90 days) with Completed, Cancelled, No Show, and Rescheduled statuses; completed records carry ActualStartTime/ActualEndTime with realistic variance; cancel/no-show notes explain why; customer label falls back to ContactFirst/LastName for residential customers - Fix future appointment title for residential customers (was always using CompanyName which is null for individuals) - New SeedDataService.AiPredictions.cs: seeds 8 AiItemPrediction records (varied complexity/confidence/tags/reasoning) and attaches them to the first 8 eligible QuoteItems, marking those items IsAiItem=true; 3 of 8 have UserOverrodeEstimate=true for AI Accuracy report demo - SeedDataService.cs: wire SeedAiPredictionsAsync after Invoices - Remove.cs: collect QuoteItem.AiPredictionId FKs before deleting items, then delete orphaned AiItemPrediction records after quotes are removed Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -180,6 +180,14 @@ public partial class SeedDataService
|
||||
|
||||
if (seededQuoteIds.Any())
|
||||
{
|
||||
// Collect prediction IDs before removing items (FK is NoAction — predictions
|
||||
// must be deleted after the items that reference them are gone).
|
||||
var predictionIds = await _context.QuoteItems.IgnoreQueryFilters()
|
||||
.Where(qi => seededQuoteIds.Contains(qi.QuoteId) && qi.AiPredictionId != null)
|
||||
.Select(qi => qi.AiPredictionId!.Value)
|
||||
.Distinct()
|
||||
.ToListAsync();
|
||||
|
||||
var quoteItems = await _context.QuoteItems.IgnoreQueryFilters()
|
||||
.Where(qi => seededQuoteIds.Contains(qi.QuoteId)).ToListAsync();
|
||||
if (quoteItems.Any()) _context.QuoteItems.RemoveRange(quoteItems);
|
||||
@@ -193,6 +201,21 @@ public partial class SeedDataService
|
||||
_context.Quotes.RemoveRange(quotes);
|
||||
totalRemoved += quotes.Count;
|
||||
details.Add($"✓ Removed {quotes.Count} seeded quote(s)");
|
||||
|
||||
// Remove orphaned AI predictions now that QuoteItems no longer reference them
|
||||
if (predictionIds.Any())
|
||||
{
|
||||
var predictions = await _context.Set<Core.Entities.AiItemPrediction>()
|
||||
.IgnoreQueryFilters()
|
||||
.Where(p => predictionIds.Contains(p.Id))
|
||||
.ToListAsync();
|
||||
if (predictions.Any())
|
||||
{
|
||||
_context.Set<Core.Entities.AiItemPrediction>().RemoveRange(predictions);
|
||||
totalRemoved += predictions.Count;
|
||||
details.Add($"✓ Removed {predictions.Count} AI prediction(s)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Customer notes
|
||||
|
||||
Reference in New Issue
Block a user