brewman/brewman/brewman/routers/credit_salary.py

103 lines
3.0 KiB
Python

from calendar import monthrange
from datetime import date, datetime
from fastapi import APIRouter, Body, Depends, HTTPException, Security, status
from sqlalchemy import or_
from sqlalchemy.orm import Session
from ..core.security import get_current_active_user as get_user
from ..core.session import get_first_day, get_last_day
from ..db.session import SessionLocal
from ..models.master import Account, AttendanceType, Employee
from ..models.voucher import Attendance, Journal, Voucher, VoucherType
from ..schemas.auth import UserToken
router = APIRouter()
# Dependency
def get_db() -> Session:
try:
db = SessionLocal()
yield db
finally:
db.close()
@router.post("")
def credit_salary(
month: str = Body(..., embed=True),
db: Session = Depends(get_db),
user: UserToken = Security(get_user, scopes=["attendance"]),
):
month = datetime.strptime(month, "%d-%b-%Y").date()
start_date = get_first_day(month)
finish_date = get_last_day(month)
voucher = Voucher(
date=finish_date,
narration="Auto Generated Salary Entry",
user_id=user.id_,
type_=VoucherType.by_name("Journal"),
posted=True,
poster_id=user.id_,
)
db.add(voucher)
for item in salary_journals(start_date, finish_date, db):
voucher.journals.append(item)
db.add(item)
db.commit()
return {"message": "Salary Entry created"}
def salary_journals(start_date: date, finish_date: date, db: Session):
days = monthrange(start_date.year, start_date.month)[1]
amount = 0
journals = []
employees = (
db.query(Employee)
.filter(Employee.joining_date <= finish_date)
.filter(or_(Employee.is_active, Employee.leaving_date >= start_date))
.order_by(Employee.cost_centre_id)
.order_by(Employee.designation)
.order_by(Employee.name)
.all()
)
for employee in employees:
att = (
db.query(Attendance)
.filter(Attendance.employee_id == employee.id)
.filter(Attendance.date >= start_date)
.filter(Attendance.date <= finish_date)
.filter(Attendance.is_valid == True)
.all()
)
att = sum(map(lambda x: AttendanceType.by_id(x.attendance_type).value, att))
att = round(att * employee.salary / days)
if att != 0:
amount += att
journals.append(
Journal(
amount=att,
debit=-1,
account_id=employee.id,
cost_centre_id=employee.cost_centre_id,
)
)
salary = db.query(Account).filter(Account.id == Account.salary_id()).first()
if amount == 0:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="No salaries to credit",
)
journals.append(
Journal(
amount=amount,
debit=1,
account_id=salary.id,
cost_centre_id=salary.cost_centre_id,
)
)
return journals