103 lines
3.0 KiB
Python
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
|