Fix damaged-parts flow bug on carAngles

This commit is contained in:
2026-05-01 14:44:28 +03:30
parent 6429cb0f2b
commit d9dc4ecdff
3 changed files with 143 additions and 8 deletions

View File

@@ -0,0 +1,74 @@
/**
* Car-angle captures must live under {@code media.carAngles} with lowercase keys
* {@code front | back | left | right}. Clients sometimes send Title Case keys or
* mistakenly use {@code captureType: "part"} for angles, which previously wrote
* into {@code media.damagedParts} and broke step-completion checks.
*/
export const CLAIM_CAR_ANGLE_KEYS = ["front", "back", "left", "right"] as const;
export type ClaimCarAngleKey = (typeof CLAIM_CAR_ANGLE_KEYS)[number];
export function canonicalizeClaimCarAngleKey(
raw: string | undefined | null,
): ClaimCarAngleKey | null {
const t = String(raw ?? "").trim().toLowerCase();
return (CLAIM_CAR_ANGLE_KEYS as readonly string[]).includes(t)
? (t as ClaimCarAngleKey)
: null;
}
function getCaptureBlob(data: unknown, key: string): unknown {
if (data == null) return undefined;
if (data instanceof Map) return (data as Map<string, unknown>).get(key);
return (data as Record<string, unknown>)[key];
}
/** Prefer carAngles; fall back to legacy mis-placed blobs under damagedParts. */
export function getClaimCarAngleCaptureBlob(
carAnglesData: unknown,
damagedPartsData: unknown,
angle: ClaimCarAngleKey,
): unknown {
return (
getCaptureBlob(carAnglesData, angle) ??
getCaptureBlob(damagedPartsData, angle) ??
getCaptureBlob(
damagedPartsData,
angle.charAt(0).toUpperCase() + angle.slice(1),
)
);
}
export function hasClaimCarAngleCapture(
carAnglesData: unknown,
damagedPartsData: unknown,
angle: ClaimCarAngleKey,
): boolean {
return getClaimCarAngleCaptureBlob(carAnglesData, damagedPartsData, angle) != null;
}
/**
* Field names under media.damagedParts that should be removed when we persist the
* same shot under media.carAngles (migration). Skips keys that are also real selected part ids.
*/
export function legacyAngleDamagedPartFieldKeysToUnset(
canonical: ClaimCarAngleKey,
rawCaptureKey: string,
selectedParts: string[],
): string[] {
const selected = new Set((selectedParts ?? []).map((p) => String(p)));
const variants = new Set(
[
rawCaptureKey,
canonical,
canonical.charAt(0).toUpperCase() + canonical.slice(1),
].filter(Boolean),
);
const out: string[] = [];
for (const k of variants) {
if (canonicalizeClaimCarAngleKey(k) === null) continue;
if (selected.has(k)) continue;
out.push(k);
}
return [...new Set(out)];
}