Previously only a log in the exact scheduled month cleared overdue. Now any log on or after the start of the scheduled month counts, so pruning late (e.g. in May for a March schedule) correctly shows upcoming. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
44 lines
1.4 KiB
Python
44 lines
1.4 KiB
Python
from datetime import date
|
|
|
|
|
|
def months_before(d, n):
|
|
"""Return a date on the 1st of the month n months before d."""
|
|
m = (d.month - 1 - n) % 12 + 1
|
|
y = d.year + (d.month - 1 - n) // 12
|
|
return date(y, m, 1)
|
|
|
|
|
|
def pruning_status(plant, today=None):
|
|
"""
|
|
Returns one of: 'overdue', 'due_this_month', 'upcoming', 'no_schedule'.
|
|
|
|
A scheduled month is 'overdue' only if its most recent occurrence is within
|
|
the past 6 months and was not logged. Beyond 6 months, the next occurrence
|
|
is sooner than the missed one, so it is 'upcoming'.
|
|
"""
|
|
if today is None:
|
|
today = date.today()
|
|
|
|
months = plant.pruning_months or []
|
|
if not months:
|
|
return 'no_schedule'
|
|
|
|
logs = list(plant.pruning_logs.all())
|
|
|
|
if today.month in months:
|
|
if not any(l.pruned_on.year == today.year and l.pruned_on.month == today.month for l in logs):
|
|
return 'due_this_month'
|
|
return 'upcoming'
|
|
|
|
for i in range(1, 13):
|
|
past = months_before(today, i)
|
|
if past.month in months:
|
|
if i >= 6:
|
|
return 'upcoming'
|
|
# Any log on or after the start of the scheduled month clears overdue
|
|
cutoff = date(past.year, past.month, 1)
|
|
if any(l.pruned_on >= cutoff for l in logs):
|
|
return 'upcoming'
|
|
return 'overdue'
|
|
|
|
return 'upcoming'
|