From 50401a73c9647c1304a4e7d5a3725e3cfeb8dea1 Mon Sep 17 00:00:00 2001 From: Dias Baskara <25913324+diasbaskara@users.noreply.github.com> Date: Wed, 26 Nov 2025 13:02:55 +0700 Subject: [PATCH] Add Case History tab with grouped history view Introduces a new 'Case History' tab to display case routing history, grouped by case type and including current role information. Implements API calls to fetch history and subprocess data, adds filtering and group toggling, and updates tab switching logic to support the new feature. --- coretabs.user.js | 258 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 239 insertions(+), 19 deletions(-) diff --git a/coretabs.user.js b/coretabs.user.js index 3c8065d..4aecdbe 100644 --- a/coretabs.user.js +++ b/coretabs.user.js @@ -48,11 +48,14 @@ let allMyCases = [], allCaseDocuments = [], allCaseUsers = [], - refundReviewData = []; - let filteredRefundData = []; - let selectedCaseId = null; - let loadedDocsForCaseId = null; - let loadedUsersForCaseId = null; + caseHistoryData = [], + caseSubProcessData = {}, + refundReviewData = [], + filteredRefundData = [], + selectedCaseId = null, + loadedDocsForCaseId = null, + loadedUsersForCaseId = null, + loadedHistoryForCaseId = null; function addStyles() { GM_addStyle(` @@ -109,12 +112,20 @@ +
Loading my cases...
Please select a case to view its documents.
Please select a case to view its users.
Please select a case to view its history.
No history data available for this case.
'; + return; + } + + const filterValue = document.getElementById("history-type-filter").value; + const filteredHistory = caseHistoryData.filter( + (item) => filterValue === "all" || item.CaseType === filterValue, + ); + + if (filteredHistory.length === 0) { + responseArea.innerHTML = + 'No history items match the selected filter.
'; + return; + } + + const table = createTable([ + "Routing Date", + "Performed By", + "Workflow Step", + ]), + tbody = document.createElement("tbody"); + + // Group items by CaseType + const groupedHistory = {}; + filteredHistory.forEach((item) => { + const caseType = item.CaseType || "Unknown"; + if (!groupedHistory[caseType]) { + groupedHistory[caseType] = []; + } + groupedHistory[caseType].push(item); + }); + + // Create table rows with grouping + Object.keys(groupedHistory).forEach((caseType) => { + const groupItems = groupedHistory[caseType]; + + // Create group header row + const sanitizedCaseType = caseType.replace(/[^a-zA-Z0-9]/g, "_"); + tbody.innerHTML += `Loading history...
'; + try { + if (!caseId) throw new Error("No Case ID provided."); + const apiUrl = + "https://coretax.intranet.pajak.go.id/casemanagement/api/caseroutinghistory/list", + payload = { + AggregateIdentifier: caseId, + First: 0, + Rows: 1000, + SortField: "RoutingDate", + SortOrder: -1, + Filters: [], + LanguageId: "id-ID", + }, + fetchOptions = { + method: "POST", + headers: getHeaders(caseId), + body: JSON.stringify(payload), + }, + response = await fetch(apiUrl, fetchOptions); + if (!response.ok) { + const errorData = await response.json(); + throw new Error( + `API Error: ${errorData.Message || response.statusText}`, + ); + } + const data = await response.json(); + caseHistoryData = data?.Payload?.Data || []; + loadedHistoryForCaseId = caseId; + + // Fetch CaseRoleTypeCode for each ToWorkflowStepIdentifier + await fetchCaseSubProcessData(caseId); + + populateFilter("history-type-filter", caseHistoryData, "CaseType"); + renderCaseHistoryTable(); + } catch (error) { + handleError(error, responseArea); + } + } + async function fetchCaseSubProcessData(caseId) { + try { + const apiUrl = + "https://coretax.intranet.pajak.go.id/casemanagement/api/casesubprocess/list", + payload = { + First: 0, + Rows: 10000, + Filters: [], + AggregateIdentifier: caseId, + }, + fetchOptions = { + method: "POST", + headers: getHeaders(caseId), + body: JSON.stringify(payload), + }, + response = await fetch(apiUrl, fetchOptions); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error( + `Case SubProcess API Error: ${errorData.Message || response.statusText}`, + ); + } + + const data = await response.json(); + const subProcessData = data?.Payload?.Data || []; + + // Create a lookup map for WorkflowStepIdentifier to CaseRoleTypeCode + caseSubProcessData = {}; + subProcessData.forEach((item) => { + if (item.WorkflowStepIdentifier && item.CaseRoleTypeCode) { + caseSubProcessData[item.WorkflowStepIdentifier] = + item.CaseRoleTypeCode; + } + }); + } catch (error) { + console.error("Error fetching case subprocess data:", error); + caseSubProcessData = {}; + } + } + async function downloadDocument(docId, filename, button) { const originalText = button.textContent; ((button.textContent = "Downloading..."), (button.disabled = !0)); @@ -673,11 +881,9 @@ const table = document.createElement("table"); table.className = "ct-results-table"; const thead = document.createElement("thead"); - return ( - (thead.innerHTML = `