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>
This commit is contained in:
@@ -521,6 +521,20 @@ public class JobsController : Controller
|
||||
ViewBag.JobPhotoUsed = photoUsed;
|
||||
ViewBag.JobPhotoMax = photoMax;
|
||||
|
||||
// Customer list for inline customer-change dropdown
|
||||
var allCustomers = await _unitOfWork.Customers.GetAllAsync();
|
||||
ViewBag.CustomerSelectList = allCustomers
|
||||
.Where(c => c.IsActive)
|
||||
.Select(c => new SelectListItem
|
||||
{
|
||||
Value = c.Id.ToString(),
|
||||
Text = !string.IsNullOrWhiteSpace(c.CompanyName)
|
||||
? c.CompanyName
|
||||
: $"{c.ContactFirstName} {c.ContactLastName}".Trim()
|
||||
})
|
||||
.OrderBy(c => c.Text)
|
||||
.ToList();
|
||||
|
||||
return View(jobDto);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -531,6 +545,30 @@ public class JobsController : Controller
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reassigns a job to a different customer.
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> ChangeCustomer(int id, int customerId)
|
||||
{
|
||||
var job = await _unitOfWork.Jobs.GetByIdAsync(id);
|
||||
if (job == null) return NotFound();
|
||||
|
||||
var customer = await _unitOfWork.Customers.GetByIdAsync(customerId);
|
||||
if (customer == null)
|
||||
return Json(new { success = false, error = "Customer not found." });
|
||||
|
||||
job.CustomerId = customerId;
|
||||
await _unitOfWork.CompleteAsync();
|
||||
|
||||
var customerName = !string.IsNullOrWhiteSpace(customer.CompanyName)
|
||||
? customer.CompanyName
|
||||
: $"{customer.ContactFirstName} {customer.ContactLastName}".Trim();
|
||||
|
||||
return Json(new { success = true, customerName, customerId = customer.Id });
|
||||
}
|
||||
|
||||
// ── Shop Floor QR Status Bump ────────────────────────────────────────────
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user