GUI updates and misc fixes for the Cancel cutoff

This commit is contained in:
2026-08-31 17:01:13 -05:00
parent 9651b82415
commit df9958cb97
7 changed files with 148 additions and 61 deletions
+42 -18
View File
@@ -16,7 +16,7 @@ from sqlalchemy import select
from app.database import get_session
from app.models import Order
from app.schedule import get_cutoff_time, is_past_cutoff
from app.schedule import get_cutoff_time, is_past_cutoff_today
from app.services.base import OrderService, NormalizedOrder
from app.status_rules import get_active_statuses, get_cancelled_statuses, status_in
from app.tracking import get_fulfilled_statuses
@@ -99,7 +99,9 @@ def save_orders(orders: List[NormalizedOrder]) -> SaveResult:
Whenever a JIRA ticket's status transitions INTO a fulfilled status
(Waiting For Return / Device Return Not Needed), fulfilled_at is
stamped - that's what lets the dashboard show "fulfilled today" and
what moves it into the Done pile.
what moves it into the Done pile. cancelled_at works the same way for
CANCELLED_STATUSES - it's what limits the Cancelled tab to "cancelled
today" rather than showing every cancelled ticket ever.
"""
session = get_session()
new_count = 0
@@ -108,6 +110,7 @@ def save_orders(orders: List[NormalizedOrder]) -> SaveResult:
status_changes: List[StatusChange] = []
unmatched_tracking_tickets: List[str] = []
fulfilled_statuses = get_fulfilled_statuses()
cancelled_statuses = get_cancelled_statuses()
try:
for order in orders:
@@ -148,6 +151,7 @@ def save_orders(orders: List[NormalizedOrder]) -> SaveResult:
line_items=order.get("line_items", []),
shipping_info=order.get("shipping_info", {}),
creator=order.get("creator"),
tracking_numbers=order.get("tracking_numbers", []),
summary=order["summary"],
status=new_status,
source_created_at=order["source_created_at"],
@@ -155,6 +159,9 @@ def save_orders(orders: List[NormalizedOrder]) -> SaveResult:
fulfilled_at=(
dt.datetime.utcnow() if status_in(new_status, fulfilled_statuses) else None
),
cancelled_at=(
dt.datetime.utcnow() if status_in(new_status, cancelled_statuses) else None
),
)
)
new_count += 1
@@ -172,6 +179,10 @@ def save_orders(orders: List[NormalizedOrder]) -> SaveResult:
old_status, fulfilled_statuses
):
existing.fulfilled_at = dt.datetime.utcnow()
if status_in(new_status, cancelled_statuses) and not status_in(
old_status, cancelled_statuses
):
existing.cancelled_at = dt.datetime.utcnow()
existing.ticket_number = order.get("ticket_number")
existing.company = order.get("company", "Unknown")
@@ -213,21 +224,28 @@ def split_orders_by_view(orders: List[Order]) -> Tuple[List[Order], List[Order],
Three tabs, allowlist-driven:
- Active: status is in ACTIVE_STATUSES (just "Created" by default) -
the only tickets that represent real work still to do.
- Cancelled: status is in CANCELLED_STATUSES - its own tab so it
doesn't clutter Active, but still reviewable on demand.
- Cancelled: status is in CANCELLED_STATUSES AND it was cancelled
TODAY. A ticket cancelled on a prior day falls through to Done
instead - the Cancelled tab is meant to be reviewed same-day and
then filed away, not accumulate forever.
- Done: everything else. This deliberately doesn't enumerate every
"finished" status by name - a JIRA-side automation status like
"1st Contact Attempt" falls in here automatically just by not
being Created or Cancelled, with no code change needed when your
JIRA workflow adds another downstream status later.
being Created or (today's) Cancelled, with no code change needed
when your JIRA workflow adds another downstream status later.
"""
active_statuses = get_active_statuses()
cancelled_statuses = get_cancelled_statuses()
today = dt.date.today()
active, cancelled, done = [], [], []
for order in orders:
if status_in(order.status, active_statuses):
active.append(order)
elif status_in(order.status, cancelled_statuses):
elif (
status_in(order.status, cancelled_statuses)
and order.cancelled_at
and order.cancelled_at.date() == today
):
cancelled.append(order)
else:
done.append(order)
@@ -238,6 +256,21 @@ def load_orders_by_view() -> Tuple[List[Order], List[Order], List[Order]]:
return split_orders_by_view(load_all_orders())
def mark_shipstation_sent(ticket_number: str) -> None:
"""Stamps shipstation_sent_at after a CONFIRMED emergency API send -
called once ShipStation's own response confirms creation succeeded."""
session = get_session()
try:
order = session.execute(
select(Order).where(Order.source == "jira", Order.ticket_number == ticket_number)
).scalar_one_or_none()
if order is not None:
order.shipstation_sent_at = dt.datetime.utcnow()
session.commit()
finally:
session.close()
def get_dashboard_stats() -> dict:
"""
Counts for the dashboard. "Active Orders" and the company breakdown
@@ -276,23 +309,14 @@ def get_dashboard_stats() -> dict:
# A ticket that arrived today but after the cutoff won't get worked
# today either - it's known carryover before the date even rolls
# over, not just once tomorrow arrives.
arrived_past_cutoff_today = bool(
order.source_created_at
and order.source_created_at.date() == today
and is_past_cutoff(order.source_created_at, cutoff)
)
if created_before_today or arrived_past_cutoff_today:
if created_before_today or is_past_cutoff_today(order.source_created_at, cutoff):
carryover_count += 1
fulfilled_today_count = sum(
1 for o in orders if o.fulfilled_at and o.fulfilled_at.date() == today
)
past_cutoff_today_count = sum(
1
for o in orders
if o.source_created_at
and o.source_created_at.date() == today
and is_past_cutoff(o.source_created_at, cutoff)
1 for o in orders if is_past_cutoff_today(o.source_created_at, cutoff)
)
return {