brewman/brewman/brewman/routers/reports/product_ledger.py

184 lines
5.6 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, joinedload
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 08:08:13 +00:00
@router.get("", response_model=schemas.ProductLedger)
def show_blank(
2020-10-07 15:18:43 +00:00
request: Request,
user: UserToken = Security(get_user, scopes=["product-ledger"]),
):
return {
2020-05-12 04:25:33 +00:00
"startDate": get_start_date(request.session),
"finishDate": get_finish_date(request.session),
"product": None,
"body": [],
}
2020-05-14 08:08:13 +00:00
@router.get("/{id_}", response_model=schemas.ProductLedger)
def show_data(
id_: uuid.UUID,
request: Request,
s: str = None,
f: str = None,
db: Session = Depends(get_db),
user: UserToken = Security(get_user, scopes=["product-ledger"]),
):
product = db.query(Product).filter(Product.id == id_).first()
2020-05-12 04:25:33 +00:00
start_date = s if s is not None else get_start_date(request.session)
finish_date = f if f is not None else get_finish_date(request.session)
2020-05-14 08:08:13 +00:00
body = build_report(
2020-10-07 15:18:43 +00:00
product.id,
datetime.strptime(start_date, "%d-%b-%Y"),
datetime.strptime(finish_date, "%d-%b-%Y"),
db,
2020-05-14 08:08:13 +00:00
)
2020-05-12 04:25:33 +00:00
set_period(start_date, finish_date, request.session)
return {
"startDate": start_date,
"finishDate": finish_date,
"product": {"id": product.id, "name": product.name},
"body": body,
}
2020-10-07 16:59:24 +00:00
def build_report(
product_id: uuid.UUID, start_date: date, finish_date: date, db: Session
):
body = []
2020-10-07 16:59:24 +00:00
running_total_q, running_total_a, opening = opening_balance(
product_id, start_date, db
)
body.append(opening)
query = (
db.query(Voucher, Inventory, Journal)
2020-10-07 15:18:43 +00:00
.options(
joinedload(Journal.account, innerjoin=True),
joinedload(Journal.cost_centre, innerjoin=True),
)
.filter(Voucher.id == Inventory.voucher_id)
.filter(Voucher.id == Journal.voucher_id)
.filter(Inventory.product_id == product_id)
.filter(Journal.cost_centre_id != CostCentre.cost_centre_purchase())
2020-05-14 08:08:13 +00:00
.filter(Voucher.date >= start_date)
.filter(Voucher.date <= finish_date)
.order_by(Voucher.date)
.order_by(Voucher.last_edit_date)
.all()
)
for row in query:
journal_debit = row.Journal.debit * -1
name = (
row.Journal.cost_centre.name
if row.Voucher.type == VoucherType.by_name("Issue").id
else row.Journal.account.name
)
2020-05-14 08:08:13 +00:00
debit_q = row.Inventory.quantity if journal_debit == 1 else None
debit_a = row.Inventory.amount if journal_debit == 1 else None
credit_q = row.Inventory.quantity if journal_debit != 1 else None
credit_a = row.Inventory.amount if journal_debit != 1 else None
running_total_q += row.Inventory.quantity * journal_debit
running_total_a += row.Inventory.amount * journal_debit
body.append(
{
"id": row.Voucher.id,
"date": row.Voucher.date.strftime("%d-%b-%Y"),
"name": name,
2020-10-07 15:18:43 +00:00
"url": [
"/",
VoucherType.by_id(row.Voucher.type).name.replace(" ", "-").lower(),
str(row.Voucher.id),
],
"type": VoucherType.by_id(row.Voucher.type).name,
"narration": row.Voucher.narration,
2020-10-07 16:59:24 +00:00
"posted": row.Voucher.posted
or VoucherType.by_id(row.Voucher.type).name == "Issue",
"debitQuantity": debit_q,
"debitAmount": debit_a,
"creditQuantity": credit_q,
"creditAmount": credit_a,
"runningQuantity": running_total_q,
"runningAmount": running_total_a,
}
)
return body
2020-05-14 08:08:13 +00:00
def opening_balance(product_id: uuid.UUID, start_date: date, db: Session):
quantity, amount = (
2020-10-07 15:18:43 +00:00
db.query(
func.sum(Inventory.quantity * Journal.debit),
func.sum(Inventory.amount * Journal.debit),
)
.join(Inventory.voucher)
.join(Voucher.journals)
.filter(Voucher.id == Inventory.voucher_id)
.filter(Voucher.id == Journal.voucher_id)
.filter(Inventory.product_id == product_id)
.filter(Journal.cost_centre_id == CostCentre.cost_centre_purchase())
2020-05-14 08:08:13 +00:00
.filter(Voucher.date < start_date)
.one()
)
if quantity and quantity > 0:
debit_quantity = quantity
debit_amount = amount
else:
2020-05-14 08:08:13 +00:00
debit_quantity = None
debit_amount = None
if quantity is None:
quantity = 0
amount = 0
return (
quantity,
amount,
{
2020-05-14 08:08:13 +00:00
"id": None,
"date": start_date.strftime("%d-%b-%Y"),
"name": "Opening Balance",
2020-05-14 08:08:13 +00:00
"url": [],
"type": "Opening Balance",
"narration": "",
"posted": True,
"debitQuantity": debit_quantity,
"debitAmount": debit_amount,
"creditQuantity": 0,
"creditAmount": 0,
"runningQuantity": quantity,
"runningAmount": amount,
},
)