Add Formula Library ratings, Job Profitability report, and Quote Revision History improvements
- Formula Library ratings: thumbs up/down per company per formula; toggle on/off; sorts by net score; own formulas not rateable; FormulaLibraryRating entity + migration AddFormulaLibraryRatings - Job Profitability report: actual labor cost (logged hours x StandardLaborRate) vs powder cost vs billed price per job; gross margin % color-coded; time-tracked-only filter; totals footer - Quote Revision History: track Total price changes on every save; log Sent/Resent events with recipient email; replace flat table with grouped timeline UI (icons per event type, total-change badge on header) - Setup Wizard: cap CompletedCount at TotalSteps so old 10-step data no longer shows 10/5 - Formula Library card: fix badge overflow on long titles; add Rate: label to make voting buttons discoverable - Help docs and AI knowledge base updated for all three features Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -295,6 +295,9 @@ public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IDataPro
|
||||
/// <summary>Per-company record of which community library formulas a company has imported.</summary>
|
||||
public DbSet<FormulaLibraryImport> FormulaLibraryImports { get; set; }
|
||||
|
||||
/// <summary>Per-company thumbs-up / thumbs-down vote on community library formulas.</summary>
|
||||
public DbSet<FormulaLibraryRating> FormulaLibraryRatings { get; set; }
|
||||
|
||||
/// <summary>User-submitted bug reports; tenant-filtered with soft delete.</summary>
|
||||
public DbSet<BugReport> BugReports { get; set; }
|
||||
/// <summary>File attachments for bug reports; soft-delete only (no tenant filter — access controlled via parent BugReport).</summary>
|
||||
@@ -2116,6 +2119,18 @@ modelBuilder.Entity<Job>()
|
||||
.IsUnique()
|
||||
.HasDatabaseName("IX_FormulaLibraryImports_Company_Item");
|
||||
|
||||
// FormulaLibraryRating — platform-level; one vote per company per formula
|
||||
modelBuilder.Entity<FormulaLibraryRating>()
|
||||
.HasOne(r => r.FormulaLibraryItem)
|
||||
.WithMany()
|
||||
.HasForeignKey(r => r.FormulaLibraryItemId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<FormulaLibraryRating>()
|
||||
.HasIndex(r => new { r.FormulaLibraryItemId, r.CompanyId })
|
||||
.IsUnique()
|
||||
.HasDatabaseName("IX_FormulaLibraryRatings_Item_Company");
|
||||
|
||||
// CustomItemTemplate → FormulaLibraryItem (nullable; only set on imported templates)
|
||||
modelBuilder.Entity<CustomItemTemplate>()
|
||||
.HasOne(t => t.SourceFormulaLibraryItem)
|
||||
|
||||
Reference in New Issue
Block a user