brewman/brewman/brewman/routers/employee.py

273 lines
8.4 KiB
Python
Raw Normal View History

import uuid
2020-10-07 15:18:43 +00:00
import brewman.schemas.master as schemas
from fastapi import APIRouter, Depends, HTTPException, Security, status
from sqlalchemy import desc
from sqlalchemy.exc import SQLAlchemyError
2020-10-07 15:18:43 +00:00
from sqlalchemy.orm import Session, joinedload_all
from ..core.security import get_current_active_user as get_user
from ..db.session import SessionLocal
2020-10-07 15:18:43 +00:00
from ..models.master import Account, AccountBase, CostCentre, Employee
from ..models.voucher import Journal, Voucher, VoucherType
from ..schemas.auth import UserToken
router = APIRouter()
# Dependency
def get_db():
try:
db = SessionLocal()
yield db
finally:
db.close()
@router.post("", response_model=schemas.Employee)
def save(
2020-10-07 15:18:43 +00:00
data: schemas.EmployeeIn,
db: Session = Depends(get_db),
user: UserToken = Security(get_user, scopes=["employees"]),
):
try:
item = Employee(
name=data.name,
is_starred=data.is_starred,
is_active=data.is_active,
cost_centre_id=data.cost_centre.id_,
designation=data.designation,
salary=data.salary,
points=data.points,
joining_date=data.joining_date,
leaving_date=None if data.is_active else data.leaving_date,
).create(db)
db.commit()
return employee_info(item.id, db)
except SQLAlchemyError as e:
db.rollback()
raise HTTPException(
2020-10-07 15:18:43 +00:00
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=str(e),
)
except Exception:
db.rollback()
raise
@router.put("/{id_}", response_model=schemas.Employee)
def update(
id_: uuid.UUID,
data: schemas.EmployeeIn,
db: Session = Depends(get_db),
user: UserToken = Security(get_user, scopes=["employees"]),
):
try:
item: Employee = db.query(Employee).filter(Employee.id == id_).first()
if item.is_fixture:
raise HTTPException(
2020-10-07 15:18:43 +00:00
status_code=status.HTTP_423_LOCKED,
detail=f"{item.name} is a fixture and cannot be edited or deleted.",
)
item.name = data.name
item.cost_centre_id = data.cost_centre.id_
item.designation = data.designation
item.salary = data.salary
item.points = data.points
item.joining_date = data.joining_date
item.is_starred = data.is_starred
item.is_active = data.is_active
item.leaving_date = data.leaving_date
db.commit()
return employee_info(item.id, db)
except SQLAlchemyError as e:
db.rollback()
raise HTTPException(
2020-10-07 15:18:43 +00:00
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=str(e),
)
except Exception:
db.rollback()
raise
@router.delete("/{id_}")
def delete(
2020-10-07 15:18:43 +00:00
id_: uuid.UUID,
db: Session = Depends(get_db),
user: UserToken = Security(get_user, scopes=["employees"]),
):
employee: Employee = db.query(Employee).filter(Employee.id == id_).first()
can_delete, reason = employee.can_delete("advanced-delete" in user.permissions)
if can_delete:
delete_with_data(employee, db)
db.commit()
return employee_info(None, db)
2012-10-17 07:57:14 +00:00
else:
db.rollback()
raise HTTPException(
2020-10-07 15:18:43 +00:00
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Cannot delete account because {reason}",
)
@router.get("")
def show_blank(
2020-10-07 15:18:43 +00:00
db: Session = Depends(get_db),
user: UserToken = Security(get_user, scopes=["employees"]),
):
return employee_info(None, db)
@router.get("/list")
async def show_list(db: Session = Depends(get_db), user: UserToken = Depends(get_user)):
return [
{
"id": item.id,
"code": item.code,
"name": item.name,
"designation": item.designation,
"salary": item.salary,
"points": item.points,
"isActive": item.is_active,
"costCentre": item.cost_centre.name,
"joiningDate": item.joining_date.strftime("%d-%b-%Y"),
2020-10-07 16:59:24 +00:00
"leavingDate": ""
if item.is_active
else item.leaving_date.strftime("%d-%b-%Y"),
2020-05-31 09:11:11 +00:00
"isStarred": item.is_starred,
}
for item in db.query(Employee)
.order_by(desc(Employee.is_active))
.order_by(Account.cost_centre_id)
.order_by(Employee.designation)
.order_by(Employee.name)
.all()
]
2012-10-17 07:57:14 +00:00
@router.get("/query")
async def show_term(
2020-10-07 15:18:43 +00:00
q: str,
c: int = None,
db: Session = Depends(get_db),
current_user: UserToken = Depends(get_user),
):
list_ = []
for index, item in enumerate(AccountBase.query(q=q, type_=10, db=db)):
list_.append(
{
"id": item.id,
"name": item.name,
"designation": item.designation,
2020-10-07 15:18:43 +00:00
"costCentre": {
"id": item.cost_centre.id,
"name": item.cost_centre.name,
},
}
)
if c is not None and index == c - 1:
break
return list_
@router.get("/{id_}")
def show_id(
2020-10-07 15:18:43 +00:00
id_: uuid.UUID,
db: Session = Depends(get_db),
user: UserToken = Security(get_user, scopes=["employees"]),
):
return employee_info(id_, db)
def employee_info(id_, db):
if id_ is None:
employee = {
"code": "(Auto)",
"isStarred": False,
"isActive": True,
"costCentre": CostCentre.overall(),
}
2012-10-17 07:57:14 +00:00
else:
employee = db.query(Employee).filter(Employee.id == id_).first()
if employee is None:
2020-10-07 15:18:43 +00:00
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Employee not found",
)
employee = {
"id": employee.id,
"code": employee.code,
"name": employee.name,
"isActive": employee.is_active,
"isStarred": employee.is_starred,
"designation": employee.designation,
"salary": employee.salary,
"points": employee.points,
"joiningDate": employee.joining_date.strftime("%d-%b-%Y"),
2020-10-07 16:59:24 +00:00
"leavingDate": None
if employee.is_active
else employee.leaving_date.strftime("%d-%b-%Y"),
2020-10-07 15:18:43 +00:00
"costCentre": {
"id": employee.cost_centre_id,
"name": employee.cost_centre.name,
},
"isFixture": employee.is_fixture,
}
return employee
def delete_with_data(employee, db):
2020-10-07 16:59:24 +00:00
suspense_account = (
db.query(Account).filter(Account.id == Account.suspense()).first()
)
query = (
db.query(Voucher)
.options(joinedload_all(Voucher.journals, Journal.account, innerjoin=True))
.filter(Voucher.journals.any(Journal.account_id == employee.id))
.all()
)
for voucher in query:
others, sus_jnl, acc_jnl = False, None, None
for journal in voucher.journals:
if journal.account_id == employee.id:
acc_jnl = journal
elif journal.account_id == Account.suspense():
sus_jnl = journal
else:
others = True
if not others:
db.delete(voucher)
else:
if sus_jnl is None:
acc_jnl.account = suspense_account
2020-10-07 16:59:24 +00:00
voucher.narration += (
f"\nSuspense \u20B9 {acc_jnl.amount:,.2f} is {employee.name}"
)
else:
2020-10-07 16:59:24 +00:00
amount = (sus_jnl.debit * sus_jnl.amount) + (
acc_jnl.debit * acc_jnl.amount
)
if acc_jnl.employee_benefit is not None:
db.delete(acc_jnl.employee_benefit)
db.delete(acc_jnl)
if amount == 0:
db.delete(sus_jnl)
else:
sus_jnl.amount = abs(amount)
sus_jnl.debit = -1 if amount < 0 else 1
voucher.narration += f"\nDeleted \u20B9 {acc_jnl.amount * acc_jnl.debit:,.2f} of {employee.name}"
2020-10-07 15:18:43 +00:00
if voucher.type in (
VoucherType.by_name("Payment").id,
VoucherType.by_name("Receipt").id,
):
voucher.type = VoucherType.by_name("Journal")
for fingerprint in employee.fingerprints:
db.delete(fingerprint)
for attendance in employee.attendances:
db.delete(attendance)
db.delete(employee)