from datetime import date, datetime import brewman.schemas.reports as schemas from fastapi import APIRouter, Depends, Request, Security from sqlalchemy.orm import Session from sqlalchemy.sql.expression import func from ...core.security import get_current_active_user as get_user from ...core.session import get_finish_date, get_start_date, set_period from ...db.session import SessionLocal from ...models.master import CostCentre, Product from ...models.voucher import Inventory, Journal, Voucher from ...schemas.auth import UserToken router = APIRouter() # Dependency def get_db() -> Session: try: db = SessionLocal() yield db finally: db.close() @router.get("", response_model=schemas.ClosingStock) def report_blank( request: Request, user: UserToken = Security(get_user, scopes=["closing-stock"]), ): return {"date": get_finish_date(request.session), "body": []} @router.get("/{date_}", response_model=schemas.ClosingStock) def report_data( date_: str, request: Request, db: Session = Depends(get_db), user: UserToken = Security(get_user, scopes=["closing-stock"]), ): set_period(get_start_date(request.session), date_, request.session) return { "date": date_, "body": build_report(datetime.strptime(date_, "%d-%b-%Y").date(), db), } def build_report(date_: date, db: Session): amount_sum = func.sum( Journal.debit * Inventory.quantity * Inventory.rate * (1 + Inventory.tax) ).label("amount") quantity_sum = func.sum(Journal.debit * Inventory.quantity).label("quantity") query = ( db.query(Product, quantity_sum, amount_sum) .join(Product.inventories) .join(Inventory.voucher) .join(Voucher.journals) .filter(Voucher.date <= date_) .filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase()) .group_by(Product) .order_by(amount_sum.desc()) .all() ) body = [] for product, quantity, amount in query: if quantity != 0 and amount != 0: body.append( { "product": product.full_name, "group": product.product_group.name, "quantity": quantity, "amount": amount, } ) return body def get_opening_stock(date_: date, db: Session): opening_stock = ( db.query( func.sum( Inventory.quantity * Inventory.rate * (1 + Inventory.tax) * Journal.debit ) ) .join(Journal.voucher) .join(Journal.account) .join(Voucher.inventories) .filter(Voucher.date < date_) .filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase()) .scalar() ) return 0 if opening_stock is None else opening_stock def get_closing_stock(date_, db: Session): closing_stock = ( db.query( func.sum( Inventory.quantity * Inventory.rate * (1 + Inventory.tax) * Journal.debit ) ) .join(Journal.voucher) .join(Journal.account) .join(Voucher.inventories) .filter(Voucher.date <= date_) .filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase()) .scalar() ) return 0 if closing_stock is None else closing_stock