Untitled
unknown
plain_text
2 months ago
12 kB
7
Indexable
var ACWAPP = ACWAPP || {};
var Sdk = window.Sdk || {};
ACWAPP.JoinAwardReview = (function () {
/* =========================
CONFIG
========================= */
const WEBR_CTRL_NAME = "WebResource_JoinAwardReview";
const RELATED_SUBGRID_NAME = "RelatedCaseRef";
const RELATIONSHIP_NAME = "acwapp_acwapp_abusecases_acwapp_abusecases";
const CASE_LOGICAL = "acwapp_abusecases";
const ALLEG_LOGICAL = "acwapp_suspectedabuse";
/* =========================
FILTER VALUES
========================= */
const CASECATEGORY_YES = 100000000;
const CASESTATUS_AWARD = 100000005;
/* =========================
CASE FIELDS
========================= */
const CASE_ID = "acwapp_abusecasesid";
const CASE_NUMBER_FIELD = "acwapp_name";
const CASE_STAGE_FIELD = "acwapp_casestatus";
const CASE_CATEGORY_FIELD = "acwapp_casecategory";
const CASE_PROPERTY_LOOKUP_VALUE = "_acwapp_propertycodemainflat_value";
const CASE_COT_FIELD = "acwapp_commencementoftenancydate";
const CASE_ESTATE_LOOKUP_VALUE = "_acwapp_estate_value";
const CASE_SOURCE_OF_ALLEGATION = "acwapp_sourceofallegation";
/* =========================
ALLEGATION FIELDS
========================= */
const ALLEG_CASE_LOOKUP_VALUE = "_acwapp_abusecase_value";
const ALLEG_TYPE_FIELD = "acwapp_typeofsuspectedabuse";
const ALLEG_REFER_TO_MOT = "acwapp_refertomot";
const ALLEG_RESULT_FIELD = "acwapp_investigationresult";
const ALLEG_RESULT_MOT_FIELD = "acwapp_suggestedinvestigationresult2";
const ALLEG_SUGGESTED_ACTION_FIELD = "acwapp_suggestedtenancyactions";
const ALLEG_STATUS_FIELD = "acwapp_allegationstatus";
const ALLEG_ACTIONS_FOR_SUGGESTED_TENANCY = "acwapp_actionsforsuggestedtenancy";
const ALLEG_REASON_NO_TENANCY_ACTION = "acwapp_reasonofnotenancyactionrequired";
/* =========================
OPTION SET VALUES
========================= */
const REFER_TO_MOT = {
NO: 100000000,
YES: 100000001
};
/* =========================
ASSOCIATE REQUEST
========================= */
Sdk.AssociateRequest = function (target, relatedEntities, relationship) {
this.target = target;
this.relatedEntities = relatedEntities;
this.relationship = relationship;
};
Sdk.AssociateRequest.prototype.getMetadata = function () {
return {
boundParameter: null,
parameterTypes: {
target: { typeName: "mscrm.crmbaseentity", structuralProperty: 5 },
relatedEntities: {
typeName: "Collection(mscrm.crmbaseentity)",
structuralProperty: 4
},
relationship: { typeName: "Edm.String", structuralProperty: 1 }
},
operationType: 2,
operationName: "Associate"
};
};
/* =========================
HELPERS
========================= */
function stripBraces(id) {
return (id || "").replace(/[{}]/g, "");
}
function escapeHtml(s) {
return (s ?? "").toString()
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">");
}
function fmt(e, f) {
return e?.[`${f}@OData.Community.Display.V1.FormattedValue`] ?? e?.[f] ?? "";
}
function fmtLookup(e, f) {
return e?.[`${f}@OData.Community.Display.V1.FormattedValue`] ?? "";
}
function formatDate(d) {
if (!d) return "";
const dt = new Date(d);
return `${dt.getFullYear()}-${String(dt.getMonth() + 1).padStart(2, "0")}-${String(dt.getDate()).padStart(2, "0")}`;
}
function dayRangeUtc(dateValue) {
const start = new Date(dateValue);
start.setUTCHours(0, 0, 0, 0);
const end = new Date(start);
end.setUTCDate(start.getUTCDate() + 1);
return { start, end };
}
async function getRoot(formContext) {
const ctrl = formContext.getControl(WEBR_CTRL_NAME);
const win = await ctrl.getContentWindow();
return win.document.getElementById("root");
}
function wait(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
/* =========================
READ RELATED SUBGRID IDS
========================= */
function getRelatedCaseIds(formContext) {
const set = new Set();
const grid = formContext.getControl(RELATED_SUBGRID_NAME);
if (!grid || !grid.getGrid) return set;
try {
grid.getGrid().getRows().forEach(r => {
const id = stripBraces(r.getData().getEntity().getId());
if (id) set.add(id);
});
} catch (error) {
console.error("Failed to read related subgrid rows:", error);
}
return set;
}
/* =========================
TABLE RENDER
========================= */
function renderTable(root, rows, formContext, relatedSet) {
root.innerHTML = `
<table style="width:100%;border-collapse:collapse">
<thead>
<tr style="background:#f5f5f5">
<th></th>
<th>Case Number</th>
<th>Estate</th>
<th>Allegation</th>
<th>Property Code</th>
<th>COT</th>
<th>Case Stage</th>
<th>Allegation Result</th>
<th>Suggested Action</th>
<th>Allegation Status</th>
<th>Actions for Suggested Tenancy</th>
<th>Reason of No Tenancy Action Required</th>
</tr>
</thead>
<tbody>
${rows.map(r => {
const added = relatedSet.has(stripBraces(r.caseId));
return `
<tr data-id="${r.caseId}">
<td>
<button class="add-btn" ${added ? "disabled" : ""}>
${added ? "Added" : "Add"}
</button>
</td>
<td>${escapeHtml(r.caseNumber)}</td>
<td>${escapeHtml(r.estate)}</td>
<td>${escapeHtml(r.allegation)}</td>
<td>${escapeHtml(r.property)}</td>
<td>${escapeHtml(r.cot)}</td>
<td>${escapeHtml(r.stage)}</td>
<td>${escapeHtml(r.result)}</td>
<td>${escapeHtml(r.action)}</td>
<td>${escapeHtml(r.allegStatus)}</td>
<td>${escapeHtml(r.actionsForSuggestedTenancy)}</td>
<td>${escapeHtml(r.reasonNoTenancyAction)}</td>
</tr>
`;
}).join("")}
</tbody>
</table>
`;
root.querySelectorAll(".add-btn:not([disabled])").forEach(btn => {
btn.onclick = async (e) => {
e.stopPropagation();
const tr = btn.closest("tr");
const relatedId = stripBraces(tr.dataset.id);
const parentId = stripBraces(formContext.data.entity.getId());
btn.disabled = true;
btn.textContent = "Adding...";
try {
await Xrm.WebApi.online.execute(
new Sdk.AssociateRequest(
{ entityType: CASE_LOGICAL, id: parentId },
[{ entityType: CASE_LOGICAL, id: relatedId }],
RELATIONSHIP_NAME
)
);
btn.textContent = "Added";
relatedSet.add(relatedId);
const subgrid = formContext.getControl(RELATED_SUBGRID_NAME);
if (subgrid) {
subgrid.refresh();
}
await wait(1000);
await render({ getFormContext: () => formContext });
} catch (error) {
console.error("Associate failed:", error);
btn.disabled = false;
btn.textContent = "Add";
await Xrm.Navigation.openAlertDialog({
text: error?.message || "Failed to add related abuse case."
});
}
};
});
root.querySelectorAll("tbody tr").forEach(tr => {
tr.style.cursor = "pointer";
tr.addEventListener("click", () => {
const id = stripBraces(tr.dataset.id);
if (!id) return;
Xrm.Navigation.openForm({ entityName: CASE_LOGICAL, entityId: id });
});
});
}
/* =========================
MAIN
========================= */
async function render(executionContext) {
try {
const formContext = executionContext.getFormContext();
const root = await getRoot(formContext);
root.innerHTML = "Loading Join Award Review…";
const parentId = stripBraces(formContext.data.entity.getId());
const parent = await Xrm.WebApi.retrieveRecord(
CASE_LOGICAL,
parentId,
`?$select=${CASE_COT_FIELD},${CASE_PROPERTY_LOOKUP_VALUE}`
);
const { start, end } = dayRangeUtc(parent[CASE_COT_FIELD]);
const propId = stripBraces(parent[CASE_PROPERTY_LOOKUP_VALUE]);
const cases = (await Xrm.WebApi.retrieveMultipleRecords(
CASE_LOGICAL,
`?$select=${CASE_ID},
${CASE_NUMBER_FIELD},
${CASE_STAGE_FIELD},
${CASE_COT_FIELD},
${CASE_ESTATE_LOOKUP_VALUE},
${CASE_PROPERTY_LOOKUP_VALUE},
${CASE_SOURCE_OF_ALLEGATION}` +
`&$filter=${CASE_PROPERTY_LOOKUP_VALUE} eq ${propId}` +
` and ${CASE_COT_FIELD} ge ${start.toISOString()}` +
` and ${CASE_COT_FIELD} lt ${end.toISOString()}` +
` and ${CASE_CATEGORY_FIELD} eq ${CASECATEGORY_YES}` +
` and ${CASE_STAGE_FIELD} le ${CASESTATUS_AWARD}`
)).entities;
const caseMap = {};
cases.forEach(c => {
caseMap[c[CASE_ID]] = c;
});
let allegs = [];
if (cases.length > 0) {
allegs = (await Xrm.WebApi.retrieveMultipleRecords(
ALLEG_LOGICAL,
`?$select=${ALLEG_CASE_LOOKUP_VALUE},
${ALLEG_TYPE_FIELD},
${ALLEG_REFER_TO_MOT},
${ALLEG_RESULT_FIELD},
${ALLEG_RESULT_MOT_FIELD},
${ALLEG_SUGGESTED_ACTION_FIELD},
${ALLEG_STATUS_FIELD},
${ALLEG_ACTIONS_FOR_SUGGESTED_TENANCY},
${ALLEG_REASON_NO_TENANCY_ACTION}` +
`&$filter=${cases.map(c => `${ALLEG_CASE_LOOKUP_VALUE} eq ${c[CASE_ID]}`).join(" or ")}`
)).entities;
}
const rows = allegs.map(a => {
const c = caseMap[a[ALLEG_CASE_LOOKUP_VALUE]];
if (!c) return null;
const source = c[CASE_SOURCE_OF_ALLEGATION];
const referToMot = a[ALLEG_REFER_TO_MOT] === REFER_TO_MOT.YES;
let resultValue = "";
if (source === 100000002 || source === 100000003) {
resultValue = fmt(a, ALLEG_RESULT_MOT_FIELD);
} else if (source === 100000000 || source === 100000001) {
if (!referToMot) {
resultValue = fmt(a, ALLEG_RESULT_FIELD);
} else {
resultValue = fmt(a, ALLEG_RESULT_MOT_FIELD);
}
}
return {
caseId: c[CASE_ID],
caseNumber: fmt(c, CASE_NUMBER_FIELD),
estate: fmtLookup(c, CASE_ESTATE_LOOKUP_VALUE),
property: fmtLookup(c, CASE_PROPERTY_LOOKUP_VALUE),
cot: formatDate(c[CASE_COT_FIELD]),
stage: fmt(c, CASE_STAGE_FIELD),
allegation: fmt(a, ALLEG_TYPE_FIELD),
result: resultValue,
action: fmt(a, ALLEG_SUGGESTED_ACTION_FIELD),
allegStatus: fmt(a, ALLEG_STATUS_FIELD),
actionsForSuggestedTenancy: fmt(a, ALLEG_ACTIONS_FOR_SUGGESTED_TENANCY),
reasonNoTenancyAction: fmt(a, ALLEG_REASON_NO_TENANCY_ACTION)
};
}).filter(Boolean);
renderTable(root, rows, formContext, getRelatedCaseIds(formContext));
} catch (error) {
console.error("Join Award Review render failed:", error);
try {
const formContext = executionContext.getFormContext();
const root = await getRoot(formContext);
root.innerHTML = `<div style="color:red;">Failed to load Join Award Review.</div>`;
} catch {}
}
}
return { render };
})();Editor is loading...
Leave a Comment