/** * Regenerates a single existing invoice using the offline session token, * downloads the resulting PDF and pretty-prints the closing/footer text so * we can verify the new wording end-to-end against the live dev store. * * Usage: npx tsx scripts/regenerate-invoice.ts [invoiceNumber] * default invoiceNumber = RE-1001 */ import "dotenv/config"; import { writeFileSync } from "node:fs"; import { execFileSync } from "node:child_process"; import { resolve } from "node:path"; import db from "../app/db.server"; import { unauthenticated } from "../app/shopify.server"; import { generateInvoice } from "../app/services/invoice/generateInvoice.server"; async function main() { const wanted = process.argv[2] ?? "RE-1001"; const invoice = await db.invoice.findFirst({ where: { invoiceNumber: wanted, kind: "invoice", cancelledAt: null }, orderBy: [{ version: "desc" }, { createdAt: "desc" }], }); if (!invoice) throw new Error(`No invoice ${wanted} found in DB`); console.log(`Found ${invoice.invoiceNumber} (status=${invoice.status}, sentAt=${invoice.sentAt ?? "—"}) for order ${invoice.orderId}`); const { admin } = await unauthenticated.admin(invoice.shopDomain); const result = await generateInvoice({ shopDomain: invoice.shopDomain, admin, orderId: invoice.orderId, forceRegenerate: true, }); console.log(`Regenerated → version ${result.version}, pdfUrl=${result.pdfUrl}`); const out = resolve(process.cwd(), "data", `regen-${result.invoiceNumber}.pdf`); const res = await fetch(result.pdfUrl); if (!res.ok) throw new Error(`download failed: ${res.status}`); const buf = Buffer.from(await res.arrayBuffer()); writeFileSync(out, buf); console.log(`Saved ${out} (${buf.length} bytes)`); const text = execFileSync("pdftotext", ["-layout", "-enc", "UTF-8", out, "-"], { encoding: "utf8" }); const okDe = text.includes("Danke für deinen Einkauf"); const okEn = text.includes("Thank you for your purchase."); const oldDe = text.includes("Mit freundlichen Grüßen"); const oldEn = /\bKind regards\b/.test(text); console.log(`\n--- closing text checks ---`); console.log(` contains 'Danke für deinen Einkauf' : ${okDe}`); console.log(` contains 'Thank you for your purchase.': ${okEn}`); console.log(` contains old 'Mit freundlichen Grüßen' : ${oldDe}`); console.log(` contains old 'Kind regards' : ${oldEn}`); const langOk = invoice.language === "en" ? okEn : okDe; const cleanOld = invoice.language === "en" ? !oldEn : !oldDe; if (!langOk || !cleanOld) { console.error(`FAIL: closing line did not match expected wording for language=${invoice.language}`); process.exit(1); } console.log(`PASS: regenerated ${invoice.invoiceNumber} (lang=${invoice.language}) shows the new closing.`); } main() .catch((e) => { console.error(e); process.exit(1); }) .finally(() => db.$disconnect());