Add financial year selector to Cash Payment Review
This commit is contained in:
@@ -4,6 +4,7 @@ from datetime import date, datetime
|
||||
from decimal import Decimal, InvalidOperation
|
||||
from urllib.parse import quote
|
||||
import uuid
|
||||
import re
|
||||
|
||||
from fastapi import APIRouter, Request
|
||||
from fastapi.responses import RedirectResponse, JSONResponse
|
||||
@@ -148,6 +149,30 @@ def _review_financial_year(date_from: str, date_to: str, fallback_today: date) -
|
||||
return fy, parsed_from, parsed_to
|
||||
|
||||
|
||||
def _financial_year_bounds(financial_year: str) -> tuple[date, date]:
|
||||
text = str(financial_year or "").strip()
|
||||
match = re.fullmatch(r"(\d{4})-(\d{2})", text)
|
||||
if not match:
|
||||
raise ValueError("Invalid financial year.")
|
||||
start_year = int(match.group(1))
|
||||
expected_suffix = str((start_year + 1) % 100).zfill(2)
|
||||
if match.group(2) != expected_suffix:
|
||||
raise ValueError("Invalid financial year.")
|
||||
return date(start_year, 4, 1), date(start_year + 1, 3, 31)
|
||||
|
||||
|
||||
def _financial_year_options(selected_fy: str, today: date) -> list[str]:
|
||||
current = _financial_year_for_date(today)
|
||||
current_start = int(current.split("-", 1)[0])
|
||||
selected_start = int(str(selected_fy).split("-", 1)[0]) if selected_fy else current_start
|
||||
newest = max(current_start, selected_start)
|
||||
oldest = min(current_start - 7, selected_start)
|
||||
return [
|
||||
f"{year}-{str((year + 1) % 100).zfill(2)}"
|
||||
for year in range(newest, oldest - 1, -1)
|
||||
]
|
||||
|
||||
|
||||
def _render(request: Request, db, user, **context):
|
||||
base = {
|
||||
"request": request,
|
||||
@@ -170,6 +195,7 @@ def cash_payment_review(
|
||||
tally_guid: str = "",
|
||||
date_from: str = "",
|
||||
date_to: str = "",
|
||||
financial_year: str = "",
|
||||
job_id: str = "",
|
||||
cash_ledger_name: str = "",
|
||||
analyze: int = 0,
|
||||
@@ -196,16 +222,35 @@ def cash_payment_review(
|
||||
|
||||
today = date.today()
|
||||
|
||||
# Default period still follows the current date when the user first opens
|
||||
# the page, but once a date range is supplied the mirror is resolved
|
||||
# strictly from that review period rather than from the workspace FY.
|
||||
# Financial Year is now an explicit review selector. This avoids any
|
||||
# ambiguity between the ERP workspace FY and the local mirror FY.
|
||||
default_fy = _financial_year_for_date(today)
|
||||
default_start_year = int(default_fy.split("-", 1)[0])
|
||||
start_text = date_from or date(default_start_year, 4, 1).isoformat()
|
||||
end_text = date_to or today.isoformat()
|
||||
review_fy, parsed_from, parsed_to = _review_financial_year(start_text, end_text, today)
|
||||
requested_fy = str(financial_year or "").strip()
|
||||
try:
|
||||
review_fy = requested_fy if requested_fy else (
|
||||
_financial_year_for_date(_parse_review_date(date_from, today))
|
||||
if date_from else default_fy
|
||||
)
|
||||
fy_start, fy_end = _financial_year_bounds(review_fy)
|
||||
except Exception:
|
||||
review_fy = default_fy
|
||||
fy_start, fy_end = _financial_year_bounds(review_fy)
|
||||
|
||||
parsed_from = _parse_review_date(date_from, fy_start) if date_from else fy_start
|
||||
parsed_to = _parse_review_date(date_to, fy_end) if date_to else fy_end
|
||||
|
||||
# Keep manual sub-period review possible, but never allow a reversed
|
||||
# range such as 01/04/2025 -> 31/03/2025.
|
||||
if parsed_from < fy_start or parsed_from > fy_end:
|
||||
parsed_from = fy_start
|
||||
if parsed_to < fy_start or parsed_to > fy_end:
|
||||
parsed_to = fy_end
|
||||
if parsed_to < parsed_from:
|
||||
parsed_from, parsed_to = fy_start, fy_end
|
||||
|
||||
start_text = parsed_from.isoformat()
|
||||
end_text = parsed_to.isoformat()
|
||||
financial_year_options = _financial_year_options(review_fy, today)
|
||||
|
||||
review = None
|
||||
mirror_status = None
|
||||
@@ -294,6 +339,7 @@ def cash_payment_review(
|
||||
allocation_input={"total_amount": "", "party_name": "", "expense_ledger": "", "source_payments": ""},
|
||||
page_mode="compliance",
|
||||
review_financial_year=review_fy,
|
||||
financial_year_options=financial_year_options,
|
||||
)
|
||||
finally:
|
||||
db.close()
|
||||
@@ -737,7 +783,13 @@ async def save_cash_payment_settings(request: Request):
|
||||
except Exception:
|
||||
db.rollback()
|
||||
client_id = str(form.get("client_id") or "").strip()
|
||||
suffix = f"&client_id={client_id}" if client_id else ""
|
||||
financial_year = str(form.get("financial_year") or "").strip()
|
||||
parts = []
|
||||
if client_id:
|
||||
parts.append("client_id=" + quote(client_id))
|
||||
if financial_year:
|
||||
parts.append("financial_year=" + quote(financial_year))
|
||||
suffix = ("&" + "&".join(parts)) if parts else ""
|
||||
return RedirectResponse(url=f"/tools/accounting/cash-payments?saved=1{suffix}", status_code=303)
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
Reference in New Issue
Block a user