Fix: reso gia' esistente -> stato 'exists' + messaggio corretto al merchant
Se l'ordine ha gia' un reso (order.returns), createShopifyReturn ritorna 'exists' invece di fallire: la notifica dice 'esiste gia' un reso, gestiscilo dall'ordine' al posto del fuorviante 'reso non creato, fallo manualmente'. Audit shopify_return_exists. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Mv83a29B4eFv5ixoj6PoE1
This commit is contained in:
@@ -118,7 +118,7 @@ export async function sendMerchantNotification(params: {
|
|||||||
customerEmail: string;
|
customerEmail: string;
|
||||||
orderUrl: string;
|
orderUrl: string;
|
||||||
transmittedAt: string;
|
transmittedAt: string;
|
||||||
returnStatus: "created" | "no_returnable" | "error";
|
returnStatus: "created" | "no_returnable" | "exists" | "error";
|
||||||
}): Promise<ReceiptResult> {
|
}): Promise<ReceiptResult> {
|
||||||
const transport = buildTransport();
|
const transport = buildTransport();
|
||||||
if (!transport) {
|
if (!transport) {
|
||||||
@@ -128,9 +128,11 @@ export async function sendMerchantNotification(params: {
|
|||||||
const actionLine =
|
const actionLine =
|
||||||
params.returnStatus === "created"
|
params.returnStatus === "created"
|
||||||
? "E' stato creato un reso nell'ordine: gestiscilo dalla pagina dell'ordine."
|
? "E' stato creato un reso nell'ordine: gestiscilo dalla pagina dell'ordine."
|
||||||
: params.returnStatus === "no_returnable"
|
: params.returnStatus === "exists"
|
||||||
? "L'ordine non risulta evaso: valuta annullamento o rimborso."
|
? "Esiste gia' un reso per questo ordine: gestiscilo dalla pagina dell'ordine."
|
||||||
: "Reso non creato automaticamente: verifica manualmente l'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)
|
const orderBtn = /^https?:\/\//i.test(params.orderUrl)
|
||||||
? `<p style="margin:16px 0 0;"><a href="${escM(params.orderUrl)}" style="display:inline-block;padding:10px 18px;background:#1a1a1a;color:#fff;text-decoration:none;border-radius:8px;font-size:14px;font-weight:600;">Apri l'ordine</a></p>`
|
? `<p style="margin:16px 0 0;"><a href="${escM(params.orderUrl)}" style="display:inline-block;padding:10px 18px;background:#1a1a1a;color:#fff;text-decoration:none;border-radius:8px;font-size:14px;font-weight:600;">Apri l'ordine</a></p>`
|
||||||
|
|||||||
@@ -356,6 +356,9 @@ export async function getShopInfo(admin: AdminApiContext): Promise<ShopInfo> {
|
|||||||
const RETURNABLE_QUERY = `#graphql
|
const RETURNABLE_QUERY = `#graphql
|
||||||
query recessoOrderFulfillments($orderId: ID!) {
|
query recessoOrderFulfillments($orderId: ID!) {
|
||||||
order(id: $orderId) {
|
order(id: $orderId) {
|
||||||
|
returns(first: 1) {
|
||||||
|
edges { node { id } }
|
||||||
|
}
|
||||||
fulfillments(first: 10) {
|
fulfillments(first: 10) {
|
||||||
fulfillmentLineItems(first: 50) {
|
fulfillmentLineItems(first: 50) {
|
||||||
edges {
|
edges {
|
||||||
@@ -380,6 +383,7 @@ const RETURN_CREATE_MUTATION = `#graphql
|
|||||||
interface ReturnableGraphQL {
|
interface ReturnableGraphQL {
|
||||||
data?: {
|
data?: {
|
||||||
order?: {
|
order?: {
|
||||||
|
returns?: { edges?: Array<unknown> | null } | null;
|
||||||
fulfillments?: Array<{
|
fulfillments?: Array<{
|
||||||
fulfillmentLineItems?: {
|
fulfillmentLineItems?: {
|
||||||
edges?: Array<{
|
edges?: Array<{
|
||||||
@@ -402,6 +406,7 @@ interface ReturnCreateGraphQL {
|
|||||||
export type ReturnCreation =
|
export type ReturnCreation =
|
||||||
| { status: "created"; returnId: string }
|
| { status: "created"; returnId: string }
|
||||||
| { status: "no_returnable" }
|
| { status: "no_returnable" }
|
||||||
|
| { status: "exists" } // esiste gia' un reso per l'ordine
|
||||||
| { status: "error"; error: string };
|
| { status: "error"; error: string };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -418,6 +423,10 @@ export async function createShopifyReturn(
|
|||||||
variables: { orderId: orderGid },
|
variables: { orderId: orderGid },
|
||||||
});
|
});
|
||||||
const qBody = (await qRes.json()) as ReturnableGraphQL;
|
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<{
|
const returnLineItems: Array<{
|
||||||
fulfillmentLineItemId: string;
|
fulfillmentLineItemId: string;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
|
|||||||
@@ -426,7 +426,8 @@ export const action = async ({ request }: ActionFunctionArgs) => {
|
|||||||
// (best-effort; il recesso legale e' gia' registrato). Ordini annullati/
|
// (best-effort; il recesso legale e' gia' registrato). Ordini annullati/
|
||||||
// rimborsati -> skip (G5: evita doppio reso/rimborso). Non evaso -> il
|
// rimborsati -> skip (G5: evita doppio reso/rimborso). Non evaso -> il
|
||||||
// merchant gestisce annullo/rimborso.
|
// merchant gestisce annullo/rimborso.
|
||||||
let returnStatus: "created" | "no_returnable" | "error" = "error";
|
let returnStatus: "created" | "no_returnable" | "exists" | "error" =
|
||||||
|
"error";
|
||||||
const orderClosed =
|
const orderClosed =
|
||||||
!!match.cancelledAt ||
|
!!match.cancelledAt ||
|
||||||
match.financialStatus === "REFUNDED" ||
|
match.financialStatus === "REFUNDED" ||
|
||||||
@@ -464,6 +465,14 @@ export const action = async ({ request }: ActionFunctionArgs) => {
|
|||||||
detail: "ordine non evaso o nulla da rendere",
|
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 {
|
} else {
|
||||||
console.error("[recesso] returnCreate:", ret.error);
|
console.error("[recesso] returnCreate:", ret.error);
|
||||||
await db.auditLog.create({
|
await db.auditLog.create({
|
||||||
|
|||||||
Reference in New Issue
Block a user