import uuid from datetime import date, datetime, time, timedelta from fastapi import APIRouter, Cookie, Depends, Security from sqlalchemy import func, or_, select from sqlalchemy.orm import Session from ...core.config import settings from ...core.security import get_current_active_user as get_user from ...db.session import SessionFuture from ...models.inventory import Inventory from ...models.kot import Kot from ...models.product import Product from ...models.product_version import ProductVersion from ...models.sale_category import SaleCategory from ...models.settle_option import SettleOption from ...models.settlement import Settlement from ...models.voucher import Voucher from ...models.voucher_type import VoucherType from ...printing.sale_report import print_sale_report from ...schemas.sale_report import SaleReport, SaleReportItem from ...schemas.user import UserLink from ...schemas.user_token import UserToken from . import check_audit_permission, report_finish_date, report_start_date from .tax_report import get_tax router = APIRouter() @router.get("", response_model=SaleReport) def get_sale_report( start_date: date = Depends(report_start_date), finish_date: date = Depends(report_finish_date), user: UserToken = Security(get_user, scopes=["sale-report"]), ) -> SaleReport: check_audit_permission(start_date, user.permissions) with SessionFuture() as db: return SaleReport( startDate=start_date, finishDate=finish_date, amounts=( get_sale(start_date, finish_date, db) + [SaleReportItem(name="--", amount=0)] + get_settlements(start_date, finish_date, db) + [SaleReportItem(name="--", amount=0)] + [SaleReportItem(name=i.name, amount=i.amount) for i in get_tax(start_date, finish_date, db)] ), user=UserLink(id=user.id_, name=user.name), ) def get_sale(s: date, f: date, db: Session) -> list[SaleReportItem]: start_date = datetime.combine(s, time()) + timedelta( minutes=settings.NEW_DAY_OFFSET_MINUTES - settings.TIMEZONE_OFFSET_MINUTES ) finish_date = datetime.combine(f, time()) + timedelta( days=1, minutes=settings.NEW_DAY_OFFSET_MINUTES - settings.TIMEZONE_OFFSET_MINUTES ) day = func.date_trunc("day", Voucher.date - timedelta(minutes=settings.NEW_DAY_OFFSET_MINUTES)).label("day") list_ = db.execute( select(SaleCategory.name, func.sum(Inventory.net)) .join(Inventory.kot) .join(Kot.voucher) .join(Inventory.product) .join(Product.versions) .join(ProductVersion.sale_category) .where( Voucher.date >= start_date, Voucher.date <= finish_date, Voucher.voucher_type == VoucherType.REGULAR_BILL, ~Voucher.settlements.any(Settlement.settled == SettleOption.UNSETTLED()), or_( ProductVersion.valid_from == None, # noqa: E711 ProductVersion.valid_from <= day, ), or_( ProductVersion.valid_till == None, # noqa: E711 ProductVersion.valid_till >= day, ), ) .group_by(SaleCategory.name) .order_by(SaleCategory.name) ).all() total = 0 info = [] for gt, am in list_: total += am info.append(SaleReportItem(name=gt, amount=am)) return info + [SaleReportItem(name="Total Settled", amount=total)] def get_settlements(s: date, f: date, db: Session) -> list[SaleReportItem]: start_date = datetime.combine(s, time()) + timedelta( minutes=settings.NEW_DAY_OFFSET_MINUTES - settings.TIMEZONE_OFFSET_MINUTES ) finish_date = datetime.combine(f, time()) + timedelta( days=1, minutes=settings.NEW_DAY_OFFSET_MINUTES - settings.TIMEZONE_OFFSET_MINUTES ) list_ = db.execute( select(SettleOption.name, func.sum(Settlement.amount)) .join(Voucher.settlements) .join(Settlement.settle_option) .where(Voucher.date >= start_date, Voucher.date <= finish_date) .group_by(SettleOption.name) .order_by(SettleOption.name) ).all() total = 0 info = [] for gt, am in list_: total += am info.append(SaleReportItem(name=gt, amount=am)) return info + [SaleReportItem(name="Total", amount=total)] @router.get("/print", response_model=bool) def print_report( start_date: date = Depends(report_start_date), finish_date: date = Depends(report_finish_date), device_id: uuid.UUID = Cookie(None), user: UserToken = Security(get_user, scopes=["sale-report"]), ) -> bool: check_audit_permission(start_date, user.permissions) with SessionFuture() as db: report = SaleReport( startDate=start_date, finishDate=finish_date, amounts=( get_sale(start_date, finish_date, db) + [SaleReportItem(name="--", amount=0)] + get_settlements(start_date, finish_date, db) + [SaleReportItem(name="--", amount=0)] + [SaleReportItem(name=i.name, amount=i.amount) for i in get_tax(start_date, finish_date, db)] ), user=UserLink(id=user.id_, name=user.name), ) print_sale_report(report, device_id, db) return True