Add backdating support to egg harvest and sell forms
Both forms now have datetime pickers like the feed forms, allowing users to record events at past timestamps. Each form has a unique field_id (harvest_datetime, sell_datetime) to avoid conflicts. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,26 @@ from animaltrack.services.products import ProductService, ValidationError
|
||||
from animaltrack.web.templates import render_page
|
||||
from animaltrack.web.templates.eggs import eggs_page
|
||||
|
||||
|
||||
def _parse_ts_utc(form_value: str | None) -> int:
|
||||
"""Parse ts_utc from form, defaulting to current time if empty or zero.
|
||||
|
||||
Args:
|
||||
form_value: The ts_utc value from form data.
|
||||
|
||||
Returns:
|
||||
Timestamp in milliseconds. Returns current time if form_value is
|
||||
None, empty, or "0".
|
||||
"""
|
||||
if not form_value or form_value == "0":
|
||||
return int(time.time() * 1000)
|
||||
try:
|
||||
ts = int(form_value)
|
||||
return ts if ts > 0 else int(time.time() * 1000)
|
||||
except (ValueError, TypeError):
|
||||
return int(time.time() * 1000)
|
||||
|
||||
|
||||
# APIRouter for multi-file route organization
|
||||
ar = APIRouter()
|
||||
|
||||
@@ -147,8 +167,8 @@ async def product_collected(request: Request, session):
|
||||
request, locations, products, location_id, "Quantity must be at least 1"
|
||||
)
|
||||
|
||||
# Get current timestamp
|
||||
ts_utc = int(time.time() * 1000)
|
||||
# Get timestamp - use provided or current (supports backdating)
|
||||
ts_utc = _parse_ts_utc(form.get("ts_utc"))
|
||||
|
||||
# Resolve ducks at location
|
||||
resolved_ids = resolve_ducks_at_location(db, location_id, ts_utc)
|
||||
@@ -276,8 +296,8 @@ async def product_sold(request: Request, session):
|
||||
request, locations, products, product_code, "Total price cannot be negative"
|
||||
)
|
||||
|
||||
# Get current timestamp
|
||||
ts_utc = int(time.time() * 1000)
|
||||
# Get timestamp - use provided or current (supports backdating)
|
||||
ts_utc = _parse_ts_utc(form.get("ts_utc"))
|
||||
|
||||
# Create product service
|
||||
event_store = EventStore(db)
|
||||
|
||||
@@ -16,6 +16,7 @@ from monsterui.all import (
|
||||
from ulid import ULID
|
||||
|
||||
from animaltrack.models.reference import Location, Product
|
||||
from animaltrack.web.templates.actions import event_datetime_field
|
||||
|
||||
|
||||
def eggs_page(
|
||||
@@ -163,6 +164,8 @@ def harvest_form(
|
||||
name="notes",
|
||||
placeholder="Optional notes",
|
||||
),
|
||||
# Event datetime picker (for backdating)
|
||||
event_datetime_field("harvest_datetime"),
|
||||
# Hidden nonce for idempotency
|
||||
Hidden(name="nonce", value=str(ULID())),
|
||||
# Submit button
|
||||
@@ -263,6 +266,8 @@ def sell_form(
|
||||
name="notes",
|
||||
placeholder="Optional notes",
|
||||
),
|
||||
# Event datetime picker (for backdating)
|
||||
event_datetime_field("sell_datetime"),
|
||||
# Hidden nonce for idempotency
|
||||
Hidden(name="nonce", value=str(ULID())),
|
||||
# Submit button
|
||||
|
||||
Reference in New Issue
Block a user