Files
brewman/brewman/routers/voucher/purchase.py
T
tanshu a0f27fe364 Attendance and Employee Attendance done!!
Journal Done!!
But there is issue of validation in purchase due to lack of proper journals when getting data from the frontend.
The proposed solution is to create different schemas for various vouchers and then reexport and import them in a master schema for persisting

Also, change "Supplier" to vendor in Purchase, etc.
Also, convert all date field to date from datetime

Rename "Salary Deduction" to "Employee Benefits" across the board
2020-05-17 15:38:13 +05:30

193 lines
7.1 KiB
Python

import datetime
import uuid
from decimal import Decimal
from fastapi import HTTPException, status
from sqlalchemy import func
from brewman.models.master import Product, AccountBase
from brewman.models.operations import inventory_valid
from brewman.models.voucher import (
Voucher,
VoucherType,
Batch,
Inventory,
Journal,
DbImage,
)
def purchase_update_voucher(voucher, json, files, user, dbsession):
voucher.date = datetime.datetime.strptime(json["date"], "%d-%b-%Y")
voucher.is_starred = json["isStarred"]
voucher.narration = json["narration"].strip()
voucher.user_id = user.id
voucher.posted = False
voucher.last_edit_date = datetime.datetime.utcnow()
purchase_update_inventory(voucher, json["inventories"], dbsession)
purchase_update_journals(voucher, json["journals"], dbsession)
journals_valid(voucher)
inventory_valid(voucher)
old_files = [
uuid.UUID(f["id"]) for f in json["files"] if "id" in f and f["id"] is not None
]
images = dbsession.query(DbImage).filter(DbImage.resource_id == voucher.id).all()
for image in [i for i in images if i.id not in old_files]:
dbsession.delete(image)
for key, value in files.items():
dbsession.add(DbImage(voucher.id, "voucher", value["f"], value["t"]))
return voucher
def purchase_update_inventory(voucher, new_inventories, dbsession):
for it in range(len(voucher.inventories), 0, -1):
item = voucher.inventories[it - 1]
found = False
for j in range(len(new_inventories), 0, -1):
i = new_inventories[j - 1]
if "id" in i and i["id"] is not None and item.id == uuid.UUID(i["id"]):
product = (
dbsession.query(Product)
.filter(Product.id == uuid.UUID(i["product"]["id"]))
.first()
)
found = True
if item.product_id != product.id:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail="Product cannot be changed",
)
new_quantity = round(Decimal(i["quantity"]), 2)
old_quantity = round(Decimal(item.quantity), 2)
quantity_remaining = round(Decimal(item.batch.quantity_remaining), 2)
if new_quantity <= 0:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail=f"Quantity of {item.product.name} cannot be zero",
)
if old_quantity > new_quantity and quantity_remaining < (
old_quantity - new_quantity
):
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail=f"{old_quantity - quantity_remaining} has been issued, minimum quantity is",
)
item.batch.quantity_remaining -= old_quantity - new_quantity
item.quantity = new_quantity
rate = round(Decimal(i["rate"]), 2)
discount = round(Decimal(i["discount"]), 5)
tax = round(Decimal(i["tax"]), 5)
if voucher.date != item.batch.name:
item.batch.name = voucher.date
if voucher.date < item.batch.name:
# TODO: check for issued products which might have been in a back date
pass
item.rate = rate
item.batch.rate = rate
item.discount = discount
item.batch.discount = discount
item.tax = tax
item.batch.tax = tax
product.price = rate
new_inventories.remove(i)
# TODO: Update all references of the batch with the new rates
break
if not found:
uses = (
dbsession.query(func.count(Inventory.id))
.filter(Inventory.batch_id == item.batch.id)
.filter(Inventory.id != item.id)
.scalar()
)
if uses > 0:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail=f"{item.product.name} has been issued, it cannot be deleted",
)
else:
dbsession.delete(item.batch)
dbsession.delete(item)
voucher.inventories.remove(item)
for i in new_inventories:
product = (
dbsession.query(Product)
.filter(Product.id == uuid.UUID(i["product"]["id"]))
.first()
)
new_quantity = round(Decimal(i["quantity"]), 2)
rate = round(Decimal(i["rate"]), 2)
tax = round(Decimal(i["tax"]), 5)
discount = round(Decimal(i["discount"]), 5)
batch = Batch(
name=voucher.date,
product_id=product.id,
quantity_remaining=new_quantity,
rate=rate,
tax=tax,
discount=discount,
)
inventory = Inventory(
id=None,
product_id=product.id,
batch=batch,
quantity=new_quantity,
rate=rate,
tax=tax,
discount=discount,
)
inventory.voucher_id = voucher.id
dbsession.add(batch)
inventory.batch_id = batch.id
product.price = rate
voucher.inventories.append(inventory)
dbsession.add(inventory)
def purchase_update_journals(voucher, journals, dbsession):
other_account = [ff for ff in journals if ff["debit"] == -1]
other_account = (
dbsession.query(AccountBase)
.filter(AccountBase.id == uuid.UUID(other_account[0]["account"]["id"]))
.first()
)
journals = dict()
amount = 0
for item in voucher.inventories:
product = dbsession.query(Product).filter(Product.id == item.product_id).first()
account = product.account
amount += item.amount
if account.id in journals:
journals[account.id].amount += item.amount
else:
journals[account.id] = Journal(
debit=1,
cost_centre_id=account.cost_centre_id,
account_id=account.id,
amount=item.amount,
)
journals[other_account.id] = Journal(
debit=-1,
cost_centre_id=other_account.cost_centre_id,
account_id=other_account.id,
amount=amount,
)
for i in range(len(voucher.journals), 0, -1):
item = voucher.journals[i - 1]
if item.account_id in journals:
item.debit = journals[item.account_id].debit
item.amount = round(journals[item.account_id].amount, 2)
item.cost_centre_id = journals[item.account_id].cost_centre_id
del journals[item.account_id]
else:
dbsession.delete(item)
voucher.journals.remove(item)
for item in journals.values():
item.amount = round(item.amount, 2)
voucher.journals.append(item)
dbsession.add(item)