General source code refactoring

This commit is contained in:
2026-09-17 12:07:01 -03:00
parent 4421b28efe
commit ac817a69d4
92 changed files with 18211 additions and 19394 deletions

View File

@@ -0,0 +1,166 @@
function createFusionOpportunities({
OPPORTUNITIES_PAGE_LIMIT,
OPPORTUNITIES_QUERY_URL,
isCurrentPeriodRequest,
logRequestFailure,
logRequestStart,
logRequestSuccess,
maskToken,
getOpportunityTypeValues,
readResponseBodyForDebug,
environment
}) {
const { fetch } = environment;
async function requestOpportunitiesPage(token, period, dateRange, offset, accumulatedItems, requestVersion, page) {
if (!isCurrentPeriodRequest(requestVersion)) {
return null;
}
const payload = createOpportunitiesQueryPayload(dateRange, offset);
const requestBody = JSON.stringify(payload);
const requestEntry = logRequestStart({
name: "requestOpportunities",
method: "POST",
url: OPPORTUNITIES_QUERY_URL,
headers: {
Accept: "application/json",
Authorization: `Bearer ${maskToken(token)}`,
"Content-Type": "application/json",
Origin: "https://eeho.fa.us2.oraclecloud.com",
Preference: "transient"
},
body: JSON.stringify(payload, null, 2),
metadata: {
period,
page,
offset,
startCloseDate: dateRange.startCloseDate,
endCloseDate: dateRange.endCloseDate
}
});
try {
const response = await fetch(OPPORTUNITIES_QUERY_URL, {
method: "POST",
credentials: "include",
headers: {
Accept: "application/json",
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
Origin: "https://eeho.fa.us2.oraclecloud.com",
Preference: "transient"
},
body: requestBody
});
const responseBody = await readResponseBodyForDebug(response);
logRequestSuccess(requestEntry, response, responseBody);
if (!response.ok) {
throw new Error(`Opportunities query failed with status ${response.status}.`);
}
const responseData = await response.json();
const pageItems = Array.isArray(responseData.items) ? responseData.items : [];
const allItems = accumulatedItems.concat(pageItems);
if (!responseData.hasMore) {
return allItems;
}
const responseOffset = Number(responseData.offset);
const responseCount = Number(responseData.count);
const receivedCount = Number.isFinite(responseCount) ? responseCount : pageItems.length;
const currentOffset = Number.isFinite(responseOffset) ? responseOffset : offset;
if (receivedCount <= 0) {
throw new Error("Opportunities query returned hasMore without additional results.");
}
return requestOpportunitiesPage(
token,
period,
dateRange,
currentOffset + receivedCount,
allItems,
requestVersion,
page + 1
);
} catch (error) {
logRequestFailure(requestEntry, error.message || "Request failed.");
throw error;
}
}
function createOpportunitiesQueryPayload(dateRange, offset) {
return {
aggregationResults: false,
applications: ["ORACLE-ISS-APP"],
onlyData: true,
entity: "Opportunity",
q: {
op: "$and",
criteria: [
{
op: "$or",
criteria: Array.from(getOpportunityTypeValues(), (value) => ({
op: "$eq",
attribute: "RecordSet",
value
}))
},
{
op: "$wi",
attribute: "EffectiveDate",
value1: dateRange.startCloseDate,
value2: dateRange.endCloseDate,
dynamicDate: false
}
]
},
keywords: null,
keywordsFields: [
"Name",
"OptyNumber",
"PrimaryRevenue.WinProb",
"CustomerAccount",
"PrimaryRevenue.RevnAmount",
"EffectiveDate",
"StatusCode",
"DealRisk_c",
"Owner",
"ForecastGroup_c",
"LastUpdateDate",
"PrimaryRevenue.RevnAmountCurcyCode",
"OptyId"
],
fields: [
"Name",
"OptyNumber",
"PrimaryRevenue.WinProb",
"CustomerAccount",
"PrimaryRevenue.RevnAmount",
"EffectiveDate",
"StatusCode",
"DealRisk_c",
"Owner",
"ForecastGroup_c",
"LastUpdateDate",
"PrimaryRevenue.RevnAmountCurcyCode",
"OptyId",
"CustomerAccount.PartyUniqueName",
"CustomerAccount.PartyId",
"CustomerAccount.PartyNumber"
],
sort: [],
language: "en",
skipInValidFields: true,
skipHiddenFromUIFields: true,
copiedFrom: "queries/d5dbcd01-9ff3-40be-9b5b-64744cbf7162",
limit: OPPORTUNITIES_PAGE_LIMIT,
offset
};
}
return { requestOpportunitiesPage, createOpportunitiesQueryPayload };
}

View File

@@ -0,0 +1,65 @@
function createFusionProducts({
OPPTY_PRODUCTS_FIELDS,
OPPTY_PRODUCTS_MAX_PAGES,
OPPTY_PRODUCTS_PAGE_LIMIT,
ORACLE_DOMAIN,
environment
}) {
const { fetch } = environment;
async function fetchAllOpptyProducts(optyNumber, accessToken) {
let offset = 0;
let page = 0;
const items = [];
while (page < OPPTY_PRODUCTS_MAX_PAGES) {
const response = await fetch(createOpptyProductsUrl(optyNumber, offset), {
method: "GET",
credentials: "include",
headers: {
Accept: "application/json",
Authorization: `Bearer ${accessToken}`
}
});
if (!response.ok) {
throw new Error(`requestOpptyProducts failed with status ${response.status}.`);
}
const responseData = await response.json();
const pageItems = Array.isArray(responseData.items) ? responseData.items : [];
items.push(...pageItems);
page += 1;
if (!responseData.hasMore) {
return items;
}
const responseOffset = Number(responseData.offset);
const responseCount = Number(responseData.count);
const receivedCount = Number.isFinite(responseCount) ? responseCount : pageItems.length;
const currentOffset = Number.isFinite(responseOffset) ? responseOffset : offset;
if (receivedCount <= 0) {
throw new Error("requestOpptyProducts returned hasMore without additional results.");
}
offset = currentOffset + receivedCount;
}
throw new Error("requestOpptyProducts exceeded the pagination safety limit.");
}
function createOpptyProductsUrl(optyNumber, offset) {
const url = new URL(`https://${ORACLE_DOMAIN}/crmRestApi/rest/rv:be91c002-2e5d-4ed2-a37e-e0c837bf141f/en/11.13.18.05:9/opportunities/${encodeURIComponent(optyNumber)}/child/ChildRevenue`);
url.searchParams.set("onlyData", "true");
url.searchParams.set("q", "(SplitTypeCode!='DETAILCHILDSPLIT') AND (RecurTypeCode!='CHILDRECUR')");
url.searchParams.set("totalResults", "false");
url.searchParams.set("fields", OPPTY_PRODUCTS_FIELDS.join(","));
url.searchParams.set("orderBy", "CreationDate:desc");
url.searchParams.set("limit", String(OPPTY_PRODUCTS_PAGE_LIMIT));
url.searchParams.set("offset", String(offset));
return url.toString();
}
return { fetchAllOpptyProducts, createOpptyProductsUrl };
}

View File

@@ -0,0 +1,169 @@
function createHttpBackgroundJson({
DEBUG_BODY_LIMIT,
environment
}) {
const { fetch } = environment;
async function fetchJson(url, options, requestName, debugRequests = null) {
const startedAt = new Date();
const debugEntry = createBackgroundDebugEntry(requestName, url, options, startedAt);
let response;
try {
response = await fetch(url, options);
} catch (error) {
completeBackgroundDebugEntry(debugEntry, null, "", error.message || "Network request failed.");
appendBackgroundDebugEntry(debugRequests, debugEntry);
throw error;
}
const responsePayload = await readResponsePayload(response);
const responseBody = createDebugBody(responsePayload.text);
completeBackgroundDebugEntry(debugEntry, response, responseBody, "");
debugEntry.metadata.responseContentType = response.headers.get("content-type") || "(not provided)";
debugEntry.metadata.responseLength = String(responsePayload.text.length);
appendBackgroundDebugEntry(debugRequests, debugEntry);
if (!response.ok) {
throw new Error(`${requestName} failed with status ${response.status}.`);
}
if (responsePayload.error) {
throw new Error(`${requestName} response body could not be read.`);
}
try {
return parseJsonResponse(responsePayload.text, requestName);
} catch (error) {
error.httpStatus = response.status;
debugEntry.status = "failed";
debugEntry.error = error.message;
throw error;
}
}
function createBackgroundDebugEntry(requestName, url, options, startedAt) {
return {
name: requestName,
method: options.method || "GET",
url,
status: "pending",
startedAt: startedAt.toISOString(),
completedAt: null,
durationMs: null,
httpStatus: null,
statusText: "",
requestHeaders: normalizeDebugHeaders(options.headers),
requestBody: formatDebugRequestBody(options.body),
metadata: {
executionContext: "background"
},
responseHeaders: {},
responseBody: "",
responseBodyTruncated: false,
error: ""
};
}
function completeBackgroundDebugEntry(entry, response, responseBody, errorMessage) {
const completedAt = new Date();
entry.completedAt = completedAt.toISOString();
entry.durationMs = completedAt.getTime() - new Date(entry.startedAt).getTime();
entry.error = errorMessage;
if (!response) {
entry.status = "failed";
return;
}
entry.status = response.ok ? "success" : "failed";
entry.httpStatus = response.status;
entry.statusText = response.statusText || "";
entry.responseHeaders = headersToObject(response.headers);
entry.responseBody = responseBody.value;
entry.responseBodyTruncated = responseBody.truncated;
}
function appendBackgroundDebugEntry(debugRequests, entry) {
if (Array.isArray(debugRequests)) {
debugRequests.push(entry);
}
}
async function readResponsePayload(response) {
try {
return {
text: await response.text(),
error: ""
};
} catch (error) {
return {
text: `Unable to read response body: ${error.message || "unknown error"}`,
error: error.message || "unknown error"
};
}
}
function parseJsonResponse(text, requestName) {
const normalizedText = String(text)
.replace(/^\uFEFF/, "")
.trimStart()
.replace(/^\)\]\}',?\s*/, "")
.replace(/^while\s*\(1\);\s*/, "");
try {
return JSON.parse(normalizedText);
} catch (error) {
const invalidJsonError = new Error(`${requestName} returned an invalid JSON response.`);
invalidJsonError.code = "INVALID_JSON_RESPONSE";
throw invalidJsonError;
}
}
function createDebugBody(text) {
if (text.length > DEBUG_BODY_LIMIT) {
return {
value: `${text.slice(0, DEBUG_BODY_LIMIT)}\n... truncated ${text.length - DEBUG_BODY_LIMIT} characters`,
truncated: true
};
}
return {
value: text || "(empty response body)",
truncated: false
};
}
function normalizeDebugHeaders(headers) {
const normalized = {};
Object.entries(headers || {}).forEach(([key, value]) => {
normalized[key] = String(value);
});
return normalized;
}
function headersToObject(headers) {
const values = {};
if (headers && typeof headers.forEach === "function") {
headers.forEach((value, key) => {
values[key] = value;
});
}
return values;
}
function formatDebugRequestBody(body) {
if (!body) {
return "";
}
try {
return JSON.stringify(JSON.parse(body), null, 2);
} catch (error) {
return String(body);
}
}
return { fetchJson, createBackgroundDebugEntry, completeBackgroundDebugEntry, appendBackgroundDebugEntry, readResponsePayload, parseJsonResponse, createDebugBody, normalizeDebugHeaders, headersToObject, formatDebugRequestBody };
}

View File

@@ -0,0 +1,75 @@
function createSpaAccounts({
ACCOUNT_PLANS_PAYLOAD,
ACCOUNT_PLANS_URL,
ACCOUNT_SUMMARY_URL,
extractAccountPlans,
fetchJson,
findAccountPlanId,
normalizeMessageAuthorization
}) {
async function requestAccountPlans(message) {
const partyNumber = typeof message.partyNumber === "string" ? message.partyNumber.trim() : "";
const accountSummaryAuthorization = normalizeMessageAuthorization(
message.authorizations && message.authorizations.accountSummary,
"account-ti-authorization"
);
const accountPlansAuthorization = normalizeMessageAuthorization(
message.authorizations && message.authorizations.accountPlans,
"g2m-authorization"
);
const debugRequests = [];
if (!partyNumber) {
throw new Error("Customer Party Number is required.");
}
if (!accountSummaryAuthorization.value) {
throw new Error("ACCP-TS authorization is unavailable. requestConsumerTokenService must complete first.");
}
if (!accountPlansAuthorization.value) {
throw new Error("OCICONS-TS authorization is unavailable. requestConsumerTokenService must complete first.");
}
try {
const accountSummary = await fetchJson(ACCOUNT_SUMMARY_URL, {
method: "POST",
credentials: "include",
headers: {
Accept: "application/json",
[accountSummaryAuthorization.name]: accountSummaryAuthorization.value,
"Content-Type": "application/json"
},
body: JSON.stringify([{ key: "regId", value: partyNumber }])
}, "requestAccountSummary", debugRequests);
const accountPlanId = findAccountPlanId(accountSummary);
if (!accountPlanId) {
throw new Error("Account plan id was not found in requestAccountSummary.");
}
const accountPlansResponse = await fetchJson(`${ACCOUNT_PLANS_URL}/${encodeURIComponent(String(accountPlanId))}`, {
method: "POST",
credentials: "include",
headers: {
Accept: "application/json",
[accountPlansAuthorization.name]: accountPlansAuthorization.value,
"Content-Type": "application/json"
},
body: JSON.stringify(ACCOUNT_PLANS_PAYLOAD)
}, "requestAccountPlans", debugRequests);
return {
ok: true,
accountPlanId: String(accountPlanId),
plans: extractAccountPlans(accountPlansResponse),
debugRequests
};
} catch (error) {
error.debugRequests = debugRequests;
throw error;
}
}
return { requestAccountPlans };
}

View File

@@ -0,0 +1,58 @@
function createSpaConsumption({
CONSUMPTION_TREND_REQUESTS,
CONSUMPTION_TREND_URL,
fetchJson,
normalizeMessageAuthorization
}) {
async function requestConsumptionTrend(message) {
const subPlanNum = typeof message.subPlanNum === "string" ? message.subPlanNum.trim() : "";
const period = typeof message.period === "string" ? message.period.toLowerCase() : "";
const requestName = CONSUMPTION_TREND_REQUESTS[period];
const authorization = normalizeMessageAuthorization(message.authorization, "g2m-authorization");
const debugRequests = [];
if (!subPlanNum) {
throw new Error("Sub plan number is required for the consumption trend.");
}
if (!requestName) {
throw new Error(`Unsupported consumption trend period: ${period || "(missing)"}.`);
}
if (!authorization.value) {
throw new Error("OCICONS-TS authorization is unavailable for the consumption trend.");
}
const url = `${CONSUMPTION_TREND_URL}/${encodeURIComponent(subPlanNum)}?quarter=All&timePeriod=${period}`;
try {
const response = await fetchJson(url, {
method: "GET",
credentials: "include",
cache: "no-store",
headers: {
Accept: "application/json",
"G2m-Authorization": authorization.value
}
}, requestName, debugRequests);
const items = Array.isArray(response)
? response
: Array.isArray(response && response.items)
? response.items
: [];
return {
ok: true,
subPlanNum,
period,
items,
debugRequests
};
} catch (error) {
error.debugRequests = debugRequests;
throw error;
}
}
return { requestConsumptionTrend };
}

View File

@@ -0,0 +1,61 @@
function createSpaResponseShapes() {
function findNestedObject(value, predicate, visited = new Set()) {
if (!value || typeof value !== "object" || visited.has(value)) {
return null;
}
visited.add(value);
if (!Array.isArray(value) && predicate(value)) {
return value;
}
for (const child of Object.values(value)) {
const match = findNestedObject(child, predicate, visited);
if (match) {
return match;
}
}
return null;
}
function findAccountPlanId(response) {
const account = findNestedObject(response, (value) => (
Object.prototype.hasOwnProperty.call(value, "id")
&& value.id !== null
&& value.id !== undefined
&& value.id !== ""
));
return account ? account.id : "";
}
function extractAccountPlans(response) {
const plans = [];
const visited = new Set();
const visit = (value) => {
if (!value || typeof value !== "object" || visited.has(value)) {
return;
}
visited.add(value);
if (!Array.isArray(value) && (
Object.prototype.hasOwnProperty.call(value, "planType")
|| Object.prototype.hasOwnProperty.call(value, "subPlanNum")
)) {
plans.push(value);
return;
}
Object.values(value).forEach(visit);
};
visit(response);
return plans;
}
return { findNestedObject, findAccountPlanId, extractAccountPlans };
}