barker/barker/barker/routers/reports/menu_engineering_report.py

137 lines
4.7 KiB
Python
Raw Normal View History

import uuid
from datetime import date, datetime, time, timedelta
from typing import Any
from fastapi import APIRouter, Cookie, Depends, Security
from sqlalchemy import func, nulls_last, 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.menu_category import MenuCategory
from ...models.product import Product
from ...models.product_version import ProductVersion
from ...models.sale_category import SaleCategory
from ...models.voucher import Voucher
from ...models.voucher_type import VoucherType
from ...printing.product_sale_report import print_product_sale_report
from ...schemas.user_token import UserToken
from . import check_audit_permission, report_finish_date, report_start_date
router = APIRouter()
@router.get("")
def menu_engineering_report_view(
start_date: date = Depends(report_start_date),
finish_date: date = Depends(report_finish_date),
user: UserToken = Security(get_user, scopes=["product-sale-report"]),
):
check_audit_permission(start_date, user.permissions)
with SessionFuture() as db:
return {
"startDate": start_date.strftime("%d-%b-%Y"),
"finishDate": finish_date.strftime("%d-%b-%Y"),
"amounts": menu_engineering_report(start_date, finish_date, db),
}
def menu_engineering_report(s: date, f: date, db: Session):
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")
q = (
select(
SaleCategory.name,
MenuCategory.name,
ProductVersion.id,
ProductVersion.full_name,
ProductVersion.price,
func.sum(Inventory.quantity),
func.sum(Inventory.net),
)
.join(ProductVersion.sale_category)
.join(ProductVersion.menu_category)
.join(ProductVersion.product)
.join(Product.inventories, isouter=True)
.join(Inventory.kot, isouter=True)
.join(Kot.voucher, isouter=True)
.where(
or_(
Voucher.date == None, # noqa: E711
Voucher.date >= start_date,
),
or_(
Voucher.date == None, # noqa: E711
Voucher.date <= finish_date,
),
or_(
Voucher.voucher_type == None, # noqa: E711
Voucher.voucher_type == VoucherType.REGULAR_BILL,
),
or_(
ProductVersion.valid_from == None, # noqa: E711
ProductVersion.valid_from <= day,
Voucher.date == None, # noqa: E711
),
or_(
ProductVersion.valid_till == None, # noqa: E711
ProductVersion.valid_till >= day,
Voucher.date == None, # noqa: E711
),
)
.group_by(
SaleCategory.name,
MenuCategory.name,
ProductVersion.id,
ProductVersion.full_name,
)
.order_by(SaleCategory.name, nulls_last(func.sum(Inventory.net).desc()))
)
print(q)
list_ = db.execute(q).all()
info: list[Any] = []
for sc, mc, id_, name, price, quantity, amount in list_:
info.append(
{
"id": id_,
"name": name,
"price": price,
"average": round(amount / quantity) if amount and quantity else price,
"saleCategory": sc,
"menuCategory": mc,
"quantity": quantity,
"amount": amount,
}
)
return info
@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=["product-sale-report"]),
) -> bool:
check_audit_permission(start_date, user.permissions)
with SessionFuture() as db:
report = {
"userName": user.name,
"startDate": start_date.strftime("%d-%b-%Y"),
"finishDate": finish_date.strftime("%d-%b-%Y"),
"amounts": menu_engineering_report(start_date, finish_date, db),
}
print_product_sale_report(report, device_id, db)
return True