Webshop: IP-Hash entfällt mit Zahlung oder Storno, keine Käufer-Telefonnummer mehr gespeichert

schliesseAb und verwirf entfernen ipHash aus dem Bestell-JSON, sobald die Bestellung nicht mehr offen ist
(Begrenzung offener Bestellungen je IP bleibt). customer_details.phone wird nicht mehr in kaeufer.telefon
übernommen; Kundenansicht und Bestelldetail geben auch in alten Datensätzen keine Telefonnummer aus.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-05 10:26:56 +00:00
1 parent 4ab84e31ac
commit 43473c0879
9 files changed
+79 -19

No files matched your search

+7 -5
View File
@@ -145,7 +145,7 @@ function bestellung(over = {}, datenOver = {}) {
shopname: 'Brot & Mehr',
lieferzeit: '2–4 Werktage',
zahlungsarten: ['card'],
kaeufer: { name: 'Max Mustermann', email: 'max@example.com', telefon: '+49 170 1234567' },
kaeufer: { name: 'Max Mustermann', email: 'max@example.com', telefon: '+49 170 1234567' }, // alter Datensatz mit Telefonnummer: wird nie ausgegeben
lieferadresse: lieferart === 'versand' ? { name: 'Max Mustermann', line1: 'Lieferweg 7', line2: '', postal_code: '67655', city: 'Kaiserslautern', country: 'DE' } : undefined,
zahlungsart: 'card',
verlauf: [{ at: T0.toISOString(), was: 'angelegt' }, { at: nach(60).toISOString(), was: 'bezahlt' }],
@@ -355,7 +355,7 @@ test('erstatte: Stripe-Fehler => 502 mit festem Text ohne Stripe-Wortlaut, nicht
test('listeBestellungen: neueste zuerst, ohne Filter nur bezahlte, Statusfilter, Suche (Nummer-Anfang, Name, E-Mail), Blättern mit 50 je Seite', async () => {
const ids = []
for (let i = 0; i < 55; i += 1) ids.push(bestellung({ kaeuferEmail: `k${i}@example.com` }, { kaeufer: { name: i === 3 ? 'Erika Beispiel' : `Kunde ${i}`, email: `k${i}@example.com`, telefon: '' } }))
for (let i = 0; i < 55; i += 1) ids.push(bestellung({ kaeuferEmail: `k${i}@example.com` }, { kaeufer: { name: i === 3 ? 'Erika Beispiel' : `Kunde ${i}`, email: `k${i}@example.com` } }))
const offen = bestellung({ status: 'offen' })
const storniert = bestellung({ status: 'storniert' })
const versendet = bestellung({ status: 'versendet' })
@@ -390,6 +390,8 @@ test('bestellungKunde: alle Händlerdaten, keine Token-/Stripe-Kennungen, mögli
const id = bestellung({}, { erstattungen: [{ rid: 're_1', betragCent: 190, grund: 'Kulanz', at: nach(9).toISOString(), quelle: 'portal' }], ueberverkauft: true })
const ansicht = B.bestellungKunde(await B.bestellungLesen(id))
assert.equal(ansicht.kaeufer.email, 'max@example.com')
assert.deepEqual(ansicht.kaeufer, { name: 'Max Mustermann', email: 'max@example.com' }, 'eine alte Telefonnummer im Datensatz wird nicht ausgegeben')
assert.ok(!JSON.stringify(ansicht).includes('1234567'))
assert.equal(ansicht.lieferadresse.line1, 'Lieferweg 7')
assert.equal(ansicht.erstattetCent, 190)
assert.equal(ansicht.restCent, 1500)
@@ -407,10 +409,10 @@ test('bestellungKunde: alle Händlerdaten, keine Token-/Stripe-Kennungen, mögli
// ------------------------------------------------------------------------------------------------ CSV
test('csv: BOM, Semikolon, Kopfzeile, Beträge ohne NBSP, Berliner Datum, Formel-Injektion entschärft, Anführungszeichen verdoppelt', async () => {
const a = bestellung({ bezahltAt: '2026-10-04T22:30:00.000Z', summeCent: 1250, kaeuferEmail: '+evil@example.com' }, { kaeufer: { name: '=HYPERLINK("http://x.example";"a")', email: '+evil@example.com', telefon: '' } })
const a = bestellung({ bezahltAt: '2026-10-04T22:30:00.000Z', summeCent: 1250, kaeuferEmail: '+evil@example.com' }, { kaeufer: { name: '=HYPERLINK("http://x.example";"a")', email: '+evil@example.com' } })
const b = bestellung(
{ bezahltAt: '2026-10-06T08:00:00.000Z', status: 'erstattet', kaeuferEmail: 'anna@example.com' },
{ kaeufer: { name: 'Anna; "Annie" Schmidt', email: 'anna@example.com', telefon: '' }, erstattungen: [{ rid: 're_x', betragCent: 1690, grund: '', at: T0.toISOString(), quelle: 'portal' }] }
{ kaeufer: { name: 'Anna; "Annie" Schmidt', email: 'anna@example.com' }, erstattungen: [{ rid: 're_x', betragCent: 1690, grund: '', at: T0.toISOString(), quelle: 'portal' }] }
)
bestellung({ status: 'offen' })
bestellung({ status: 'storniert' })
@@ -551,7 +553,7 @@ test('Routen: Kundenansicht darf lesen (Liste, Detail, CSV, Widerrufe), aber wed
})
test('Routen: CSV als Download mit BOM, Dateiname und Zeitraum; ungültiges Datum 400', async () => {
bestellung({ bezahltAt: '2026-10-05T10:00:00.000Z' }, { kaeufer: { name: '@SUM(A1)', email: 'a@example.com', telefon: '' } })
bestellung({ bezahltAt: '2026-10-05T10:00:00.000Z' }, { kaeufer: { name: '@SUM(A1)', email: 'a@example.com' } })
bestellung({ bezahltAt: '2026-09-01T10:00:00.000Z' })
const res = await fetch(`${app.url}/api/shop/bestellungen.csv?projectId=${PROJEKT}&von=2026-10-01&bis=2026-10-31`, { headers: { cookie } })
assert.equal(res.status, 200)