Sweep all .cshtml files for encoding corruption; add pre-commit guard

Replace all corruption variants with HTML entities across 226 view files:
- 3-char UTF-8-as-Win1252 sequences (ae-corruption)
- Standalone smart/curly quotes that break C# Razor expressions
- Partially re-corrupted variants where the 3rd byte was normalised to ASCII

tools/Fix-Encoding.ps1: re-runnable sweep; uses [char] code points so the
script itself never contains a literal non-ASCII character; supports -DryRun

.githooks/pre-commit: blocks commits containing the ae-corruption byte
signature (xc3xa2xe2x82xac); git core.hooksPath = .githooks so the
hook is repo-committed and active for all future work on this machine.

Build clean; 225 unit tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-20 21:37:10 -04:00
parent 21b39161a3
commit a0bdd2b5b4
252 changed files with 1785 additions and 1633 deletions
@@ -22,7 +22,7 @@
<p>
The Customers section is the starting point for all work in the shop. Every quote, job, and invoice
belongs to a customer record. Keeping your customer list accurate and up to date ensures you can
quickly pull up a customer's full history all their past jobs, outstanding quotes, and unpaid
quickly pull up a customer's full history &mdash; all their past jobs, outstanding quotes, and unpaid
invoices in one place.
</p>
<p>
@@ -49,7 +49,7 @@
</div>
<div class="card-body">
<p class="card-text small mb-0">
Use this for businesses auto body shops, fabricators, manufacturers, or any company
Use this for businesses &mdash; auto body shops, fabricators, manufacturers, or any company
that sends you work regularly. Commercial customers can have a <strong>pricing tier</strong>
applied (e.g., volume discounts) and a <strong>credit limit</strong> set. They typically
have a company name in addition to a contact person.
@@ -64,7 +64,7 @@
</div>
<div class="card-body">
<p class="card-text small mb-0">
Use this for individuals homeowners who bring in patio furniture, hobbyists with
Use this for individuals &mdash; homeowners who bring in patio furniture, hobbyists with
motorcycle parts, or anyone who is not representing a business. Non-commercial customers
typically do not have a company name and are priced at standard retail rates.
</p>
@@ -81,17 +81,17 @@
<p>Follow these steps to add a new customer:</p>
<ol class="mb-3">
<li class="mb-2">Go to <strong>Operations &rsaquo; Customers</strong> and click the <strong>New Customer</strong> button in the top-right corner.</li>
<li class="mb-2">Choose the <strong>Customer Type</strong> Commercial or Non-Commercial.</li>
<li class="mb-2">Choose the <strong>Customer Type</strong> &mdash; Commercial or Non-Commercial.</li>
<li class="mb-2">
Fill in the customer details:
<ul class="mt-1">
<li><strong>Company Name</strong> required for Commercial customers.</li>
<li><strong>Contact Name</strong> the person you deal with day to day.</li>
<li><strong>Email</strong> used for quote and invoice notifications.</li>
<li><strong>Phone</strong> primary contact number.</li>
<li><strong>Mobile Phone</strong> used for SMS notifications. Required if you want to text this customer.</li>
<li><strong>SMS Opt-In</strong> check this only after you have obtained the customer's consent to receive text messages. Visible only when SMS is enabled for your company.</li>
<li><strong>Address</strong> billing and shipping address fields.</li>
<li><strong>Company Name</strong> &mdash; required for Commercial customers.</li>
<li><strong>Contact Name</strong> &mdash; the person you deal with day to day.</li>
<li><strong>Email</strong> &mdash; used for quote and invoice notifications.</li>
<li><strong>Phone</strong> &mdash; primary contact number.</li>
<li><strong>Mobile Phone</strong> &mdash; used for SMS notifications. Required if you want to text this customer.</li>
<li><strong>SMS Opt-In</strong> &mdash; check this only after you have obtained the customer's consent to receive text messages. Visible only when SMS is enabled for your company.</li>
<li><strong>Address</strong> &mdash; billing and shipping address fields.</li>
</ul>
</li>
<li class="mb-2">For Commercial customers, optionally set a <strong>Pricing Tier</strong> and <strong>Credit Limit</strong>.</li>
@@ -136,24 +136,24 @@
</p>
<p>The details page shows:</p>
<ul>
<li><strong>Contact information</strong> name, email, phone, and address.</li>
<li><strong>Account summary</strong> current balance, credit limit, and pricing tier.</li>
<li><strong>Contact information</strong> &mdash; name, email, phone, and address.</li>
<li><strong>Account summary</strong> &mdash; current balance, credit limit, and pricing tier.</li>
<li>
<strong>Jobs tab</strong> every job created for this customer, with status and date. Click
<strong>Jobs tab</strong> &mdash; every job created for this customer, with status and date. Click
a job number to open it.
</li>
<li>
<strong>Quotes tab</strong> all quotes sent to this customer, including pending and
<strong>Quotes tab</strong> &mdash; all quotes sent to this customer, including pending and
historical quotes. Click a quote number to open it.
</li>
<li>
<strong>Invoices tab</strong> all invoices with payment status. Quickly see who owes money
<strong>Invoices tab</strong> &mdash; all invoices with payment status. Quickly see who owes money
and how much.
</li>
<li>
<strong>Deposits tab</strong> all deposits recorded for this customer across any job or quote.
<strong>Deposits tab</strong> &mdash; all deposits recorded for this customer across any job or quote.
</li>
<li><strong>Notes</strong> any notes saved against the customer record.</li>
<li><strong>Notes</strong> &mdash; any notes saved against the customer record.</li>
</ul>
</section>
@@ -169,7 +169,7 @@
<p>
When a customer's outstanding balance approaches or exceeds their credit limit, the system displays
a warning flag on their record and on any new jobs or invoices you try to create for them. This is
a visual warning only the system does not automatically block new work but it gives your team
a visual warning only &mdash; the system does not automatically block new work &mdash; but it gives your team
a clear signal to follow up on payment before starting more jobs.
</p>
<p>
@@ -189,7 +189,7 @@
</p>
<p>
When a tax-exempt customer is selected on a new quote or invoice, the tax rate automatically
defaults to <strong>0%</strong> no manual adjustment needed. Tax-exempt customers are marked
defaults to <strong>0%</strong> &mdash; no manual adjustment needed. Tax-exempt customers are marked
with a ★ in the customer dropdown when creating quotes and invoices so your team can spot them
at a glance.
</p>