Add QuoteApprovedByCustomer notification type; fix wrong type logged on approval

QuoteDeclinedByCustomer was used for both approve and decline responses,
so approval notifications showed the wrong type in the log. Added a distinct
QuoteApprovedByCustomer = 16 enum value, wired up the correct type in
NotificationService, added default templates in both the service fallback
dictionary and SeedData, and updated placeholder hints in CompanySettings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-06 17:13:34 -04:00
parent 4085ff7c73
commit d3863c713b
4 changed files with 39 additions and 4 deletions
@@ -977,6 +977,28 @@ New accounts walk through an 18-step setup wizard to configure company informati
CompanyId = companyId,
CreatedAt = DateTime.UtcNow
},
new NotificationTemplate
{
NotificationType = NotificationType.QuoteApprovedByCustomer,
Channel = NotificationChannel.Email,
DisplayName = "Quote Approved by Customer (Internal)",
Subject = "Customer Response: Quote {{quoteNumber}} — {{companyName}}",
Body = "<p>Hello,</p><p>A customer has responded to quote <strong>{{quoteNumber}}</strong>.</p><p><strong>Customer:</strong> {{customerName}}<br/><strong>Response:</strong> {{response}}</p><p>Log in to the portal to review and follow up.</p>",
IsActive = true,
CompanyId = companyId,
CreatedAt = DateTime.UtcNow
},
new NotificationTemplate
{
NotificationType = NotificationType.QuoteDeclinedByCustomer,
Channel = NotificationChannel.Email,
DisplayName = "Quote Declined by Customer (Internal)",
Subject = "Customer Response: Quote {{quoteNumber}} — {{companyName}}",
Body = "<p>Hello,</p><p>A customer has responded to quote <strong>{{quoteNumber}}</strong>.</p><p><strong>Customer:</strong> {{customerName}}<br/><strong>Response:</strong> {{response}}</p>{{declineReasonSection}}<p>Log in to the portal to review and follow up.</p>",
IsActive = true,
CompanyId = companyId,
CreatedAt = DateTime.UtcNow
},
];
}
@@ -900,8 +900,12 @@ public class NotificationService : INotificationService
? $"Quote {quote.QuoteNumber} APPROVED — {customerName}"
: $"Quote {quote.QuoteNumber} DECLINED — {customerName}";
var notificationType = approved
? NotificationType.QuoteApprovedByCustomer
: NotificationType.QuoteDeclinedByCustomer;
var (subject, htmlBody) = await GetRenderedEmailAsync(
quote.CompanyId, NotificationType.QuoteDeclinedByCustomer, values, defaultSubject);
quote.CompanyId, notificationType, values, defaultSubject);
var fullHtml = AppendUnsubscribeFooterHtml(htmlBody, token: null, company, await GetBaseUrlAsync());
var plainText = StripHtml(fullHtml);
@@ -913,7 +917,7 @@ public class NotificationService : INotificationService
await WriteLog(new NotificationLog
{
Channel = NotificationChannel.Email,
NotificationType = NotificationType.QuoteDeclinedByCustomer,
NotificationType = notificationType,
Status = success ? NotificationStatus.Sent : NotificationStatus.Failed,
RecipientName = companyName,
Recipient = companyEmail,
@@ -1133,6 +1137,10 @@ public class NotificationService : INotificationService
"Payment Received — Invoice {{invoiceNumber}}",
"<p>Dear {{customerName}},</p><p>We have received your payment of <strong>{{paymentAmount}}</strong> on {{paymentDate}} for invoice <strong>{{invoiceNumber}}</strong>.{{balanceDue}}</p><p>Thank you for your business with {{companyName}}.</p>"
),
[(NotificationType.QuoteApprovedByCustomer, NotificationChannel.Email)] = (
"Customer Response: Quote {{quoteNumber}} — {{companyName}}",
"<p>Hello,</p><p>A customer has responded to quote <strong>{{quoteNumber}}</strong>.</p><p><strong>Customer:</strong> {{customerName}}<br/><strong>Response:</strong> {{response}}</p><p>Log in to the portal to review and follow up.</p>"
),
[(NotificationType.QuoteDeclinedByCustomer, NotificationChannel.Email)] = (
"Customer Response: Quote {{quoteNumber}} — {{companyName}}",
"<p>Hello,</p><p>A customer has responded to quote <strong>{{quoteNumber}}</strong>.</p><p><strong>Customer:</strong> {{customerName}}<br/><strong>Response:</strong> {{response}}</p>{{declineReasonSection}}<p>Log in to the portal to review and follow up.</p>"