Spaces:
Running
Running
Download scripts/check_callback_edit.py from Shurem/mz_chatbot: direct link, hf CLI and curl.
- Browser
- Download file 3.1 kB
-
https://huggingface.co/spaces/Shurem/mz_chatbot/resolve/main/scripts/check_callback_edit.py
- Command line
-
hf download hf://spaces/Shurem/mz_chatbot/scripts/check_callback_edit.py
-
curl -L -o check_callback_edit.py https://huggingface.co/spaces/Shurem/mz_chatbot/resolve/main/scripts/check_callback_edit.py
3.1 kB
| """ | |
| check_callback_edit.py -- offline: a callback date/time can be set from the Edit form, and it reads back as | |
| the exact wall-clock time that was typed (user, 2026-09-24). | |
| uv run python scripts/check_callback_edit.py | |
| No database, no network -- throwaway in-memory SQLite. Covers: | |
| * a Callback Scheduled recorded WITHOUT a time (what the old production button did) leaves callback_at empty | |
| * UpdateLeadInput now accepts callback_at, and update_lead() saves it | |
| * LeadOut serializes it as naive wall-clock ISO (no "Z"/offset) -- it used to go through _dt_utc, which made | |
| the browser shift a typed 3:00 PM to 8:00 PM in PKT | |
| * an unrelated edit does NOT clear an existing callback_at (set-only, like every field on that model) | |
| """ | |
| from __future__ import annotations | |
| import sys | |
| from datetime import datetime | |
| from pathlib import Path | |
| sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) | |
| from sqlalchemy import create_engine # noqa: E402 | |
| from sqlalchemy.orm import sessionmaker # noqa: E402 | |
| from sqlalchemy.pool import StaticPool # noqa: E402 | |
| import app.models # noqa: E402,F401 | |
| from app.crud import leads as crud_leads # noqa: E402 | |
| from app.database import Base # noqa: E402 | |
| from app.schemas.lead import LeadOut, UpdateLeadInput # noqa: E402 | |
| FAILED = 0 | |
| def check(label: str, ok: bool, detail: str = "") -> None: | |
| global FAILED | |
| FAILED += 0 if ok else 1 | |
| print(f" [{'ok ' if ok else 'FAIL'}] {label}" + ("" if ok else f" {detail}")) | |
| def main() -> int: | |
| engine = create_engine("sqlite://", connect_args={"check_same_thread": False}, poolclass=StaticPool) | |
| Base.metadata.create_all(engine) | |
| db = sessionmaker(bind=engine)() | |
| lead = crud_leads.add_lead_dict(db, {"company_name": "Callback Co"}) | |
| crud_leads.apply_call_outcome(db, lead, "callback_scheduled") # no callback_at, like the old button | |
| print("\nCallback recorded without a time") | |
| check("callback_at is empty", lead.callback_at is None) | |
| check("last_call_outcome is callback_scheduled", lead.last_call_outcome == "callback_scheduled") | |
| print("\nSet a time from the Edit form (UpdateLeadInput.callback_at)") | |
| typed = datetime(2026, 9, 25, 15, 0, 0) | |
| lead = crud_leads.update_lead(db, lead, UpdateLeadInput(callback_at=typed)) | |
| check("callback_at saved as typed", lead.callback_at == typed, str(lead.callback_at)) | |
| out = LeadOut.from_model(lead) | |
| check("LeadOut.callback_at is naive wall-clock ISO", out.callback_at == "2026-09-25T15:00:00", out.callback_at) | |
| check("no Z / UTC offset on it", "Z" not in out.callback_at and "+" not in out.callback_at) | |
| check("stage untouched by setting it", lead.pipeline_stage == "followup_due", lead.pipeline_stage) | |
| print("\nUnrelated edit leaves the callback alone") | |
| lead = crud_leads.update_lead(db, lead, UpdateLeadInput(subject="New subject")) | |
| check("callback_at still set", lead.callback_at == typed, str(lead.callback_at)) | |
| print(f"\n{'FAILED: ' + str(FAILED) if FAILED else 'All checks passed.'}") | |
| return 1 if FAILED else 0 | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |