diff --git a/BTCPayServer/Controllers/UIInvoiceController.UI.cs b/BTCPayServer/Controllers/UIInvoiceController.UI.cs index e867d7a4d..48ef9d9fa 100644 --- a/BTCPayServer/Controllers/UIInvoiceController.UI.cs +++ b/BTCPayServer/Controllers/UIInvoiceController.UI.cs @@ -123,6 +123,7 @@ namespace BTCPayServer.Controllers var additionalData = metaData .Where(dict => !InvoiceAdditionalDataExclude.Contains(dict.Key)) .ToDictionary(dict => dict.Key, dict => dict.Value); + var model = new InvoiceDetailsModel { StoreId = store.Id, @@ -149,7 +150,6 @@ namespace BTCPayServer.Controllers StatusException = invoice.ExceptionStatus, Events = invoice.Events, Metadata = metaData, - AdditionalData = additionalData, Archived = invoice.Archived, CanRefund = invoiceState.CanRefund(), Refunds = invoice.Refunds, @@ -166,6 +166,13 @@ namespace BTCPayServer.Controllers model.CryptoPayments = details.CryptoPayments; model.Payments = details.Payments; model.Overpaid = details.Overpaid; + + if (additionalData.ContainsKey("receiptData")) + { + model.ReceiptData = (Dictionary)additionalData["receiptData"]; + additionalData.Remove("receiptData"); + } + model.AdditionalData = additionalData; return View(model); } diff --git a/BTCPayServer/Models/InvoicingModels/InvoiceDetailsModel.cs b/BTCPayServer/Models/InvoicingModels/InvoiceDetailsModel.cs index 3a60186b8..9a02d8d6e 100644 --- a/BTCPayServer/Models/InvoicingModels/InvoiceDetailsModel.cs +++ b/BTCPayServer/Models/InvoicingModels/InvoiceDetailsModel.cs @@ -127,6 +127,7 @@ namespace BTCPayServer.Models.InvoicingModels public List Events { get; internal set; } public string NotificationEmail { get; internal set; } public Dictionary Metadata { get; set; } + public Dictionary ReceiptData { get; set; } public Dictionary AdditionalData { get; set; } public List Payments { get; set; } public bool Archived { get; set; } diff --git a/BTCPayServer/Plugins/PointOfSale/Controllers/UIPointOfSaleController.cs b/BTCPayServer/Plugins/PointOfSale/Controllers/UIPointOfSaleController.cs index 2eb09384a..0cb60b184 100644 --- a/BTCPayServer/Plugins/PointOfSale/Controllers/UIPointOfSaleController.cs +++ b/BTCPayServer/Plugins/PointOfSale/Controllers/UIPointOfSaleController.cs @@ -347,9 +347,10 @@ namespace BTCPayServer.Plugins.PointOfSale.Controllers var receiptData = new JObject(); if (choice is not null) { - receiptData = JObject.FromObject(new Dictionary() + receiptData = JObject.FromObject(new Dictionary { - {"Title", choice.Title}, {"Description", choice.Description}, + {"Title", choice.Title}, + {"Description", choice.Description}, }); } else if (jposData is not null) @@ -370,21 +371,21 @@ namespace BTCPayServer.Plugins.PointOfSale.Controllers var totalPrice = _displayFormatter.Currency(cartItem.Price * cartItem.Count, settings.Currency, DisplayFormatter.CurrencyFormat.Symbol); var ident = selectedChoice.Title ?? selectedChoice.Id; var key = selectedChoice.PriceType == ViewPointOfSaleViewModel.ItemPriceType.Fixed ? ident : $"{ident} ({singlePrice})"; - cartData.Add(key, $"{singlePrice} x {cartItem.Count} = {totalPrice}"); + cartData.Add(key, $"{cartItem.Count} x {singlePrice} = {totalPrice}"); } receiptData.Add("Cart", cartData); } - + receiptData.Add("Subtotal", _displayFormatter.Currency(appPosData.Subtotal, settings.Currency, DisplayFormatter.CurrencyFormat.Symbol)); if (appPosData.DiscountAmount > 0) { - receiptData.Add("Discount", - $"{_displayFormatter.Currency(appPosData.DiscountAmount, settings.Currency, DisplayFormatter.CurrencyFormat.Symbol)} {(appPosData.DiscountPercentage > 0 ? $"({appPosData.DiscountPercentage}%)" : string.Empty)}"); + var discountFormatted = _displayFormatter.Currency(appPosData.DiscountAmount, settings.Currency, DisplayFormatter.CurrencyFormat.Symbol); + receiptData.Add("Discount", appPosData.DiscountPercentage > 0 ? $"{appPosData.DiscountPercentage}% = {discountFormatted}" : discountFormatted); } - if (appPosData.Tip > 0) { receiptData.Add("Tip", _displayFormatter.Currency(appPosData.Tip, settings.Currency, DisplayFormatter.CurrencyFormat.Symbol)); } + receiptData.Add("Total", _displayFormatter.Currency(appPosData.Total, settings.Currency, DisplayFormatter.CurrencyFormat.Symbol)); } entity.Metadata.SetAdditionalData("receiptData", receiptData); diff --git a/BTCPayServer/Views/Shared/PosData.cshtml b/BTCPayServer/Views/Shared/PosData.cshtml index 22471f6e8..e8133d6bc 100644 --- a/BTCPayServer/Views/Shared/PosData.cshtml +++ b/BTCPayServer/Views/Shared/PosData.cshtml @@ -1,77 +1,111 @@ -@using Microsoft.AspNetCore.Mvc.TagHelpers @model (Dictionary Items, int Level) @functions { - private bool IsValidURL(string source) { return Uri.TryCreate(source, UriKind.Absolute, out var uriResult) && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); } - } -@if (Model.Items.Count > 0) +@if (Model.Items.Any()) { - @foreach (var (key, value) in Model.Items) + @if (Model.Items.ContainsKey("Cart")) { - - @if (value is string str) + + @foreach (var (key, value) in (Dictionary )Model.Items["Cart"]) { - if (!string.IsNullOrEmpty(key)) + + + + + } + + + @if (Model.Items.ContainsKey("Subtotal")) + { + + + + + } + @if (Model.Items.ContainsKey("Discount")) + { + + + + + } + @if (Model.Items.ContainsKey("Tip")) + { + + + + + } + @if (Model.Items.ContainsKey("Total")) + { + + + + + } + + } + else + { + foreach (var (key, value) in Model.Items) + { + + @if (value is string str) { - + if (!string.IsNullOrEmpty(key)) + { + + } + } - - } - else if (value is Dictionary {Count: > 0 } subItems) - { - - } - else if (value is IEnumerable valueArray) - { - + } + else if (value is IEnumerable valueArray) + { + - } - + + } + + } }
@key@value
Subtotal@Model.Items["Subtotal"]
Discount@Model.Items["Discount"]
Tip@Model.Items["Tip"]
Total@Model.Items["Total"]
@key@key@* Explicitely remove whitespace at front here *@@if (IsValidURL(str)){@str}else {@str.Trim()}@* Explicitely remove whitespace at front here *@@if (IsValidURL(str)) - { - @str - } - else - { - @str.Trim() - } - - @{ - @if (!string.IsNullOrEmpty(key)) - { - Write(Html.Raw($"")); - Write(key); - Write(Html.Raw($"")); + else if (value is Dictionary { Count: > 0 } subItems) + { + + @{ + @if (!string.IsNullOrEmpty(key)) + { + Write(Html.Raw($"")); + Write(key); + Write(Html.Raw($"")); + } } - } - - - @{ - @if (!string.IsNullOrEmpty(key)) - { - Write(Html.Raw($"")); - Write(key); - Write(Html.Raw($"")); + + + @{ + @if (!string.IsNullOrEmpty(key)) + { + Write(Html.Raw($"")); + Write(key); + Write(Html.Raw($"")); + } } - } - @foreach (var item in valueArray) - { - @if (item is Dictionary {Count: > 0 } subItems2) + @foreach (var item in valueArray) { - + @if (item is Dictionary { Count: > 0 } subItems2) + { + + } + else + { + + } } - else - { - - } - } -
} diff --git a/BTCPayServer/Views/UIInvoice/Invoice.cshtml b/BTCPayServer/Views/UIInvoice/Invoice.cshtml index 2b688b06e..2477b4902 100644 --- a/BTCPayServer/Views/UIInvoice/Invoice.cshtml +++ b/BTCPayServer/Views/UIInvoice/Invoice.cshtml @@ -473,7 +473,19 @@ } - @if (Model.AdditionalData.Any()) + @if (Model.ReceiptData != null && Model.ReceiptData.Any()) + { +
+

+ Receipt Information + + + +

+ +
+ } + @if (Model.AdditionalData != null && Model.AdditionalData.Any()) {

diff --git a/BTCPayServer/Views/UIInvoice/InvoiceReceipt.cshtml b/BTCPayServer/Views/UIInvoice/InvoiceReceipt.cshtml index 86ce5f036..419dd8157 100644 --- a/BTCPayServer/Views/UIInvoice/InvoiceReceipt.cshtml +++ b/BTCPayServer/Views/UIInvoice/InvoiceReceipt.cshtml @@ -3,9 +3,6 @@ @using BTCPayServer.Client.Models @using BTCPayServer.Components.QRCode @using BTCPayServer.Services -@using Microsoft.AspNetCore.Mvc.TagHelpers -@using BTCPayServer.Abstractions.TagHelpers -@using BTCPayServer.Payments @inject BTCPayServerEnvironment Env @inject DisplayFormatter DisplayFormatter @{ @@ -84,25 +81,7 @@ {
Order ID
-
- @if (!string.IsNullOrEmpty(Model.OrderUrl)) - { - - @if (string.IsNullOrEmpty(Model.OrderId)) - { - View Order - } - else - { - @Model.OrderId - } - - } - else - { - @Model.OrderId - } -
+
@Model.OrderId
} @@ -115,6 +94,15 @@ } else if (isSettled) { + if (Model.AdditionalData?.Any() is true) + { +
+

Additional Data

+
+ +
+
+ } if (Model.Payments?.Any() is true) {
@@ -178,15 +166,10 @@

} - if (Model.AdditionalData?.Any() is true) - { -
-

Additional Data

-
- -
-
- } + } + @if (!string.IsNullOrEmpty(Model.OrderUrl)) + { + Return to @(string.IsNullOrEmpty(Model.StoreName) ? "store" : Model.StoreName) } diff --git a/BTCPayServer/wwwroot/pos/cart.js b/BTCPayServer/wwwroot/pos/cart.js index d93db5220..e8377a9cf 100644 --- a/BTCPayServer/wwwroot/pos/cart.js +++ b/BTCPayServer/wwwroot/pos/cart.js @@ -55,14 +55,11 @@ document.addEventListener("DOMContentLoaded",function () { return parseFloat(this.cart.reduce((res, item) => res + (item.price||0) * item.count, 0).toFixed(this.currencyInfo.divisibility)) }, posdata () { - const data = { - cart: this.cart, - subTotal: this.amountNumeric, - total: this.totalNumeric - } - if (this.tipNumeric > 0) data.tip = this.tipNumeric + const data = { cart: this.cart, subTotal: this.amountNumeric } if (this.discountNumeric > 0) data.discountAmount = this.discountNumeric if (this.discountPercentNumeric > 0) data.discountPercentage = this.discountPercentNumeric + if (this.tipNumeric > 0) data.tip = this.tipNumeric + data.total = this.totalNumeric return JSON.stringify(data) } },