from datetime import date, datetime, timedelta import brewman.schemas.voucher as schemas from fastapi import APIRouter, Depends, HTTPException, Request, Security, status from sqlalchemy import or_ from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.orm import Session from ..core.security import get_current_active_user as get_user from ..core.session import get_date, set_date from ..db.session import SessionLocal from ..models.master import Employee from ..models.voucher import Attendance from ..routers.fingerprint import get_prints from ..schemas.auth import UserToken router = APIRouter() # Dependency def get_db() -> Session: try: db = SessionLocal() yield db finally: db.close() @router.get("", response_model=schemas.Attendance) def attendance_blank( request: Request, user: UserToken = Security(get_user, scopes=["attendance"]) ): return {"date": get_date(request.session), "body": []} @router.get("/{date_}", response_model=schemas.Attendance) def attendance_date( date_: str, request: Request, db: Session = Depends(get_db), user: UserToken = Security(get_user, scopes=["attendance"]), ): set_date(date_, request.session) return { "date": date_, "body": attendance_date_report(datetime.strptime(date_, "%d-%b-%Y"), db), } def attendance_date_report(date_: date, db: Session): body = [] employees = ( db.query(Employee) .filter(Employee.joining_date <= date_) .filter( or_( Employee.is_active, Employee.leaving_date >= date_, ) ) .order_by(Employee.cost_centre_id) .order_by(Employee.designation) .order_by(Employee.name) .all() ) for item in employees: att = ( db.query(Attendance) .filter(Attendance.employee_id == item.id) .filter(Attendance.date == date_) .filter(Attendance.is_valid == True) .first() ) att = 0 if att is None else att.attendance_type prints, hours_worked, full_day = get_prints(item.id, date_, db) body.append( schemas.AttendanceItem( id=item.id, code=item.code, name=item.name, designation=item.designation, department=item.cost_centre.name, attendanceType=schemas.AttendanceType(id=att), prints=prints, hoursWorked=hours_worked, fullDay=full_day, ) ) return body @router.post("/{date_}", response_model=schemas.Attendance) def save( date_: str, data: schemas.Attendance, db: Session = Depends(get_db), user: UserToken = Security(get_user, scopes=["attendance"]), ): try: att_date = datetime.strptime(date_, "%d-%b-%Y").date() for item in data.body: if item.attendance_type.id_ != 0: attendance = Attendance( employee_id=item.id_, date=att_date, attendance_type=item.attendance_type.id_, user_id=user.id_, ) attendance.create(db) db.commit() return {"date": date_, "body": attendance_date_report(att_date, 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 def date_range(start: date, stop: date, step=timedelta(days=1), inclusive=False): # inclusive=False to behave like range by default if step.days > 0: while start < stop: yield start start = start + step # not +=! don't modify object passed in if it's mutable # since this function is not restricted to # only types from datetime module elif step.days < 0: while start > stop: yield start start = start + step if inclusive and start == stop: yield start