diff --git a/src/PowderCoating.Infrastructure/Services/NotificationService.cs b/src/PowderCoating.Infrastructure/Services/NotificationService.cs
index 3c09bc7..747a32e 100644
--- a/src/PowderCoating.Infrastructure/Services/NotificationService.cs
+++ b/src/PowderCoating.Infrastructure/Services/NotificationService.cs
@@ -94,7 +94,7 @@ public class NotificationService : INotificationService
quote.CompanyId, NotificationType.QuoteSent, values,
$"Your Quote {quote.QuoteNumber} from {companyName}");
- var fullHtml = AppendUnsubscribeFooterHtml(htmlBody, token: null, company, baseUrl);
+ var fullHtml = AppendUnsubscribeFooterHtml(htmlBody, token: null, company, baseUrl, replyToEmail);
var plainText = StripHtml(fullHtml);
var (success, error) = await _emailService.SendEmailAsync(
@@ -137,7 +137,7 @@ public class NotificationService : INotificationService
quote.CompanyId, NotificationType.QuoteSent, values,
$"Your Quote {quote.QuoteNumber} from {companyName}");
- var fullHtml = AppendUnsubscribeFooterHtml(htmlBody, customer.UnsubscribeToken, company, baseUrl);
+ var fullHtml = AppendUnsubscribeFooterHtml(htmlBody, customer.UnsubscribeToken, company, baseUrl, replyToEmail);
var plainText = StripHtml(fullHtml);
var (success, error, recipientsLog) = await SendToEmailListAsync(
@@ -300,7 +300,7 @@ public class NotificationService : INotificationService
quote.CompanyId, NotificationType.QuoteApproved, values,
$"Quote {quote.QuoteNumber} Approved — {companyName}");
- var fullHtml = AppendUnsubscribeFooterHtml(htmlBody, customer.UnsubscribeToken, company, await GetBaseUrlAsync());
+ var fullHtml = AppendUnsubscribeFooterHtml(htmlBody, customer.UnsubscribeToken, company, await GetBaseUrlAsync(), replyToEmail);
var plainText = StripHtml(fullHtml);
var (success, error, recipientsLog) = await SendToEmailListAsync(
@@ -383,7 +383,7 @@ public class NotificationService : INotificationService
var (subject, htmlBody) = await GetRenderedEmailAsync(
job.CompanyId, notifType, values, defaultSubject);
- var fullHtml = AppendUnsubscribeFooterHtml(htmlBody, customer.UnsubscribeToken, company, await GetBaseUrlAsync());
+ var fullHtml = AppendUnsubscribeFooterHtml(htmlBody, customer.UnsubscribeToken, company, await GetBaseUrlAsync(), replyToEmail);
var plainText = StripHtml(fullHtml);
var (success, error, recipientsLog) = await SendToEmailListAsync(
@@ -451,7 +451,7 @@ public class NotificationService : INotificationService
job.CompanyId, NotificationType.JobCompleted, values,
$"Job {job.JobNumber} Complete — {companyName}");
- var fullHtml = AppendUnsubscribeFooterHtml(htmlBody, customer.UnsubscribeToken, company, await GetBaseUrlAsync());
+ var fullHtml = AppendUnsubscribeFooterHtml(htmlBody, customer.UnsubscribeToken, company, await GetBaseUrlAsync(), replyToEmail);
var plainText = StripHtml(fullHtml);
var (success, error, recipientsLog) = await SendToEmailListAsync(
@@ -674,7 +674,7 @@ public class NotificationService : INotificationService
""";
}
- var fullHtml = AppendUnsubscribeFooterHtml(htmlBody, customer.UnsubscribeToken, company, await GetBaseUrlAsync());
+ var fullHtml = AppendUnsubscribeFooterHtml(htmlBody, customer.UnsubscribeToken, company, await GetBaseUrlAsync(), replyToEmail);
var plainText = !string.IsNullOrEmpty(paymentUrl)
? StripHtml(htmlBody) + $"\r\n\r\nPay online: {paymentUrl}"
: StripHtml(fullHtml);
@@ -793,7 +793,7 @@ public class NotificationService : INotificationService
invoice.CompanyId, NotificationType.PaymentReceived, values,
$"Payment Received — Invoice {invoice.InvoiceNumber}");
- var fullHtml = AppendUnsubscribeFooterHtml(htmlBody, customer.UnsubscribeToken, company, await GetBaseUrlAsync());
+ var fullHtml = AppendUnsubscribeFooterHtml(htmlBody, customer.UnsubscribeToken, company, await GetBaseUrlAsync(), replyToEmail);
var plainText = StripHtml(fullHtml);
var (success, error, recipientsLog) = await SendToEmailListAsync(
@@ -867,7 +867,7 @@ public class NotificationService : INotificationService
invoice.CompanyId, NotificationType.PaymentReminder, values,
$"Payment Reminder — Invoice {invoice.InvoiceNumber} ({daysOverdue} days overdue)");
- var fullHtml = AppendUnsubscribeFooterHtml(htmlBody, customer.UnsubscribeToken, company, await GetBaseUrlAsync());
+ var fullHtml = AppendUnsubscribeFooterHtml(htmlBody, customer.UnsubscribeToken, company, await GetBaseUrlAsync(), replyToEmail);
var plainText = StripHtml(fullHtml);
var (success, error, recipientsLog) = await SendToEmailListAsync(
@@ -971,7 +971,7 @@ public class NotificationService : INotificationService
var (subject, htmlBody) = await GetRenderedEmailAsync(
quote.CompanyId, notificationType, values, defaultSubject);
- var fullHtml = AppendUnsubscribeFooterHtml(htmlBody, token: null, company, await GetBaseUrlAsync());
+ var fullHtml = AppendUnsubscribeFooterHtml(htmlBody, token: null, company, await GetBaseUrlAsync(), replyToEmail);
var plainText = StripHtml(fullHtml);
var (success, error) = await _emailService.SendEmailAsync(
@@ -1218,7 +1218,7 @@ public class NotificationService : INotificationService
var (custSubject, custHtml) = await GetRenderedEmailAsync(
appointment.CompanyId, NotificationType.AppointmentReminder, customerValues, defaultSubject);
- var custFullHtml = AppendUnsubscribeFooterHtml(custHtml, customer.UnsubscribeToken, company, baseUrl);
+ var custFullHtml = AppendUnsubscribeFooterHtml(custHtml, customer.UnsubscribeToken, company, baseUrl, replyToEmail);
var custPlainText = StripHtml(custFullHtml);
var (custOk, custErr, custLog) = await SendToEmailListAsync(
@@ -1388,17 +1388,25 @@ public class NotificationService : INotificationService
///
";
+ if (hasReplyTo)
+ {
+ var encodedEmail = WebUtility.HtmlEncode(replyToEmail!);
+ footer += $"Questions? Reply to this email or contact us at {encodedEmail}";
+ if (hasAddress || hasUnsubscribeUrl) footer += "
";
+ }
+
if (hasAddress)
{
var addressLine = BuildAddressLine(company!);
diff --git a/src/PowderCoating.Web/Controllers/QuotesController.cs b/src/PowderCoating.Web/Controllers/QuotesController.cs
index 7929231..ff3cd3d 100644
--- a/src/PowderCoating.Web/Controllers/QuotesController.cs
+++ b/src/PowderCoating.Web/Controllers/QuotesController.cs
@@ -1957,12 +1957,10 @@ public class QuotesController : Controller
if (dto.SmsConsent)
await _notificationService.NotifySmsConsentGrantedAsync(customer);
- // Get "Converted" status (cached)
- var companyId = _tenantContext.GetCurrentCompanyId() ?? 0;
- var statuses = await _lookupCache.GetQuoteStatusLookupsAsync(companyId);
- var convertedStatus = statuses.FirstOrDefault(s => s.StatusCode == AppConstants.StatusCodes.Quote.Converted);
-
- // Update quote to link to new customer
+ // Update quote to link to new customer.
+ // Do NOT set "Converted" status here — that status is reserved for when a job is
+ // actually created via CreateJobFromQuote. Keeping the quote at "Approved" lets the
+ // user immediately click "Create Job from Quote" on the next screen.
quote.CustomerId = customer.Id;
// Clear prospect fields
@@ -1977,14 +1975,11 @@ public class QuotesController : Controller
quote.ProspectSmsConsent = false;
quote.ProspectSmsConsentedAt = null;
- // Update status to converted
- quote.QuoteStatusId = convertedStatus?.Id ?? quote.QuoteStatusId;
-
await _unitOfWork.Quotes.UpdateAsync(quote);
await _unitOfWork.CompleteAsync();
- this.ToastSuccess($"Prospect/Walk-In successfully converted to customer! Quote {quote.QuoteNumber} has been updated.");
- return RedirectToAction("Details", "Customers", new { id = customer.Id });
+ this.ToastSuccess($"Customer record created! You can now create a job from quote {quote.QuoteNumber}.");
+ return RedirectToAction(nameof(Details), new { id = dto.QuoteId });
}
catch (Exception ex)
{