|
|
|
|
@ -1,11 +1,20 @@
|
|
|
|
|
import traceback
|
|
|
|
|
import uuid
|
|
|
|
|
from typing import Optional
|
|
|
|
|
from datetime import datetime, date
|
|
|
|
|
import uuid
|
|
|
|
|
from decimal import Decimal
|
|
|
|
|
|
|
|
|
|
from fastapi import (
|
|
|
|
|
APIRouter,
|
|
|
|
|
HTTPException,
|
|
|
|
|
status,
|
|
|
|
|
Depends,
|
|
|
|
|
Security,
|
|
|
|
|
)
|
|
|
|
|
from sqlalchemy import func, or_
|
|
|
|
|
from sqlalchemy.exc import SQLAlchemyError
|
|
|
|
|
from sqlalchemy.orm import Session
|
|
|
|
|
|
|
|
|
|
from brewman.models.auth import User
|
|
|
|
|
from brewman.models.master import (
|
|
|
|
|
AccountBase,
|
|
|
|
|
CostCentre,
|
|
|
|
|
@ -14,7 +23,6 @@ from brewman.models.master import (
|
|
|
|
|
Account,
|
|
|
|
|
)
|
|
|
|
|
from brewman.models.voucher import (
|
|
|
|
|
Voucher,
|
|
|
|
|
VoucherType,
|
|
|
|
|
Inventory,
|
|
|
|
|
DbImage,
|
|
|
|
|
@ -22,97 +30,81 @@ from brewman.models.voucher import (
|
|
|
|
|
Journal,
|
|
|
|
|
)
|
|
|
|
|
from brewman.routers import get_lock_info
|
|
|
|
|
from ...core.session import get_first_day
|
|
|
|
|
|
|
|
|
|
from fastapi import APIRouter, Depends, Security, Request, HTTPException, status
|
|
|
|
|
|
|
|
|
|
from ...schemas.auth import UserToken
|
|
|
|
|
from brewman.core.session import get_first_day
|
|
|
|
|
from ..schemas import to_camel
|
|
|
|
|
from ..schemas.auth import UserToken
|
|
|
|
|
from ..core.security import get_current_active_user as get_user
|
|
|
|
|
from ..db.session import SessionLocal
|
|
|
|
|
from ..models.voucher import Voucher
|
|
|
|
|
import brewman.schemas.voucher as output
|
|
|
|
|
|
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/api/voucher/{id}") # , request_param="p" "Post Vouchers"
|
|
|
|
|
def voucher_post(request):
|
|
|
|
|
user = (
|
|
|
|
|
request.dbsession.query(User)
|
|
|
|
|
.filter(User.id == uuid.UUID(request.authenticated_userid))
|
|
|
|
|
.one()
|
|
|
|
|
)
|
|
|
|
|
voucher = (
|
|
|
|
|
request.dbsession.query(Voucher)
|
|
|
|
|
.filter(Voucher.id == uuid.UUID(request.matchdict["id"]))
|
|
|
|
|
.first()
|
|
|
|
|
)
|
|
|
|
|
start, finish = get_lock_info(request.dbsession)
|
|
|
|
|
if start is not None and start > voucher.date:
|
|
|
|
|
raise ValidationError(
|
|
|
|
|
f"Vouchers before {start.strftime('%d-%b-%Y')} have been locked."
|
|
|
|
|
)
|
|
|
|
|
elif finish is not None and finish < voucher.date:
|
|
|
|
|
raise ValidationError(
|
|
|
|
|
f"Vouchers after {finish.strftime('%d-%b-%Y')} have been locked."
|
|
|
|
|
)
|
|
|
|
|
voucher.posted = True
|
|
|
|
|
voucher.poster_id = user.id
|
|
|
|
|
transaction.commit()
|
|
|
|
|
new_voucher = (
|
|
|
|
|
request.dbsession.query(Voucher).filter(Voucher.id == voucher.id).first()
|
|
|
|
|
)
|
|
|
|
|
return voucher_info(new_voucher, request)
|
|
|
|
|
# Dependency
|
|
|
|
|
def get_db() -> Session:
|
|
|
|
|
try:
|
|
|
|
|
db = SessionLocal()
|
|
|
|
|
yield db
|
|
|
|
|
finally:
|
|
|
|
|
db.close()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def check_delete_permissions(request, voucher):
|
|
|
|
|
user = (
|
|
|
|
|
request.dbsession.query(User)
|
|
|
|
|
.filter(User.id == uuid.UUID(request.authenticated_userid))
|
|
|
|
|
.one()
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if voucher.posted and not request.has_permission("Edit Posted Vouchers"):
|
|
|
|
|
response = Response("You are not allowed to edit posted vouchers")
|
|
|
|
|
response.status_int = 403
|
|
|
|
|
return response
|
|
|
|
|
elif voucher.user_id != user.id and not request.has_permission(
|
|
|
|
|
"Edit Other User's Vouchers"
|
|
|
|
|
):
|
|
|
|
|
response = Response("You are not allowed to edit other user's vouchers")
|
|
|
|
|
response.status_int = 403
|
|
|
|
|
return response
|
|
|
|
|
elif not request.has_permission(VoucherType.by_id(voucher.type).name):
|
|
|
|
|
response = Response(
|
|
|
|
|
f"You are not allowed ({VoucherType.by_id(voucher.type).name}) vouchers"
|
|
|
|
|
@router.post("/post-voucher/{id_}", response_model=output.Voucher)
|
|
|
|
|
def post_voucher(
|
|
|
|
|
id_: uuid.UUID,
|
|
|
|
|
db: Session = Depends(get_db),
|
|
|
|
|
user: UserToken = Security(get_user, scopes=["post-vouchers"]),
|
|
|
|
|
):
|
|
|
|
|
try:
|
|
|
|
|
voucher: Voucher = db.query(Voucher).filter(Voucher.id == id_).first()
|
|
|
|
|
check_voucher_lock_info(voucher.date, voucher.date, db)
|
|
|
|
|
voucher.posted = True
|
|
|
|
|
voucher.poster_id = user.id_
|
|
|
|
|
db.commit()
|
|
|
|
|
return voucher_info(voucher, db)
|
|
|
|
|
except SQLAlchemyError as e:
|
|
|
|
|
db.rollback()
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e),
|
|
|
|
|
)
|
|
|
|
|
response.status_int = 403
|
|
|
|
|
return response
|
|
|
|
|
start, finish = get_lock_info(request.dbsession)
|
|
|
|
|
if start is not None and start > voucher.date:
|
|
|
|
|
response = Response(
|
|
|
|
|
f"Vouchers before {start.strftime('%d-%b-%Y')} have been locked."
|
|
|
|
|
except Exception:
|
|
|
|
|
db.rollback()
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
|
|
|
detail=traceback.format_exc(),
|
|
|
|
|
)
|
|
|
|
|
response.status_int = 403
|
|
|
|
|
return response
|
|
|
|
|
elif finish is not None and finish < voucher.date:
|
|
|
|
|
response = Response(
|
|
|
|
|
f"Vouchers after {finish.strftime('%d-%b-%Y')} have been locked."
|
|
|
|
|
)
|
|
|
|
|
response.status_int = 403
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.delete("/api/voucher/{id}")
|
|
|
|
|
def delete(request):
|
|
|
|
|
voucher = (
|
|
|
|
|
request.dbsession.query(Voucher)
|
|
|
|
|
.filter(Voucher.id == uuid.UUID(request.matchdict["id"]))
|
|
|
|
|
.first()
|
|
|
|
|
)
|
|
|
|
|
images = (
|
|
|
|
|
request.dbsession.query(DbImage).filter(DbImage.resource_id == voucher.id).all()
|
|
|
|
|
)
|
|
|
|
|
permission = check_delete_permissions(request, voucher)
|
|
|
|
|
if permission is not None:
|
|
|
|
|
return permission
|
|
|
|
|
json_voucher = voucher_info(voucher, request)
|
|
|
|
|
def check_delete_permissions(voucher: Voucher, user: UserToken):
|
|
|
|
|
voucher_type = VoucherType.by_id(voucher.type).name.replace(" ", "-").lower()
|
|
|
|
|
if voucher_type in ["payment", "purchase"]:
|
|
|
|
|
voucher_type = "journal"
|
|
|
|
|
if voucher.posted and "edit-posted-vouchers" not in user.permissions:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_403_FORBIDDEN, detail="You are not allowed to edit posted vouchers",
|
|
|
|
|
)
|
|
|
|
|
elif voucher.user_id != user.id_ and "edit-other-user's-vouchers" not in user.permissions:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_403_FORBIDDEN, detail="You are not allowed to edit other user's vouchers",
|
|
|
|
|
)
|
|
|
|
|
elif voucher_type not in user.permissions:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_403_FORBIDDEN, detail=f"You are not allowed ({VoucherType.by_id(voucher.type).name}) vouchers",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.delete("/delete/{id_}")
|
|
|
|
|
def delete_voucher(
|
|
|
|
|
id_: uuid.UUID,
|
|
|
|
|
db: Session = Depends(get_db),
|
|
|
|
|
user: UserToken = Security(get_user),
|
|
|
|
|
):
|
|
|
|
|
voucher: Voucher = db.query(Voucher).filter(Voucher.id == id_).first()
|
|
|
|
|
images = db.query(DbImage).filter(DbImage.resource_id == voucher.id).all()
|
|
|
|
|
check_delete_permissions(voucher, user)
|
|
|
|
|
check_voucher_lock_info(None, voucher.date, db)
|
|
|
|
|
json_voucher = voucher_info(voucher, db)
|
|
|
|
|
batches_to_delete = []
|
|
|
|
|
if voucher.type == VoucherType.by_name("Issue").id:
|
|
|
|
|
for item in voucher.journals:
|
|
|
|
|
@ -142,7 +134,7 @@ def delete(request):
|
|
|
|
|
elif voucher.type == VoucherType.by_name("Purchase").id:
|
|
|
|
|
for item in voucher.inventories:
|
|
|
|
|
uses = (
|
|
|
|
|
request.dbsession.query(func.count(Inventory.id))
|
|
|
|
|
db.query(func.count(Inventory.id))
|
|
|
|
|
.filter(Inventory.batch_id == item.batch.id)
|
|
|
|
|
.filter(Inventory.id != item.id)
|
|
|
|
|
.scalar()
|
|
|
|
|
@ -156,21 +148,12 @@ def delete(request):
|
|
|
|
|
for item in voucher.inventories:
|
|
|
|
|
item.batch.quantity_remaining += item.quantity
|
|
|
|
|
for b in batches_to_delete:
|
|
|
|
|
request.dbsession.delete(b)
|
|
|
|
|
request.dbsession.delete(voucher)
|
|
|
|
|
db.delete(b)
|
|
|
|
|
db.delete(voucher)
|
|
|
|
|
for image in images:
|
|
|
|
|
request.dbsession.delete(image)
|
|
|
|
|
transaction.commit()
|
|
|
|
|
return blank_voucher(info=json_voucher, dbsession=request.dbsession)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/api/voucher/{id}")
|
|
|
|
|
def get_old(request):
|
|
|
|
|
id_ = request.matchdict.get("id", None)
|
|
|
|
|
voucher = (
|
|
|
|
|
request.dbsession.query(Voucher).filter(Voucher.id == uuid.UUID(id_)).first()
|
|
|
|
|
)
|
|
|
|
|
return voucher_info(voucher, request)
|
|
|
|
|
db.delete(image)
|
|
|
|
|
db.commit()
|
|
|
|
|
return blank_voucher(info=json_voucher, db=db)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def voucher_info(voucher, db):
|