Account done
This commit is contained in:
parent
2466efb208
commit
6765f0a93e
brewman
@ -1,17 +1,19 @@
|
|||||||
|
import traceback
|
||||||
import uuid
|
import uuid
|
||||||
|
from typing import List
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, Security
|
from fastapi import APIRouter, HTTPException, status, Depends, Security
|
||||||
from pydantic import ValidationError
|
|
||||||
from sqlalchemy import func
|
from sqlalchemy import func
|
||||||
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
from sqlalchemy.orm import joinedload_all, Session
|
from sqlalchemy.orm import joinedload_all, Session
|
||||||
|
|
||||||
from ..core.security import User, get_current_active_user as get_user
|
from ..core.security import User, get_current_active_user as get_user
|
||||||
from ..db.session import SessionLocal
|
from ..db.session import SessionLocal
|
||||||
from ..models.master import CostCentre, Account, AccountType, AccountBase
|
from ..models.master import CostCentre, Account, AccountType, AccountBase
|
||||||
from ..models.validation_exception import ValidationError
|
|
||||||
from ..models.voucher import Voucher, Journal, VoucherType
|
from ..models.voucher import Voucher, Journal, VoucherType
|
||||||
from ..schemas.master import Account as AccountSchema
|
import brewman.schemas.master as schemas
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
@ -24,11 +26,14 @@ def get_db():
|
|||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
@router.post("/")
|
@router.post("/", response_model=schemas.Account)
|
||||||
def save(data: AccountSchema, db: Session = Depends(get_db), user: User = Security(get_user, scopes=["accounts"])):
|
def save(
|
||||||
|
data: schemas.AccountSaveUpdate,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
user: User = Security(get_user, scopes=["accounts"]),
|
||||||
|
):
|
||||||
try:
|
try:
|
||||||
item = Account(
|
item = Account(
|
||||||
code=0,
|
|
||||||
name=data.name,
|
name=data.name,
|
||||||
type=data.type,
|
type=data.type,
|
||||||
is_starred=data.is_starred,
|
is_starred=data.is_starred,
|
||||||
@ -38,56 +43,85 @@ def save(data: AccountSchema, db: Session = Depends(get_db), user: User = Securi
|
|||||||
).create(db)
|
).create(db)
|
||||||
db.commit()
|
db.commit()
|
||||||
return account_info(item.id, db)
|
return account_info(item.id, db)
|
||||||
except:
|
except SQLAlchemyError as e:
|
||||||
db.rollback()
|
db.rollback()
|
||||||
finally:
|
raise HTTPException(
|
||||||
db.close()
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail=str(e),
|
||||||
|
)
|
||||||
@router.put("/{id_}")
|
except Exception:
|
||||||
def update(id_: uuid.UUID, db: Session = Depends(get_db), user: User = Security(get_user, scopes=["accounts"])):
|
db.rollback()
|
||||||
item = (
|
raise HTTPException(
|
||||||
db.query(Account)
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
.filter(Account.id == id_)
|
detail=traceback.format_exc(),
|
||||||
.first()
|
|
||||||
)
|
|
||||||
if item.is_fixture:
|
|
||||||
raise ValidationError(
|
|
||||||
"{0} is a fixture and cannot be edited or deleted.".format(item.name)
|
|
||||||
)
|
)
|
||||||
new_type = int(request.json_body["type"])
|
|
||||||
if not item.type == new_type:
|
|
||||||
item.code = Account.get_code(new_type, request.dbsession)
|
|
||||||
item.type = new_type
|
|
||||||
item.name = request.json_body["name"]
|
|
||||||
item.is_active = request.json_body["isActive"]
|
|
||||||
item.is_reconcilable = request.json_body["isReconcilable"]
|
|
||||||
item.is_starred = request.json_body["isStarred"]
|
|
||||||
item.cost_centre_id = uuid.UUID(request.json_body["costCentre"]["id"])
|
|
||||||
transaction.commit()
|
|
||||||
return account_info(item.id, request.dbsession)
|
|
||||||
|
|
||||||
|
|
||||||
@router.delete("/{id}") # "Accounts"
|
@router.put("/{id_}", response_model=schemas.Account)
|
||||||
def delete(id_: uuid.UUID, db: Session = Depends(get_db), user: User = Security(get_user, scopes=["accounts"])):
|
def update(
|
||||||
account = (
|
id_: uuid.UUID,
|
||||||
db.query(Account)
|
data: schemas.AccountSaveUpdate,
|
||||||
.filter(Account.id == id_)
|
db: Session = Depends(get_db),
|
||||||
.first()
|
user: User = Security(get_user, scopes=["accounts"]),
|
||||||
)
|
):
|
||||||
can_delete, reason = account.can_delete(request.has_permission("Advanced Delete"))
|
try:
|
||||||
|
item: Account = db.query(Account).filter(Account.id == id_).first()
|
||||||
|
if item.is_fixture:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail=f"{item.name} is a fixture and cannot be edited or deleted.",
|
||||||
|
)
|
||||||
|
if not item.type == data.type:
|
||||||
|
item.code = Account.get_code(data.type, db)
|
||||||
|
item.type = data.type
|
||||||
|
item.name = data.name
|
||||||
|
item.is_active = data.is_active
|
||||||
|
item.is_reconcilable = data.is_reconcilable
|
||||||
|
item.is_starred = data.is_starred
|
||||||
|
item.cost_centre_id = data.cost_centre.id_
|
||||||
|
db.commit()
|
||||||
|
return account_info(item.id, 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 HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail=traceback.format_exc(),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.delete("/{id}")
|
||||||
|
def delete(
|
||||||
|
id_: uuid.UUID,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
user: User = Security(get_user, scopes=["accounts"]),
|
||||||
|
):
|
||||||
|
account: Account = db.query(Account).filter(Account.id == id_).first()
|
||||||
|
can_delete, reason = account.can_delete("Advanced Delete" in user.permissions)
|
||||||
if can_delete:
|
if can_delete:
|
||||||
delete_with_data(account, db)
|
delete_with_data(account, db)
|
||||||
transaction.commit()
|
db.commit()
|
||||||
return account_info(None, db)
|
return account_info(None, db)
|
||||||
else:
|
else:
|
||||||
transaction.abort()
|
db.abort()
|
||||||
response = Response("Cannot delete account because {0}".format(reason))
|
raise HTTPException(
|
||||||
response.status_int = 500
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
return response
|
detail=f"Cannot delete account because {reason}",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/list") # "Authenticated"
|
@router.get("/")
|
||||||
|
def show_blank(
|
||||||
|
db: Session = Depends(get_db), user: User = Security(get_user, scopes=["accounts"])
|
||||||
|
):
|
||||||
|
return account_info(None, db)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/list")
|
||||||
async def show_list(db: Session = Depends(get_db), user: User = Depends(get_user)):
|
async def show_list(db: Session = Depends(get_db), user: User = Depends(get_user)):
|
||||||
list_ = (
|
list_ = (
|
||||||
db.query(Account)
|
db.query(Account)
|
||||||
@ -113,9 +147,16 @@ async def show_list(db: Session = Depends(get_db), user: User = Depends(get_user
|
|||||||
return accounts
|
return accounts
|
||||||
|
|
||||||
|
|
||||||
@router.get("/query") # "Authenticated"
|
@router.get("/query")
|
||||||
async def show_term(q: str, t: int = None, r: bool = None, a: bool = None, c: int = None,
|
async def show_term(
|
||||||
db: Session = Depends(get_db), current_user: User = Depends(get_user)):
|
q: str,
|
||||||
|
t: int = None,
|
||||||
|
r: bool = None,
|
||||||
|
a: bool = None,
|
||||||
|
c: int = None,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
current_user: User = Depends(get_user),
|
||||||
|
):
|
||||||
count = c
|
count = c
|
||||||
|
|
||||||
list_ = []
|
list_ = []
|
||||||
@ -126,29 +167,32 @@ async def show_term(q: str, t: int = None, r: bool = None, a: bool = None, c: in
|
|||||||
return {"user": current_user.name, "list": list_}
|
return {"user": current_user.name, "list": list_}
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{id_}/balance") # "Authenticated"
|
@router.get("/{id_}/balance")
|
||||||
async def show_balance(id_: uuid.UUID, d: str = None, db: Session = Depends(get_db), user: User = Depends(get_user)):
|
async def show_balance(
|
||||||
date = (
|
id_: uuid.UUID,
|
||||||
None
|
d: str = None,
|
||||||
if d is None or d == ""
|
db: Session = Depends(get_db),
|
||||||
else datetime.datetime.strptime(d, "%d-%b-%Y")
|
user: User = Depends(get_user),
|
||||||
)
|
):
|
||||||
|
date = None if d is None or d == "" else datetime.datetime.strptime(d, "%d-%b-%Y")
|
||||||
return {"date": balance(id_, date, db), "total": balance(id_, None, db)}
|
return {"date": balance(id_, date, db), "total": balance(id_, None, db)}
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{id_}") # "Accounts"
|
@router.get("/{id_}")
|
||||||
def show_id(id_: uuid.UUID, db: Session = Depends(get_db), user: User = Security(get_user, scopes=["accounts"])):
|
def show_id(
|
||||||
|
id_: uuid.UUID,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
user: User = Security(get_user, scopes=["accounts"]),
|
||||||
|
):
|
||||||
return account_info(id_, db)
|
return account_info(id_, db)
|
||||||
|
|
||||||
|
|
||||||
def balance(id_: uuid.UUID, date, dbsession: Session):
|
def balance(id_: uuid.UUID, date, db: Session):
|
||||||
account = dbsession.query(AccountBase).filter(AccountBase.id == id_).first()
|
account = db.query(AccountBase).filter(AccountBase.id == id_).first()
|
||||||
if not account.type_object.balance_sheet:
|
if not account.type_object.balance_sheet:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
bal = dbsession.query(func.sum(Journal.amount * Journal.debit)).join(
|
bal = db.query(func.sum(Journal.amount * Journal.debit)).join(Journal.voucher)
|
||||||
Journal.voucher
|
|
||||||
)
|
|
||||||
if date is not None:
|
if date is not None:
|
||||||
bal = bal.filter(Voucher.date <= date)
|
bal = bal.filter(Voucher.date <= date)
|
||||||
|
|
||||||
@ -160,11 +204,6 @@ def balance(id_: uuid.UUID, date, dbsession: Session):
|
|||||||
return 0 if bal is None else bal
|
return 0 if bal is None else bal
|
||||||
|
|
||||||
|
|
||||||
@router.get("/") # "Accounts"
|
|
||||||
def show_blank(db: Session = Depends(get_db), user: User = Security(get_user, scopes=["accounts"])):
|
|
||||||
return account_info(None, db)
|
|
||||||
|
|
||||||
|
|
||||||
def account_info(id_, db):
|
def account_info(id_, db):
|
||||||
if id_ is None:
|
if id_ is None:
|
||||||
account = {
|
account = {
|
||||||
@ -198,7 +237,7 @@ def delete_with_data(account, db):
|
|||||||
suspense_account = (
|
suspense_account = (
|
||||||
db.query(Account).filter(Account.id == Account.suspense()).first()
|
db.query(Account).filter(Account.id == Account.suspense()).first()
|
||||||
)
|
)
|
||||||
query = (
|
query: List[Voucher] = (
|
||||||
db.query(Voucher)
|
db.query(Voucher)
|
||||||
.options(joinedload_all(Voucher.journals, Journal.account, innerjoin=True))
|
.options(joinedload_all(Voucher.journals, Journal.account, innerjoin=True))
|
||||||
.filter(Voucher.journals.any(Journal.account_id == account.id))
|
.filter(Voucher.journals.any(Journal.account_id == account.id))
|
||||||
@ -219,8 +258,8 @@ def delete_with_data(account, db):
|
|||||||
else:
|
else:
|
||||||
if sus_jnl is None:
|
if sus_jnl is None:
|
||||||
acc_jnl.account = suspense_account
|
acc_jnl.account = suspense_account
|
||||||
voucher.narration += "\nSuspense \u20B9{0:,.2f} is {1}".format(
|
voucher.narration += (
|
||||||
acc_jnl.amount, account.name
|
f"\nSuspense \u20B9{acc_jnl.amount:,.2f} is {account.name}"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
amount = (sus_jnl.debit * sus_jnl.amount) + (
|
amount = (sus_jnl.debit * sus_jnl.amount) + (
|
||||||
@ -232,9 +271,7 @@ def delete_with_data(account, db):
|
|||||||
else:
|
else:
|
||||||
sus_jnl.amount = abs(amount)
|
sus_jnl.amount = abs(amount)
|
||||||
sus_jnl.debit = -1 if amount < 0 else 1
|
sus_jnl.debit = -1 if amount < 0 else 1
|
||||||
voucher.narration += "\nDeleted \u20B9{0:,.2f} of {1}".format(
|
voucher.narration += f"\nDeleted \u20B9{acc_jnl.amount * acc_jnl.debit:,.2f} of {account.name}"
|
||||||
acc_jnl.amount * acc_jnl.debit, account.name
|
|
||||||
)
|
|
||||||
if voucher.type in (
|
if voucher.type in (
|
||||||
VoucherType.by_name("Payment").id,
|
VoucherType.by_name("Payment").id,
|
||||||
VoucherType.by_name("Receipt").id,
|
VoucherType.by_name("Receipt").id,
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
|
from fastapi import APIRouter, Depends
|
||||||
|
|
||||||
|
from ..core.security import User, get_current_active_user as get_user
|
||||||
from brewman.models.master import AccountType
|
from brewman.models.master import AccountType
|
||||||
from fastapi import APIRouter
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
@router.get("/") # "Authenticated"
|
@router.get("/")
|
||||||
def account_type_list(request):
|
def account_type_list(user: User = Depends(get_user)):
|
||||||
account_types = []
|
return [
|
||||||
for item in AccountType.list():
|
{"id": item.id, "name": item.name}
|
||||||
account_types.append({"id": item.id, "name": item.name})
|
for item in AccountType.list()
|
||||||
return account_types
|
]
|
||||||
|
@ -1,19 +1,14 @@
|
|||||||
import traceback
|
import traceback
|
||||||
import uuid
|
import uuid
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from sqlalchemy.exc import SQLAlchemyError
|
|
||||||
|
|
||||||
import brewman.schemas.master as schemas
|
|
||||||
|
|
||||||
from fastapi import APIRouter, HTTPException, status, Depends, Security
|
from fastapi import APIRouter, HTTPException, status, Depends, Security
|
||||||
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
import brewman.schemas.master as schemas
|
||||||
from ..core.security import User, get_current_active_user as get_user
|
from ..core.security import User, get_current_active_user as get_user
|
||||||
from ..db.session import SessionLocal
|
from ..db.session import SessionLocal
|
||||||
from ..models.master import CostCentre
|
from ..models.master import CostCentre
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,15 +62,18 @@ class CostCentre(CostCentreSaveUpdate):
|
|||||||
is_fixture: bool = Field(alias="isFixture")
|
is_fixture: bool = Field(alias="isFixture")
|
||||||
|
|
||||||
|
|
||||||
class Account(BaseModel):
|
class AccountSaveUpdate(BaseModel):
|
||||||
id_: uuid.UUID
|
|
||||||
code: int
|
|
||||||
name: str
|
name: str
|
||||||
type: int
|
type: int
|
||||||
is_starred: bool
|
is_starred: bool
|
||||||
is_active: bool
|
is_active: bool
|
||||||
is_reconcilable: bool
|
is_reconcilable: bool
|
||||||
cost_centre: CostCentre
|
cost_centre: CostCentre
|
||||||
|
|
||||||
|
|
||||||
|
class Account(AccountSaveUpdate):
|
||||||
|
id_: uuid.UUID = Field(alias="id")
|
||||||
|
code: int
|
||||||
is_fixture: bool
|
is_fixture: bool
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user