Fix isPaidImmediately's exact-match regression, add unpaid Vorkasse instructions
Validate e-invoices / mustang (push) Successful in 41s
Validate e-invoices / mustang (push) Successful in 41s
isPaidImmediately() matched paymentMethodTitle with an exact !== check
against the literal "Überweisung" — the consuming shop renamed its
Vorkasse row to "Überweisung (Vorkasse)" the same day, which would have
silently made every unpaid Vorkasse invoice show "✓ Bereits beglichen".
Changed to startsWith("Überweisung") — same design, tolerant of a
suffix qualifier.
Also adds an explicit instruction for the unpaid case (previously the
absence of the paid confirmation was the only signal, no actual text):
pay to the listed bank details, order processed after payment received
(~1-2 business days).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -29,6 +29,8 @@ One canonical implementation, consumed by both repos, makes this class of drift
|
||||
|
||||
**2026-07-24, Kleinunternehmerregelung (§19 UStG).** `InvoiceOrder`/`CorrectionInvoiceOrder` gained optional `kleinunternehmer`, a third order-level VAT treatment alongside `vatExempt` — see "Kleinunternehmerregelung" below. Takes precedence over `vatExempt` wherever both would otherwise apply (a Kleinunternehmer never charges VAT to begin with, so there's nothing left to "exempt" via the separate intra-community rule).
|
||||
|
||||
**2026-07-25, Vorkasse fixes (v0.2.3).** `isPaidImmediately()` matched `paymentMethodTitle` with an exact `!==` check against the literal string `"Überweisung"` — the consuming shop renamed its Vorkasse row to `"Überweisung (Vorkasse)"` the same day (to make room for a possible future *automated* bank-transfer method, e.g. "Sofortüberweisung", routed through a real payment gateway), which would have silently made every unpaid Vorkasse invoice show "✓ Bereits beglichen". Changed to `startsWith("Überweisung")` — same "only Überweisung is the named exception" design, tolerant of a suffix qualifier on that one title. Also added an explicit instruction in the unpaid case (previously the *absence* of the paid confirmation was the only signal, no actual text): "Bitte überweisen Sie den Rechnungsbetrag unter Angabe der Bestellnummer … auf die unten stehende Bankverbindung. Die Bestellung wird nach Zahlungseingang bearbeitet (in der Regel innerhalb von 1–2 Werktagen)." — same plain-text treatment as the paid confirmation (`unpaidNoticeText`, muted rather than green — an unpaid Vorkasse invoice isn't a problem, just an expected pending state).
|
||||
|
||||
## How this is consumed
|
||||
|
||||
Not published to npm — installed as a git dependency:
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@einfach-produktiv/invoicing",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@einfach-produktiv/invoicing",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.2",
|
||||
"dependencies": {
|
||||
"@e-invoice-eu/core": "^3.1.1"
|
||||
},
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@einfach-produktiv/invoicing",
|
||||
"version": "0.2.2",
|
||||
"version": "0.2.3",
|
||||
"private": true,
|
||||
"description": "Shared invoice / correction-invoice (Stornorechnung, Gutschrift) PDF generation and VAT-breakdown math, consumed as a git dependency by both the einfach-produktiv frontend and the payload backend — not published to npm.",
|
||||
"type": "module",
|
||||
|
||||
@@ -42,10 +42,17 @@ describe("isPaidImmediately", () => {
|
||||
expect(isPaidImmediately("PayPal")).toBe(true);
|
||||
});
|
||||
|
||||
it("is false only for Überweisung", () => {
|
||||
it("is false for Überweisung", () => {
|
||||
expect(isPaidImmediately("Überweisung")).toBe(false);
|
||||
});
|
||||
|
||||
it("is false for a suffixed Überweisung title too (startsWith, not exact match)", () => {
|
||||
// Regression: the shop renamed its Vorkasse row to this exact title
|
||||
// (2026-07-25) — an exact `!==` match would have silently started
|
||||
// showing "✓ Bereits beglichen" on unpaid invoices.
|
||||
expect(isPaidImmediately("Überweisung (Vorkasse)")).toBe(false);
|
||||
});
|
||||
|
||||
it("defaults to true for any future/unknown payment method (only Überweisung is the named exception)", () => {
|
||||
expect(isPaidImmediately("Sofortüberweisung")).toBe(true);
|
||||
expect(isPaidImmediately("Klarna")).toBe(true);
|
||||
|
||||
+29
-8
@@ -50,6 +50,12 @@ const styles = StyleSheet.create({
|
||||
metaLabel: { fontSize: 7, color: TEXT_MUTED, textTransform: "uppercase", marginBottom: 2 },
|
||||
metaValue: { fontSize: 10, fontFamily: "Helvetica-Bold" },
|
||||
paidBadgeText: { fontSize: 10, fontFamily: "Helvetica-Bold", color: SUCCESS },
|
||||
// Same plain-text treatment as paidBadgeText (no pill/box, see that
|
||||
// style's own comment) — muted, not an error/warning color, since an
|
||||
// unpaid Vorkasse invoice isn't a problem, just a pending, expected
|
||||
// state. Right-aligned + a max width so the two-sentence instruction
|
||||
// wraps under the summary card instead of running the full page width.
|
||||
unpaidNoticeText: { fontSize: 9, color: TEXT_MUTED, textAlign: "right", maxWidth: 220 },
|
||||
table: { borderRadius: 6, overflow: "hidden", borderWidth: 1, borderColor: BORDER, marginTop: 8, marginBottom: 16 },
|
||||
tableHeader: { flexDirection: "row", backgroundColor: BG_MUTED, paddingVertical: 8, paddingHorizontal: 10 },
|
||||
// Every item row shares this same tinted background now — no more
|
||||
@@ -222,14 +228,23 @@ export const SAMPLE_INVOICE_ORDER: InvoiceOrder = {
|
||||
total: 37.7,
|
||||
};
|
||||
|
||||
// "Überweisung" (bank transfer) is the only payment method on this shop
|
||||
// that ISN'T settled immediately — Kreditkarte/PayPal both capture at
|
||||
// checkout. Rather than hardcode a list of "immediate" method titles
|
||||
// (fragile the moment a new one is added in Payload's payment-methods
|
||||
// collection), the only method that's ever NOT immediate is named
|
||||
// explicitly — everything else defaults to "paid already".
|
||||
// "Überweisung" (bank transfer, Vorkasse) is the only payment method on
|
||||
// this shop that ISN'T settled immediately — Kreditkarte/PayPal both
|
||||
// capture at checkout. Rather than hardcode a list of "immediate" method
|
||||
// titles (fragile the moment a new one is added in Payload's
|
||||
// payment-methods collection), the only method that's ever NOT immediate
|
||||
// is named explicitly — everything else defaults to "paid already".
|
||||
//
|
||||
// `startsWith`, not an exact `!==` match — the consuming shop renamed its
|
||||
// Vorkasse row to "Überweisung (Vorkasse)" (2026-07-25, to distinguish it
|
||||
// from a possible future *automated* bank-transfer method routed through
|
||||
// Stripe, e.g. "Sofortüberweisung" — see the test below asserting that one
|
||||
// stays `true`). An exact-match check would have silently started showing
|
||||
// "✓ Bereits beglichen" on unpaid Vorkasse invoices the moment that title
|
||||
// changed. `startsWith` keeps the same "only Überweisung is the named
|
||||
// exception" design while tolerating a suffix qualifier on that one title.
|
||||
function isPaidImmediately(paymentMethodTitle: string): boolean {
|
||||
return paymentMethodTitle !== "Überweisung";
|
||||
return !paymentMethodTitle.startsWith("Überweisung");
|
||||
}
|
||||
|
||||
// Distributes the order-level discount/shipping proportionally across each
|
||||
@@ -448,10 +463,16 @@ export function InvoiceDocument({ order, seller }: { order: InvoiceOrder; seller
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
{paid && (
|
||||
{paid ? (
|
||||
<View style={styles.paidBadgeRow}>
|
||||
<Text style={styles.paidBadgeText}>✓ Bereits beglichen ({order.paymentMethodTitle})</Text>
|
||||
</View>
|
||||
) : (
|
||||
<View style={styles.paidBadgeRow}>
|
||||
<Text style={styles.unpaidNoticeText}>
|
||||
Bitte überweisen Sie den Rechnungsbetrag unter Angabe der Bestellnummer {order.orderNumber} auf die unten stehende Bankverbindung. Die Bestellung wird nach Zahlungseingang bearbeitet (in der Regel innerhalb von 1–2 Werktagen).
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
Reference in New Issue
Block a user