brewman/brewman/brewman/routers/reports/ledger.py

147 lines
4.4 KiB
Python

import datetime
import uuid
import brewman.schemas.reports as schemas
from fastapi import APIRouter, Depends, Request, Security
from sqlalchemy.orm import Session, joinedload_all
from sqlalchemy.sql.expression import func
from ...core.security import get_current_active_user as get_user
from ...core.session import get_finish_date, get_start_date, set_period
from ...db.session import SessionLocal
from ...models.master import AccountBase
from ...models.voucher import Journal, Voucher, VoucherType
from ...schemas.auth import UserToken
router = APIRouter()
# Dependency
def get_db() -> Session:
try:
db = SessionLocal()
yield db
finally:
db.close()
@router.get("", response_model=schemas.Ledger)
def show_blank(
request: Request,
user: UserToken = Security(get_user, scopes=["ledger"]),
):
return {
"startDate": get_start_date(request.session),
"finishDate": get_finish_date(request.session),
"account": None,
"body": [],
}
@router.get("/{id_}", response_model=schemas.Ledger)
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=["ledger"]),
):
account = db.query(AccountBase).filter(AccountBase.id == id_).first()
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)
body = build_report(account.id, start_date, finish_date, db)
set_period(start_date, finish_date, request.session)
return {
"startDate": start_date,
"finishDate": finish_date,
"account": {"id": account.id, "name": account.name},
"body": body,
}
def build_report(account_id, start_date, finish_date, db):
body = []
opening = opening_balance(account_id, start_date, db)
body.append(opening)
query = (
db.query(Voucher)
.options(joinedload_all(Voucher.journals, Journal.account, innerjoin=True))
.filter(Voucher.journals.any(Journal.account_id == account_id))
.filter(Voucher.date >= datetime.datetime.strptime(start_date, "%d-%b-%Y"))
.filter(Voucher.date <= datetime.datetime.strptime(finish_date, "%d-%b-%Y"))
.filter(Voucher.type != VoucherType.by_name("Issue").id)
.order_by(Voucher.date)
.order_by(Voucher.last_edit_date)
.all()
)
for voucher in query:
debit = 0
credit = 0
journal_debit = 0
name = ""
for journal in voucher.journals:
if journal.account_id == account_id:
journal_debit = journal.debit
if journal.debit == 1:
debit = journal.amount
credit = 0
else:
credit = journal.amount
debit = 0
for journal in voucher.journals:
if journal.debit != journal_debit:
name += "{0} / ".format(journal.account.name)
name = name[:-3]
body.append(
{
"id": voucher.id,
"date": voucher.date.strftime("%d-%b-%Y"),
"name": name,
"url": [
"/",
VoucherType.by_id(voucher.type).name.replace(" ", "-").lower(),
str(voucher.id),
],
"type": VoucherType.by_id(voucher.type).name,
"narration": voucher.narration,
"debit": debit,
"credit": credit,
"posted": voucher.posted,
}
)
return body
def opening_balance(account_id, start_date, db):
opening = (
db.query(func.sum(Journal.amount * Journal.debit))
.join(Journal.voucher)
.filter(Voucher.date < datetime.datetime.strptime(start_date, "%d-%b-%Y"))
.filter(Voucher.type != VoucherType.by_name("Issue").id)
.filter(Journal.account_id == account_id)
.scalar()
)
opening = 0 if opening is None else opening
if opening < 0:
credit = opening * -1
debit = 0
else:
debit = opening
credit = 0
return {
"date": start_date,
"id": None,
"name": "Opening Balance",
"type": "Opening Balance",
"url": [],
"narration": "",
"debit": debit,
"credit": credit,
"posted": True,
}