Files
linumiq-invoice/scripts/regenerate-invoice.ts
T
Gerhard Scheikl 770c6fd16a many updates :-)
2026-05-08 10:40:19 +02:00

72 lines
2.9 KiB
TypeScript

/**
* 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());