Fix: Errors raised were not HTTP Errors, but were value errors. This raised 500 errors on the front end without valid details.
v7.4.0
This commit is contained in:
parent
cfeef1795d
commit
4e05131b41
@ -145,7 +145,9 @@ def update_route(
|
|||||||
days_in_month = dt.day
|
days_in_month = dt.day
|
||||||
item: Voucher = update(id_, data, user, db)
|
item: Voucher = update(id_, data, user, db)
|
||||||
if dt != item.date:
|
if dt != item.date:
|
||||||
raise ValueError("Date Cannot be changed for Employee Benefit voucher!")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_423_LOCKED, detail="Date Cannot be changed for Employee Benefit voucher!",
|
||||||
|
)
|
||||||
exp, total = update_employee_benefits(item, data.employee_benefits, days_in_month, db)
|
exp, total = update_employee_benefits(item, data.employee_benefits, days_in_month, db)
|
||||||
update_journals(item, exp, total)
|
update_journals(item, exp, total)
|
||||||
# journals_valid(voucher)
|
# journals_valid(voucher)
|
||||||
|
@ -1,38 +1,66 @@
|
|||||||
import csv
|
import csv
|
||||||
from datetime import datetime, date, timedelta, time
|
|
||||||
import uuid
|
import uuid
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
from datetime import datetime, date, time, timedelta
|
||||||
|
from fastapi import (
|
||||||
|
APIRouter,
|
||||||
|
HTTPException,
|
||||||
|
status,
|
||||||
|
Depends,
|
||||||
|
File,
|
||||||
|
UploadFile,
|
||||||
|
)
|
||||||
from sqlalchemy import bindparam, select, exists, and_
|
from sqlalchemy import bindparam, select, exists, and_
|
||||||
from sqlalchemy.dialects.postgresql import insert as pg_insert
|
from sqlalchemy.dialects.postgresql import insert as pg_insert
|
||||||
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from brewman.models.master import Employee
|
from ..schemas.auth import UserToken
|
||||||
from brewman.models.voucher import Fingerprint
|
from ..core.security import get_current_active_user as get_user
|
||||||
from brewman.routers import get_lock_info
|
from ..db.session import SessionLocal
|
||||||
|
from ..models.master import Employee
|
||||||
from fastapi import APIRouter
|
from ..models.voucher import Fingerprint
|
||||||
|
from ..routers import get_lock_info
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
@router.post("/") # "Authenticated"
|
# Dependency
|
||||||
def upload_prints(request):
|
def get_db() -> Session:
|
||||||
fingerprints_file = request.POST["uploadedFile"].file
|
try:
|
||||||
start, finish = get_lock_info(request.dbsession)
|
db = SessionLocal()
|
||||||
|
yield db
|
||||||
|
finally:
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("")
|
||||||
|
def upload_prints(
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
fingerprints: UploadFile = File(None),
|
||||||
|
user: UserToken = Depends(get_user)
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
start, finish = get_lock_info(db)
|
||||||
employees = {}
|
employees = {}
|
||||||
for id_, code in request.dbsession.query(Employee.id, Employee.code).all():
|
for id_, code in db.query(Employee.id, Employee.code).all():
|
||||||
employees[code] = id_
|
employees[code] = id_
|
||||||
file_data = read_file(fingerprints_file)
|
file_data = read_file(fingerprints)
|
||||||
prints = [d for d in fp(file_data, employees) if start <= d["date"] <= finish]
|
prints = [d for d in fp(file_data, employees) if start <= d["date"] <= finish]
|
||||||
paged_data = [prints[i: i + 100] for i in range(0, len(prints), 100)]
|
paged_data = [prints[i: i + 100] for i in range(0, len(prints), 100)]
|
||||||
for i, page in enumerate(paged_data):
|
for i, page in enumerate(paged_data):
|
||||||
print("Processing page ", i, " of ", len(paged_data))
|
print(f"Processing page {i} of {len(paged_data)}")
|
||||||
request.dbsession.execute(get_query(9.4), page)
|
db.execute(get_query(9.4), page)
|
||||||
|
db.commit()
|
||||||
mark_changed(request.dbsession)
|
|
||||||
transaction.commit()
|
|
||||||
return {}
|
return {}
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
db.rollback()
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e),
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
db.rollback()
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
def get_query(version):
|
def get_query(version):
|
||||||
@ -55,7 +83,7 @@ def get_query(version):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def read_file(input_file):
|
def read_file(input_file: UploadFile):
|
||||||
input_file.seek(0)
|
input_file.seek(0)
|
||||||
output = bytearray()
|
output = bytearray()
|
||||||
while 1:
|
while 1:
|
||||||
|
@ -257,7 +257,11 @@ def check_if_employees_changed(
|
|||||||
)
|
)
|
||||||
if voucher is None:
|
if voucher is None:
|
||||||
if len(json ^ db) != 0:
|
if len(json ^ db) != 0:
|
||||||
raise ValueError("Employee missing in json data")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="Employee missing in json data",
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
if len(json ^ db) != 0 or len(db ^ voucher) != 0:
|
if len(json ^ db) != 0 or len(db ^ voucher) != 0:
|
||||||
raise ValueError("Employee missing in json data")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="Employee missing in json data",
|
||||||
|
)
|
||||||
|
@ -158,13 +158,10 @@ def get_id(
|
|||||||
try:
|
try:
|
||||||
item: Voucher = db.query(Voucher).filter(Voucher.id == id_).first()
|
item: Voucher = db.query(Voucher).filter(Voucher.id == id_).first()
|
||||||
if item is None:
|
if item is None:
|
||||||
raise ValueError("Voucher not found")
|
|
||||||
return voucher_info(item, db)
|
|
||||||
except ValueError as e:
|
|
||||||
db.rollback()
|
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_404_NOT_FOUND, detail=str(e),
|
status_code=status.HTTP_404_NOT_FOUND, detail="Voucher not found",
|
||||||
)
|
)
|
||||||
|
return voucher_info(item, db)
|
||||||
except SQLAlchemyError as e:
|
except SQLAlchemyError as e:
|
||||||
db.rollback()
|
db.rollback()
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
@ -88,9 +88,15 @@ def save_inventories(voucher: Voucher, inventories: List[schema_in.Inventory], d
|
|||||||
batch = db.query(Batch).filter(Batch.id == item.batch.id_).first()
|
batch = db.query(Batch).filter(Batch.id == item.batch.id_).first()
|
||||||
|
|
||||||
if item.quantity > batch.quantity_remaining:
|
if item.quantity > batch.quantity_remaining:
|
||||||
raise ValueError(f"Maximum quantity is {batch.quantity_remaining}.")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||||
|
detail=f"Maximum quantity is {batch.quantity_remaining}.",
|
||||||
|
)
|
||||||
if batch.name > voucher.date:
|
if batch.name > voucher.date:
|
||||||
raise ValueError(f"Return date cannot be before {batch.product.name.strftime('%d-%b-%Y')}")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||||
|
detail=f"Return date cannot be before {batch.product.name.strftime('%d-%b-%Y')}",
|
||||||
|
)
|
||||||
|
|
||||||
batch.quantity_remaining -= item.quantity
|
batch.quantity_remaining -= item.quantity
|
||||||
|
|
||||||
@ -187,7 +193,10 @@ def update_inventory(voucher: Voucher, new_inventories: List[schema_in.Inventory
|
|||||||
detail=f"{old_quantity + quantity_remaining} is the maximum for {item.product.full_name}.",
|
detail=f"{old_quantity + quantity_remaining} is the maximum for {item.product.full_name}.",
|
||||||
)
|
)
|
||||||
if item.batch.name > voucher.date:
|
if item.batch.name > voucher.date:
|
||||||
raise ValueError(f"Voucher cannot be before {item.product.name.strftime('%d-%b-%Y')}")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||||
|
detail=f"Voucher cannot be before {item.product.name.strftime('%d-%b-%Y')}",
|
||||||
|
)
|
||||||
item.batch.quantity_remaining -= new_inventory.quantity - old_quantity
|
item.batch.quantity_remaining -= new_inventory.quantity - old_quantity
|
||||||
item.quantity = new_inventory.quantity
|
item.quantity = new_inventory.quantity
|
||||||
new_inventories.remove(new_inventory)
|
new_inventories.remove(new_inventory)
|
||||||
|
@ -3,7 +3,9 @@ import uuid
|
|||||||
from fastapi import (
|
from fastapi import (
|
||||||
APIRouter,
|
APIRouter,
|
||||||
Depends,
|
Depends,
|
||||||
|
status,
|
||||||
Security,
|
Security,
|
||||||
|
HTTPException,
|
||||||
)
|
)
|
||||||
from sqlalchemy import func
|
from sqlalchemy import func
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
@ -37,14 +39,19 @@ def rebase(
|
|||||||
product: Product = db.query(Product).filter(Product.id == id_).first()
|
product: Product = db.query(Product).filter(Product.id == id_).first()
|
||||||
|
|
||||||
if item.reset_date > item.stock_date:
|
if item.reset_date > item.stock_date:
|
||||||
raise ValueError("Reset cannot be after the stock date")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="Reset cannot be after the stock date",
|
||||||
|
)
|
||||||
|
|
||||||
change = round(item.quantity, 2) - get_closing_stock(product, item.stock_date, db=db)
|
change = round(item.quantity, 2) - get_closing_stock(product, item.stock_date, db=db)
|
||||||
if change == 0:
|
if change == 0:
|
||||||
return {"No Change Needed"}
|
return {"No Change Needed"}
|
||||||
final = get_closing_stock(product, db=db)
|
final = get_closing_stock(product, db=db)
|
||||||
if final + change < 0:
|
if final + change < 0:
|
||||||
raise ValueError("Current Quantity will get negative. Cannot proceed")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||||
|
detail="Current Quantity will get negative. Cannot proceed",
|
||||||
|
)
|
||||||
|
|
||||||
batch = get_last_batch(product, db)
|
batch = get_last_batch(product, db)
|
||||||
set_batches(batch, final + change, db)
|
set_batches(batch, final + change, db)
|
||||||
@ -72,7 +79,10 @@ def get_closing_stock(product, finish_date=None, db=None):
|
|||||||
def get_last_batch(product, db):
|
def get_last_batch(product, db):
|
||||||
batch = db.query(Batch).filter(Batch.product_id == product.id).order_by(Batch.name.desc()).first()
|
batch = db.query(Batch).filter(Batch.product_id == product.id).order_by(Batch.name.desc()).first()
|
||||||
if batch is None:
|
if batch is None:
|
||||||
raise ValueError("Details for the product exist. Just add a purchase entry")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||||
|
detail="Details for the product exist. Just add a purchase entry",
|
||||||
|
)
|
||||||
return batch
|
return batch
|
||||||
|
|
||||||
|
|
||||||
|
@ -118,9 +118,10 @@ def delete_voucher(
|
|||||||
item.batch.quantity_remaining += item.quantity
|
item.batch.quantity_remaining += item.quantity
|
||||||
else:
|
else:
|
||||||
for item in voucher.inventories:
|
for item in voucher.inventories:
|
||||||
if item.batch.quantity_remaining < item.batch.quantity_remaining:
|
if item.batch.quantity_remaining < item.quantity:
|
||||||
raise ValueError(
|
raise HTTPException(
|
||||||
f"Quantity remaining for {item.product.name} is less than issued, hence cannot be deleted"
|
status_code=status.HTTP_423_LOCKED,
|
||||||
|
detail=f"Only {item.batch.quantity_remaining} of {item.product.name} remaining.\n So it cannot be deleted",
|
||||||
)
|
)
|
||||||
item.batch.quantity_remaining -= item.quantity
|
item.batch.quantity_remaining -= item.quantity
|
||||||
elif voucher.type == VoucherType.by_name("Purchase").id:
|
elif voucher.type == VoucherType.by_name("Purchase").id:
|
||||||
@ -132,7 +133,10 @@ def delete_voucher(
|
|||||||
.scalar()
|
.scalar()
|
||||||
)
|
)
|
||||||
if uses > 0:
|
if uses > 0:
|
||||||
raise ValueError(f"{item.product.name} has been issued and cannot be deleted")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_423_LOCKED,
|
||||||
|
detail=f"{item.product.name} has been issued and cannot be deleted",
|
||||||
|
)
|
||||||
batches_to_delete.append(item.batch)
|
batches_to_delete.append(item.batch)
|
||||||
elif voucher.type == VoucherType.by_name("Purchase Return").id:
|
elif voucher.type == VoucherType.by_name("Purchase Return").id:
|
||||||
for item in voucher.inventories:
|
for item in voucher.inventories:
|
||||||
@ -261,10 +265,14 @@ def voucher_info(voucher, db):
|
|||||||
|
|
||||||
def blank_voucher(info, db):
|
def blank_voucher(info, db):
|
||||||
if "type" not in info:
|
if "type" not in info:
|
||||||
raise ValueError("Voucher Type is null")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Voucher Type is null",
|
||||||
|
)
|
||||||
type_ = info["type"]
|
type_ = info["type"]
|
||||||
if "date" not in info:
|
if "date" not in info:
|
||||||
raise ValueError("Date cannot be null")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail=f"Date cannot be null",
|
||||||
|
)
|
||||||
json_voucher = {
|
json_voucher = {
|
||||||
"type": type_,
|
"type": type_,
|
||||||
"date": info["date"],
|
"date": info["date"],
|
||||||
@ -314,7 +322,9 @@ def blank_voucher(info, db):
|
|||||||
elif type_ == "Incentive":
|
elif type_ == "Incentive":
|
||||||
json_voucher["incentives"], json_voucher["incentive"] = incentive_employees(info["date"], db)
|
json_voucher["incentives"], json_voucher["incentive"] = incentive_employees(info["date"], db)
|
||||||
else:
|
else:
|
||||||
raise ValueError(f'Voucher of type "{type_}" does not exist.')
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail=f'Voucher of type "{type_}" does not exist.',
|
||||||
|
)
|
||||||
json_voucher["files"] = []
|
json_voucher["files"] = []
|
||||||
return json_voucher
|
return json_voucher
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "overlord",
|
"name": "overlord",
|
||||||
"version": "7.3.0",
|
"version": "7.4.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"ng": "ng",
|
"ng": "ng",
|
||||||
"prettier": "prettier",
|
"prettier": "prettier",
|
||||||
|
2
setup.py
2
setup.py
@ -11,7 +11,7 @@ with open(os.path.join(here, 'requirements.txt'), "r") as r:
|
|||||||
requires = r.read().splitlines()
|
requires = r.read().splitlines()
|
||||||
|
|
||||||
setup(name='brewman',
|
setup(name='brewman',
|
||||||
version='7.3.0',
|
version='7.4.0',
|
||||||
description='brewman',
|
description='brewman',
|
||||||
long_description=README + '\n\n' + CHANGES,
|
long_description=README + '\n\n' + CHANGES,
|
||||||
classifiers=[
|
classifiers=[
|
||||||
|
Loading…
Reference in New Issue
Block a user