mirror of
https://github.com/escalante29/WealthySmart.git
synced 2026-07-17 11:28:47 +02:00
Validate month input and document cycle labeling convention
Review finding BE-06 (suspected off-by-one in get_cycle_range) is a FALSE POSITIVE: budget month M composes get_previous_cycle with get_cycle_range to cover [(M-1)/18, M/18), matching both the code comment and the frontend convention. Verified against prod data: May 2026 cycle-window SQL sum matches the API (95 txs exactly, refunds to the colón, 0.13%% delta from one EUR tx). The docstring now spells out the labeling convention, and month is validated 1-12 (BE-07). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -65,8 +65,14 @@ def get_effective_amount(item: RecurringItem, month: int, year: int) -> float |
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _validate_month(month: int) -> None:
|
||||||
|
if not 1 <= month <= 12:
|
||||||
|
raise ValueError(f"month must be 1-12, got {month}")
|
||||||
|
|
||||||
|
|
||||||
def get_month_range(year: int, month: int) -> tuple[datetime, datetime]:
|
def get_month_range(year: int, month: int) -> tuple[datetime, datetime]:
|
||||||
"""Return (start, end) for a calendar month."""
|
"""Return (start, end) for a calendar month."""
|
||||||
|
_validate_month(month)
|
||||||
start = datetime(year, month, 1)
|
start = datetime(year, month, 1)
|
||||||
if month == 12:
|
if month == 12:
|
||||||
end = datetime(year + 1, 1, 1)
|
end = datetime(year + 1, 1, 1)
|
||||||
@@ -76,7 +82,15 @@ def get_month_range(year: int, month: int) -> tuple[datetime, datetime]:
|
|||||||
|
|
||||||
|
|
||||||
def get_cycle_range(year: int, month: int) -> tuple[datetime, datetime]:
|
def get_cycle_range(year: int, month: int) -> tuple[datetime, datetime]:
|
||||||
"""Return (start, end) for billing cycle: month/18 to month+1/18."""
|
"""Return (start, end) of the billing cycle that STARTS on the 18th of
|
||||||
|
`month`: [month/18, month+1/18).
|
||||||
|
|
||||||
|
Note the labeling convention: budget month M covers the cycle that ENDS
|
||||||
|
on the 18th of M, so callers compose get_previous_cycle(year, M) with
|
||||||
|
this function — see compute_actuals_by_source. Pinned by
|
||||||
|
tests/test_cycle_math.py.
|
||||||
|
"""
|
||||||
|
_validate_month(month)
|
||||||
start = datetime(year, month, 18)
|
start = datetime(year, month, 18)
|
||||||
if month == 12:
|
if month == 12:
|
||||||
end = datetime(year + 1, 1, 18)
|
end = datetime(year + 1, 1, 18)
|
||||||
|
|||||||
Reference in New Issue
Block a user