fix(cf): merge ePay + intern extracts into a single Extrase CF list
Yesterday's pin to /api/ancpi exposed a real architecture split: there are two CfExtract stores with no overlap and the previous pilot routing only ever showed one at a time: architools_postgres.CfExtract → ePay paid orders (type=epay) gis_core.CfExtract via gis-api → CF intern (type=intern) The pin made today's 50198 ePay visible but hid the 51 historic intern rows; the pre-pin state was the opposite. Neither was right — users think of "my CF extracts" as one timeline regardless of source. Revert the pin and add client-side merge for pilot users (`useGisAc=true`): fetchCfOrdersList now fans out to both /api/ancpi/orders and /api/cf/orders in parallel, normalizes each row through a dedicated adapter (legacy or gisApi), dedupes by id, and sorts by createdAt descending. fetchCfHas- CompletedForCadastral checks both backends too (either a fresh intern or a recent ePay row means "you already have one"). CfExtractRecord grows a required `type: 'epay' | 'intern'` field; the existing rendering adds a small colored badge (sky=intern, emerald=ePay) next to the status pill so users can tell where each row came from at a glance. cfDownloadUrl is now type-aware — intern rows download via /api/cf/:id/pdf, ePay rows via /api/ancpi/download regardless of pilot flag, matching how each store keeps its files. Legacy (useGisAc, id) signature still works for the few call sites that don't have the full row in scope. No data was deleted yesterday; the 51 intern rows in gis_core stayed intact (verified via gis_superuser). The single edit was cancelling the stuck 354686 pending row from 2026-05-19. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -670,15 +670,32 @@ export function EpayTab() {
|
||||
|
||||
{/* Status */}
|
||||
<td className="px-3 py-2">
|
||||
<span
|
||||
className={cn(
|
||||
"inline-flex items-center rounded-full border px-2 py-0.5 text-[10px] font-medium",
|
||||
badge.className,
|
||||
badge.pulse && "animate-pulse",
|
||||
)}
|
||||
>
|
||||
{badge.label}
|
||||
</span>
|
||||
<div className="flex flex-wrap items-center gap-1">
|
||||
<span
|
||||
className={cn(
|
||||
"inline-flex items-center rounded-full border px-2 py-0.5 text-[10px] font-medium",
|
||||
badge.className,
|
||||
badge.pulse && "animate-pulse",
|
||||
)}
|
||||
>
|
||||
{badge.label}
|
||||
</span>
|
||||
<span
|
||||
className={cn(
|
||||
"inline-flex items-center rounded-full border px-1.5 py-0.5 text-[9px] font-medium",
|
||||
order.type === "intern"
|
||||
? "border-sky-500/30 bg-sky-500/10 text-sky-700 dark:text-sky-300"
|
||||
: "border-emerald-500/30 bg-emerald-500/10 text-emerald-700 dark:text-emerald-300",
|
||||
)}
|
||||
title={
|
||||
order.type === "intern"
|
||||
? "CF intern (gratuit, copycf)"
|
||||
: "Extras CF ePay (1 credit ANCPI)"
|
||||
}
|
||||
>
|
||||
{order.type === "intern" ? "intern" : "ePay"}
|
||||
</span>
|
||||
</div>
|
||||
{order.errorMessage && (
|
||||
<p
|
||||
className="text-[10px] text-destructive mt-0.5 max-w-48 truncate"
|
||||
@@ -730,7 +747,7 @@ export function EpayTab() {
|
||||
asChild
|
||||
>
|
||||
<a
|
||||
href={cfDownloadUrl(useGisAc, order.id)}
|
||||
href={cfDownloadUrl(order)}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
@@ -756,7 +773,7 @@ export function EpayTab() {
|
||||
asChild
|
||||
>
|
||||
<a
|
||||
href={cfDownloadUrl(useGisAc, order.id)}
|
||||
href={cfDownloadUrl(order)}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user