feat(invoice): add Send invoice email action
Adds a Send button to the order action extension and a corresponding "send" op to /api/orders/:orderId/invoice. Generates the invoice on demand if missing, then sends via the configured SMTP.
This commit is contained in:
@@ -3,6 +3,7 @@ import { authenticate } from "../shopify.server";
|
||||
import db from "../db.server";
|
||||
import { generateInvoice } from "../services/invoice/generateInvoice.server";
|
||||
import { cancelAndReissue } from "../services/invoice/cancelAndReissue.server";
|
||||
import { sendInvoiceEmail } from "../services/invoice/email.server";
|
||||
|
||||
/**
|
||||
* GET /api/orders/:orderId/invoice → returns latest invoice metadata + history
|
||||
@@ -60,6 +61,50 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {
|
||||
return cors(Response.json({ ok: true, op, ...result }));
|
||||
}
|
||||
|
||||
if (op === "send") {
|
||||
const orderGid = orderId.startsWith("gid://")
|
||||
? orderId
|
||||
: `gid://shopify/Order/${orderId}`;
|
||||
let invoice = await db.invoice.findFirst({
|
||||
where: {
|
||||
shopDomain: session.shop,
|
||||
orderId: orderGid,
|
||||
kind: "invoice",
|
||||
cancelledAt: null,
|
||||
},
|
||||
orderBy: [{ version: "desc" }, { createdAt: "desc" }],
|
||||
});
|
||||
if (!invoice) {
|
||||
const generated = await generateInvoice({
|
||||
shopDomain: session.shop,
|
||||
admin,
|
||||
orderId,
|
||||
});
|
||||
invoice = await db.invoice.findUnique({ where: { id: generated.invoiceId } });
|
||||
}
|
||||
if (!invoice) throw new Error("Failed to materialise an invoice for this order.");
|
||||
const sendResult = await sendInvoiceEmail({
|
||||
shopDomain: session.shop,
|
||||
invoiceId: invoice.id,
|
||||
});
|
||||
if (!sendResult.ok) {
|
||||
return cors(
|
||||
Response.json(
|
||||
{ ok: false, op: "send", error: sendResult.errorMessage ?? "Email send failed." },
|
||||
{ status: 422 },
|
||||
),
|
||||
);
|
||||
}
|
||||
return cors(
|
||||
Response.json({
|
||||
ok: true,
|
||||
op: "send",
|
||||
invoiceNumber: invoice.invoiceNumber,
|
||||
toAddress: sendResult.toAddress,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
const result = await generateInvoice({
|
||||
shopDomain: session.shop,
|
||||
admin,
|
||||
|
||||
Reference in New Issue
Block a user