Dealer_Onboarding_Backend/trigger-relocation.js

168 lines
5.9 KiB
JavaScript

const args = Object.fromEntries(
process.argv.slice(2)
.map((arg) => arg.replace(/^--/, "").split("="))
.map(([k, v]) => [k, v ?? "true"])
);
const BASE_URL = args.baseUrl || process.env.BASE_URL || "http://localhost:5000/api";
const PASSWORD = "Admin@123";
const STEP_DELAY_MS = Number(args.delayMs || 500);
const EMAILS = {
DD_ADMIN: args.ddAdminEmail || "lince@royalenfield.com",
DEALER: args.dealerEmail,
ASM: args.asmEmail || "abhishek@royalenfield.com",
RBM: args.rbmEmail || "manish@royalenfield.com",
DD_ZM: args.ddZmEmail || "piyush@royalenfield.com",
ZBH: args.zbhEmail || "manav@royalenfield.com",
DD_LEAD: args.ddLeadEmail || "jaya@royalenfield.com",
DD_HEAD: args.ddHeadEmail || "ganesh@royalenfield.com",
NBH: args.nbhEmail || "yashwin@royalenfield.com",
LEGAL: args.legalEmail || "legal@royalenfield.com",
};
const ROLE_BY_STAGE = {
"ASM Review": ["ASM"],
"RBM Review": ["RBM"],
"DD ZM Review": ["DD_ZM"],
"ZBH Review": ["ZBH"],
"DD Lead Review": ["DD_LEAD"],
"DD Head Approval": ["DD_HEAD"],
"NBH Approval": ["NBH"],
"Legal Clearance": ["LEGAL"],
"NBH Clearance with EOR": ["NBH"],
};
const delay = (ms = STEP_DELAY_MS) => new Promise((r) => setTimeout(r, ms));
async function apiRequest(endpoint, method = "GET", body = null, token = null) {
const headers = { "Content-Type": "application/json" };
if (token) headers.Authorization = `Bearer ${token}`;
const config = { method, headers };
if (body) config.body = JSON.stringify(body);
const response = await fetch(`${BASE_URL}${endpoint}`, config);
const data = await response.json();
if (!response.ok) {
throw new Error(`API Error ${method} ${endpoint}: ${JSON.stringify(data)}`);
}
return data;
}
async function login(email) {
if (!login.cache) login.cache = {};
if (login.cache[email]) return login.cache[email];
const data = await apiRequest("/auth/login", "POST", { email, password: PASSWORD });
login.cache[email] = data.token;
return data.token;
}
async function getRelocationByAnyId(id, token) {
return apiRequest(`/self-service/relocation/${id}`, "GET", null, token);
}
async function approveCurrentStage(requestId, stageName) {
const candidateRoles = ROLE_BY_STAGE[stageName] || [];
if (!candidateRoles.length) {
throw new Error(`No actor mapping found for stage: ${stageName}`);
}
let lastError = null;
const attempts = [];
for (const roleKey of candidateRoles) {
const email = EMAILS[roleKey];
if (!email) {
attempts.push(`${roleKey}:missing-email`);
continue;
}
try {
const token = await login(email);
const res = await apiRequest(`/self-service/relocation/${requestId}/action`, "POST", {
action: "APPROVE",
comments: `${roleKey} approved relocation request.`,
}, token);
return { roleKey, email, message: res.message || "Approved" };
} catch (error) {
lastError = error;
attempts.push(`${roleKey}:${error.message}`);
}
}
throw new Error(
`Approval failed for stage: ${stageName}. Attempts -> ${attempts.join(" | ")}`
+ (lastError ? ` | Last error: ${lastError.message}` : "")
);
}
async function resolveDealerOutlet(dealerToken) {
const dashboard = await apiRequest("/dealer/dashboard", "GET", null, dealerToken);
const outlet = dashboard?.data?.outlets?.[0];
if (!outlet) throw new Error("No dealer outlet found to create relocation request.");
return outlet;
}
async function run() {
try {
console.log("--- STARTING RELOCATION E2E FLOW ---");
if (!EMAILS.DEALER) {
throw new Error("Missing --dealerEmail. This script requires an existing dealer user email.");
}
const adminToken = await login(EMAILS.DD_ADMIN);
const dealerToken = await login(EMAILS.DEALER);
let requestId = args.requestId;
if (!requestId) {
const outlet = await resolveDealerOutlet(dealerToken);
console.log(`[STEP 1] Submitting relocation for outlet: ${outlet.name} (${outlet.id})`);
const createRes = await apiRequest("/self-service/relocation", "POST", {
outletId: args.outletId || outlet.id,
relocationType: args.relocationType || "Intercity",
newAddress: args.newAddress || "Sector 21, New Premises",
newCity: args.newCity || "Gurugram",
newState: args.newState || "Haryana",
reason: args.reason || "Business expansion and better customer access",
proposedDate: args.proposedDate || new Date().toISOString().split("T")[0],
}, dealerToken);
requestId = createRes.requestId;
console.log(`[STEP 1] Request Created: ${requestId}`);
await delay();
} else {
console.log(`[STEP 1] Resuming request: ${requestId}`);
}
let step = 2;
while (true) {
const detailsRes = await getRelocationByAnyId(requestId, adminToken);
const request = detailsRes.request;
const stage = request.currentStage;
const status = request.status;
if (stage === "Completed" || status === "Completed") {
console.log(`[STEP ${step}] SUCCESS: Relocation request is completed.`);
break;
}
if (stage === "Rejected" || status === "Rejected") {
throw new Error(`Relocation request is rejected at stage: ${stage}`);
}
console.log(`[STEP ${step}] Current Stage: ${stage} | Status: ${status}`);
const actor = await approveCurrentStage(requestId, stage);
console.log(`[STEP ${step}] ${actor.roleKey} (${actor.email}) -> ${actor.message}`);
step++;
await delay();
}
const finalRes = await getRelocationByAnyId(requestId, adminToken);
console.log("--- VERIFICATION RESULTS ---");
console.log(`RequestId: ${finalRes.request.requestId || requestId}`);
console.log(`Final Stage: ${finalRes.request.currentStage}`);
console.log(`Final Status: ${finalRes.request.status}`);
console.log("Outcome: RELOCATION FLOW COMPLETED SUCCESSFULLY");
process.exit(0);
} catch (error) {
console.error("Workflow failed:", error.message);
process.exit(1);
}
}
run();