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