import uuid from datetime import datetime from typing import List import brewman.schemas.input as schema_in import brewman.schemas.voucher as output from fastapi import APIRouter, Depends, File, HTTPException, Request, Security, status from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.orm import Session from ..core.security import get_current_active_user as get_user from ..core.session import get_date, set_date from ..db.session import SessionLocal from ..models import AccountBase from ..models.voucher import Journal, Voucher, VoucherType from ..schemas.auth import UserToken from .db_image import save_files, update_files from .voucher import ( blank_voucher, check_voucher_edit_allowed, check_voucher_lock_info, voucher_info, ) router = APIRouter() # Dependency def get_db() -> Session: try: db = SessionLocal() yield db finally: db.close() @router.post("", response_model=output.Voucher) def save_route( request: Request, data: schema_in.JournalIn = Depends(schema_in.JournalIn.load_form), db: Session = Depends(get_db), i: List[bytes] = File(None), t: List[bytes] = File(None), user: UserToken = Security(get_user, scopes=["journal"]), ): try: item: Voucher = save(data, user, db) db.flush() save_files(item.id, i, t, db) db.commit() set_date(data.date_.strftime("%d-%b-%Y"), request.session) info = voucher_info(item, db) return info 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 save(data: schema_in.JournalIn, user: UserToken, db: Session) -> Voucher: check_voucher_lock_info(None, data.date_, db) voucher = Voucher( date=data.date_, narration=data.narration, is_starred=data.is_starred, user_id=user.id_, type_=VoucherType.by_name(data.type_), ) db.add(voucher) for item in data.journals: account: AccountBase = ( db.query(AccountBase).filter(AccountBase.id == item.account.id_).first() ) journal = Journal( amount=item.amount, debit=item.debit, account_id=account.id, cost_centre_id=account.cost_centre_id, ) voucher.journals.append(journal) db.add(journal) return voucher @router.put("/{id_}", response_model=output.Voucher) def update_route( id_: uuid.UUID, request: Request, data: schema_in.JournalIn = Depends(schema_in.JournalIn.load_form), db: Session = Depends(get_db), i: List[bytes] = File(None), t: List[bytes] = File(None), user: UserToken = Security(get_user, scopes=["journal"]), ): try: item: Voucher = update(id_, data, user, db) update_files(item.id, data.files, i, t, db) db.commit() set_date(data.date_.strftime("%d-%b-%Y"), request.session) return voucher_info(item, db) 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 update( id_: uuid.UUID, data: schema_in.JournalIn, user: UserToken, db: Session ) -> Voucher: voucher: Voucher = db.query(Voucher).filter(Voucher.id == id_).first() check_voucher_lock_info(voucher.date, data.date_, db) check_voucher_edit_allowed(voucher, user) voucher.date = data.date_ voucher.is_starred = data.is_starred voucher.narration = data.narration voucher.user_id = user.id_ voucher.posted = False voucher.last_edit_date = datetime.utcnow() for i in range(len(voucher.journals), 0, -1): item = voucher.journals[i - 1] found = False for j in range(len(data.journals), 0, -1): new_item = data.journals[j - 1] if new_item.id_ is not None and item.id == new_item.id_: account = ( db.query(AccountBase) .filter(AccountBase.id == new_item.account.id_) .first() ) found = True item.debit = new_item.debit item.amount = new_item.amount item.account_id = account.id item.cost_centre_id = account.cost_centre_id data.journals.remove(new_item) break if not found: voucher.journals.remove(item) for new_item in data.journals: account = ( db.query(AccountBase).filter(AccountBase.id == new_item.account.id_).first() ) journal = Journal( amount=new_item.amount, debit=new_item.debit, account_id=account.id, cost_centre_id=account.cost_centre_id, ) db.add(journal) voucher.journals.append(journal) return voucher @router.get("/{id_}", response_model=output.Voucher) def get_id( id_: uuid.UUID, db: Session = Depends(get_db), user: UserToken = Security(get_user, scopes=["journal"]), ): try: item: Voucher = db.query(Voucher).filter(Voucher.id == id_).first() if item is None: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Voucher not found", ) return voucher_info(item, db) except SQLAlchemyError as e: db.rollback() raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e), ) except Exception: db.rollback() raise @router.get("", response_model=output.Voucher) def show_blank( request: Request, a: str = None, db: Session = Depends(get_db), user: UserToken = Security(get_user, scopes=["journal"]), ): if request.scope.get("path") == "/api/payment": type_ = "Payment" elif request.scope.get("path") == "/api/receipt": type_ = "Receipt" else: type_ = "Journal" additional_info = {"date": get_date(request.session), "type": type_} if a: additional_info["account"] = a return blank_voucher(additional_info, db)