brewman/brewman/brewman/routers/reports/stock_movement.py

145 lines
4.8 KiB
Python
Raw Normal View History

2020-10-07 15:18:43 +00:00
from datetime import date, datetime
2020-05-14 10:39:31 +00:00
from decimal import Decimal
2020-10-07 15:18:43 +00:00
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
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 CostCentre, Product
from ...models.voucher import Inventory, Journal, Voucher, VoucherType
from ...schemas.auth import UserToken
router = APIRouter()
# Dependency
def get_db() -> Session:
try:
db = SessionLocal()
yield db
finally:
db.close()
2020-05-14 10:39:31 +00:00
@router.get("", response_model=schemas.StockMovement)
def report_blank(
2020-10-07 15:18:43 +00:00
request: Request,
user: UserToken = Security(get_user, scopes=["stock-movement"]),
):
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:39:31 +00:00
@router.get("/{start}/{finish}", response_model=schemas.StockMovement)
def report_data(
start: str,
finish: str,
request: Request,
db: Session = Depends(get_db),
user: UserToken = Security(get_user, scopes=["stock-movement"]),
):
2020-10-07 16:59:24 +00:00
body = build_stock_movement(
datetime.strptime(start, "%d-%b-%Y"), datetime.strptime(finish, "%d-%b-%Y"), db
)
2020-05-12 04:25:33 +00:00
set_period(start, finish, request.session)
return {"startDate": start, "finishDate": finish, "body": body}
2020-05-14 10:39:31 +00:00
def build_stock_movement(start_date: date, finish_date: date, db: Session):
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,
2020-05-14 10:39:31 +00:00
"opening": Decimal(round(quantity, 2)),
2020-05-31 09:11:11 +00:00
"url": ["/", "product-ledger", str(product.id)],
}
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_:
2020-05-14 10:39:31 +00:00
dict_[product.id]["purchase"] = Decimal(round(quantity, 2))
else:
dict_[product.id] = {
"id": product.id,
"name": product.full_name,
"group": product.product_group.name,
2020-05-14 10:39:31 +00:00
"purchase": Decimal(round(quantity, 2)),
2020-05-31 09:11:11 +00:00
"url": ["/", "product-ledger", str(product.id)],
}
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_:
2020-05-14 10:39:31 +00:00
dict_[product.id]["issue"] = Decimal(round(quantity * -1, 2))
else:
dict_[product.id] = {
"id": product.id,
"name": product.full_name,
"group": product.product_group.name,
2020-05-14 10:39:31 +00:00
"issue": Decimal(round(quantity * -1, 2)),
2020-05-31 09:11:11 +00:00
"url": ["/", "product-ledger", str(product.id)],
}
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]
2020-05-14 10:39:31 +00:00
if "opening" not in item:
item["opening"] = 0
opening = item["opening"]
if "purchase" not in item:
item["purchase"] = 0
purchase = item["purchase"]
if "issue" not in item:
item["issue"] = 0
issue = item["issue"]
closing = round(opening + purchase - issue, 2)
if opening == 0 and purchase == 0 and issue == 0:
list_.remove(item)
else:
item["closing"] = closing
return list_