Files
bodyshop/server/rr/rr-export-logs.js

172 lines
5.0 KiB
JavaScript

const { GraphQLClient } = require("graphql-request");
const queries = require("../graphql-client/queries");
const CreateRRLogEvent = require("./rr-logger-event");
/** Get bearer token from the socket (same approach used elsewhere) */
function getAuthToken(socket) {
return (socket?.data && socket.data.authToken) || (socket?.handshake?.auth && socket.handshake.auth.token) || null;
}
/** Compact metadata for RR */
function buildRRExportMeta({ result, extra = {} }) {
const roStatus = result?.roStatus || result?.data?.roStatus || null;
return {
provider: "rr",
success: Boolean(result?.success || roStatus?.status === "Success"),
customerNo: result?.customerNo,
svId: result?.svId,
roStatus: roStatus && {
status: roStatus.status ?? roStatus.Status,
statusCode: roStatus.statusCode ?? roStatus.StatusCode,
message: roStatus.message ?? roStatus.Message
},
statusBlocks: result?.statusBlocks || undefined,
xml: result?.xml,
parsed: result?.parsed,
...extra
};
}
/** Build a stringified JSON array for the `message` text column */
function buildMessageJSONString({ error, classification, result, fallback }) {
const msgs = [];
const clean = (v) => {
if (v == null) return null;
try {
const s = String(v).replace(/\s+/g, " ").trim();
return s.length ? s : null;
} catch {
return null;
}
};
const push = (v) => {
const s = clean(v);
if (s && !msgs.includes(s)) msgs.push(s);
};
// Friendly first
push(classification?.friendlyMessage);
push(classification?.title);
// Error text
if (error instanceof Error) push(error.message);
else if (typeof error === "string") push(error);
else if (error?.message) push(error.message);
// RR status message
push(result?.roStatus?.message ?? result?.roStatus?.Message);
// Fallback
push(fallback || "RR export failed");
const arr = msgs.length ? msgs : ["RR export failed"];
return JSON.stringify(arr);
}
/**
* Success: mark job exported + (optionally) insert a success log.
* Uses queries.MARK_JOB_EXPORTED (same shape as Fortellis/PBS).
*/
async function markRRExportSuccess({ socket, jobId, job, bodyshop, result, metaExtra = {} }) {
const endpoint = process.env.GRAPHQL_ENDPOINT;
if (!endpoint) throw new Error("GRAPHQL_ENDPOINT not configured");
const token = getAuthToken(socket);
if (!token) throw new Error("Auth token missing on socket");
const client = new GraphQLClient(endpoint, {});
client.setHeaders({ Authorization: `Bearer ${token}` });
const exportedStatus =
job?.bodyshop?.md_ro_statuses?.default_exported || bodyshop?.md_ro_statuses?.default_exported || "Exported*";
const meta = buildRRExportMeta({ result, extra: metaExtra });
try {
await client.request(queries.MARK_JOB_EXPORTED, {
jobId,
job: {
status: exportedStatus,
date_exported: new Date()
},
log: {
bodyshopid: bodyshop?.id || job?.bodyshop?.id,
jobid: jobId,
successful: true,
useremail: socket?.user?.email || null,
metadata: meta,
message: buildMessageJSONString({ result, fallback: "RR export succeeded" })
},
bill: {
exported: true,
exported_at: new Date()
}
});
CreateRRLogEvent(socket, "INFO", "RR export: job marked exported + success log inserted", {
jobId,
exportedStatus
});
} catch (e) {
CreateRRLogEvent(socket, "ERROR", "RR export: failed to persist success markers/log", {
jobId,
error: e?.message
});
}
}
/**
* Failure: insert failure ExportsLog with `message` as JSON **string** (text column).
* Uses queries.INSERT_EXPORT_LOG($logs: [exportlog_insert_input!]!).
*/
async function insertRRFailedExportLog({ socket, jobId, job, bodyshop, error, classification, result }) {
const endpoint = process.env.GRAPHQL_ENDPOINT;
if (!endpoint) throw new Error("GRAPHQL_ENDPOINT not configured");
const token = getAuthToken(socket);
if (!token) throw new Error("Auth token missing on socket");
const client = new GraphQLClient(endpoint, {});
client.setHeaders({ Authorization: `Bearer ${token}` });
const meta = buildRRExportMeta({
result,
extra: {
error: error?.message || String(error),
classification: classification || undefined
}
});
const message = buildMessageJSONString({
error,
classification,
result,
fallback: "RR export failed"
});
const entry = {
bodyshopid: bodyshop?.id || job?.bodyshop?.id,
jobid: jobId,
successful: false,
message, // stringified JSON array
useremail: socket?.user?.email || null,
metadata: meta
};
try {
// Your mutation expects $logs (array). Keep to that signature.
await client.request(queries.INSERT_EXPORT_LOG, { logs: [entry] });
CreateRRLogEvent(socket, "INFO", "RR export: failure log inserted", { jobId });
} catch (e) {
CreateRRLogEvent(socket, "ERROR", "RR export: failed to insert failure log", {
jobId,
error: e?.message
});
}
}
module.exports = {
markRRExportSuccess,
insertRRFailedExportLog
};