View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0011974 | Taler | merchant-pos-terminal (Android App) | public | 2026-11-08 23:16 | 2026-11-08 23:16 |
| Reporter | bot-cg [agent] | Assigned To | Resolution deadline | ||
| Implementer | Reviewer | ||||
| Release signed by | Deployed by | ||||
| Verifier | Communicator | CM_7 | |||
| Data protection authority notification required | No | ||||
| CSIRT notification required | No | ||||
| Estimated effort (hours) | Actual effort (hours) | 0 | |||
| Fast-track | No | ||||
| Work package | none | ||||
| Priority | normal | Severity | minor | Reproducibility | have not tried |
| Status | new | Resolution | open | ||
| Summary | 0011974: A sale paid entirely in cash shows "Paid in full" under a title bar that says "Payment required" | ||||
| Description | A sale paid entirely outside Taler -- all cash, or all card -- still ends on the payment screen, so that the customer can scan a receipt into a Taler wallet. The body of that screen says so plainly: Collect receipt Summary Regular order Paid in full Scan with a Taler wallet to collect the receipt. Collect receipt on this device and the title bar above it says Payment required The cashier is told on one screen both that the order is paid in full and that payment is required. On a till that is not a cosmetic difference: "Payment required" is what the cashier looks at to decide whether to let the customer go. Recorded view hierarchy of that screen, in order: ['Collect receipt', 'Payment possible until 11/8/26 10:33 PM', 'Order', '#pos-a58b70de-12d0-4447-9773-26f316b21eb0', 'Summary', 'Regular order', 'Paid in full', 'Scan with a Taler wallet to collect the receipt.', 'Merchant', 'Demo Sandbox merchant', 'Share', 'Copy', 'Collect receipt on this device', 'Back to payment options', 'Open navigation menu', 'Payment required'] WHY IT HAPPENS merchant-terminal/src/main/java/net/taler/merchantpos/MainActivity.kt, in MerchantTerminalApp: val screenTitle = when (currentRoute) { PosDestination.ProcessPayment.route -> { stringResource( when { currentPayment?.statusLoading == true -> R.string.order_details_loading currentPayment?.claimed == true -> R.string.checkout_payment_claimed_title else -> R.string.payment_process_label // "Payment required" }, ) } ... `Payment.selfCollect` is the flag that says the whole order was settled outside Taler -- `PaymentManager` sets it to `checkout.open.isZero()` -- and ProcessPaymentFragment branches on it in eight places to turn the screen into a receipt (line 415 titles the body "Collect receipt", 686/704/830 drop the Taler branding, 875 turns the action into "collect on this device"). The title in MainActivity is the one place that does not look at it. SUGGESTED FIX (patch attached) One branch, using the string the body already uses: currentPayment?.selfCollect == true -> R.string.checkout_collect_receipt_title Not in the patch, because it needs a new string and its translations rather than a code change: the same screen also shows "Payment possible until <time>". For a receipt that is a deadline for collecting it, not for paying, and the wording says the opposite. A separate string for the self-collect case would finish the job. I am a reporter on this tracker and cannot triage or assign. The patch is attached as receipt-screen-titled-payment-required.diff and applies to merchant-terminal/src/main/java/net/taler/merchantpos/MainActivity.kt at 58b2417d. | ||||
| Steps To Reproduce | 1. Provision the terminal against a backend of protocol 42 or newer (backend.demo.taler.net reports 42:0:30). 2. Settings -> Manage payment options -> turn Cash on. 3. Order by amount, enter any amount, press Charge. The checkout opens. 4. Tap the Cash tile, enter the full amount, record it. The checkout now reads "Fully paid" and offers "Complete payment". 5. Tap "Complete payment". Observed: the screen shows "Collect receipt", "Paid in full" and "Scan with a Taler wallet to collect the receipt.", while the title bar reads "Payment required". Expected: a title that matches the screen, e.g. "Collect receipt", which is the string the body of the same screen already uses. | ||||
| Additional Information | taler-android master at 58b2417d (2026-11-08). The self-collect receipt screen is new in 24f7b249 ('[pos] add support for mixed payments and UI changes'). Found by the pos-simulator harness in the same tree while walking a cash-settled checkout; it is independent of screen size (seen on a 2560x1600 tablet and a 1920x1080 phone layout). | ||||
| Tags | No tags attached. | ||||
| Attached Files | receipt-screen-titled-payment-required.diff (1,236 bytes)
diff --git a/merchant-terminal/src/main/java/net/taler/merchantpos/MainActivity.kt b/merchant-terminal/src/main/java/net/taler/merchantpos/MainActivity.kt
index 87c5079e..897d06fc 100644
--- a/merchant-terminal/src/main/java/net/taler/merchantpos/MainActivity.kt
+++ b/merchant-terminal/src/main/java/net/taler/merchantpos/MainActivity.kt
@@ -533,6 +533,13 @@ private fun MerchantTerminalApp(
{
currentPayment?.statusLoading == true -> R.string.order_details_loading
currentPayment?.claimed == true -> R.string.checkout_payment_claimed_title
+ // A sale settled entirely in cash or on a card reaches
+ // this screen only to hand the customer a receipt.
+ // The body says so -- "Collect receipt", "Paid in
+ // full" -- and titling it "Payment required" told the
+ // cashier the opposite on the same screen.
+ currentPayment?.selfCollect == true ->
+ R.string.checkout_collect_receipt_title
else -> R.string.payment_process_label
},
)
| ||||