Add TCPA-compliant SMS consent tracking for prospect quotes
- Quote entity: ProspectSmsConsent (bool) + ProspectSmsConsentedAt (DateTime?) fields - QuoteDtos: consent fields on Create/Update/Convert DTOs with TCPA guidance text - Quote Create/Edit views: SMS consent checkbox shown when mobile number is entered - Quote ConvertToCustomer view: staff must re-confirm consent carries over to customer record - QuoteApproval: consent state exposed in ViewModel and ApprovalPage for transparency - Consent timestamp cleared when prospect quote is linked to an existing customer - Migration: AddProspectSmsConsent Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -59,6 +59,8 @@ public class QuoteDto
|
||||
public string? ProspectCity { get; set; }
|
||||
public string? ProspectState { get; set; }
|
||||
public string? ProspectZipCode { get; set; }
|
||||
public bool ProspectSmsConsent { get; set; }
|
||||
public DateTime? ProspectSmsConsentedAt { get; set; }
|
||||
|
||||
public string? PreparedById { get; set; }
|
||||
public string? PreparedByName { get; set; }
|
||||
@@ -186,6 +188,9 @@ public class CreateQuoteDto
|
||||
[StringLength(10)]
|
||||
public string? ProspectZipCode { get; set; }
|
||||
|
||||
[Display(Name = "SMS Consent")]
|
||||
public bool ProspectSmsConsent { get; set; } = false;
|
||||
|
||||
// Oven Selection
|
||||
[Display(Name = "Oven")]
|
||||
public int? OvenCostId { get; set; }
|
||||
@@ -322,6 +327,9 @@ public class UpdateQuoteDto
|
||||
[StringLength(10)]
|
||||
public string? ProspectZipCode { get; set; }
|
||||
|
||||
[Display(Name = "SMS Consent")]
|
||||
public bool ProspectSmsConsent { get; set; } = false;
|
||||
|
||||
// Oven Selection
|
||||
[Display(Name = "Oven")]
|
||||
public int? OvenCostId { get; set; }
|
||||
@@ -685,6 +693,16 @@ public class ConvertQuoteToCustomerDto
|
||||
[Display(Name = "Notes")]
|
||||
[DataType(DataType.MultilineText)]
|
||||
public string? Notes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Staff must explicitly confirm verbal SMS consent before it carries over to the new customer record.
|
||||
/// Pre-checked when ProspectSmsConsent was true on the source quote.
|
||||
/// </summary>
|
||||
[Display(Name = "Customer has given verbal consent to receive SMS notifications")]
|
||||
public bool SmsConsent { get; set; }
|
||||
|
||||
/// <summary>Timestamp from the source quote — preserved so the consent record reflects when consent was originally given.</summary>
|
||||
public DateTime? ProspectSmsConsentedAt { get; set; }
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -745,6 +763,16 @@ public class CreateQuoteItemCoatDto
|
||||
/// When true, the additional layer labor charge is not applied even if this is not the first coat.
|
||||
/// </summary>
|
||||
public bool NoExtraLayerCharge { get; set; }
|
||||
|
||||
/// <summary>Platform powder catalog item ID selected via the Custom tab lookup.</summary>
|
||||
public int? CatalogItemId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When true (and CatalogItemId is set), the server creates a 0-balance IsIncoming inventory
|
||||
/// item from the catalog entry so QR codes can be printed while the powder is in transit.
|
||||
/// The coat is then linked to that new inventory record.
|
||||
/// </summary>
|
||||
public bool AddAsIncoming { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user