fix(rectification): open cases for uncertain birth times
This commit is contained in:
@@ -108,16 +108,45 @@ function shiftedTime(time: string, offsetMinutes: number): string {
|
||||
return `${String(Math.floor(normalized / 60)).padStart(2, "0")}:${String(normalized % 60).padStart(2, "0")}`;
|
||||
}
|
||||
|
||||
// This is an engine execution boundary, not a user-declared uncertainty. Fresh
|
||||
// Cases always start from reported_birth_time with enough room to rectify.
|
||||
// This is an engine execution boundary, not a user-declared uncertainty.
|
||||
// Exact-time Cases receive a movable search radius; imprecise declarations keep
|
||||
// the honest server-owned range instead of inventing a baseline minute.
|
||||
const FRESH_CASE_SEARCH_RADIUS_MINUTES = 15;
|
||||
const PERIOD_CANDIDATE_RANGES = {
|
||||
early_morning: { start_time: "04:00", end_time: "07:59" },
|
||||
morning: { start_time: "08:00", end_time: "11:59" },
|
||||
afternoon: { start_time: "12:00", end_time: "17:59" },
|
||||
evening: { start_time: "18:00", end_time: "22:59" },
|
||||
late_night: { start_time: "23:00", end_time: "03:59" },
|
||||
} as const;
|
||||
|
||||
function deriveCandidateRange(reportedTime: string | null): { start_time: string; end_time: string } {
|
||||
if (!reportedTime) throw new RectificationCaseServiceError("profile_incomplete");
|
||||
return {
|
||||
start_time: shiftedTime(reportedTime, -FRESH_CASE_SEARCH_RADIUS_MINUTES),
|
||||
end_time: shiftedTime(reportedTime, FRESH_CASE_SEARCH_RADIUS_MINUTES),
|
||||
};
|
||||
function deriveCandidateRange(input: {
|
||||
reportedTime: string | null;
|
||||
source: string;
|
||||
period: string | null;
|
||||
}): { start_time: string; end_time: string } {
|
||||
if (input.reportedTime) {
|
||||
return {
|
||||
start_time: shiftedTime(input.reportedTime, -FRESH_CASE_SEARCH_RADIUS_MINUTES),
|
||||
end_time: shiftedTime(input.reportedTime, FRESH_CASE_SEARCH_RADIUS_MINUTES),
|
||||
};
|
||||
}
|
||||
|
||||
if (input.source === "period_only" || input.source === "legacy_import") {
|
||||
const periodRange = input.period && Object.hasOwn(PERIOD_CANDIDATE_RANGES, input.period)
|
||||
? PERIOD_CANDIDATE_RANGES[input.period as keyof typeof PERIOD_CANDIDATE_RANGES]
|
||||
: null;
|
||||
if (periodRange) return periodRange;
|
||||
if (input.source === "period_only") {
|
||||
throw new RectificationCaseServiceError("profile_incomplete");
|
||||
}
|
||||
}
|
||||
|
||||
if (input.source === "unknown" || input.source === "legacy_import") {
|
||||
return { start_time: "00:00", end_time: "23:59" };
|
||||
}
|
||||
|
||||
throw new RectificationCaseServiceError("profile_incomplete");
|
||||
}
|
||||
|
||||
function baselineFingerprint(baseline: V9BaselineSnapshot): string {
|
||||
@@ -187,7 +216,7 @@ export async function loadV9RectificationProfile(
|
||||
userId,
|
||||
baseline,
|
||||
baselineFingerprint: baselineFingerprint(baseline),
|
||||
candidateRange: deriveCandidateRange(reportedTime),
|
||||
candidateRange: deriveCandidateRange({ reportedTime, source, period }),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user