From 4e05131b41844575faf58c7823d641fecbb749b3 Mon Sep 17 00:00:00 2001 From: tanshu Date: Wed, 7 Oct 2020 19:37:28 +0530 Subject: [PATCH] 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 --- brewman/routers/employee_benefit.py | 4 +- brewman/routers/fingerprint.py | 76 ++++++++++++++++++++--------- brewman/routers/incentive.py | 8 ++- brewman/routers/journal.py | 9 ++-- brewman/routers/purchase_return.py | 15 ++++-- brewman/routers/reset_stock.py | 16 ++++-- brewman/routers/voucher.py | 24 ++++++--- overlord/package.json | 2 +- setup.py | 2 +- 9 files changed, 108 insertions(+), 48 deletions(-) diff --git a/brewman/routers/employee_benefit.py b/brewman/routers/employee_benefit.py index b1aef138..6e1cb6e5 100644 --- a/brewman/routers/employee_benefit.py +++ b/brewman/routers/employee_benefit.py @@ -145,7 +145,9 @@ def update_route( days_in_month = dt.day item: Voucher = update(id_, data, user, db) 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) update_journals(item, exp, total) # journals_valid(voucher) diff --git a/brewman/routers/fingerprint.py b/brewman/routers/fingerprint.py index 1370a2a9..29e6f78b 100644 --- a/brewman/routers/fingerprint.py +++ b/brewman/routers/fingerprint.py @@ -1,38 +1,66 @@ import csv -from datetime import datetime, date, timedelta, time import uuid 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.dialects.postgresql import insert as pg_insert +from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.orm import Session -from brewman.models.master import Employee -from brewman.models.voucher import Fingerprint -from brewman.routers import get_lock_info - -from fastapi import APIRouter +from ..schemas.auth import UserToken +from ..core.security import get_current_active_user as get_user +from ..db.session import SessionLocal +from ..models.master import Employee +from ..models.voucher import Fingerprint +from ..routers import get_lock_info router = APIRouter() -@router.post("/") # "Authenticated" -def upload_prints(request): - fingerprints_file = request.POST["uploadedFile"].file - start, finish = get_lock_info(request.dbsession) - employees = {} - for id_, code in request.dbsession.query(Employee.id, Employee.code).all(): - employees[code] = id_ - file_data = read_file(fingerprints_file) - 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)] - for i, page in enumerate(paged_data): - print("Processing page ", i, " of ", len(paged_data)) - request.dbsession.execute(get_query(9.4), page) +# Dependency +def get_db() -> Session: + try: + db = SessionLocal() + yield db + finally: + db.close() - mark_changed(request.dbsession) - transaction.commit() - return {} + +@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 = {} + for id_, code in db.query(Employee.id, Employee.code).all(): + employees[code] = id_ + file_data = read_file(fingerprints) + 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)] + for i, page in enumerate(paged_data): + print(f"Processing page {i} of {len(paged_data)}") + db.execute(get_query(9.4), page) + db.commit() + 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): @@ -55,7 +83,7 @@ def get_query(version): ) -def read_file(input_file): +def read_file(input_file: UploadFile): input_file.seek(0) output = bytearray() while 1: diff --git a/brewman/routers/incentive.py b/brewman/routers/incentive.py index 7ac5e18d..92404ddd 100644 --- a/brewman/routers/incentive.py +++ b/brewman/routers/incentive.py @@ -257,7 +257,11 @@ def check_if_employees_changed( ) if voucher is None: 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: 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", + ) diff --git a/brewman/routers/journal.py b/brewman/routers/journal.py index f8fba246..3d3c7ca4 100644 --- a/brewman/routers/journal.py +++ b/brewman/routers/journal.py @@ -158,13 +158,10 @@ def get_id( try: item: Voucher = db.query(Voucher).filter(Voucher.id == id_).first() if item is None: - raise ValueError("Voucher not found") + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, detail="Voucher not found", + ) return voucher_info(item, db) - except ValueError as e: - db.rollback() - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, detail=str(e), - ) except SQLAlchemyError as e: db.rollback() raise HTTPException( diff --git a/brewman/routers/purchase_return.py b/brewman/routers/purchase_return.py index 9b72870c..82411e02 100644 --- a/brewman/routers/purchase_return.py +++ b/brewman/routers/purchase_return.py @@ -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() 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: - 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 @@ -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}.", ) 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.quantity = new_inventory.quantity new_inventories.remove(new_inventory) diff --git a/brewman/routers/reset_stock.py b/brewman/routers/reset_stock.py index 2beabeb2..7fc9690e 100644 --- a/brewman/routers/reset_stock.py +++ b/brewman/routers/reset_stock.py @@ -3,7 +3,9 @@ import uuid from fastapi import ( APIRouter, Depends, + status, Security, + HTTPException, ) from sqlalchemy import func from sqlalchemy.orm import Session @@ -37,14 +39,19 @@ def rebase( product: Product = db.query(Product).filter(Product.id == id_).first() 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) if change == 0: return {"No Change Needed"} final = get_closing_stock(product, db=db) 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) 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): batch = db.query(Batch).filter(Batch.product_id == product.id).order_by(Batch.name.desc()).first() 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 diff --git a/brewman/routers/voucher.py b/brewman/routers/voucher.py index 4f622769..61fb92ca 100644 --- a/brewman/routers/voucher.py +++ b/brewman/routers/voucher.py @@ -118,9 +118,10 @@ def delete_voucher( item.batch.quantity_remaining += item.quantity else: for item in voucher.inventories: - if item.batch.quantity_remaining < item.batch.quantity_remaining: - raise ValueError( - f"Quantity remaining for {item.product.name} is less than issued, hence cannot be deleted" + if item.batch.quantity_remaining < item.quantity: + raise HTTPException( + 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 elif voucher.type == VoucherType.by_name("Purchase").id: @@ -132,7 +133,10 @@ def delete_voucher( .scalar() ) 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) elif voucher.type == VoucherType.by_name("Purchase Return").id: for item in voucher.inventories: @@ -261,10 +265,14 @@ def voucher_info(voucher, db): def blank_voucher(info, db): 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"] 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 = { "type": type_, "date": info["date"], @@ -314,7 +322,9 @@ def blank_voucher(info, db): elif type_ == "Incentive": json_voucher["incentives"], json_voucher["incentive"] = incentive_employees(info["date"], db) 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"] = [] return json_voucher diff --git a/overlord/package.json b/overlord/package.json index b0682fff..b02de7b9 100644 --- a/overlord/package.json +++ b/overlord/package.json @@ -1,6 +1,6 @@ { "name": "overlord", - "version": "7.3.0", + "version": "7.4.0", "scripts": { "ng": "ng", "prettier": "prettier", diff --git a/setup.py b/setup.py index 70510e5e..38746ec4 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ with open(os.path.join(here, 'requirements.txt'), "r") as r: requires = r.read().splitlines() setup(name='brewman', - version='7.3.0', + version='7.4.0', description='brewman', long_description=README + '\n\n' + CHANGES, classifiers=[