Add SMS gating, TCPA terms agreement, and compose-before-send modal

- Three-tier SMS gate: platform kill-switch → admin force-disable → plan AllowSms → company opt-in
- CompanySmsAgreement entity records admin acceptance of TCPA terms with IP, user agent, and terms version
- SMS terms of service modal on Company Settings with versioned re-agreement (AppConstants.SmsTermsVersion)
- Dev redirect: non-production SMS routed to Twilio:DevRedirectPhone to protect real customer numbers
- Removed redundant Ready for Pickup SMS (Job Completed covers it)
- Role-based compose modal on job completion: Admin/Manager reviews and edits before send; ShopFloor auto-sends
- Send SMS button on job details for ad-hoc messages (Admin/Manager only)
- SendJobSmsAsync auto-appends STOP opt-out language if missing
- Migrations: AddSmsGating, AddCompanySmsAgreement

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-01 22:29:39 -04:00
parent 2b89fcf483
commit 6569d9c4ea
32 changed files with 19855 additions and 106 deletions
@@ -132,6 +132,19 @@
</div>
</div>
<h5 class="mb-3 pb-2 border-bottom mt-4">SMS Notifications</h5>
<div class="mb-4">
<div class="form-check form-switch">
<input asp-for="AllowSms" class="form-check-input" type="checkbox" role="switch" />
<label asp-for="AllowSms" class="form-check-label fw-medium">Allow SMS Notifications</label>
</div>
<div class="form-text">
When enabled, companies on this plan can send SMS job-status notifications to customers
(subject to the platform SMS kill-switch and the company's own opt-in setting).
</div>
</div>
<h5 class="mb-3 pb-2 border-bottom mt-4">AI Features</h5>
<div class="mb-3">
@@ -169,6 +169,19 @@
}
</td>
</tr>
<tr>
<td class="text-muted">SMS Notifications</td>
<td>
@if (plan.AllowSms)
{
<span class="badge bg-success">Enabled</span>
}
else
{
<span class="badge bg-secondary">Disabled</span>
}
</td>
</tr>
<tr class="table-light">
<td colspan="2" class="fw-semibold small text-uppercase text-muted py-1">Stripe</td>
</tr>