/**
* D-Sec アラート画面の保存(編集モード)で使う純粋関数(指示書AX 2-6・表3)。
*
* ★書き込みはエラー一覧と同じ `PATCH /errors/{error_id}/status`★(指示書AX D6)。応答は `ErrorReportItem` なので、
* `dsAlertWithResolution()` で画面の `DsAlert` に戻す。
* ★保存後に一覧を取り直さない★(D15)— 成功した行だけ差し替え、`summary` は `adjustDsAlertSummary()` で付け替える。
*
* テストは `lib/ds-alerts/__tests__/edit.test.ts`(表3 S1〜S6)。
*/
import type { DsAlertSummary } from "@/lib/ds-alerts/query";
import type { DsAlert, ErrorReportItem, PrecheckStatus } from "@/lib/types";
/**
* PATCH /errors/{error_id}/status の応答(`ErrorReportItem`)を `DsAlert` に戻す。
* ★4項目(`resolution_status` / `responded_at` / `resolved_at` / `note`)だけ差し替え★ — 他は `row` のまま。
* ★id が違えば例外★(呼び出しの誤り。別の行の応答を貼ると誰も気づけない)。
*/
export function dsAlertWithResolution(row: DsAlert, updated: ErrorReportItem): DsAlert {
if (updated.id !== row.id) {
throw new Error(
`[ds-alerts/edit] 応答の id が食い違っています(行 id=${row.id} に id=${updated.id} の応答が渡された)`
);
}
return {
...row,
resolution_status: updated.resolution_status,
responded_at: updated.responded_at,
resolved_at: updated.resolved_at,
note: updated.note,
};
}
/**
* 保存で状態が変わった行の分だけ `summary` を付け替える(旧状態 −1・新状態 +1)。★入力を書き換えない★。
*
* @param before 保存前の画面の行(`id` で `updated` と突き合わせる)
* @param updated 保存に成功した行(id → 保存後の `DsAlert`)。★無い行・状態が同じ行は数えない★
*/
export function adjustDsAlertSummary(
summary: DsAlertSummary,
before: readonly DsAlert[],
updated: ReadonlyMap<string, DsAlert>
): DsAlertSummary {
const next: Record<PrecheckStatus, number> = { ...summary };
for (const row of before) {
const after = updated.get(row.id);
if (after === undefined || after.resolution_status === row.resolution_status) continue;
next[row.resolution_status] -= 1;
next[after.resolution_status] += 1;
}
return { unresolved: next.unresolved, in_progress: next.in_progress, resolved: next.resolved };
}