diff --git a/app/app/lib/mailer.server.ts b/app/app/lib/mailer.server.ts index bfa14e9..7623c90 100644 --- a/app/app/lib/mailer.server.ts +++ b/app/app/lib/mailer.server.ts @@ -118,7 +118,7 @@ export async function sendMerchantNotification(params: { customerEmail: string; orderUrl: string; transmittedAt: string; - returnStatus: "created" | "no_returnable" | "error"; + returnStatus: "created" | "no_returnable" | "exists" | "error"; }): Promise { const transport = buildTransport(); if (!transport) { @@ -128,9 +128,11 @@ export async function sendMerchantNotification(params: { const actionLine = params.returnStatus === "created" ? "E' stato creato un reso nell'ordine: gestiscilo dalla pagina dell'ordine." - : params.returnStatus === "no_returnable" - ? "L'ordine non risulta evaso: valuta annullamento o rimborso." - : "Reso non creato automaticamente: verifica manualmente l'ordine."; + : params.returnStatus === "exists" + ? "Esiste gia' un reso per questo ordine: gestiscilo dalla pagina dell'ordine." + : params.returnStatus === "no_returnable" + ? "L'ordine non risulta evaso: valuta annullamento o rimborso." + : "Reso non creato automaticamente: verifica manualmente l'ordine."; const orderBtn = /^https?:\/\//i.test(params.orderUrl) ? `

Apri l'ordine

` diff --git a/app/app/lib/recesso.server.ts b/app/app/lib/recesso.server.ts index cca9e56..0725b29 100644 --- a/app/app/lib/recesso.server.ts +++ b/app/app/lib/recesso.server.ts @@ -356,6 +356,9 @@ export async function getShopInfo(admin: AdminApiContext): Promise { const RETURNABLE_QUERY = `#graphql query recessoOrderFulfillments($orderId: ID!) { order(id: $orderId) { + returns(first: 1) { + edges { node { id } } + } fulfillments(first: 10) { fulfillmentLineItems(first: 50) { edges { @@ -380,6 +383,7 @@ const RETURN_CREATE_MUTATION = `#graphql interface ReturnableGraphQL { data?: { order?: { + returns?: { edges?: Array | null } | null; fulfillments?: Array<{ fulfillmentLineItems?: { edges?: Array<{ @@ -402,6 +406,7 @@ interface ReturnCreateGraphQL { export type ReturnCreation = | { status: "created"; returnId: string } | { status: "no_returnable" } + | { status: "exists" } // esiste gia' un reso per l'ordine | { status: "error"; error: string }; /** @@ -418,6 +423,10 @@ export async function createShopifyReturn( variables: { orderId: orderGid }, }); const qBody = (await qRes.json()) as ReturnableGraphQL; + // Se esiste gia' un reso per l'ordine, non crearne un altro (evita errore fuorviante). + if ((qBody.data?.order?.returns?.edges ?? []).length > 0) { + return { status: "exists" }; + } const returnLineItems: Array<{ fulfillmentLineItemId: string; quantity: number; diff --git a/app/app/routes/proxy.tsx b/app/app/routes/proxy.tsx index 1c6aae5..7cc8f19 100644 --- a/app/app/routes/proxy.tsx +++ b/app/app/routes/proxy.tsx @@ -426,7 +426,8 @@ export const action = async ({ request }: ActionFunctionArgs) => { // (best-effort; il recesso legale e' gia' registrato). Ordini annullati/ // rimborsati -> skip (G5: evita doppio reso/rimborso). Non evaso -> il // merchant gestisce annullo/rimborso. - let returnStatus: "created" | "no_returnable" | "error" = "error"; + let returnStatus: "created" | "no_returnable" | "exists" | "error" = + "error"; const orderClosed = !!match.cancelledAt || match.financialStatus === "REFUNDED" || @@ -464,6 +465,14 @@ export const action = async ({ request }: ActionFunctionArgs) => { detail: "ordine non evaso o nulla da rendere", }, }); + } else if (ret.status === "exists") { + await db.auditLog.create({ + data: { + shop, + event: "shopify_return_exists", + detail: match.orderName, + }, + }); } else { console.error("[recesso] returnCreate:", ret.error); await db.auditLog.create({