brewman/brewman/brewman/routers/reports/raw_material_cost.py

187 lines
5.3 KiB
Python
Raw Normal View History

import uuid
2020-10-07 15:18:43 +00:00
from datetime import date, datetime
import brewman.schemas.reports as schemas
from fastapi import APIRouter, Depends, Request, Security
from sqlalchemy.orm import Session
2020-10-07 15:18:43 +00:00
from sqlalchemy.sql.expression import case, func
from ...core.security import get_current_active_user as get_user
2020-10-07 15:18:43 +00:00
from ...core.session import get_finish_date, get_start_date, set_period
from ...db.session import SessionLocal
2020-10-07 15:18:43 +00:00
from ...models.master import AccountBase, CostCentre, Product, ProductGroup
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()
2020-05-14 10:13:20 +00:00
@router.get("", response_model=schemas.RawMaterialCost)
def report_blank(
2020-10-07 15:18:43 +00:00
request: Request,
user: UserToken = Security(get_user, scopes=["raw-material-cost"]),
):
return {
2020-05-12 04:25:33 +00:00
"startDate": get_start_date(request.session),
"finishDate": get_finish_date(request.session),
"body": [],
2020-05-14 10:13:20 +00:00
"footer": None,
}
2020-05-14 10:13:20 +00:00
@router.get("/data", response_model=schemas.RawMaterialCost)
def report_data(
request: Request,
s: str = None,
f: str = None,
db: Session = Depends(get_db),
user: UserToken = Security(get_user, scopes=["raw-material-cost"]),
):
2020-10-07 16:59:24 +00:00
body, footer = build_report(
datetime.strptime(s, "%d-%b-%Y"), datetime.strptime(f, "%d-%b-%Y"), db
)
2020-05-12 04:25:33 +00:00
set_period(s, f, request.session)
return {
"startDate": s,
"finishDate": f,
"body": body,
"footer": footer,
}
2020-05-14 10:13:20 +00:00
@router.get("/{id_}", response_model=schemas.RawMaterialCost)
def report_id(
id_: uuid.UUID,
request: Request,
s: str = None,
f: str = None,
db: Session = Depends(get_db),
user: UserToken = Security(get_user, scopes=["raw-material-cost"]),
):
2020-10-07 16:59:24 +00:00
body = build_report_id(
id_, datetime.strptime(s, "%d-%b-%Y"), datetime.strptime(f, "%d-%b-%Y"), db
)
2020-05-12 04:25:33 +00:00
set_period(s, f, request.session)
return {
"id": id_,
"startDate": s,
"finishDate": f,
"body": body,
}
2020-05-14 10:13:20 +00:00
def build_report(start_date: date, finish_date: date, db: Session):
body = []
2020-10-07 16:59:24 +00:00
sum_issue = func.sum(
case([(AccountBase.type == 2, Journal.signed_amount)], else_=0)
).label("issue")
sum_sale = func.sum(
case([(AccountBase.type == 3, Journal.signed_amount * -1)], else_=0)
).label("sale")
query = (
db.query(CostCentre, sum_issue, sum_sale)
.join(CostCentre.journals)
.join(Journal.voucher)
.join(Journal.account)
2020-05-14 10:13:20 +00:00
.filter(Voucher.date >= start_date)
.filter(Voucher.date <= finish_date)
.filter(Journal.cost_centre_id != CostCentre.cost_centre_purchase())
.filter(AccountBase.type.in_([2, 3]))
.group_by(CostCentre)
.order_by(sum_sale.desc())
.all()
)
issues = 0
sales = 0
for cost_centre, issue, sale in query:
issues += issue
sales += sale
rmc = 0 if sale == 0 else issue / sale
body.append(
{
"name": cost_centre.name,
"issue": issue,
"sale": sale,
"rmc": rmc,
2020-05-31 09:11:11 +00:00
"url": ["/", "raw-material-cost", str(cost_centre.id)],
}
)
rmc = 0 if sales == 0 else issues / sales
return body, {"name": "Total", "issue": issues, "sale": sales, "rmc": rmc}
2020-10-07 16:59:24 +00:00
def build_report_id(
cost_centre_id: uuid.UUID, start_date: date, finish_date: date, db: Session
):
sum_quantity = func.sum(Inventory.quantity * Journal.debit).label("quantity")
sum_net = func.sum(Inventory.rate * Inventory.quantity * Journal.debit).label("net")
sum_gross = func.sum(Inventory.amount * Journal.debit).label("gross")
query = (
db.query(Product, sum_quantity, sum_net, sum_gross)
.join(Product.inventories)
.join(Inventory.voucher)
.join(Voucher.journals)
.join(Product.product_group)
2020-05-14 10:13:20 +00:00
.filter(Voucher.date >= start_date)
.filter(Voucher.date <= finish_date)
.filter(Voucher.type == 3)
.filter(Journal.cost_centre_id == cost_centre_id)
.group_by(Product)
.group_by(Journal.debit)
.group_by(ProductGroup.name)
.order_by(ProductGroup.name)
.order_by(sum_net.desc())
.all()
)
groups = {}
counter = 0
list_ = []
for product, quantity, net, gross in query:
if product.product_group_id in groups:
group = groups[product.product_group_id]
group["net"] += net
group["gross"] += gross
else:
counter += 500
group = {
"group": product.product_group.name,
"net": net,
"gross": gross,
"order": counter,
"heading": True,
}
groups[product.product_group_id] = group
counter += 1
list_.append(
{
"name": product.full_name,
"quantity": quantity,
"net": net,
"gross": gross,
"order": counter,
"heading": False,
}
)
for item in groups.values():
list_.append(item)
return sorted(list_, key=lambda d: d["order"])