fix: preserve countdown dates and restore ids
This commit is contained in:
+23
-10
@@ -5,7 +5,7 @@ import json
|
||||
import re
|
||||
from datetime import UTC, date, datetime, time, timedelta
|
||||
from pathlib import Path
|
||||
from uuid import UUID
|
||||
from uuid import UUID, uuid5
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from fastapi import APIRouter, Depends, File, HTTPException, Query, Response, UploadFile
|
||||
@@ -461,6 +461,9 @@ async def edit_countdown(countdown_id: UUID, payload: CountdownUpdate, user: Use
|
||||
"lunar_day": values.get("lunar_day", row.lunar_day),
|
||||
"ignore_year": values.get("ignore_year", row.ignore_year),
|
||||
}
|
||||
calendar_fields_changed = bool(
|
||||
{"event_date", "calendar_mode", "lunar_month", "lunar_day"} & values.keys()
|
||||
)
|
||||
if combined["calendar_mode"] == "solar":
|
||||
if combined["lunar_month"] is not None or combined["lunar_day"] is not None:
|
||||
if "calendar_mode" not in values:
|
||||
@@ -469,12 +472,17 @@ async def edit_countdown(countdown_id: UUID, payload: CountdownUpdate, user: Use
|
||||
else:
|
||||
if combined["lunar_month"] is None or combined["lunar_day"] is None:
|
||||
raise HTTPException(422, "农历倒数日需要月份和日期")
|
||||
converted = lunar_to_solar_safe(
|
||||
combined["event_date"].year, combined["lunar_month"], combined["lunar_day"]
|
||||
)
|
||||
if converted is None:
|
||||
raise HTTPException(422, "所选年份不存在该农历日期")
|
||||
combined["event_date"] = converted
|
||||
if calendar_fields_changed:
|
||||
if "event_date" in values:
|
||||
lunar_year = combined["event_date"].year
|
||||
else:
|
||||
lunar_year, _, _ = solar_to_lunar_parts(row.event_date)
|
||||
converted = lunar_to_solar_safe(
|
||||
lunar_year, combined["lunar_month"], combined["lunar_day"]
|
||||
)
|
||||
if converted is None:
|
||||
raise HTTPException(422, "所选年份不存在该农历日期")
|
||||
combined["event_date"] = converted
|
||||
values.update(combined)
|
||||
for key, value in values.items():
|
||||
setattr(row, key, value)
|
||||
@@ -982,13 +990,17 @@ async def restore_json(payload: dict, mode: str = Query("merge", pattern="^(merg
|
||||
)
|
||||
db.add(row)
|
||||
existing_countdown_ids = set((await db.scalars(select(Countdown.id).where(Countdown.user_id == user.id))).all())
|
||||
occupied_countdown_ids = dict((await db.execute(select(Countdown.id, Countdown.user_id))).all())
|
||||
has_pinned_countdown = bool(await db.scalar(select(Countdown.id).where(Countdown.user_id == user.id, Countdown.pinned.is_(True))))
|
||||
for raw in payload.get("countdowns", []):
|
||||
try:
|
||||
source_id = UUID(raw["id"])
|
||||
except (KeyError, TypeError, ValueError) as exc:
|
||||
raise HTTPException(422, "无效的倒数日备份 ID") from exc
|
||||
if mode == "merge" and source_id in existing_countdown_ids:
|
||||
row_id = source_id
|
||||
while row_id in occupied_countdown_ids and occupied_countdown_ids[row_id] != user.id:
|
||||
row_id = uuid5(user.id, str(row_id))
|
||||
if mode == "merge" and row_id in existing_countdown_ids:
|
||||
continue
|
||||
try:
|
||||
item = CountdownInput(
|
||||
@@ -1009,7 +1021,7 @@ async def restore_json(payload: dict, mode: str = Query("merge", pattern="^(merg
|
||||
except (KeyError, TypeError, ValueError) as exc:
|
||||
raise HTTPException(422, "无效的倒数日备份数据") from exc
|
||||
row = Countdown(
|
||||
id=source_id,
|
||||
id=row_id,
|
||||
user_id=user.id,
|
||||
**item.model_dump(),
|
||||
archived_at=datetime.fromisoformat(raw["archived_at"]) if raw.get("archived_at") else None,
|
||||
@@ -1020,7 +1032,8 @@ async def restore_json(payload: dict, mode: str = Query("merge", pattern="^(merg
|
||||
row.pinned = False
|
||||
has_pinned_countdown = has_pinned_countdown or row.pinned
|
||||
db.add(row)
|
||||
existing_countdown_ids.add(source_id)
|
||||
existing_countdown_ids.add(row_id)
|
||||
occupied_countdown_ids[row_id] = user.id
|
||||
audit(db, user.id, "restore", "backup", count=restored, mode=mode)
|
||||
await db.commit()
|
||||
return {"restored": restored, "mode": mode}
|
||||
|
||||
Reference in New Issue
Block a user