Compare commits
4 Commits
ln-deploy
...
v1.11.7-af
Author | SHA1 | Date | |
---|---|---|---|
25c30512ec | |||
52df7a5b89 | |||
1a85da27db | |||
10326a822e |
@ -11,13 +11,14 @@ namespace BTCPayServer.Components.QRCode
|
||||
{
|
||||
private static QRCodeGenerator _qrGenerator = new();
|
||||
|
||||
public IViewComponentResult Invoke(string data)
|
||||
public IViewComponentResult Invoke(string data, int size=256)
|
||||
{
|
||||
var qrCodeData = _qrGenerator.CreateQrCode(data, QRCodeGenerator.ECCLevel.Q);
|
||||
var qrCode = new PngByteQRCode(qrCodeData);
|
||||
var bytes = qrCode.GetGraphic(5, new byte[] { 0, 0, 0, 255 }, new byte[] { 0xf5, 0xf5, 0xf7, 255 });
|
||||
var b64 = Convert.ToBase64String(bytes);
|
||||
return new HtmlContentViewComponentResult(new HtmlString($"<img style=\"image-rendering:pixelated;image-rendering:-moz-crisp-edges;min-width:256px;min-height:256px\" src=\"data:image/png;base64,{b64}\" class=\"qr-code\" />"));
|
||||
return new HtmlContentViewComponentResult(new HtmlString(
|
||||
$"<img style=\"image-rendering:pixelated;image-rendering:-moz-crisp-edges;min-width:{size}px;min-height:{size}px\" src=\"data:image/png;base64,{b64}\" class=\"qr-code\" />"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -254,7 +254,7 @@ namespace BTCPayServer.Controllers
|
||||
Amount = paymentEntity.PaidAmount.Gross,
|
||||
Paid = paymentEntity.InvoicePaidAmount.Net,
|
||||
ReceivedDate = paymentEntity.ReceivedTime.DateTime,
|
||||
AmountFormatted = _displayFormatter.Currency(paymentEntity.PaidAmount.Gross, paymentEntity.PaidAmount.Currency, DisplayFormatter.CurrencyFormat.None),
|
||||
AmountFormatted = _displayFormatter.Currency(paymentEntity.PaidAmount.Gross, paymentEntity.PaidAmount.Currency),
|
||||
PaidFormatted = _displayFormatter.Currency(paymentEntity.InvoicePaidAmount.Net, i.Currency, DisplayFormatter.CurrencyFormat.Symbol),
|
||||
RateFormatted = _displayFormatter.Currency(paymentEntity.Rate, i.Currency, DisplayFormatter.CurrencyFormat.Symbol),
|
||||
PaymentMethod = paymentMethodId.ToPrettyString(),
|
||||
|
@ -135,7 +135,7 @@ namespace BTCPayServer.PaymentRequest
|
||||
Amount = paymentEntity.PaidAmount.Gross,
|
||||
Paid = paymentEntity.InvoicePaidAmount.Net,
|
||||
ReceivedDate = paymentEntity.ReceivedTime.DateTime,
|
||||
AmountFormatted = _displayFormatter.Currency(paymentEntity.PaidAmount.Gross, paymentEntity.PaidAmount.Currency, DisplayFormatter.CurrencyFormat.None),
|
||||
AmountFormatted = _displayFormatter.Currency(paymentEntity.PaidAmount.Gross, paymentEntity.PaidAmount.Currency),
|
||||
PaidFormatted = _displayFormatter.Currency(paymentEntity.InvoicePaidAmount.Net, blob.Currency, DisplayFormatter.CurrencyFormat.Symbol),
|
||||
RateFormatted = _displayFormatter.Currency(paymentEntity.Rate, blob.Currency, DisplayFormatter.CurrencyFormat.Symbol),
|
||||
PaymentMethod = paymentMethodId.ToPrettyString(),
|
||||
|
@ -1,2 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 192 84" role="img" alt="BTCPay Server" class="d-print-none"><path d="M5.206 83.433a4.86 4.86 0 01-4.859-4.861V5.431a4.86 4.86 0 119.719 0v73.141a4.861 4.861 0 01-4.86 4.861" fill="currentColor" class="logo-brand-light"/><path d="M5.209 83.433a4.862 4.862 0 01-2.086-9.253L32.43 60.274 2.323 38.093a4.861 4.861 0 015.766-7.826l36.647 26.999a4.864 4.864 0 01-.799 8.306L7.289 82.964a4.866 4.866 0 01-2.08.469" fill="currentColor" class="logo-brand-medium"/><path d="M5.211 54.684a4.86 4.86 0 01-2.887-8.774L32.43 23.73 3.123 9.821a4.861 4.861 0 014.166-8.784l36.648 17.394a4.86 4.86 0 01.799 8.305l-36.647 27a4.844 4.844 0 01-2.878.948" fill="currentColor" class="logo-brand-light"/><path d="M10.066 31.725v20.553L24.01 42.006z" fill="currentColor" class="logo-brand-dark"/><path d="M10.066 5.431A4.861 4.861 0 005.206.57 4.86 4.86 0 00.347 5.431v61.165h9.72V5.431h-.001z" fill="currentColor" class="logo-brand-light"/><path d="M74.355 41.412c3.114.884 4.84 3.704 4.84 7.238 0 5.513-3.368 8.082-7.955 8.082H60.761V27.271h9.259c4.504 0 7.997 2.146 7.997 7.743 0 2.821-1.179 5.43-3.662 6.398m-4.293-.716c3.324 0 6.018-1.179 6.018-5.724 0-4.586-2.776-5.808-6.145-5.808h-7.197v11.531h7.324v.001zm1.052 14.099c3.366 0 6.06-1.768 6.06-6.145 0-4.713-3.072-6.144-6.901-6.144h-7.534v12.288h8.375v.001zM98.893 27.271v1.81h-8.122v27.651h-1.979V29.081h-8.123v-1.81zM112.738 26.85c5.01 0 9.554 2.524 10.987 8.543h-1.895c-1.348-4.923-5.303-6.732-9.134-6.732-6.944 0-10.605 5.681-10.605 13.341 0 8.08 3.661 13.256 10.646 13.256 4.125 0 7.828-1.85 9.26-7.279h1.895c-1.264 6.271-6.229 9.174-11.154 9.174-7.87 0-12.583-5.808-12.583-15.15 0-8.966 4.969-15.153 12.583-15.153M138.709 27.271c5.091 0 8.795 3.326 8.795 9.764 0 6.06-3.704 9.722-8.795 9.722h-7.746v9.976h-1.935V27.271h9.681zm0 17.549c3.745 0 6.816-2.397 6.816-7.827 0-5.429-2.947-7.869-6.816-7.869h-7.746V44.82h7.746zM147.841 56.732v-.255l11.741-29.29h.885l11.615 29.29v.255h-2.062l-3.322-8.501H153.27l-3.324 8.501h-2.105zm12.164-26.052l-6.059 15.697h12.078l-6.019-15.697zM189.551 27.271h2.104v.293l-9.176 16.92v12.248h-2.02V44.484l-9.216-16.961v-.252h2.147l3.997 7.492 4.043 7.786h.04l4.081-7.786z" fill="currentColor" class="logo-brand-text"/></svg>
|
||||
<span class="d-none d-print-inline">BTCPay Server</span>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 192 84" role="img" alt="BTCPay Server"><path d="M5.206 83.433a4.86 4.86 0 01-4.859-4.861V5.431a4.86 4.86 0 119.719 0v73.141a4.861 4.861 0 01-4.86 4.861" fill="currentColor" class="logo-brand-light"/><path d="M5.209 83.433a4.862 4.862 0 01-2.086-9.253L32.43 60.274 2.323 38.093a4.861 4.861 0 015.766-7.826l36.647 26.999a4.864 4.864 0 01-.799 8.306L7.289 82.964a4.866 4.866 0 01-2.08.469" fill="currentColor" class="logo-brand-medium"/><path d="M5.211 54.684a4.86 4.86 0 01-2.887-8.774L32.43 23.73 3.123 9.821a4.861 4.861 0 014.166-8.784l36.648 17.394a4.86 4.86 0 01.799 8.305l-36.647 27a4.844 4.844 0 01-2.878.948" fill="currentColor" class="logo-brand-light"/><path d="M10.066 31.725v20.553L24.01 42.006z" fill="currentColor" class="logo-brand-dark"/><path d="M10.066 5.431A4.861 4.861 0 005.206.57 4.86 4.86 0 00.347 5.431v61.165h9.72V5.431h-.001z" fill="currentColor" class="logo-brand-light"/><path d="M74.355 41.412c3.114.884 4.84 3.704 4.84 7.238 0 5.513-3.368 8.082-7.955 8.082H60.761V27.271h9.259c4.504 0 7.997 2.146 7.997 7.743 0 2.821-1.179 5.43-3.662 6.398m-4.293-.716c3.324 0 6.018-1.179 6.018-5.724 0-4.586-2.776-5.808-6.145-5.808h-7.197v11.531h7.324v.001zm1.052 14.099c3.366 0 6.06-1.768 6.06-6.145 0-4.713-3.072-6.144-6.901-6.144h-7.534v12.288h8.375v.001zM98.893 27.271v1.81h-8.122v27.651h-1.979V29.081h-8.123v-1.81zM112.738 26.85c5.01 0 9.554 2.524 10.987 8.543h-1.895c-1.348-4.923-5.303-6.732-9.134-6.732-6.944 0-10.605 5.681-10.605 13.341 0 8.08 3.661 13.256 10.646 13.256 4.125 0 7.828-1.85 9.26-7.279h1.895c-1.264 6.271-6.229 9.174-11.154 9.174-7.87 0-12.583-5.808-12.583-15.15 0-8.966 4.969-15.153 12.583-15.153M138.709 27.271c5.091 0 8.795 3.326 8.795 9.764 0 6.06-3.704 9.722-8.795 9.722h-7.746v9.976h-1.935V27.271h9.681zm0 17.549c3.745 0 6.816-2.397 6.816-7.827 0-5.429-2.947-7.869-6.816-7.869h-7.746V44.82h7.746zM147.841 56.732v-.255l11.741-29.29h.885l11.615 29.29v.255h-2.062l-3.322-8.501H153.27l-3.324 8.501h-2.105zm12.164-26.052l-6.059 15.697h12.078l-6.019-15.697zM189.551 27.271h2.104v.293l-9.176 16.92v12.248h-2.02V44.484l-9.216-16.961v-.252h2.147l3.997 7.492 4.043 7.786h.04l4.081-7.786z" fill="currentColor" class="logo-brand-text"/></svg>
|
||||
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
@ -31,6 +31,7 @@
|
||||
</script>
|
||||
}
|
||||
<style>
|
||||
#InvoiceReceipt { --wrap-max-width: 768px; }
|
||||
#InvoiceSummary { gap: var(--btcpay-space-l); }
|
||||
#PaymentDetails table tbody tr:first-child td { padding-top: 1rem; }
|
||||
#PaymentDetails table tbody:not(:last-child) tr:last-child > th,td { padding-bottom: 1rem; }
|
||||
@ -39,38 +40,34 @@
|
||||
</style>
|
||||
</head>
|
||||
<body class="min-vh-100">
|
||||
<div class="public-page-wrap">
|
||||
<div id="InvoiceReceipt" class="public-page-wrap">
|
||||
<main class="flex-grow-1">
|
||||
<div class="container" style="max-width:720px;">
|
||||
<div class="d-flex flex-column justify-content-center gap-4">
|
||||
<partial name="_StoreHeader" model="(Model.StoreName, Model.LogoFileId)" />
|
||||
<partial name="_StatusMessage" model="@(new ViewDataDictionary(ViewData) { { "Margin", "mb-4" } })"/>
|
||||
|
||||
<div class="d-flex flex-column justify-content-center gap-4">
|
||||
<partial name="_StoreHeader" model="(Model.StoreName, Model.LogoFileId)" />
|
||||
<div id="InvoiceSummary" class="bg-tile p-3 p-sm-4 rounded d-flex flex-wrap align-items-center justify-content-center">
|
||||
@if (isProcessing)
|
||||
<div id="InvoiceSummary" class="tile d-flex flex-wrap align-items-center justify-content-center">
|
||||
@if (isProcessing)
|
||||
{
|
||||
<div class="lead text-center p-4 fw-semibold" id="invoice-processing">
|
||||
The invoice has detected a payment but is still waiting to be settled.
|
||||
</div>
|
||||
}
|
||||
else if (!isSettled)
|
||||
{
|
||||
<div class="lead text-center p-4 fw-semibold" id="invoice-unsettled">
|
||||
The invoice is not settled.
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Model.ReceiptOptions.ShowQR is true)
|
||||
{
|
||||
<div class="lead text-center p-4 fw-semibold" id="invoice-processing">
|
||||
The invoice has detected a payment but is still waiting to be settled.
|
||||
</div>
|
||||
<vc:qr-code data="@Context.Request.GetCurrentUrl()"></vc:qr-code>
|
||||
}
|
||||
else if (!isSettled)
|
||||
{
|
||||
<div class="lead text-center p-4 fw-semibold" id="invoice-unsettled">
|
||||
The invoice is not settled.
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Model.ReceiptOptions.ShowQR is true)
|
||||
{
|
||||
<vc:qr-code data="@Context.Request.GetCurrentUrl()"></vc:qr-code>
|
||||
}
|
||||
<div class="d-flex gap-4 mb-0 flex-fill">
|
||||
<dl class="d-flex flex-column gap-4 mb-0 flex-fill">
|
||||
<div class="d-flex flex-column">
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<a href="?print=true" class="btn btn-link p-0 d-print-none fw-semibold order-1" target="_blank">Print</a>
|
||||
<dd class="text-muted mb-0 fw-semibold">Amount Paid</dd>
|
||||
</div>
|
||||
<dd class="text-muted mb-0 fw-semibold">Amount Paid</dd>
|
||||
<dt class="fs-2 mb-0 text-nowrap fw-semibold">@DisplayFormatter.Currency(Model.Amount, Model.Currency, DisplayFormatter.CurrencyFormat.Symbol)</dt>
|
||||
</div>
|
||||
<div class="d-flex flex-column">
|
||||
@ -85,91 +82,92 @@
|
||||
</div>
|
||||
}
|
||||
</dl>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (isProcessing)
|
||||
{
|
||||
<small class="d-block text-muted text-center px-4">This page will refresh periodically until the invoice is settled.</small>
|
||||
}
|
||||
else if (isSettled)
|
||||
{
|
||||
if (Model.AdditionalData?.Any() is true)
|
||||
{
|
||||
<div id="AdditionalData" class="bg-tile p-3 p-sm-4 rounded">
|
||||
<h2 class="h4 mb-3">Additional Data</h2>
|
||||
<div class="table-responsive my-0">
|
||||
<partial name="PosData" model="(Model.AdditionalData, 1)"/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
if (Model.Payments?.Any() is true)
|
||||
{
|
||||
<div id="PaymentDetails" class="bg-tile p-3 p-sm-4 rounded">
|
||||
<h2 class="h4 mb-3">Payment Details</h2>
|
||||
<div class="table-responsive my-0 d-print-none">
|
||||
<table class="invoice table table-borderless">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="fw-normal text-secondary date-col w-125px">Date</th>
|
||||
<th class="fw-normal text-secondary amount-col">Paid</th>
|
||||
<th class="fw-normal text-secondary amount-col w-225px">Payment</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var payment in Model.Payments)
|
||||
{
|
||||
<tr>
|
||||
<td class="date-col">@payment.ReceivedDate.ToBrowserDate()</td>
|
||||
<td class="amount-col">@payment.PaidFormatted</td>
|
||||
<td class="amount-col">@payment.AmountFormatted @payment.PaymentMethod</td>
|
||||
</tr>
|
||||
@if (!string.IsNullOrEmpty(payment.Destination))
|
||||
{
|
||||
<tr>
|
||||
<th class="fw-normal text-nowrap text-secondary">
|
||||
Destination
|
||||
</th>
|
||||
<td class="fw-normal" colspan="2">
|
||||
<vc:truncate-center text="@payment.Destination" classes="truncate-center-id" />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(payment.PaymentProof))
|
||||
{
|
||||
<tr>
|
||||
<th class="fw-normal text-nowrap text-secondary">
|
||||
Payment Proof
|
||||
</th>
|
||||
<td class="fw-normal" colspan="2">
|
||||
<vc:truncate-center text="@payment.PaymentProof" link="@payment.Link" classes="truncate-center-id" />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="d-none d-print-block">
|
||||
@foreach (var payment in Model.Payments)
|
||||
{
|
||||
<div class="mb-4">
|
||||
<strong>@payment.PaidFormatted</strong> = @payment.AmountFormatted @payment.PaymentMethod, Rate: @payment.RateFormatted
|
||||
@if (!string.IsNullOrEmpty(payment.PaymentProof))
|
||||
{
|
||||
<div>Proof: @payment.PaymentProof</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(Model.OrderUrl))
|
||||
{
|
||||
<a href="@Model.OrderUrl" class="btn btn-secondary rounded-pill mx-auto mt-3" rel="noreferrer noopener" target="_blank">Return to @(string.IsNullOrEmpty(Model.StoreName) ? "store" : Model.StoreName)</a>
|
||||
<a href="?print=true" class="flex-grow-0 align-self-start btn btn-secondary d-print-none fs-4" target="_blank">Print</a>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (isProcessing)
|
||||
{
|
||||
<small class="d-block text-muted text-center px-4">This page will refresh periodically until the invoice is settled.</small>
|
||||
}
|
||||
else if (isSettled)
|
||||
{
|
||||
if (Model.AdditionalData?.Any() is true)
|
||||
{
|
||||
<div id="AdditionalData" class="tile">
|
||||
<h2 class="h4 mb-3">Additional Data</h2>
|
||||
<div class="table-responsive my-0">
|
||||
<partial name="PosData" model="(Model.AdditionalData, 1)"/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
if (Model.Payments?.Any() is true)
|
||||
{
|
||||
<div id="PaymentDetails" class="tile">
|
||||
<h2 class="h4 mb-3">Payment Details</h2>
|
||||
<div class="table-responsive my-0 d-print-none">
|
||||
<table class="invoice table table-borderless">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="fw-normal text-secondary date-col w-125px">Date</th>
|
||||
<th class="fw-normal text-secondary amount-col">Paid</th>
|
||||
<th class="fw-normal text-secondary amount-col w-225px">Payment</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@foreach (var payment in Model.Payments)
|
||||
{
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="date-col">@payment.ReceivedDate.ToBrowserDate()</td>
|
||||
<td class="amount-col">@payment.PaidFormatted</td>
|
||||
<td class="amount-col">@payment.AmountFormatted</td>
|
||||
</tr>
|
||||
@if (!string.IsNullOrEmpty(payment.Destination))
|
||||
{
|
||||
<tr>
|
||||
<th class="fw-normal text-nowrap text-secondary">
|
||||
Destination
|
||||
</th>
|
||||
<td class="fw-normal" colspan="2">
|
||||
<vc:truncate-center text="@payment.Destination" classes="truncate-center-id" />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(payment.PaymentProof))
|
||||
{
|
||||
<tr>
|
||||
<th class="fw-normal text-nowrap text-secondary">
|
||||
Payment Proof
|
||||
</th>
|
||||
<td class="fw-normal" colspan="2">
|
||||
<vc:truncate-center text="@payment.PaymentProof" link="@payment.Link" classes="truncate-center-id" />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
}
|
||||
</table>
|
||||
</div>
|
||||
<div class="d-none d-print-block">
|
||||
@foreach (var payment in Model.Payments)
|
||||
{
|
||||
<div class="mb-4">
|
||||
<strong>@payment.PaidFormatted</strong> = @payment.Amount @payment.PaymentMethod, Rate: @payment.RateFormatted
|
||||
@if (!string.IsNullOrEmpty(payment.PaymentProof))
|
||||
{
|
||||
<div>Proof: @payment.PaymentProof</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(Model.OrderUrl))
|
||||
{
|
||||
<a href="@Model.OrderUrl" class="btn btn-secondary rounded-pill mx-auto mt-3" rel="noreferrer noopener" target="_blank">Return to @(string.IsNullOrEmpty(Model.StoreName) ? "store" : Model.StoreName)</a>
|
||||
}
|
||||
</div>
|
||||
</main>
|
||||
<footer class="store-footer">
|
||||
|
@ -2,71 +2,208 @@
|
||||
@using BTCPayServer.Client.Models
|
||||
@using BTCPayServer.Components.QRCode
|
||||
@using BTCPayServer.Services
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@using BTCPayServer.Abstractions.TagHelpers
|
||||
@inject DisplayFormatter DisplayFormatter
|
||||
@{
|
||||
Layout = null;
|
||||
ViewData["Title"] = $"Receipt from {Model.StoreName}";
|
||||
var isProcessing = Model.Status == InvoiceStatus.Processing;
|
||||
var isFreeInvoice = (Model.Status == InvoiceStatus.New && Model.Amount == 0);
|
||||
var isSettled = Model.Status == InvoiceStatus.Settled;
|
||||
}
|
||||
|
||||
<link href="~/main/bootstrap/bootstrap.css" asp-append-version="true" rel="stylesheet" />
|
||||
<link href="~/main/site.css" asp-append-version="true" rel="stylesheet" />
|
||||
|
||||
|
||||
<p class="text-center">@Model.StoreName</p>
|
||||
<p class="text-center">@Model.Timestamp.ToBrowserDate()</p>
|
||||
<p> </p>
|
||||
|
||||
@if (isProcessing)
|
||||
{
|
||||
<div class="lead text-center p-4 fw-semibold" id="invoice-processing">
|
||||
The invoice has detected a payment but is still waiting to be settled.
|
||||
</div>
|
||||
}
|
||||
else if (!isSettled)
|
||||
{
|
||||
<div class="lead text-center p-4 fw-semibold" id="invoice-unsettled">
|
||||
The invoice is not settled.
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<h3 class="text-center">
|
||||
<strong>@DisplayFormatter.Currency(Model.Amount, Model.Currency, DisplayFormatter.CurrencyFormat.Symbol)</strong>
|
||||
</h3>
|
||||
|
||||
@if (Model.Payments?.Any() is true)
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="icon" href="~/favicon.ico" type="image/x-icon">
|
||||
<meta name="robots" content="noindex">
|
||||
<title>@ViewData["Title"]</title>
|
||||
@* CSS *@
|
||||
<link href="~/main/bootstrap/bootstrap.css" asp-append-version="true" rel="stylesheet" />
|
||||
<link href="~/main/fonts/OpenSans.css" asp-append-version="true" rel="stylesheet" />
|
||||
<link href="~/main/layout.css" asp-append-version="true" rel="stylesheet" />
|
||||
<link href="~/main/site.css" asp-append-version="true" rel="stylesheet" />
|
||||
<link href="~/main/themes/default.css" asp-append-version="true" rel="stylesheet" />
|
||||
<meta name="robots" content="noindex,nofollow">
|
||||
@if (isProcessing)
|
||||
{
|
||||
<p> </p>
|
||||
<p class="text-center"><strong>Payments</strong></p>
|
||||
@foreach (var payment in Model.Payments)
|
||||
{
|
||||
<p> </p>
|
||||
<p class="text-center">@payment.AmountFormatted <span class="text-nowrap">@payment.PaymentMethod</span></p>
|
||||
<p class="text-center">Rate: @payment.RateFormatted</p>
|
||||
<p class="text-center">= @payment.PaidFormatted</p>
|
||||
<script type="text/javascript">
|
||||
setTimeout(() => { window.location.reload(); }, 10000);
|
||||
</script>
|
||||
}
|
||||
else if (isFreeInvoice)
|
||||
{
|
||||
<script type="text/javascript">
|
||||
setTimeout(() => { window.location.reload(); }, 2000);
|
||||
</script>
|
||||
}
|
||||
<style>
|
||||
h1 {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
if (Model.AdditionalData?.Any() is true)
|
||||
{
|
||||
<p> </p>
|
||||
<p class="text-center"><strong>Additional Data</strong></p>
|
||||
<partial name="PosData" model="(Model.AdditionalData, 1)"/>
|
||||
}
|
||||
|
||||
@if (!string.IsNullOrEmpty(Model.OrderId))
|
||||
{
|
||||
<p> </p>
|
||||
<p class="text-break">Order ID: @Model.OrderId</p>
|
||||
}
|
||||
}
|
||||
|
||||
@if (Model.ReceiptOptions.ShowQR is true)
|
||||
{
|
||||
<vc:qr-code data="@Context.Request.GetCurrentUrl()"></vc:qr-code>
|
||||
}
|
||||
.qr-code {
|
||||
width: 128px;
|
||||
}
|
||||
|
||||
<script>window.print();</script>
|
||||
/* change height as you like */
|
||||
@@media print {
|
||||
body {
|
||||
width: 58mm;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.p-1 {
|
||||
padding: 1mm !important;
|
||||
}
|
||||
|
||||
.m-1 {
|
||||
margin: 1mm !important;
|
||||
}
|
||||
}
|
||||
/* this line is needed for fixing Chrome's bug */
|
||||
@@page {
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body class="m-0 p-0 bg-white">
|
||||
<center>
|
||||
<partial name="_StoreHeader" model="(Model.StoreName, Model.LogoFileId)" />
|
||||
<div id="InvoiceSummary" style="max-width:600px">
|
||||
@if (isProcessing)
|
||||
{
|
||||
<div class="lead text-center fw-semibold" id="invoice-processing">
|
||||
The invoice has detected a payment but is still waiting to be settled.
|
||||
</div>
|
||||
}
|
||||
else if (!isSettled)
|
||||
{
|
||||
<div class="lead text-center fw-semibold" id="invoice-unsettled">
|
||||
The invoice is not settled.
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div id="PaymentDetails">
|
||||
<div class="my-2 text-center small">
|
||||
@if (!string.IsNullOrEmpty(Model.OrderId))
|
||||
{
|
||||
<div>Order ID: @Model.OrderId</div>
|
||||
}
|
||||
@Model.Timestamp.ToBrowserDate()
|
||||
</div>
|
||||
<table class="table table-borderless table-sm small my-0">
|
||||
<tr>
|
||||
<td class="text-nowrap text-secondary">Total</td>
|
||||
<td class="text-end fw-semibold">@DisplayFormatter.Currency(Model.Amount, Model.Currency, DisplayFormatter.CurrencyFormat.Symbol)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><hr class="w-100 my-0"/></td>
|
||||
</tr>
|
||||
@if (Model.AdditionalData?.Any() is true &&
|
||||
(Model.AdditionalData.ContainsKey("Cart") || Model.AdditionalData.ContainsKey("Discount") || Model.AdditionalData.ContainsKey("Tip")))
|
||||
{
|
||||
@if (Model.AdditionalData.ContainsKey("Cart"))
|
||||
{
|
||||
@foreach (var (key, value) in (Dictionary<string, object>)Model.AdditionalData["Cart"])
|
||||
{
|
||||
<tr>
|
||||
<td class="text-secondary">@key</td>
|
||||
<td class="text-end">@value</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
@if (Model.AdditionalData.ContainsKey("Subtotal"))
|
||||
{
|
||||
<tr>
|
||||
<td class="text-secondary">Subtotal</td>
|
||||
<td class="text-end">@Model.AdditionalData["Subtotal"]</td>
|
||||
</tr>
|
||||
}
|
||||
@if (Model.AdditionalData.ContainsKey("Discount"))
|
||||
{
|
||||
<tr>
|
||||
<td class="text-secondary">Discount</td>
|
||||
<td class="text-end">@Model.AdditionalData["Discount"]</td>
|
||||
</tr>
|
||||
}
|
||||
@if (Model.AdditionalData.ContainsKey("Tip"))
|
||||
{
|
||||
<tr>
|
||||
<td class="text-secondary">Tip</td>
|
||||
<td class="text-end">@Model.AdditionalData["Tip"]</td>
|
||||
</tr>
|
||||
}
|
||||
<tr>
|
||||
<td colspan="2"><hr class="w-100 my-0"/></td>
|
||||
</tr>
|
||||
}
|
||||
@if (Model.Payments?.Any() is true)
|
||||
{
|
||||
@for (var i = 0; i < Model.Payments.Count; i++)
|
||||
{
|
||||
var payment = Model.Payments[i];
|
||||
@if (Model.Payments.Count > 1)
|
||||
{
|
||||
<tr>
|
||||
<td colspan="2" class="text-nowrap text-secondary">Payment @(i + 1)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-nowrap">Received</td>
|
||||
<td>@payment.ReceivedDate.ToBrowserDate()</td>
|
||||
</tr>
|
||||
}
|
||||
<tr>
|
||||
<td class="text-nowrap text-secondary">@(Model.Payments.Count == 1 ? "Paid" : "")</td>
|
||||
<td class="text-end">@payment.AmountFormatted</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="text-end">@payment.PaidFormatted</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-nowrap text-secondary">Rate</td>
|
||||
<td class="text-end">@payment.RateFormatted</td>
|
||||
</tr>
|
||||
@if (!string.IsNullOrEmpty(payment.Destination))
|
||||
{
|
||||
<tr>
|
||||
<td class="text-nowrap text-secondary">Destination</td>
|
||||
<td class="text-break">@payment.Destination</td>
|
||||
</tr>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(payment.PaymentProof))
|
||||
{
|
||||
<tr>
|
||||
<td class="text-nowrap text-secondary">Pay Proof</td>
|
||||
<td class="text-break">@payment.PaymentProof</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
<tr>
|
||||
<td colspan="2"><hr class="w-100 my-0"/></td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
</div>
|
||||
if (Model.ReceiptOptions.ShowQR is true)
|
||||
{
|
||||
<vc:qr-code data="@Context.Request.GetCurrentUrl()" size="128" />
|
||||
}
|
||||
}
|
||||
</div>
|
||||
<div class="store-footer p-3">
|
||||
<a class="store-powered-by" style="color:#000;">Powered by <partial name="_StoreFooterLogo" /></a>
|
||||
</div>
|
||||
<hr class="w-100 my-0 bg-none"/>
|
||||
</center>
|
||||
</body>
|
||||
<script>
|
||||
window.print();
|
||||
</script>
|
||||
</html>
|
||||
|
@ -299,7 +299,7 @@
|
||||
<tr>
|
||||
<td class="text-break"><vc:truncate-center text="@payment.Id" link="@payment.Link" padding="7" classes="truncate-center-id" /></td>
|
||||
<td class="amount-col">@payment.PaidFormatted</td>
|
||||
<td class="text-end text-nowrap">@payment.AmountFormatted @payment.PaymentMethod</td>
|
||||
<td class="text-end text-nowrap">@payment.AmountFormatted</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user