Implemented the feature to identify and update estimates based on the ACR value, consumption start date, and ramp-up

This commit is contained in:
2026-10-20 15:55:58 -03:00
parent 71d550dfb1
commit 60daabfe91
31 changed files with 2800 additions and 43 deletions

View File

@@ -0,0 +1,79 @@
function createSpaWorkloads({ fetchJson, getCachedWorkloads, normalizeCacheMaxAge, invalidateWorkloadsCache }) {
async function requestWorkloadForecastUpdate(message) {
const debugRequests = [];
try {
const id = String(message.workloadId ?? "");
const token = message.authorization?.value;
if (!/^\d+$/.test(id)) throw new Error("A numeric workload ID is required.");
if (typeof token !== "string" || !token.trim()) throw new Error("WWB-TS uiaasHeader.value is unavailable.");
if (!Array.isArray(message.payload) || !message.payload.length) throw new Error("Monthly estimates are required.");
const periods = new Set();
const payload = message.payload.map(({ year, month, amount, updatedBy }) => {
if (!Number.isInteger(year) || year < 1000 || year > 9999 || !Number.isInteger(month) || month < 1 || month > 12
|| typeof amount !== "number" || !Number.isFinite(amount) || amount < 0
|| typeof updatedBy !== "string" || !updatedBy.trim()) throw new Error("Invalid monthly estimate.");
const period = `${year}-${month}`;
if (periods.has(period)) throw new Error("Duplicate forecast month.");
periods.add(period);
return { year, month, amount, updatedBy: updatedBy.trim() };
});
const result = await fetchJson(`https://spa.oracle.com/oalcrm/web/api/provider-proxy/wwb-provider/service/workbench-proxy/wwb/mgmt/workloads/${id}/forecast`, {
method: "PATCH", credentials: "include",
headers: { Accept: "application/json", "Content-Type": "application/json", "wwb-provider-authorization": token.trim() },
body: JSON.stringify(payload)
}, "requestWorkloadForecastUpdate", debugRequests, { allowEmpty: true });
await invalidateWorkloadsCache().catch(() => {});
return { ok: true, result, debugRequests };
} catch (error) {
error.debugRequests = debugRequests;
throw error;
}
}
async function requestWorkloads(message) {
const customerId = String(message.customerId ?? "").trim();
const token = message.authorization?.value;
if (!/^\d+$/.test(customerId)) throw new Error("A numeric CustomerAccount.PartyId is required.");
if (typeof token !== "string" || !token.trim()) throw new Error("WWB-TS uiaasHeader.value is unavailable.");
const result = await getCachedWorkloads(customerId, token.trim(), normalizeCacheMaxAge(message.cacheMaxAgeMs), message.principal);
return { ok: true, customerId, ...result };
}
async function fetchAllWorkloads(customerId, token) {
const debugRequests = [];
const workloads = new Map();
let offset = 0;
let limit = 500;
try {
for (let page = 0; page < 1000; page += 1) {
const url = new URL(`https://spa.oracle.com/oalcrm/web/api/provider-proxy/wwb-provider/service/workbench-proxy/wwb/mgmt/customers/${customerId}/workloads`);
for (const [name, value] of Object.entries({ workloadStatus: "Pipeline,Implementation,Live", opportunityForecastType: "All",
includeForEstimates: "ALL", financialYear: "ROLLING_4_QTRS", offset, limit })) url.searchParams.set(name, String(value));
const result = await fetchJson(url.toString(), {
method: "GET", credentials: "include",
headers: { Accept: "application/json", "wwb-provider-authorization": token }
}, "requestWorkloads", debugRequests);
if (!result || !Array.isArray(result.workloads) || typeof result.hasNext !== "boolean"
|| result.workloads.some(item => !item || !/^\d+$/.test(String(item.id ?? "")))) {
throw new Error("requestWorkloads returned an invalid collection.");
}
const countBefore = workloads.size;
for (const item of result.workloads) workloads.set(String(item.id), item);
if (!result.hasNext) return { workloads: [...workloads.values()], debugRequests };
const responseOffset = Number(result.offset ?? offset);
const responseLimit = Number(result.limit ?? limit);
if (workloads.size === countBefore || !Number.isSafeInteger(responseOffset) || responseOffset !== offset
|| !Number.isSafeInteger(responseLimit) || responseLimit <= 0 || !Number.isSafeInteger(responseOffset + responseLimit)) {
throw new Error("requestWorkloads pagination did not advance.");
}
offset = responseOffset + responseLimit;
limit = responseLimit;
}
throw new Error("requestWorkloads exceeded the pagination limit.");
} catch (error) {
error.debugRequests = debugRequests;
throw error;
}
}
return { requestWorkloads, fetchAllWorkloads, requestWorkloadForecastUpdate };
}