fix(audit): H5 — keep yacht ownership-history ledger consistent on archive/restore

Extracts transferOwnershipTx (close open yacht_ownership_history row + open
a new one + update denormalized owner) from transferOwnership, and uses it in
client-archive + client-restore instead of writing only the denormalized
columns — which left the ledger showing the old owner as current and let the
next real transfer close the wrong row.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-02 12:24:46 +02:00
parent 1882bcb2e4
commit 77829485a7
3 changed files with 105 additions and 40 deletions

View File

@@ -30,6 +30,7 @@ import {
type ClientArchiveDossier,
} from '@/lib/services/client-archive-dossier.service';
import { activeInterestsWhere } from '@/lib/services/active-interest';
import { transferOwnershipTx } from '@/lib/services/yachts.service';
// ─── Decision payload (what the UI sends to the server) ─────────────────────
@@ -246,10 +247,17 @@ export async function archiveClientWithDecisions(args: {
`Yacht ${d.yachtId}: transfer requires newOwnerType + newOwnerId`,
);
}
await tx
.update(yachts)
.set({ currentOwnerType: d.newOwnerType, currentOwnerId: d.newOwnerId })
.where(eq(yachts.id, d.yachtId));
// Move ownership through the shared ledger-aware helper so the
// yacht_ownership_history row is closed + reopened in lock-step
// with the denormalized columns. Writing only the denorm columns
// (the prior bug) left the history's open row pointing at the
// archived client, corrupting the ledger on the next real transfer.
await transferOwnershipTx(tx as unknown as typeof db, {
yachtId: d.yachtId,
newOwner: { type: d.newOwnerType, id: d.newOwnerId },
transferReason: `Smart-archive: ${decisions.reason || 'client archived'}`,
createdBy: meta.userId,
});
persistedDecisions.push({
kind: 'yacht_transferred',
refId: d.yachtId,