Files
PowderCoatingLogix/src/PowderCoating.Web/Views/Quotes/ConvertToCustomer.cshtml
T
spouliot f40d58ac2e 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>
2026-05-08 20:47:04 -04:00

336 lines
17 KiB
Plaintext

@model PowderCoating.Application.DTOs.Quote.ConvertQuoteToCustomerDto
@{
ViewData["Title"] = "Convert Prospect/Walk-In to Customer";
ViewData["PageIcon"] = "bi-arrow-right-circle-fill";
}
<div class="container-fluid mt-4">
<div class="mb-4">
<p class="text-muted">Quote: <strong>@Model.QuoteNumber</strong></p>
</div>
<div class="row">
<div class="col-lg-8">
<form asp-action="ConvertToCustomer" method="post">
<input type="hidden" asp-for="QuoteId" />
<input type="hidden" asp-for="QuoteNumber" />
<partial name="_ValidationSummary" />
<!-- Quote Summary (Read-Only) -->
<div class="card mb-4">
<div class="card-header bg-info text-white">
<h5 class="mb-0">
<i class="bi bi-file-text me-2"></i>Quote Summary
</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<p><strong>Quote Number:</strong> @Model.QuoteNumber</p>
<p><strong>Current Prospect/Walk-In:</strong> @(Model.CompanyName ?? Model.ContactName ?? "Unknown")</p>
</div>
<div class="col-md-6">
<p><strong>Email:</strong> @(Model.Email ?? "-")</p>
<p><strong>Phone:</strong> @(Model.Phone ?? "-")</p>
</div>
</div>
<div class="alert alert-warning mb-0">
<i class="bi bi-exclamation-triangle me-2"></i>
<strong>Note:</strong> Converting this prospect will create a new customer record
and link this quote to that customer. The quote status will change to "Converted".
</div>
</div>
</div>
<!-- Customer Information -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="bi bi-building me-2"></i>Customer Information
</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-12">
<div class="mb-3">
<label asp-for="IsCommercial" class="form-label">Customer Type</label>
<select asp-for="IsCommercial" class="form-select" id="customerTypeSelect" onchange="toggleCompanyNameRequired()">
<option value="false">Individual</option>
<option value="true">Commercial</option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label asp-for="CompanyName" class="form-label">
Company Name <span id="companyNameRequired" class="text-danger" style="display:none;">*</span>
</label>
<input asp-for="CompanyName" class="form-control" />
<span asp-validation-for="CompanyName" class="text-danger"></span>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label asp-for="ContactName" class="form-label">Contact Name <span class="text-danger">*</span></label>
<input asp-for="ContactName" class="form-control" placeholder="First and last name" />
<span asp-validation-for="ContactName" class="text-danger"></span>
</div>
</div>
</div>
<div class="row">
<div class="col-12 mb-2">
<small class="text-muted"><span class="text-danger">*</span> At least one of email or phone is required.</small>
</div>
<div class="col-md-6">
<div class="mb-3">
<label asp-for="Email" class="form-label">Email</label>
<input asp-for="Email" class="form-control" type="email" placeholder="customer@example.com" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label asp-for="Phone" class="form-label">Phone</label>
<input asp-for="Phone" class="form-control" type="tel" placeholder="(555) 000-0000" />
<span asp-validation-for="Phone" class="text-danger"></span>
</div>
</div>
</div>
</div>
</div>
<!-- Address Information -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="bi bi-geo-alt me-2"></i>Address Information
</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-12">
<div class="mb-3">
<label asp-for="Address" class="form-label"></label>
<input asp-for="Address" class="form-control" />
<span asp-validation-for="Address" class="text-danger"></span>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label asp-for="City" class="form-label"></label>
<input asp-for="City" class="form-control" />
<span asp-validation-for="City" class="text-danger"></span>
</div>
</div>
<div class="col-md-3">
<div class="mb-3">
<label asp-for="State" class="form-label"></label>
<input asp-for="State" class="form-control" maxlength="2" />
<span asp-validation-for="State" class="text-danger"></span>
</div>
</div>
<div class="col-md-3">
<div class="mb-3">
<label asp-for="ZipCode" class="form-label"></label>
<input asp-for="ZipCode" class="form-control" />
<span asp-validation-for="ZipCode" class="text-danger"></span>
</div>
</div>
</div>
</div>
</div>
<!-- Additional Customer Details -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="bi bi-gear me-2"></i>Additional Details
</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label asp-for="TaxId" class="form-label"></label>
<input asp-for="TaxId" class="form-control" />
<span asp-validation-for="TaxId" class="text-danger"></span>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label asp-for="PaymentTerms" class="form-label"></label>
<select asp-for="PaymentTerms" class="form-select">
<option value="">Select payment terms</option>
<option value="Net 15">Net 15</option>
<option value="Net 30">Net 30</option>
<option value="Net 45">Net 45</option>
<option value="Net 60">Net 60</option>
<option value="Due on Receipt">Due on Receipt</option>
<option value="Cash on Delivery">Cash on Delivery</option>
</select>
<span asp-validation-for="PaymentTerms" class="text-danger"></span>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label asp-for="CreditLimit" class="form-label"></label>
<input asp-for="CreditLimit" class="form-control" type="number" step="0.01" />
<span asp-validation-for="CreditLimit" class="text-danger"></span>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label asp-for="PricingTierId" class="form-label"></label>
<select asp-for="PricingTierId" class="form-select" asp-items="ViewBag.PricingTiers">
<option value="">-- No Pricing Tier --</option>
</select>
<span asp-validation-for="PricingTierId" class="text-danger"></span>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="mb-3">
<label asp-for="Notes" class="form-label"></label>
<textarea asp-for="Notes" class="form-control" rows="3"></textarea>
<span asp-validation-for="Notes" class="text-danger"></span>
</div>
</div>
</div>
</div>
</div>
<!-- SMS Notifications -->
<div class="card mb-4 border-info">
<div class="card-header bg-info bg-opacity-10">
<h5 class="mb-0">
<i class="bi bi-phone me-2"></i>SMS Notifications
</h5>
</div>
<div class="card-body">
<input type="hidden" asp-for="ProspectSmsConsentedAt" />
@if (Model.SmsConsent)
{
<div class="alert alert-success alert-permanent mb-3 py-2">
<i class="bi bi-check-circle me-1"></i>
<strong>SMS consent was recorded on the quote</strong>
@if (Model.ProspectSmsConsentedAt.HasValue)
{
<span>on @Model.ProspectSmsConsentedAt.Value.ToLocalTime().ToString("MM/dd/yyyy")</span>
}
</div>
}
else
{
<div class="alert alert-warning alert-permanent mb-3 py-2">
<i class="bi bi-exclamation-triangle me-1"></i>
<strong>No SMS consent was recorded on the quote.</strong>
</div>
}
<div class="form-check">
<input asp-for="SmsConsent" class="form-check-input" id="SmsConsent" />
<label class="form-check-label fw-semibold" for="SmsConsent">
Customer has given verbal consent to receive SMS notifications
</label>
</div>
<small class="text-muted d-block mt-1">
<i class="bi bi-shield-check me-1"></i>
Only check if the customer has explicitly agreed to receive text messages (TCPA compliance).
If checked, the new customer record will have SMS enabled and a confirmation text will be sent.
</small>
</div>
</div>
<!-- Form Actions -->
<div class="mb-4">
<button type="submit" class="btn btn-success btn-lg">
<i class="bi bi-arrow-right-circle me-1"></i>Convert to Customer
</button>
<a asp-action="Details" asp-route-id="@Model.QuoteId" class="btn btn-outline-secondary btn-lg">
<i class="bi bi-x-circle me-1"></i>Cancel
</a>
</div>
</form>
</div>
<!-- Right Column: Help Info -->
<div class="col-lg-4">
<div class="card">
<div class="card-header bg-light">
<h5 class="mb-0">
<i class="bi bi-info-circle me-2"></i>What Happens Next?
</h5>
</div>
<div class="card-body">
<ol class="mb-0">
<li class="mb-2">
<strong>Customer Created:</strong> A new customer record will be created with a unique customer number.
</li>
<li class="mb-2">
<strong>Quote Updated:</strong> The quote will be linked to the new customer and marked as "Converted".
</li>
<li class="mb-2">
<strong>Future Quotes:</strong> You can now create additional quotes for this customer.
</li>
<li class="mb-0">
<strong>Jobs:</strong> You'll be able to convert quotes to jobs for this customer.
</li>
</ol>
</div>
</div>
<div class="card mt-3">
<div class="card-header bg-light">
<h5 class="mb-0">
<i class="bi bi-lightbulb me-2"></i>Tips
</h5>
</div>
<div class="card-body">
<ul class="mb-0">
<li class="mb-2">
Review all contact information carefully before converting.
</li>
<li class="mb-2">
Set an appropriate credit limit if offering credit terms.
</li>
<li class="mb-0">
Assign a pricing tier to give this customer automatic discounts on future quotes.
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script>
function toggleCompanyNameRequired() {
const isCommercial = document.getElementById('IsCommercial').value === 'true';
const $companyName = $('#CompanyName');
const $requiredMark = $('#companyNameRequired');
if (isCommercial) {
$requiredMark.show();
$companyName.rules('add', { required: true, messages: { required: 'Company Name is required for commercial customers.' } });
} else {
$requiredMark.hide();
$companyName.rules('add', { required: false });
$companyName.valid(); // clear any existing error
}
}
$(document).ready(function () {
toggleCompanyNameRequired();
});
</script>
}