brewman/brewman/routers/reports/stock_movement.py

136 lines
4.3 KiB
Python
Raw Normal View History

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 brewman.routers.services.session import (
session_period_set,
session_period_start,
session_period_finish,
)
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": session_period_start(request.session),
"finishDate": session_period_finish(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)
session_period_set( 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_