brewman/brewman/routers/attendance.py

127 lines
3.9 KiB
Python

from datetime import datetime, date, timedelta
from fastapi import APIRouter, HTTPException, status, Depends, Security, Request
from sqlalchemy import or_
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.orm import Session
from ..schemas.auth import UserToken
from ..core.security import get_current_active_user as get_user
from ..db.session import SessionLocal
from ..models.master import Employee
from ..models.voucher import Attendance
from ..routers.fingerprint import get_prints
from ..core.session import get_date, set_date
import brewman.schemas.voucher as schemas
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