brewman/brewman/brewman/routers/attendance.py

141 lines
4.1 KiB
Python

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