Conditional upsert: upload skips edited records, updates not-edited

- Add last_edited_at + last_edited_by columns to holidays + leave_records
- Migration: ALTER TABLE adds columns (idempotent)
- PUT endpoints set last_edited_at on every manual edit
- POST /api/leave/upload: skip if last_edited_at NOT NULL, update otherwise
- New POST /api/holidays/upload: same logic, admin only
- LeaveOut + HolidayOut schemas include last_edited_at
- Response includes added/updated/skipped counters
- Verified: edited Jay Lam SL preserved, not-edited May Chan SL updated
This commit is contained in:
IT Dog
2026-07-19 20:26:59 +08:00
parent bbc0048c24
commit 8e0d73c37e
2 changed files with 137 additions and 3 deletions
+8
View File
@@ -187,6 +187,10 @@ class Holiday(Base):
source = Column(String(50), nullable=True) # "gov_hk_1823" / "manual"
notes = Column(Text, nullable=True)
# Manual edit tracking - upload skips records with non-null last_edited_at
last_edited_at = Column(DateTime, nullable=True)
last_edited_by = Column(Integer, ForeignKey("users.id"), nullable=True)
created_at = Column(DateTime, default=now_hkt)
updated_at = Column(DateTime, default=now_hkt, onupdate=now_hkt)
@@ -210,6 +214,10 @@ class LeaveRecord(Base):
source = Column(String(50), nullable=True) # "csv_upload" / "manual"
notes = Column(Text, nullable=True)
# Manual edit tracking - upload skips records with non-null last_edited_at
last_edited_at = Column(DateTime, nullable=True)
last_edited_by = Column(Integer, ForeignKey("users.id"), nullable=True)
created_by = Column(Integer, ForeignKey("users.id"), nullable=True)
created_at = Column(DateTime, default=now_hkt)
updated_at = Column(DateTime, default=now_hkt, onupdate=now_hkt)