Shop Review B I-6, I-7: Archiv der bestaetigten Rechtstexte, G09 ohne Link-Ersatz
I-6: Neue Collection shopRechtstexteArchiv (ID r + 35 Hex aus sha256(shopId + hash)); das Bestaetigen legt die Fassung samt Versand-/Zahlungstext und Gewaehrleistungstext ab, G09 zeigt die Fassung zum rechtstexteHash der Bestellung (Rueckfall mit Warnung auf die aktuell bestaetigte), loescheShopDaten loescht das Archiv mit. I-7: Grenzen AGB 20000, Belehrung 12000, Formular 3000 plus Pruefung der maskierten Laenge beim Speichern; G09 ersetzt die AGB nie mehr durch einen Link, sondern scheitert (Marker bleibt offen, wird wiederholt). Test mit Texten in Hoechstlaenge gegen die Grenzen der Warteschlange. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2f4f360a21
commit
08d837d690
17 files changed
+288
-65
No files matched your search
@@ -16,6 +16,7 @@ const aw = await startAppwriteMock({
|
||||
shopConfig: schemaKeys('shopConfig'),
|
||||
shopProducts: schemaKeys('shopProducts'),
|
||||
shopOrders: schemaKeys('shopOrders'),
|
||||
shopRechtstexteArchiv: schemaKeys('shopRechtstexteArchiv'),
|
||||
termineOutbox: schemaKeys('termineOutbox'),
|
||||
},
|
||||
datetimes: { ...SHOP_DATETIMES, ...TERMINE_DATETIMES },
|
||||
@@ -29,6 +30,7 @@ const { deleteDocument, updateDocument } = await import('../server/services/appw
|
||||
const { setMailTransportForTests } = await import('../server/services/mailer.js')
|
||||
const { resetOutboxForTests, warteAufVersand } = await import('../server/services/termine/outbox.js')
|
||||
const K = await import('../server/services/shop/kontext.js')
|
||||
const { archiviereRechtstexte } = await import('../server/services/shop/archiv.js')
|
||||
const B = await import('../server/services/shop/bestellungen.js')
|
||||
const J = await import('../server/services/shop/jobs.js')
|
||||
const { normalisiereProdukt } = await import('../server/services/shop/produkte.js')
|
||||
@@ -87,7 +89,7 @@ let sink
|
||||
let log
|
||||
let ctx
|
||||
async function aufbau({ produkte = [artikel('a1', { bestand: 5 })], shop = {} } = {}) {
|
||||
for (const c of ['portalFeatures', 'shopConfig', 'shopProducts', 'shopOrders', 'websiteProjects', 'termineOutbox', 'customers']) {
|
||||
for (const c of ['portalFeatures', 'shopConfig', 'shopProducts', 'shopOrders', 'shopRechtstexteArchiv', 'websiteProjects', 'termineOutbox', 'customers']) {
|
||||
for (const id of [...aw.docs(c).keys()]) await deleteDocument(config.collections[c], id)
|
||||
}
|
||||
aw.seed('websiteProjects', { $id: PROJEKT, customerId: KUNDE, projectName: 'Brotladen', liveDomain: 'https://www.brot.example' })
|
||||
@@ -185,6 +187,23 @@ test('schliesseAb: Normalfall - bezahlt, Käuferdaten, Bestand abgezogen, G09 an
|
||||
assert.equal(order(b.orderId).status, 'bezahlt')
|
||||
})
|
||||
|
||||
test('schliesseAb I-6: G09 enthält die Rechtstexte der Bestellung (Archiv zum Hash), auch wenn der Händler sie danach geändert und neu bestätigt hat', async () => {
|
||||
await aufbau()
|
||||
const b = await bestelle()
|
||||
await archiviereRechtstexte({ shopId: FEATURE, customerId: KUNDE, hash: HASH, at: T0.toISOString(), von: 'k@example.invalid', texte: { ...TEXTE, agb: 'AGB ZUM ZEITPUNKT DER BESTELLUNG', versandUndZahlung: 'x', gewaehrleistung: 'GEWÄHRLEISTUNG DAMALS' } })
|
||||
// neue Fassung bestätigt, bevor bezahlt wird (SEPA: Tage später)
|
||||
const neu = { ...TEXTE, agb: 'NEUE AGB NACH DER BESTELLUNG' }
|
||||
aw.seed('shopConfig', shopDoc({ rechtstexte: JSON.stringify({ entwurf: neu, bestaetigt: { texte: neu, hash: 'e'.repeat(64), at: '2026-10-06T10:00:00.000Z', von: 'k@example.invalid' } }) }))
|
||||
K.leereCache()
|
||||
assert.equal(JSON.parse(order(b.orderId).bestellung).rechtstexteHash, HASH)
|
||||
await B.schliesseAb({ accountId: ACCOUNT, session: zahle(b), now: nach(120) })
|
||||
await warteAufVersand()
|
||||
const g09 = sink.sent.find((m) => m.to[0].address === 'max@example.com')
|
||||
assert.match(g09.text, /AGB ZUM ZEITPUNKT DER BESTELLUNG/)
|
||||
assert.match(g09.text, /GEWÄHRLEISTUNG DAMALS/)
|
||||
assert.doesNotMatch(g09.text, /NEUE AGB/)
|
||||
})
|
||||
|
||||
test('schliesseAb: idempotent - zweiter Aufruf ändert nichts, keine zweite Mail, Bestand nur einmal', async () => {
|
||||
await aufbau()
|
||||
const b = await bestelle()
|
||||
|
||||
Reference in new issue
Block a user