Commit Graph

11 Commits

Author SHA1 Message Date
spouliot cad728ba66 Fix passkey login tracking, add email opt-out UI guards, and add Quick/Full quote mode toggle
- 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>
2026-04-27 13:32:34 -04:00
spouliot 0ea192d55b Harden legacy file paths and Twilio webhook validation 2026-04-26 18:14:16 -04:00
spouliot 8491b308eb Add admin email wizard and logging 2026-04-26 17:01:09 -04:00
spouliot cb7bbc37bd Add three-layer feature gating for AI Catalog Price Check
Adds platform-level, plan-level (Enterprise only), and per-company
toggles for the AI Catalog Price Check feature. Includes:
- Company.AiCatalogPriceCheckEnabled per-company flag
- SubscriptionPlanConfig.AllowAiCatalogPriceCheck plan-level flag
- PlatformSetting 'AiCatalogPriceCheckEnabled' global kill switch
- IPlatformSettingsService.GetBoolAsync helper
- ISubscriptionService.CanUseAiCatalogPriceCheckAsync
- UI controls in Companies/Edit, PlatformSubscription/Edit+Index,
  and SubscriptionManagement/Manage
- Migration AddAiCatalogPriceCheckGating applied

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 08:29:51 -04:00
spouliot 54f444d981 Add AI Catalog Price Check feature
Claude reviews every active catalog item against the shop's own operating costs
and returns a per-item verdict (below-cost / thin-margin / high / ok) with a
suggested price range, cost floor, and assumptions.

- New entity: CatalogPriceCheckReport (JSON blob, archived per company)
- New service: IAiCatalogPriceCheckService / AiCatalogPriceCheckService
  batches items 25 at a time to stay within model context limits
- Two new controller actions: GET AiPriceCheck (view report) + POST RunAiPriceCheck
- AiPriceCheck view: summary cards (counts by verdict), color-coded item cards
  with Edit Price link, assumptions detail, and loading spinner on submit
- AI Price Check button added to catalog Index header
- Migration AddCatalogPriceCheckReport applied

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 18:41:56 -04:00
spouliot dbe4170986 Add unit tests for 9 new services/controllers and expand existing test coverage
116 tests passing: JobPhotoService, MeasurementConversionService, PlatformSettingsService,
QuoteApprovalController, QuotePhotoService, ShopCapabilityCalculator, StorageMigrationService,
TenantContext, UsageQuotaController — plus expanded PricingCalculation, Registration, and
Subscription tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 18:27:30 -04:00
spouliot 00bf8a4cd0 Add catalog item images with thumbnail preview in wizard
Each catalog item now supports one optional image (jpg/jpeg/png/gif/webp,
max 10 MB). Uploading generates a 200x200 JPEG thumbnail automatically via
SixLabors.ImageSharp. Images are stored in Azure Blob Storage under a new
catalogimages container, keyed by {companyId}/catalog/{itemId}/.

- CatalogItem entity: ImagePath + ThumbnailPath (nullable string fields)
- Migration: AddCatalogItemImages applied
- ICatalogImageService / CatalogImageService: upload, thumbnail generation,
  delete; old blobs replaced atomically on re-upload
- CatalogItemsController: Create/Edit accept optional IFormFile image;
  Image(id, thumbnail) action serves blobs with [Authorize] so wizard users
  can load thumbnails without CanManageProducts policy
- Catalog index (_CategoryNode): 40x40 thumbnail (or placeholder icon)
  left of each item name
- Details view: image card in right column with click-to-full-size link
- Create/Edit views: file picker with live preview; Edit shows current
  thumbnail with Remove checkbox
- Wizard (item-wizard.js): thumbnails in product list with hover preview
  that follows the cursor (showCatalogPreview / moveCatalogPreview);
  fixed Bootstrap d-flex !important bug that broke the filter box by
  moving flex layout to an inner wrapper div

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 09:33:59 -04:00
spouliot 27ac793f62 Harden paid registration flow and add unit tests 2026-04-24 21:10:28 -04:00
spouliot 4153acf3aa Add facility overhead (rent + utilities) to operating costs and pricing engine
Adds MonthlyRent, MonthlyUtilities, and MonthlyBillableHours to CompanyOperatingCosts so fixed shop occupancy costs are recovered on every quote. The pricing engine converts these into a per-hour rate and applies it as a transparent "Facility Overhead" line between oven batch cost and shop supplies. UI added in Company Settings Operating Costs tab and Setup Wizard Step 3; migration AddFacilityOverheadFields applied. Help docs and AI knowledge base updated to cover the new fields and the revised quote pricing calculation order.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 19:35:00 -04:00
spouliot 8d94013895 Add AI Quick Quote widget and inline customer reassignment
- 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>
2026-04-24 17:02:03 -04:00
spouliot 63e12a9636 Initial commit 2026-04-23 21:38:24 -04:00