brewman/brewman/brewman/routers/reports/profit_loss.py

151 lines
4.5 KiB
Python
Raw Normal View History

2020-10-07 15:18:43 +00:00
from datetime import date, datetime
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
2020-10-07 15:18:43 +00:00
from sqlalchemy.sql.expression import desc, 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 AccountBase, AccountType
from ...models.voucher import Journal, Voucher, VoucherType
from ...routers.reports.closing_stock import get_closing_stock, get_opening_stock
from ...schemas.auth import UserToken
router = APIRouter()
# Dependency
def get_db() -> Session:
try:
db = SessionLocal()
yield db
finally:
db.close()
2020-05-14 08:19:40 +00:00
@router.get("", response_model=schemas.ProfitLoss)
def report_blank(
2020-10-07 15:18:43 +00:00
request: Request,
user: UserToken = Security(get_user, scopes=["profit-&-loss"]),
):
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 08:19:40 +00:00
"footer": None,
}
2020-05-14 08:19:40 +00:00
@router.get("/{start}/{finish}", response_model=schemas.ProfitLoss)
def report_data(
start: str,
finish: str,
request: Request,
db: Session = Depends(get_db),
user: UserToken = Security(get_user, scopes=["profit-&-loss"]),
):
2020-10-07 16:59:24 +00:00
body, footer = build_profit_loss(
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,
"footer": footer,
}
2020-05-14 08:19:40 +00:00
def build_profit_loss(start_date: date, finish_date: date, db: Session):
profit_type_list = [i.id for i in AccountType.list() if i.balance_sheet == False]
report = []
groups = {}
amount_sum = func.sum(Journal.amount * Journal.debit)
query = (
db.query(AccountBase, amount_sum)
.join(Journal.voucher)
.join(Journal.account)
.filter(Voucher.date >= start_date)
.filter(Voucher.date <= finish_date)
.filter(Voucher.type != VoucherType.by_name("Issue").id)
.filter(AccountBase.type.in_(profit_type_list))
.group_by(AccountBase)
.order_by(AccountBase.type)
.order_by(desc(func.abs(amount_sum)))
.all()
)
# Get opening / closing stock
opening_stock = get_opening_stock(start_date, db)
closing_stock = get_closing_stock(finish_date, db)
total_amount = (opening_stock - closing_stock) * -1
2020-10-07 16:59:24 +00:00
report.append(
{"name": "Opening Stock", "amount": opening_stock * -1, "order": 200001}
)
2020-05-14 08:19:40 +00:00
report.append({"name": "Closing Stock", "amount": closing_stock, "order": 290000})
purchase_group = AccountType.by_id(2)
groups[purchase_group.id] = {
"group": purchase_group.name,
"total": total_amount,
"order": purchase_group.order,
}
counter = 0
for account, amount in query:
# Add Items
amount *= -1
account_type = AccountType.by_id(account.type)
total_amount += amount
if amount != 0:
2020-05-14 08:19:40 +00:00
counter += 10
report.append(
2020-10-07 15:18:43 +00:00
{
"name": account.name,
"amount": amount,
"order": account_type.order + counter,
}
)
if account_type.id in groups:
groups[account_type.id]["total"] += amount
else:
groups[account_type.id] = {
"group": account_type.name,
"total": amount,
"order": account_type.order,
}
# Add Subtotals
for item in groups.values():
report.append(item)
# Add Net
footer = {
"group": "Net Profit" if total_amount > 0 else "Net Loss",
"total": total_amount,
2020-05-14 08:19:40 +00:00
"order": 1000000,
}
return sorted(report, key=lambda d: d["order"]), footer
def get_accumulated_profit(finish_date, db):
type_list = [i.id for i in AccountType.list() if i.balance_sheet is False]
accumulated_profit = (
db.query(func.sum(Journal.amount * Journal.debit))
.join(Journal.voucher)
.join(Journal.account)
.filter(Voucher.date <= finish_date)
.filter(Voucher.type != VoucherType.by_name("Issue").id)
.filter(AccountBase.type.in_(type_list))
.scalar()
)
return 0 if accumulated_profit is None else accumulated_profit