feat(frontend): add listUnmatched, matchRemit, unmatchClaim to api
This commit is contained in:
@@ -17,6 +17,8 @@
|
|||||||
* - `health()` GETs `/api/health` and returns `{ status, version }`.
|
* - `health()` GETs `/api/health` and returns `{ status, version }`.
|
||||||
* - `listBatches / getBatch / listClaims / listRemittances / listProviders
|
* - `listBatches / getBatch / listClaims / listRemittances / listProviders
|
||||||
* / listActivity` are plain JSON GETs against the persistence surface.
|
* / listActivity` are plain JSON GETs against the persistence surface.
|
||||||
|
* - `listUnmatched / matchRemit / unmatchClaim` hit the reconciliation
|
||||||
|
* surface. POSTs throw `ApiError` so callers can branch on `.status`.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
@@ -24,6 +26,7 @@ import type {
|
|||||||
ClaimPayment,
|
ClaimPayment,
|
||||||
Envelope,
|
Envelope,
|
||||||
FinancialInfo,
|
FinancialInfo,
|
||||||
|
MatchResponse,
|
||||||
NdjsonEvent,
|
NdjsonEvent,
|
||||||
ParseResult837,
|
ParseResult837,
|
||||||
ParseResult835,
|
ParseResult835,
|
||||||
@@ -31,6 +34,8 @@ import type {
|
|||||||
Payer835,
|
Payer835,
|
||||||
Payee835,
|
Payee835,
|
||||||
ReassociationTrace,
|
ReassociationTrace,
|
||||||
|
UnmatchedClaim,
|
||||||
|
UnmatchedResponse,
|
||||||
BatchSummary as ParserBatchSummary,
|
BatchSummary as ParserBatchSummary,
|
||||||
} from "@/types";
|
} from "@/types";
|
||||||
|
|
||||||
@@ -147,6 +152,16 @@ function notConfiguredError(): Error {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error thrown for non-2xx responses. Carries the HTTP `status` so callers can
|
||||||
|
* branch on it (e.g. 404 vs 500) without parsing the message string.
|
||||||
|
*/
|
||||||
|
export class ApiError extends Error {
|
||||||
|
constructor(public status: number, message: string) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function joinUrl(path: string): string {
|
function joinUrl(path: string): string {
|
||||||
return `${BASE_URL.replace(/\/$/, "")}${path}`;
|
return `${BASE_URL.replace(/\/$/, "")}${path}`;
|
||||||
}
|
}
|
||||||
@@ -436,6 +451,61 @@ async function listActivity<T = unknown>(
|
|||||||
return (await res.json()) as PaginatedResponse<T>;
|
return (await res.json()) as PaginatedResponse<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Public surface — reconciliation endpoints (sub-project 2)
|
||||||
|
// POSTs throw `ApiError` so callers can inspect `.status`; the GET is shaped
|
||||||
|
// like the other list endpoints above.
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
async function listUnmatched(): Promise<UnmatchedResponse> {
|
||||||
|
if (!isConfigured) throw notConfiguredError();
|
||||||
|
const res = await fetch(joinUrl(`/api/reconciliation/unmatched`), {
|
||||||
|
headers: { Accept: "application/json" },
|
||||||
|
});
|
||||||
|
if (!res.ok) {
|
||||||
|
const detail = await readErrorBody(res);
|
||||||
|
throw new ApiError(res.status, detail || res.statusText);
|
||||||
|
}
|
||||||
|
return (await res.json()) as UnmatchedResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function matchRemit(
|
||||||
|
claimId: string,
|
||||||
|
remitId: string
|
||||||
|
): Promise<MatchResponse> {
|
||||||
|
if (!isConfigured) throw notConfiguredError();
|
||||||
|
const res = await fetch(joinUrl(`/api/reconciliation/match`), {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ claim_id: claimId, remit_id: remitId }),
|
||||||
|
});
|
||||||
|
if (!res.ok) {
|
||||||
|
const detail = await readErrorBody(res);
|
||||||
|
throw new ApiError(res.status, detail || res.statusText);
|
||||||
|
}
|
||||||
|
return (await res.json()) as MatchResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function unmatchClaim(claimId: string): Promise<{ claim: UnmatchedClaim }> {
|
||||||
|
if (!isConfigured) throw notConfiguredError();
|
||||||
|
const res = await fetch(joinUrl(`/api/reconciliation/unmatch`), {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ claim_id: claimId }),
|
||||||
|
});
|
||||||
|
if (!res.ok) {
|
||||||
|
const detail = await readErrorBody(res);
|
||||||
|
throw new ApiError(res.status, detail || res.statusText);
|
||||||
|
}
|
||||||
|
return (await res.json()) as { claim: UnmatchedClaim };
|
||||||
|
}
|
||||||
|
|
||||||
export const api = {
|
export const api = {
|
||||||
isConfigured,
|
isConfigured,
|
||||||
baseUrl: BASE_URL,
|
baseUrl: BASE_URL,
|
||||||
@@ -448,4 +518,7 @@ export const api = {
|
|||||||
listRemittances,
|
listRemittances,
|
||||||
listProviders,
|
listProviders,
|
||||||
listActivity,
|
listActivity,
|
||||||
|
listUnmatched,
|
||||||
|
matchRemit,
|
||||||
|
unmatchClaim,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user