Inline item editing on details pages; fix Stripe receipt_email
Allow description, quantity, and price to be edited inline on Quote, Job, and Invoice details pages without re-opening the wizard. Coating and prep service rows remain read-only by design. Invoice editing is gated to Draft/Sent/Overdue statuses; totals update live in the DOM. Remove receipt_email from Stripe PaymentIntent creation so customers can use any email they choose at checkout — Stripe validates format and sends the receipt to whatever the customer enters in the Payment Element, eliminating the risk of a stored email mismatch blocking a payment from processing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -230,21 +230,21 @@
|
||||
<tbody>
|
||||
@foreach (var item in Model.InvoiceItems)
|
||||
{
|
||||
<tr>
|
||||
<tr data-item-id="@item.Id">
|
||||
<td>
|
||||
<div class="fw-semibold">@item.Description</div>
|
||||
<span class="fw-semibold" data-inline-field="description" data-raw-value="@item.Description">@item.Description</span>
|
||||
@if (!string.IsNullOrWhiteSpace(item.ColorName))
|
||||
{
|
||||
<small class="text-muted">@item.ColorName</small>
|
||||
<small class="text-muted d-block">@item.ColorName</small>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(item.Notes))
|
||||
{
|
||||
<small class="text-muted d-block">@item.Notes</small>
|
||||
}
|
||||
</td>
|
||||
<td class="text-center">@item.Quantity.ToString("G")</td>
|
||||
<td class="text-end">@item.UnitPrice.ToString("C")</td>
|
||||
<td class="text-end fw-semibold">@item.TotalPrice.ToString("C")</td>
|
||||
<td class="text-center"><span data-inline-field="quantity" data-raw-value="@item.Quantity">@item.Quantity.ToString("G")</span></td>
|
||||
<td class="text-end"><span data-inline-field="unitPrice" data-raw-value="@item.UnitPrice">@item.UnitPrice.ToString("C")</span></td>
|
||||
<td class="text-end fw-semibold" data-line-total>@item.TotalPrice.ToString("C")</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
@@ -257,7 +257,7 @@
|
||||
<div class="col-md-4">
|
||||
<div class="d-flex justify-content-between mb-1">
|
||||
<span class="text-muted">Subtotal</span>
|
||||
<span>@Model.SubTotal.ToString("C")</span>
|
||||
<span id="inv-subtotal">@Model.SubTotal.ToString("C")</span>
|
||||
</div>
|
||||
@if (Model.DiscountAmount > 0)
|
||||
{
|
||||
@@ -276,12 +276,12 @@
|
||||
<span class="badge bg-warning-subtle text-warning-emphasis ms-1 small fw-normal">@Model.SalesTaxAccountName</span>
|
||||
}
|
||||
</span>
|
||||
<span>@Model.TaxAmount.ToString("C")</span>
|
||||
<span id="inv-tax">@Model.TaxAmount.ToString("C")</span>
|
||||
</div>
|
||||
}
|
||||
<div class="d-flex justify-content-between fw-bold border-top pt-2 mt-1 fs-5">
|
||||
<span>Total</span>
|
||||
<span>@Model.Total.ToString("C")</span>
|
||||
<span id="inv-total">@Model.Total.ToString("C")</span>
|
||||
</div>
|
||||
@if (Model.AmountPaid > 0)
|
||||
{
|
||||
@@ -291,7 +291,7 @@
|
||||
</div>
|
||||
<div class="d-flex justify-content-between fw-bold border-top pt-2 mt-1">
|
||||
<span>Balance Due</span>
|
||||
<span class="@(Model.BalanceDue > 0 ? "text-danger" : "text-success")">@Model.BalanceDue.ToString("C")</span>
|
||||
<span id="inv-balance" class="@(Model.BalanceDue > 0 ? "text-danger" : "text-success")">@Model.BalanceDue.ToString("C")</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@@ -1442,6 +1442,19 @@
|
||||
}
|
||||
|
||||
@section Scripts {
|
||||
<script src="~/js/inline-item-edit.js"></script>
|
||||
<script>
|
||||
window.inlineItemEdit = {
|
||||
patchUrl: '@Url.Action("PatchItem", "Invoices")',
|
||||
canEdit: @Json.Serialize(canEdit),
|
||||
totals: {
|
||||
subtotal: '#inv-subtotal',
|
||||
tax: '#inv-tax',
|
||||
total: '#inv-total',
|
||||
balance: '#inv-balance'
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<script>
|
||||
function submitSendInvoice(sendEmail, sendSms) {
|
||||
document.getElementById('sendInvoiceSendEmail').value = sendEmail ? 'true' : 'false';
|
||||
|
||||
Reference in New Issue
Block a user