fix(web): persist uncertain birth time as a start/end clock window

Users pick a clock range instead of a coarse period plus notes, so
rectification and window consult scan that range instead of a leftover afternoon bucket.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-08-22 20:48:01 +08:00
co-authored by Cursor
parent f3197ce3f6
commit 8ed6118b9a
31 changed files with 760 additions and 144 deletions
+93 -29
View File
@@ -49,26 +49,43 @@ export async function GET() {
const admin = createAdminSupabaseClient();
let { data: profile, error: profileError } = await supabase
.from("profiles")
.select("credits,active_birth_time,birth_time_status,birth_date,reported_birth_time,birth_time_source,birth_time_period,birth_time_clue,uncertainty_before_minutes,uncertainty_after_minutes,country_code,province_code,city_code,district_code,latitude,longitude,timezone_offset,birth_place_label,birth_place_type,birth_place_provider,birth_place_provider_id,timezone_id,timezone_source,name,birth_time,rectification_case_id")
.select("credits,active_birth_time,birth_time_status,birth_date,reported_birth_time,birth_time_source,birth_time_period,declared_window_start,declared_window_end,birth_time_clue,uncertainty_before_minutes,uncertainty_after_minutes,country_code,province_code,city_code,district_code,latitude,longitude,timezone_offset,birth_place_label,birth_place_type,birth_place_provider,birth_place_provider_id,timezone_id,timezone_source,name,birth_time,rectification_case_id")
.eq("id", userId)
.single();
if (profileError && isMissingProfileColumn(profileError)) {
const fallback = await supabase
const withoutDeclaredWindow = await supabase
.from("profiles")
.select("credits,active_birth_time,birth_time_status,birth_date,reported_birth_time,birth_time_source,birth_time_period,birth_time_clue,uncertainty_before_minutes,uncertainty_after_minutes,country_code,province_code,city_code,district_code,latitude,longitude,timezone_offset,name,birth_time,rectification_case_id")
.select("credits,active_birth_time,birth_time_status,birth_date,reported_birth_time,birth_time_source,birth_time_period,birth_time_clue,uncertainty_before_minutes,uncertainty_after_minutes,country_code,province_code,city_code,district_code,latitude,longitude,timezone_offset,birth_place_label,birth_place_type,birth_place_provider,birth_place_provider_id,timezone_id,timezone_source,name,birth_time,rectification_case_id")
.eq("id", userId)
.single();
profile = fallback.data ? {
...fallback.data,
birth_place_label: undefined,
birth_place_type: undefined,
birth_place_provider: undefined,
birth_place_provider_id: undefined,
timezone_id: undefined,
timezone_source: undefined,
} : null;
profileError = fallback.error;
if (!withoutDeclaredWindow.error && withoutDeclaredWindow.data) {
profile = {
...withoutDeclaredWindow.data,
declared_window_start: undefined,
declared_window_end: undefined,
};
profileError = withoutDeclaredWindow.error;
} else if (withoutDeclaredWindow.error && isMissingProfileColumn(withoutDeclaredWindow.error)) {
const fallback = await supabase
.from("profiles")
.select("credits,active_birth_time,birth_time_status,birth_date,reported_birth_time,birth_time_source,birth_time_period,birth_time_clue,uncertainty_before_minutes,uncertainty_after_minutes,country_code,province_code,city_code,district_code,latitude,longitude,timezone_offset,name,birth_time,rectification_case_id")
.eq("id", userId)
.single();
profile = fallback.data ? {
...fallback.data,
birth_place_label: undefined,
birth_place_type: undefined,
birth_place_provider: undefined,
birth_place_provider_id: undefined,
timezone_id: undefined,
timezone_source: undefined,
} : null;
profileError = fallback.error;
} else {
profile = withoutDeclaredWindow.data;
profileError = withoutDeclaredWindow.error;
}
}
if (profileError || !profile) {
@@ -170,28 +187,45 @@ export async function PATCH(request: Request) {
const admin = createAdminSupabaseClient();
let { data: currentProfile, error: currentProfileError } = await admin
.from("profiles")
.select("birth_date,birth_time,reported_birth_time,active_birth_time,birth_time_source,birth_time_period,birth_time_clue,uncertainty_before_minutes,uncertainty_after_minutes,birth_time_status,rectification_case_id,country_code,province_code,city_code,district_code,latitude,longitude,timezone_offset,birth_place_label,birth_place_type,birth_place_provider,birth_place_provider_id,timezone_id,timezone_source")
.select("birth_date,birth_time,reported_birth_time,active_birth_time,birth_time_source,birth_time_period,declared_window_start,declared_window_end,birth_time_clue,uncertainty_before_minutes,uncertainty_after_minutes,birth_time_status,rectification_case_id,country_code,province_code,city_code,district_code,latitude,longitude,timezone_offset,birth_place_label,birth_place_type,birth_place_provider,birth_place_provider_id,timezone_id,timezone_source")
.eq("id", userId)
.maybeSingle();
if (currentProfileError && isMissingProfileColumn(currentProfileError)) {
const fallback = await admin
const withoutDeclaredWindow = await admin
.from("profiles")
.select("birth_date,birth_time,reported_birth_time,active_birth_time,birth_time_source,birth_time_period,birth_time_clue,uncertainty_before_minutes,uncertainty_after_minutes,birth_time_status,rectification_case_id,country_code,province_code,city_code,district_code")
.select("birth_date,birth_time,reported_birth_time,active_birth_time,birth_time_source,birth_time_period,birth_time_clue,uncertainty_before_minutes,uncertainty_after_minutes,birth_time_status,rectification_case_id,country_code,province_code,city_code,district_code,latitude,longitude,timezone_offset,birth_place_label,birth_place_type,birth_place_provider,birth_place_provider_id,timezone_id,timezone_source")
.eq("id", userId)
.maybeSingle();
currentProfile = fallback.data ? {
...fallback.data,
latitude: undefined,
longitude: undefined,
timezone_offset: undefined,
birth_place_label: undefined,
birth_place_type: undefined,
birth_place_provider: undefined,
birth_place_provider_id: undefined,
timezone_id: undefined,
timezone_source: undefined,
} : null;
currentProfileError = fallback.error;
if (!withoutDeclaredWindow.error && withoutDeclaredWindow.data) {
currentProfile = {
...withoutDeclaredWindow.data,
declared_window_start: undefined,
declared_window_end: undefined,
};
currentProfileError = withoutDeclaredWindow.error;
} else if (withoutDeclaredWindow.error && isMissingProfileColumn(withoutDeclaredWindow.error)) {
const fallback = await admin
.from("profiles")
.select("birth_date,birth_time,reported_birth_time,active_birth_time,birth_time_source,birth_time_period,birth_time_clue,uncertainty_before_minutes,uncertainty_after_minutes,birth_time_status,rectification_case_id,country_code,province_code,city_code,district_code")
.eq("id", userId)
.maybeSingle();
currentProfile = fallback.data ? {
...fallback.data,
latitude: undefined,
longitude: undefined,
timezone_offset: undefined,
birth_place_label: undefined,
birth_place_type: undefined,
birth_place_provider: undefined,
birth_place_provider_id: undefined,
timezone_id: undefined,
timezone_source: undefined,
} : null;
currentProfileError = fallback.error;
} else {
currentProfile = withoutDeclaredWindow.data;
currentProfileError = withoutDeclaredWindow.error;
}
}
if (currentProfileError) {
return NextResponse.json({ error: "暂时无法核对现有出生资料" }, { status: 500 });
@@ -210,6 +244,12 @@ export async function PATCH(request: Request) {
...(payload.birth_time_period !== undefined
? { birth_time_period: payload.birth_time_period }
: {}),
...(payload.declared_window_start !== undefined
? { declared_window_start: payload.declared_window_start }
: {}),
...(payload.declared_window_end !== undefined
? { declared_window_end: payload.declared_window_end }
: {}),
...(payload.birth_time_clue !== undefined
? { birth_time_clue: payload.birth_time_clue }
: {}),
@@ -261,6 +301,30 @@ export async function PATCH(request: Request) {
data = fallback.data;
error = fallback.error;
}
if (error && isMissingProfileColumn(error)) {
const {
declared_window_start: _start,
declared_window_end: _end,
...withoutDeclaredWindow
} = withCoordinates;
void _start;
void _end;
const fallback = await writeProfile(withoutDeclaredWindow);
data = fallback.data;
error = fallback.error;
}
if (error && isMissingProfileColumn(error)) {
const {
declared_window_start: _start,
declared_window_end: _end,
...withoutCoordinatesOrWindow
} = withoutCoordinates;
void _start;
void _end;
const fallback = await writeProfile(withoutCoordinatesOrWindow);
data = fallback.data;
error = fallback.error;
}
if (!error && !data && invalidatesUnconfirmedApplication) {
return NextResponse.json({
+1 -1
View File
@@ -341,7 +341,7 @@ export async function POST(request: Request) {
async loadProfile(profileUserId) {
const { data, error } = await supabase
.from("profiles")
.select("name,birth_date,reported_birth_time,active_birth_time,birth_time_source,birth_time_period,birth_time_status,country_code,province_code,city_code,district_code,latitude,longitude,timezone_offset,birth_place_label,birth_place_type,birth_place_provider,birth_place_provider_id,timezone_id,timezone_source")
.select("name,birth_date,reported_birth_time,active_birth_time,birth_time_source,birth_time_period,declared_window_start,declared_window_end,birth_time_status,country_code,province_code,city_code,district_code,latitude,longitude,timezone_offset,birth_place_label,birth_place_type,birth_place_provider,birth_place_provider_id,timezone_id,timezone_source")
.eq("id", profileUserId)
.single();
if (error || !data) throw new ConsultationProfileTruthError("profile_unavailable");
+1 -1
View File
@@ -20,7 +20,7 @@ function createProfileRepository(
async loadProfile(userId) {
return admin
.from("profiles")
.select("id,name,birth_date,birth_time,reported_birth_time,active_birth_time,birth_time_source,birth_time_period,birth_time_clue,uncertainty_before_minutes,uncertainty_after_minutes,birth_time_status,country_code,province_code,city_code,district_code,latitude,longitude,timezone_offset,birth_place_label,birth_place_type,birth_place_provider,birth_place_provider_id,timezone_id,timezone_source,onboarding_payload,onboarding_version,onboarding_generated_at")
.select("id,name,birth_date,birth_time,reported_birth_time,active_birth_time,birth_time_source,birth_time_period,declared_window_start,declared_window_end,birth_time_clue,uncertainty_before_minutes,uncertainty_after_minutes,birth_time_status,country_code,province_code,city_code,district_code,latitude,longitude,timezone_offset,birth_place_label,birth_place_type,birth_place_provider,birth_place_provider_id,timezone_id,timezone_source,onboarding_payload,onboarding_version,onboarding_generated_at")
.eq("id", userId)
.maybeSingle();
},