Never count overlapping inferred time as accepted

This commit is contained in:
2026-09-14 15:24:41 +02:00
parent b09b536b49
commit c6040a8cb2
4 changed files with 26 additions and 8 deletions
+17 -6
View File
@@ -25,7 +25,7 @@ from starlette.middleware.sessions import SessionMiddleware
from .database import Base, engine, get_db
from .models import CallImport, RawEvent, TimeEntry
from .schemas import TimeTrackSync, ZedSync
from .services import TZ, derive_zed_suggestions, group_commits_by_day, group_entries_by_day, overlaps_accepted, parse_timestamp
from .services import TZ, derive_zed_suggestions, group_commits_by_day, group_entries_by_day, overlaps_accepted, overlaps_entries, parse_timestamp
APP_TIMEZONE = os.environ.get("APP_TIMEZONE", "Europe/Vienna")
ADMIN_PASSWORD = os.environ.get("ADMIN_PASSWORD", "")
@@ -248,11 +248,20 @@ def accept_day(day: str, request: Request, start: Annotated[str, Form()] = "", e
target = date.fromisoformat(day)
except ValueError as exc:
raise HTTPException(422, "Invalid day") from exc
for entry in db.scalars(select(TimeEntry)).all():
if entry.status == "suggested" and entry.start_at.astimezone(TZ).date() == target:
entry.status = "accepted"
if entry.kind == "zed_inferred":
entry.kind = "manual"
entries = list(db.scalars(select(TimeEntry)))
accepted_rows = [entry for entry in entries if entry.status == "accepted"]
for entry in entries:
if entry.status != "suggested" or entry.start_at.astimezone(TZ).date() != target:
continue
# Inferred time overlapping accepted time is evidence only: accepting
# it would double-count. It stays suggested (shown as overlapping) and
# can be rejected individually.
if overlaps_entries(entry, accepted_rows):
continue
entry.status = "accepted"
if entry.kind == "zed_inferred":
entry.kind = "manual"
accepted_rows.append(entry)
db.commit()
return index_redirect(start or None, end or None)
@@ -401,6 +410,8 @@ def set_entry_status(entry_id: int, request: Request, status: Annotated[str, For
entry = db.get(TimeEntry, entry_id)
if not entry:
raise HTTPException(404, "Entry not found")
if status == "accepted" and overlaps_accepted(db, entry):
raise HTTPException(422, "Entry overlaps accepted time and cannot be accepted")
entry.status = status
# An accepted inference becomes a durable user-approved manual entry.
if status == "accepted" and entry.kind == "zed_inferred":