159 lines
3.5 KiB
Python
159 lines
3.5 KiB
Python
from pydantic import BaseModel
|
|
from datetime import datetime, date
|
|
from typing import Optional
|
|
from app.models.attendance import ServiceType, AttendanceStatus
|
|
|
|
|
|
class ServiceBase(BaseModel):
|
|
title: str
|
|
description: Optional[str] = None
|
|
service_type: ServiceType
|
|
service_date: date
|
|
start_time: datetime
|
|
end_time: Optional[datetime] = None
|
|
location: Optional[str] = None
|
|
minister_id: Optional[int] = None
|
|
|
|
|
|
class ServiceCreate(ServiceBase):
|
|
pass
|
|
|
|
|
|
class ServiceUpdate(BaseModel):
|
|
title: Optional[str] = None
|
|
description: Optional[str] = None
|
|
service_type: Optional[ServiceType] = None
|
|
service_date: Optional[date] = None
|
|
start_time: Optional[datetime] = None
|
|
end_time: Optional[datetime] = None
|
|
location: Optional[str] = None
|
|
minister_id: Optional[int] = None
|
|
is_active: Optional[bool] = None
|
|
|
|
|
|
class ServiceResponse(ServiceBase):
|
|
id: int
|
|
is_active: bool
|
|
created_by: int
|
|
created_at: datetime
|
|
creator_name: Optional[str] = None
|
|
minister_name: Optional[str] = None
|
|
attendance_count: int = 0
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class AttendanceRecordBase(BaseModel):
|
|
user_id: int
|
|
status: AttendanceStatus = AttendanceStatus.PRESENT
|
|
check_in_time: Optional[datetime] = None
|
|
check_out_time: Optional[datetime] = None
|
|
notes: Optional[str] = None
|
|
|
|
|
|
class AttendanceRecordCreate(AttendanceRecordBase):
|
|
pass
|
|
|
|
|
|
class AttendanceRecordUpdate(BaseModel):
|
|
status: Optional[AttendanceStatus] = None
|
|
check_in_time: Optional[datetime] = None
|
|
check_out_time: Optional[datetime] = None
|
|
notes: Optional[str] = None
|
|
|
|
|
|
class AttendanceRecordResponse(AttendanceRecordBase):
|
|
id: int
|
|
service_id: int
|
|
recorded_by: int
|
|
recorded_at: datetime
|
|
user_name: Optional[str] = None
|
|
recorder_name: Optional[str] = None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class AttendanceGoalBase(BaseModel):
|
|
service_type: ServiceType
|
|
target_percentage: int = 80
|
|
start_date: date
|
|
end_date: date
|
|
|
|
|
|
class AttendanceGoalCreate(AttendanceGoalBase):
|
|
pass
|
|
|
|
|
|
class AttendanceGoalResponse(AttendanceGoalBase):
|
|
id: int
|
|
user_id: int
|
|
is_active: bool
|
|
created_at: datetime
|
|
current_percentage: float = 0.0
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class FamilyGroupBase(BaseModel):
|
|
name: str
|
|
description: Optional[str] = None
|
|
|
|
|
|
class FamilyGroupCreate(FamilyGroupBase):
|
|
pass
|
|
|
|
|
|
class FamilyGroupResponse(FamilyGroupBase):
|
|
id: int
|
|
head_of_family_id: int
|
|
created_at: datetime
|
|
head_of_family_name: Optional[str] = None
|
|
member_count: int = 0
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class FamilyMemberBase(BaseModel):
|
|
name: str
|
|
relationship: Optional[str] = None
|
|
date_of_birth: Optional[date] = None
|
|
user_id: Optional[int] = None
|
|
|
|
|
|
class FamilyMemberCreate(FamilyMemberBase):
|
|
pass
|
|
|
|
|
|
class FamilyMemberResponse(FamilyMemberBase):
|
|
id: int
|
|
family_group_id: int
|
|
is_registered_user: bool
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class AttendanceStats(BaseModel):
|
|
total_services: int
|
|
services_attended: int
|
|
attendance_percentage: float
|
|
most_attended_service_type: Optional[ServiceType] = None
|
|
current_streak: int = 0
|
|
longest_streak: int = 0
|
|
|
|
|
|
class ServiceAttendanceSummary(BaseModel):
|
|
service_id: int
|
|
service_title: str
|
|
service_date: date
|
|
service_type: ServiceType
|
|
total_attendees: int
|
|
present_count: int
|
|
absent_count: int
|
|
late_count: int
|
|
attendance_rate: float
|