Implement C02 form API fallback
- Adds a fallback API call to `.../c02form014/view` when the primary endpoint `.../c02form009detail/current` returns no result. - Handles the different response structures for the reference number: - Primary: `response.Payload[0].Reference` - Fallback: `response.Payload.Details[0].Reference` - This increases the reliability of fetching the reference number required for the refund review process.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// ==UserScript==
|
||||
// @name CoreTabs
|
||||
// @namespace https://git.diasbaskara.id/diasbaskara/userscripts/
|
||||
// @version 0.3.1
|
||||
// @version 0.4
|
||||
// @description Manage your cases easily.
|
||||
// @author Dias Baskara
|
||||
// @match https://coretax.intranet.pajak.go.id/*
|
||||
@@ -141,7 +141,42 @@
|
||||
async function fetchCaseUsers(caseId){const responseArea=document.querySelector("#tab-users .results-container");responseArea.innerHTML='<p style="padding:15px;color:#666;">Loading users...</p>';try{if(!caseId)throw new Error("No Case ID provided.");const apiUrl="https://coretax.intranet.pajak.go.id/casemanagement/api/caseuser/list",payload={AggregateIdentifier:caseId,First:0,Rows:200,SortField:"",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();allCaseUsers=data?.Payload?.Data||[],loadedUsersForCaseId=caseId,populateFilter("users-role-filter",allCaseUsers,"CaseRoleType"),renderCaseUsersTable()}catch(error){handleError(error,responseArea)}}
|
||||
async function downloadDocument(docId, filename, button) {const originalText=button.textContent;button.textContent="Downloading...",button.disabled=!0;try{const apiUrl="https://coretax.intranet.pajak.go.id/documentmanagement/api/download",payload={DocumentAggregateIdentifier:docId,IsDocumentCases:!1,IsNeedWatermark:null},fetchOptions={method:"POST",headers:getHeaders(),body:JSON.stringify(payload)},response=await fetch(apiUrl,fetchOptions);if(!response.ok)try{const errorData=await response.json();throw new Error(`API Error: ${errorData.Message||response.statusText}`)}catch(e){throw new Error(`API request failed! Status: ${response.statusText}`)}const blob=await response.blob(),url=window.URL.createObjectURL(blob),a=document.createElement("a");a.style.display="none",a.href=url,a.download=filename||"download.pdf",document.body.appendChild(a),a.click(),window.URL.revokeObjectURL(url),a.remove()}catch(error){alert(`Download failed: ${error.message}`)}finally{button.textContent=originalText,button.disabled=!1}}
|
||||
async function fetchSubProcessId(caseId) {const apiUrl="https://coretax.intranet.pajak.go.id/casemanagement/api/caserouting/view",payload={AggregateIdentifier:caseId,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(`Sub Process ID API Error: ${errorData.Message||response.statusText}`)}const data=await response.json(),firstResult=data?.Payload?.[0];if(!firstResult||!firstResult.SubProcessIdentifier)throw new Error("Could not find a 'SubProcessIdentifier' in the caserouting/view response.");return firstResult.SubProcessIdentifier}
|
||||
async function fetchC02FormDetail(caseId, subProcessId) {const apiUrl="https://coretax.intranet.pajak.go.id/casecomponentspayment/api/c02form014/c02form009detail/current",payload={caseAggregateIdentifier:caseId,CaseSubProcessIdentifier:subProcessId},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(`C02Form Detail API Error: ${errorData.Message||response.statusText}`)}const data=await response.json(),firstResult=data?.Payload?.[0];if(!firstResult||!firstResult.Reference)throw new Error("Could not find a 'Reference' number in the C02Form Detail response.");return firstResult.Reference}
|
||||
|
||||
// NEW: This function now includes the fallback logic.
|
||||
async function fetchC02FormDetail(caseId, subProcessId) {
|
||||
const payload = { caseAggregateIdentifier: caseId, CaseSubProcessIdentifier: subProcessId };
|
||||
const fetchOptions = { method: "POST", headers: getHeaders(caseId), body: JSON.stringify(payload) };
|
||||
|
||||
// 1. Primary API Attempt
|
||||
const primaryApiUrl = "https://coretax.intranet.pajak.go.id/casecomponentspayment/api/c02form014/c02form009detail/current";
|
||||
try {
|
||||
const response = await fetch(primaryApiUrl, fetchOptions);
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
const reference = data?.Payload?.[0]?.Reference;
|
||||
if (reference) return reference; // Success on primary API
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("Primary API for C02Form failed, trying fallback.", error);
|
||||
}
|
||||
|
||||
// 2. Fallback API Attempt
|
||||
const responseArea = document.querySelector('#tab-refund .results-container');
|
||||
responseArea.innerHTML = `<p style="padding:15px;color:#666;">Step 2/3: Fetching reference number (trying fallback API)...</p>`;
|
||||
const fallbackApiUrl = "https://coretax.intranet.pajak.go.id/casecomponentspayment/api/c02form014/view";
|
||||
const fallbackResponse = await fetch(fallbackApiUrl, fetchOptions);
|
||||
if (!fallbackResponse.ok) {
|
||||
const errorData = await fallbackResponse.json();
|
||||
throw new Error(`C02Form Detail API Error (Fallback): ${errorData.Message || fallbackResponse.statusText}`);
|
||||
}
|
||||
const fallbackData = await fallbackResponse.json();
|
||||
const fallbackReference = fallbackData?.Payload?.Details?.[0]?.Reference;
|
||||
if (fallbackReference) return fallbackReference; // Success on fallback API
|
||||
|
||||
// 3. If both fail
|
||||
throw new Error("Could not find a 'Reference' number in either C02Form Detail response.");
|
||||
}
|
||||
|
||||
async function fetchRefundReview(caseId, refNumber) {const responseArea=document.querySelector("#tab-refund .results-container");try{const apiUrl="https://coretax.intranet.pajak.go.id/casecomponentspayment/api/refundprocessreview/get-detailed-review",payload={CaseAggregateIdentifier:caseId,RevenueCode:"411211",TaxPaymentCode:"100",TaxReturnType:"VAT_VATR",ReferenceNumber:refNumber},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(`Refund Review API Error: ${errorData.Message||response.statusText}`)}const data=await response.json();refundReviewData=data?.Payload||[],populateBooleanFilter("refund-reported-filter"),renderRefundReviewTable()}catch(error){handleError(error,responseArea)}}
|
||||
|
||||
// --- HELPER FUNCTIONS ---
|
||||
@@ -151,11 +186,11 @@
|
||||
function getAuthToken(){const userDataString=localStorage.getItem(AUTH_STORAGE_KEY),userData=userDataString?JSON.parse(userDataString):null,authToken=userData?.access_token;if(!authToken)throw new Error("Authorization Token not found.");return authToken}
|
||||
function createTable(headers){const table=document.createElement("table");table.className="ct-results-table";const thead=document.createElement("thead");return thead.innerHTML=`<tr>${headers.map(e=>`<th>${e}</th>`).join("")}</tr>`,table.appendChild(thead),table}
|
||||
function handleError(error,area){console.error("Userscript Error:",error);let errorHtml;error.message.includes("Authorization Token not found")?errorHtml=`
|
||||
<div style="padding:15px; color: #d9534f; text-align: center;">
|
||||
<b>Session Expired or Token Not Found</b>
|
||||
<p style="margin: 10px 0;">Please refresh the page to log in again.</p>
|
||||
<button id="auth-refresh-btn" class="refresh-btn">Refresh Page</button>
|
||||
</div>`:errorHtml=`<p style="color: #d9534f;padding:15px;"><b>An error occurred:</b><br>${error.message}</p>`,area.innerHTML=errorHtml;const refreshBtn=area.querySelector("#auth-refresh-btn");refreshBtn&&refreshBtn.addEventListener("click",()=>window.location.reload())}
|
||||
<div style="padding:15px; color: #d9534f; text-align: center;">
|
||||
<b>Session Expired or Token Not Found</b>
|
||||
<p style="margin: 10px 0;">Please refresh the page to log in again.</p>
|
||||
<button id="auth-refresh-btn" class="refresh-btn">Refresh Page</button>
|
||||
</div>`:errorHtml=`<p style="color: #d9534f;padding:15px;"><b>An error occurred:</b><br>${error.message}</p>`,area.innerHTML=errorHtml;const refreshBtn=area.querySelector("#auth-refresh-btn");refreshBtn&&refreshBtn.addEventListener("click",()=>window.location.reload())}
|
||||
function updateHeader(caseObject) {
|
||||
const titleEl = document.getElementById('ct-header-title');
|
||||
const subtitleEl = document.getElementById('ct-header-subtitle');
|
||||
@@ -167,9 +202,7 @@
|
||||
subtitleEl.textContent = caseObject.CaseNumber || 'N/A';
|
||||
const caseId = caseObject.AggregateIdentifier;
|
||||
const hasValidId = caseId && typeof caseId === 'string' && caseId.trim() !== '';
|
||||
const disabledAttribute = hasValidId ? '' : 'disabled';
|
||||
|
||||
// Create buttons programmatically to attach listeners safely
|
||||
const openBtn = document.createElement('a');
|
||||
openBtn.href = `https://coretax.intranet.pajak.go.id/case-management/id-ID/case-overview/${caseId}`;
|
||||
openBtn.className = 'action-btn open-case';
|
||||
@@ -202,6 +235,8 @@
|
||||
subtitleEl.textContent = 'Please select a case from the "My Cases" tab';
|
||||
}
|
||||
}
|
||||
|
||||
// MODIFIED: This function has updated user-facing messages.
|
||||
async function startRefundReviewProcess(caseId, button) {
|
||||
const originalText = button.textContent;
|
||||
button.textContent = '...';
|
||||
@@ -212,7 +247,7 @@
|
||||
responseArea.innerHTML = `<p style="padding:15px;color:#666;">Step 1/3: Fetching Sub Process ID...</p>`;
|
||||
if (!caseId) throw new Error("A case must be selected.");
|
||||
const subProcessId = await fetchSubProcessId(caseId);
|
||||
responseArea.innerHTML = `<p style="padding:15px;color:#666;">Step 2/3: Fetching reference number...</p>`;
|
||||
responseArea.innerHTML = `<p style="padding:15px;color:#666;">Step 2/3: Fetching reference number (trying primary API)...</p>`;
|
||||
const referenceNumber = await fetchC02FormDetail(caseId, subProcessId);
|
||||
responseArea.innerHTML = `<p style="padding:15px;color:#666;">Step 3/3: Fetching refund details...</p>`;
|
||||
await fetchRefundReview(caseId, referenceNumber);
|
||||
@@ -228,7 +263,7 @@
|
||||
const selectedRow = event.target.closest("tr");
|
||||
if (!selectedRow || selectedRow.classList.contains("group-header")) return;
|
||||
const caseId = selectedRow.dataset.id;
|
||||
if (!caseId || caseId === selectedCaseId) return; // Don't re-process if the same row is clicked
|
||||
if (!caseId || caseId === selectedCaseId) return;
|
||||
|
||||
const selectedCase = allMyCases.find(e => e.AggregateIdentifier === caseId);
|
||||
updateHeader(selectedCase);
|
||||
|
||||
Reference in New Issue
Block a user