v1
This commit is contained in:
@@ -0,0 +1,370 @@
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from typing import Optional, Any
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
# ── Magic link ─────────────────────────────────────────────────────────────────
|
||||
|
||||
class MagicLinkVerifySchema(BaseModel):
|
||||
token: str
|
||||
|
||||
|
||||
# ── Claim ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
class ClaimRequestSchema(BaseModel):
|
||||
email: str
|
||||
|
||||
|
||||
class ClaimCompleteSchema(BaseModel):
|
||||
email: str
|
||||
code: str
|
||||
password: str
|
||||
|
||||
|
||||
class MemberClaimVerifyCodeSchema(BaseModel):
|
||||
code: str
|
||||
password: str
|
||||
|
||||
|
||||
# ── Auth ───────────────────────────────────────────────────────────────────────
|
||||
|
||||
class MemberLoginSchema(BaseModel):
|
||||
email: str
|
||||
password: str
|
||||
|
||||
|
||||
class MemberLoginVerifySchema(BaseModel):
|
||||
email: str
|
||||
code: str
|
||||
|
||||
|
||||
class MemberTokenResponse(BaseModel):
|
||||
access_token: str
|
||||
refresh_token: str
|
||||
token_type: str = "bearer"
|
||||
|
||||
|
||||
class MemberRefreshSchema(BaseModel):
|
||||
refresh_token: str
|
||||
|
||||
|
||||
class MemberLogoutSchema(BaseModel):
|
||||
refresh_token: Optional[str] = None
|
||||
|
||||
|
||||
# ── Profile ────────────────────────────────────────────────────────────────────
|
||||
|
||||
class MemberProfileResponse(BaseModel):
|
||||
id: uuid.UUID
|
||||
email: str
|
||||
first_name: str
|
||||
last_name: str
|
||||
phone: Optional[str]
|
||||
address: Optional[str]
|
||||
emergency_contact: Optional[str]
|
||||
notifications_enabled: bool
|
||||
is_claimed: bool
|
||||
member_status: str
|
||||
activated_at: Optional[datetime]
|
||||
created_at: datetime
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
class MemberProfileUpdate(BaseModel):
|
||||
first_name: Optional[str] = None
|
||||
last_name: Optional[str] = None
|
||||
phone: Optional[str] = None
|
||||
address: Optional[str] = None
|
||||
emergency_contact: Optional[str] = None
|
||||
notifications_enabled: Optional[bool] = None
|
||||
|
||||
|
||||
class MemberOnboardingResponse(BaseModel):
|
||||
id: uuid.UUID
|
||||
email: str
|
||||
first_name: str
|
||||
last_name: str
|
||||
phone: Optional[str]
|
||||
address: Optional[str]
|
||||
emergency_contact: Optional[str]
|
||||
notifications_enabled: bool
|
||||
onboarding_data: Optional[Any]
|
||||
is_claimed: bool
|
||||
member_status: str
|
||||
claimed_at: Optional[datetime]
|
||||
onboarding_completed_at: Optional[datetime]
|
||||
contract_signed_at: Optional[datetime]
|
||||
contract_signer_name: Optional[str]
|
||||
contract_version: Optional[str]
|
||||
activated_at: Optional[datetime]
|
||||
created_at: datetime
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
class MemberOnboardingUpdate(BaseModel):
|
||||
first_name: Optional[str] = None
|
||||
last_name: Optional[str] = None
|
||||
phone: Optional[str] = None
|
||||
address: Optional[str] = None
|
||||
emergency_contact: Optional[str] = None
|
||||
onboarding_data: Optional[Any] = None
|
||||
complete_onboarding: bool = False
|
||||
|
||||
|
||||
class ContractSignSchema(BaseModel):
|
||||
signer_name: str
|
||||
agreed: bool
|
||||
contract_version: Optional[str] = None
|
||||
|
||||
|
||||
# ── Walks ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
class WalkResponse(BaseModel):
|
||||
id: uuid.UUID
|
||||
service_type: str
|
||||
walked_at: datetime
|
||||
duration_minutes: int
|
||||
notes: Optional[str]
|
||||
recorded_by: Optional[str]
|
||||
created_at: datetime
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
# ── Bookings ───────────────────────────────────────────────────────────────────
|
||||
|
||||
class BookingCreate(BaseModel):
|
||||
service_type: str
|
||||
requested_day: Optional[str] = None
|
||||
requested_date: Optional[datetime] = None
|
||||
requested_timeslot: Optional[str] = None
|
||||
notes: Optional[str] = None
|
||||
|
||||
|
||||
class BookingResponse(BaseModel):
|
||||
id: uuid.UUID
|
||||
service_type: str
|
||||
requested_date: Optional[datetime]
|
||||
status: str
|
||||
notes: Optional[str]
|
||||
admin_notes: Optional[str]
|
||||
created_at: datetime
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
class BookingSlotAvailabilityResponse(BaseModel):
|
||||
slot: str
|
||||
label: str
|
||||
booked: int
|
||||
capacity: int
|
||||
remaining: int
|
||||
is_available: bool
|
||||
|
||||
|
||||
class BookingAvailabilityDayResponse(BaseModel):
|
||||
date: str
|
||||
label: str
|
||||
slots: list[BookingSlotAvailabilityResponse]
|
||||
|
||||
|
||||
class BookingAvailabilityResponse(BaseModel):
|
||||
requested_date: str
|
||||
selected: BookingAvailabilityDayResponse
|
||||
alternatives: list[BookingAvailabilityDayResponse]
|
||||
|
||||
|
||||
# ── Messages ───────────────────────────────────────────────────────────────────
|
||||
|
||||
class MessageResponse(BaseModel):
|
||||
id: uuid.UUID
|
||||
subject: str
|
||||
body: str
|
||||
sent_by: Optional[str]
|
||||
read_at: Optional[datetime]
|
||||
created_at: datetime
|
||||
direction: str = "inbound"
|
||||
reply_to_id: Optional[uuid.UUID] = None
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
class MemberReplySchema(BaseModel):
|
||||
body: str
|
||||
|
||||
|
||||
# ── Admin: Create Member ───────────────────────────────────────────────────────
|
||||
|
||||
class AdminCreateMember(BaseModel):
|
||||
email: str
|
||||
first_name: str
|
||||
last_name: str
|
||||
phone: Optional[str] = None
|
||||
address: Optional[str] = None
|
||||
emergency_contact: Optional[str] = None
|
||||
onboarding_data: Optional[Any] = None
|
||||
service_pricing_overrides: Optional[Any] = None
|
||||
force_two_factor: Optional[bool] = None
|
||||
|
||||
|
||||
class AdminMemberResponse(BaseModel):
|
||||
id: uuid.UUID
|
||||
email: str
|
||||
first_name: str
|
||||
last_name: str
|
||||
phone: Optional[str]
|
||||
address: Optional[str]
|
||||
emergency_contact: Optional[str]
|
||||
notifications_enabled: bool
|
||||
onboarding_data: Optional[Any]
|
||||
is_claimed: bool
|
||||
is_active: bool
|
||||
member_status: str
|
||||
claimed_at: Optional[datetime]
|
||||
onboarding_completed_at: Optional[datetime]
|
||||
contract_signed_at: Optional[datetime]
|
||||
contract_signer_name: Optional[str]
|
||||
contract_version: Optional[str]
|
||||
activated_at: Optional[datetime]
|
||||
service_pricing_overrides: Optional[Any]
|
||||
force_two_factor: Optional[bool]
|
||||
created_at: datetime
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
class AdminMemberUpdate(BaseModel):
|
||||
first_name: Optional[str] = None
|
||||
last_name: Optional[str] = None
|
||||
phone: Optional[str] = None
|
||||
address: Optional[str] = None
|
||||
emergency_contact: Optional[str] = None
|
||||
notifications_enabled: Optional[bool] = None
|
||||
onboarding_data: Optional[Any] = None
|
||||
is_active: Optional[bool] = None
|
||||
member_status: Optional[str] = None
|
||||
service_pricing_overrides: Optional[Any] = None
|
||||
force_two_factor: Optional[bool] = None
|
||||
|
||||
|
||||
class AdminMemberToggleAction(BaseModel):
|
||||
enabled: bool
|
||||
|
||||
|
||||
class AdminBookingResponse(BaseModel):
|
||||
id: uuid.UUID
|
||||
member_id: uuid.UUID
|
||||
service_type: str
|
||||
requested_date: Optional[datetime]
|
||||
status: str
|
||||
notes: Optional[str]
|
||||
admin_notes: Optional[str]
|
||||
created_at: datetime
|
||||
# Joined fields
|
||||
member_first_name: Optional[str] = None
|
||||
member_last_name: Optional[str] = None
|
||||
member_email: Optional[str] = None
|
||||
member_dog_name: Optional[str] = None
|
||||
member_dog_breed: Optional[str] = None
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
class AdminBookingCreate(BaseModel):
|
||||
member_id: uuid.UUID
|
||||
service_type: str
|
||||
requested_date: Optional[datetime] = None
|
||||
status: str = "confirmed"
|
||||
notes: Optional[str] = None
|
||||
admin_notes: Optional[str] = None
|
||||
|
||||
|
||||
class AdminBookingUpdate(BaseModel):
|
||||
requested_date: Optional[datetime] = None
|
||||
status: Optional[str] = None # pending | confirmed | cancelled | completed
|
||||
notes: Optional[str] = None
|
||||
admin_notes: Optional[str] = None
|
||||
|
||||
|
||||
# ── Admin: Record Walk ─────────────────────────────────────────────────────────
|
||||
|
||||
class AdminRecordWalk(BaseModel):
|
||||
member_id: uuid.UUID
|
||||
walked_at: datetime
|
||||
service_type: str
|
||||
duration_minutes: int = 60
|
||||
notes: Optional[str] = None
|
||||
|
||||
|
||||
# ── Admin: Send Message ────────────────────────────────────────────────────────
|
||||
|
||||
class AdminSendMessage(BaseModel):
|
||||
member_id: uuid.UUID
|
||||
subject: str
|
||||
body: str
|
||||
|
||||
|
||||
class AdminNotificationSettingsResponse(BaseModel):
|
||||
automatic_member_notifications_enabled: bool
|
||||
nz_public_holiday_notifications_enabled: bool
|
||||
invoice_reminder_notifications_enabled: bool
|
||||
invoice_day_of_week: int
|
||||
|
||||
|
||||
class AdminNotificationSettingsUpdate(BaseModel):
|
||||
automatic_member_notifications_enabled: Optional[bool] = None
|
||||
nz_public_holiday_notifications_enabled: Optional[bool] = None
|
||||
invoice_reminder_notifications_enabled: Optional[bool] = None
|
||||
invoice_day_of_week: Optional[int] = None
|
||||
|
||||
|
||||
class AdminNotificationRunResponse(BaseModel):
|
||||
automatic_member_notifications_enabled: bool
|
||||
public_holiday_messages_sent: int
|
||||
invoice_reminders_sent: int
|
||||
|
||||
|
||||
class AdminNotificationFeedItemResponse(BaseModel):
|
||||
id: str
|
||||
type: str
|
||||
title: str
|
||||
description: str
|
||||
created_at: datetime
|
||||
href: str
|
||||
|
||||
|
||||
class AdminNotificationsResponse(BaseModel):
|
||||
items: list[AdminNotificationFeedItemResponse]
|
||||
total: int
|
||||
settings: AdminNotificationSettingsResponse
|
||||
|
||||
|
||||
class AdminMessageHistoryResponse(BaseModel):
|
||||
id: uuid.UUID
|
||||
member_id: uuid.UUID
|
||||
member_name: str
|
||||
member_email: str
|
||||
subject: str
|
||||
body: str
|
||||
sent_by: Optional[str]
|
||||
created_at: datetime
|
||||
read_at: Optional[datetime]
|
||||
|
||||
|
||||
# ── Contract ───────────────────────────────────────────────────────────────────
|
||||
|
||||
class ContractResponse(BaseModel):
|
||||
onboarding_data: Optional[Any]
|
||||
member_name: str
|
||||
email: str
|
||||
member_status: str
|
||||
contract_signed_at: Optional[datetime]
|
||||
contract_signer_name: Optional[str]
|
||||
contract_version: Optional[str]
|
||||
activated_at: Optional[datetime]
|
||||
joined_at: datetime
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
Reference in New Issue
Block a user