- Remove parseInt() from time entry worker select — GUIDs were destroyed
to NaN → sent as null → FindByIdAsync(null) threw 500
- Ledger pencil: also show for Adjustment rows (no PO) so scan-without-job
entries get an edit button, not just JobUsage rows
- InventoryController: always write JobUsage type for scan-based logs;
accept Adjustment in edit endpoints; promote Adjustment→JobUsage when
a job is assigned via edit
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
When a source quote is edited after a job was created from it, the job
details page now shows a warning banner with the date of the change and
a link to the quote. Two actions are offered:
- Re-sync from Quote: replaces all job items, coats, prep services, and
pricing from the current quote. Only available while the job is still
in a pre-production status (Pending, Quoted, Approved); hidden once
shop work has started (InPreparation or beyond).
- Dismiss: acknowledges the change without altering the job, clearing
the banner by advancing the stored snapshot timestamp.
Implemented via Job.QuoteSnapshotUpdatedAt (new nullable column), set at
quote→job conversion time. The banner fires when quote.UpdatedAt exceeds
this baseline. Migration: AddJobQuoteSnapshotUpdatedAt.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Setup Wizard: reduced from 10 steps to 5 (Company Info → QB Migration →
Pricing Defaults → Named Ovens → Notifications). Removed Doc Numbering,
Job Settings, Payment Terms, Pricing Tiers, and Team Members steps — these
all have sensible defaults and are accessible any time in Company Settings.
Wizard now completes in ~5 minutes instead of 15–20.
Dashboard progress widget (new): "Get the most out of your shop" checklist
appears for Company Admins after wizard completion. Tracks six post-setup
activation tasks with dynamic progress badge, motivating subtitle copy,
collapsed-state persistence via localStorage, and a full completion state
("Your shop is fully set up 🎉") that replaces the checklist at 100%.
The next recommended step is highlighted with a solid CTA button and a
subtle blue row tint. Completed steps show encouraging green subtext instead
of just "Done". Widget disappears from controller when AllDone would have
caused a silent vanish — now renders the completion state instead.
Guided activation (Daily Board): rewrote the BoardIntroStep callout to lead
with "This is your shop in real time" and a plain-English description of the
board's purpose. Added a separate InstructionText field to
GuidedActivationCalloutViewModel so the "Move this job to the next stage"
action prompt renders as a distinct bold line with an arrow icon rather than
being buried in the body copy. After the stage change, the confirmation
callout now reads "Nice — your workflow just updated" to reinforce what just
happened before prompting the invoice step.
All copy passes the "shop owner, not SaaS" test: no technical jargon,
benefit-driven descriptions, natural language throughout.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- PasskeyController: set LastLoginDate on passkey sign-in so Company Health
and audit pages show accurate last-login times (was always showing 'Never')
- Jobs/Index status modal: disable 'Notify customer' email toggle and show
warning when customer has notifications turned off; CustomerNotifyByEmail
added to JobListDto + JobProfile mapping + data-customer-notify attribute
- Quotes/Create: disable 'Send quote via email' checkbox with 'Notifications
off' badge when selected customer has email opt-out; ViewBag.CustomerEmailOptOutIds
added alongside existing CustomerTaxExemptIds pattern
- Quotes/Create: Quick Quote / Full Quote segmented toggle at top of form;
hides non-essential fields (dates, notes, tags, oven, discount, photos) in
Quick mode; selection persisted in localStorage
- InvoicesController Send action: improved error logging and user-facing
warning when PDF generation or email dispatch fails after status is saved
- item-wizard.js: guard item restoration with try/catch; ensure writeHiddenFields
always runs on form submit via capture-phase listener
- Help docs and AI knowledge base updated for all new features
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- StatusBump (GET + POST) now requires authentication; routes by job ID
instead of anonymous ShopAccessCode GUID; records actual user name in
status history instead of anonymous token string
- WorkOrder action generates a second "View Job" QR in the header linking
to the authenticated Details page (for verifying specs and seeing catalog
images on mobile); status bump QR updated to ID-based URL
- WorkOrder view: top QR added to header alongside job number; status bump
label updated (removed "no login required" copy)
- StatusBump view: updated form routing from asp-route-token to asp-route-id
- HelpKnowledgeBase and Jobs help article updated with two-tier QR docs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New AI Quick Quote floating button: staff type a verbal description to
get an instant price estimate for phone/walk-in customers; detected
color names are fuzzy-matched against inventory for stock status;
saves draft quote under a Walk-In / Phone customer with one click
- Inline customer change on Quote Details and Job Details: always-visible
native select with inline confirmation banner (no TomSelect dependency);
ChangeCustomer AJAX endpoints on QuotesController and JobsController
- Quote Edit page: customer dropdown is now editable (lock removed)
- Fix AutoMapper missing CatalogCategory -> UpdateCategoryDto mapping
that caused a crash on the catalog category Edit page
- Help docs and AI knowledge base updated for all three features
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>