Fix: Custom amount in Product List mode would return error 404

This commit is contained in:
nicolas.dorier
2025-06-11 18:32:20 +09:00
parent cc5a04e8f0
commit 8f3c67b3ee
5 changed files with 73 additions and 7 deletions

View File

@@ -800,6 +800,9 @@ g:
var topupInvoice = invoices.Single(invoice => invoice.ItemCode == "g");
Assert.Equal(0, topupInvoice.Price);
Assert.Equal("new", topupInvoice.Status);
var client = await user.CreateClient();
var inv = await client.GetInvoice(user.StoreId, topupInvoice.Id);
Assert.Equal(InvoiceType.TopUp, inv.Type);
}
}
}

View File

@@ -12,6 +12,7 @@ using BTCPayServer.Plugins.PointOfSale;
using BTCPayServer.Plugins.PointOfSale.Controllers;
using BTCPayServer.Plugins.PointOfSale.Models;
using BTCPayServer.Services.Apps;
using BTCPayServer.Views.Stores;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Playwright;
using Newtonsoft.Json.Linq;
@@ -474,6 +475,66 @@ goodies:
}
}
[Fact]
[Trait("Playwright", "Playwright")]
public async Task CanUsePOSProductList()
{
await using var s = CreatePlaywrightTester();
await s.StartAsync();
await s.RegisterNewUser();
s.AsTestAccount();
await s.GoToHome();
await s.CreateNewStore();
await s.GoToStore();
await s.AddDerivationScheme();
// Let's check Custom amount works as expected
await s.CreateApp("PointOfSale");
var appUrl = s.Page.Url;
await s.Page.FillAsync("#Currency", "BTC");
await s.Page.SetCheckedAsync("#ShowCustomAmount", true);
await s.ClickPagePrimary();
var o = s.Page.Context.WaitForPageAsync();
await s.Page.ClickAsync("#ViewApp");
await using (_ = await s.SwitchPage(o))
{
await s.Page.FillAsync("#card_herbal-tea [name='amount']", "123");
await s.Page.PressAsync("#card_herbal-tea [name='amount']", "Enter");
await AssertInvoiceAmount(s, "123.00000000 BTC");
await s.Page.GoBackAsync();
await s.Page.FillAsync("#card_custom_amount [name='amount']", "124");
await s.Page.PressAsync("#card_custom_amount [name='amount']", "Enter");
await AssertInvoiceAmount(s, "124.00000000 BTC");
await s.Page.GoBackAsync();
}
await s.GoToStore();
await s.GoToStore(StoreNavPages.Forms);
await s.ClickPagePrimary();
await s.Page.FillAsync("[name='Name']", "test");
await s.Page.ClickAsync("[name='newField1']");
await s.Page.SelectOptionAsync("#field-editor-field-type", "number");
await s.Page.FillAsync("#field-editor-field-name", "invoice_amount_adjustment");
await s.Page.PressAsync("#field-editor-field-name", "Enter");
await s.ClickPagePrimary();
await s.GoToUrl(appUrl);
await s.Page.SelectOptionAsync("#FormId", new SelectOptionValue { Label = "test" });
await s.ClickPagePrimary();
}
private static async Task AssertInvoiceAmount(PlaywrightTester s, string expectedAmount)
{
var el = await s.Page.WaitForSelectorAsync("#AmountDue");
var content = await el!.TextContentAsync();
Assert.Equal(expectedAmount.NormalizeWhitespaces(), content.NormalizeWhitespaces());
}
[Fact]
[Trait("Playwright", "Playwright")]
public async Task CanUsePOSKeypad()

View File

@@ -215,15 +215,16 @@ namespace BTCPayServer.Plugins.PointOfSale.Controllers
{
jposData.Cart = new PosAppCartItem[] { new() { Id = choiceKey, Count = 1, Price = amount ?? 0 } };
}
jposData.Cart ??= [];
if (currentView is PosViewType.Print)
return NotFound();
if (currentView is PosViewType.Cart or PosViewType.Static && jposData.Cart.Length == 0)
if (currentView is PosViewType.Cart && jposData.Cart.Length == 0)
return NotFound();
if (jposData.Amounts is null &&
currentView == PosViewType.Light &&
if (string.IsNullOrEmpty(choiceKey) &&
jposData.Amounts is null &&
amount is { } o)
{
order.AddLine(new("", 1, o, settings.DefaultTaxRate));
@@ -323,7 +324,8 @@ namespace BTCPayServer.Plugins.PointOfSale.Controllers
var receiptData = new PosReceiptData();
var summary = order.Calculate();
var isTopup = selectedChoices?.FirstOrDefault()?.Price is null && currentView == PosViewType.Static;
var isTopup = currentView == PosViewType.Static &&
selectedChoices.Any(c => c.PriceType == AppItemPriceType.Topup);
if (!isTopup)
{
jposData.ItemsTotal = summary.ItemsTotal;

View File

@@ -10,7 +10,7 @@ public class PoSOrder
private readonly int _decimals;
decimal _discount;
decimal _tip;
List<ItemLine> ItemLines = new();
public List<ItemLine> ItemLines = new();
public PoSOrder(int decimals)
{

View File

@@ -35,7 +35,7 @@
: item.BuyButtonText;
buttonText = buttonText.Replace("{0}", formatted).Replace("{Price}", formatted);
<div class="col posItem posItem--displayed@(x == 0 ? " posItem--first" : null)@(x == Model.Items.Length - 1 && !Model.ShowCustomAmount ? " posItem--last" : null)">
<div id="card_@item.Id" class="col posItem posItem--displayed@(x == 0 ? " posItem--first" : null)@(x == Model.Items.Length - 1 && !Model.ShowCustomAmount ? " posItem--last" : null)">
<div class="tile card" data-id="@x">
@if (!string.IsNullOrWhiteSpace(item.Image))
{
@@ -92,7 +92,7 @@
}
@if (Model.ShowCustomAmount)
{
<div class="col posItem posItem--displayed posItem--last@(Model.Items.Length == 0 ? " posItem--first" : null)">
<div id="card_custom_amount" class="col posItem posItem--displayed posItem--last@(Model.Items.Length == 0 ? " posItem--first" : null)">
<div class="card h-100 px-0">
<div class="card-body p-3 d-flex flex-column gap-2 mb-auto">
<h5 class="card-title" text-translate="true">Custom Amount</h5>