Files
brewman/brewman/routers/reports/stock_movement.py
T

136 lines
4.3 KiB
Python

import datetime
from fastapi import APIRouter, Depends, Security, Request
from sqlalchemy.orm import Session
from sqlalchemy.sql.expression import func
from ...schemas.auth import UserToken
from ...core.security import get_current_active_user as get_user
from ...db.session import SessionLocal
from brewman.models.master import Product, CostCentre
from brewman.models.voucher import Voucher, Journal, VoucherType, Inventory
from ...core.session import (
set_period,
get_start_date,
get_finish_date,
)
router = APIRouter()
# Dependency
def get_db() -> Session:
try:
db = SessionLocal()
yield db
finally:
db.close()
@router.get("")
def report_blank(
request: Request,
user: UserToken = Security(get_user, scopes=["stock-movement"]),
):
return {
"startDate": get_start_date(request.session),
"finishDate": get_finish_date(request.session),
"body": [],
}
@router.get("/{start}/{finish}")
def report_data(
start: str,
finish: str,
request: Request,
db: Session = Depends(get_db),
user: UserToken = Security(get_user, scopes=["stock-movement"]),
):
body = build_stock_movement(start, finish, db)
set_period(start, finish, request.session)
return {"startDate": start, "finishDate": finish, "body": body}
def build_stock_movement(start_date, finish_date, db):
start_date = datetime.datetime.strptime(start_date, "%d-%b-%Y")
finish_date = datetime.datetime.strptime(finish_date, "%d-%b-%Y")
dict_ = {}
quantity_sum = func.sum(Journal.debit * Inventory.quantity).label("quantity")
openings = (
db.query(Product, quantity_sum)
.join(Product.inventories)
.join(Inventory.voucher)
.join(Voucher.journals)
.filter(Voucher.date < start_date)
.filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase())
.group_by(Product)
.all()
)
for product, quantity in openings:
dict_[product.id] = {
"id": product.id,
"name": product.full_name,
"group": product.product_group.name,
"opening": quantity,
}
purchases = (
db.query(Product, quantity_sum)
.join(Product.inventories)
.join(Inventory.voucher)
.join(Voucher.journals)
.filter(Voucher.date >= start_date)
.filter(Voucher.date <= finish_date)
.filter(Voucher.type != VoucherType.by_name("Issue").id)
.filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase())
.group_by(Product)
.all()
)
for product, quantity in purchases:
if product.id in dict_:
dict_[product.id]["purchase"] = quantity
else:
dict_[product.id] = {
"id": product.id,
"name": product.full_name,
"group": product.product_group.name,
"purchase": quantity,
}
issues = (
db.query(Product, quantity_sum)
.join(Product.inventories)
.join(Inventory.voucher)
.join(Voucher.journals)
.filter(Voucher.date >= start_date)
.filter(Voucher.date <= finish_date)
.filter(Voucher.type == VoucherType.by_name("Issue").id)
.filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase())
.group_by(Product)
.all()
)
for product, quantity in issues:
if product.id in dict_:
dict_[product.id]["issue"] = quantity * -1
else:
dict_[product.id] = {
"id": product.id,
"name": product.full_name,
"group": product.product_group.name,
"issue": quantity * -1,
}
list_ = [value for key, value in dict_.items()]
list_ = sorted(list_, key=lambda x: x["name"].lower())
list_ = sorted(list_, key=lambda x: x["group"].lower())
for i in range(len(list_), 0, -1):
item = list_[i - 1]
opening = item["opening"] if "opening" in item else 0
purchase = item["purchase"] if "purchase" in item else 0
issue = item["issue"] if "issue" in item else 0
closing = opening + purchase - issue
if opening == 0 and purchase == 0 and issue == 0:
list_.remove(item)
else:
item["closing"] = closing
return list_