Skip to content
Merged

Dev #126

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,14 @@ def clear_location_data():
clear_data_location(db=session, is_commit=True)


@app.command()
def checkin_example_data():
from models import factory_session
from seeders.initial_checkin_data import initialize_checkin_data

with factory_session() as session:
initialize_checkin_data(db=session)


if __name__ == "__main__":
app()
6 changes: 5 additions & 1 deletion repository/checkin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import datetime
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError

from uuid import UUID
from sqlalchemy import select
from sqlalchemy.orm import Session
from core.log import logger
Expand All @@ -21,6 +21,10 @@ def get_user_data_by_payment_id(db: Session, payment_id: str) -> User | None:
Returns:
User | None: User data or None if not found
"""
try:
UUID(payment_id)
except ValueError:
return None
query = (
select(User)
.join(Payment, Payment.user_id == User.id)
Expand Down
15 changes: 14 additions & 1 deletion repository/speaker.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@
from schemas.speaker import SpeakerResponseItem


def get_all_speakers(db: Session, order_dir: Literal["asc", "desc"] = "asc"):
def get_all_speakers(
db: Session,
order_dir: Literal["asc", "desc"] = "asc",
search: Optional[str] = None,
):
# Query dasar
stmt = select(Speaker)

Expand All @@ -21,6 +25,15 @@ def get_all_speakers(db: Session, order_dir: Literal["asc", "desc"] = "asc"):
else:
stmt = stmt.order_by(Speaker.updated_at.desc())

if search:
search_pattern = f"%{search}%"
stmt = stmt.join(User, Speaker.user).where(
(User.username.ilike(search_pattern))
| (User.first_name.ilike(search_pattern))
| (User.last_name.ilike(search_pattern))
| (User.email.ilike(search_pattern))
)

# Tambahkan pagination (offset + limit)
# Hitung total data sebelum pagination
total_count = db.scalar(select(func.count()).select_from(stmt.subquery()))
Expand Down
4 changes: 3 additions & 1 deletion routes/speaker.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ async def get_speaker(
):
try:
if query.all:
data = speakerRepo.get_all_speakers(db=db, order_dir=query.order_dir)
data = speakerRepo.get_all_speakers(
db=db, search=query.search, order_dir=query.order_dir
)
else:
data = speakerRepo.get_speaker_per_page_by_search(
db=db,
Expand Down
2 changes: 1 addition & 1 deletion routes/tests/test_checkin.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def test_get_user_data_by_payment_id_not_found(self):
def test_get_user_data_by_payment_id_invalid(self):
"""Test response when payment ID format is invalid"""
response = self.client.get("/ticket/checkin/invalid-uuid-format")
self.assertIn(response.status_code, [404, 500])
self.assertEqual(response.status_code, 404)

def test_get_user_data_with_no_tshirt_size(self):
"""Test retrieval when user has no t-shirt size set"""
Expand Down
9 changes: 4 additions & 5 deletions routes/ticket.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import traceback

from fastapi import APIRouter, Depends, HTTPException, Request
from pydantic import ValidationError
from sqlalchemy.orm import Session
Expand All @@ -25,7 +24,7 @@
from repository.ticket import get_active_tickets
from schemas.checkin import (
CheckinUserRequest,
CheckinUserResponse,
CheckinUserResponseSchema,
user_model_to_checkin_response,
)
from schemas.common import (
Expand Down Expand Up @@ -145,7 +144,7 @@ async def get_my_ticket(
@router.get(
"/checkin/{payment_id}",
responses={
"200": {"model": CheckinUserResponse},
"200": {"model": CheckinUserResponseSchema},
"404": {"model": NotFoundResponse},
"500": {"model": InternalServerErrorResponse},
},
Expand Down Expand Up @@ -192,7 +191,7 @@ async def checkin(payment_id: str, db: Session = Depends(get_db_sync)):
@router.patch(
"/checkin",
responses={
"200": {"model": CheckinUserResponse},
"200": {"model": CheckinUserResponseSchema},
"401": {"model": UnauthorizedResponse},
"402": {"model": PaymentRequiredResponse},
"404": {"model": NotFoundResponse},
Expand Down Expand Up @@ -259,7 +258,7 @@ async def checkin_user(
@router.patch(
"/checkin/reset",
responses={
"200": {"model": CheckinUserResponse},
"200": {"model": CheckinUserResponseSchema},
"401": {"model": UnauthorizedResponse},
"402": {"model": PaymentRequiredResponse},
"404": {"model": NotFoundResponse},
Expand Down
5 changes: 5 additions & 0 deletions schemas/checkin.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ class CheckinUserResponse(BaseModel):
checked_in_day2: bool = False


class CheckinUserResponseSchema(BaseModel):
data: CheckinUserResponse
message: str = "User check-in data retrieved successfully"


def user_model_to_checkin_response(user: User) -> CheckinUserResponse:
"""Convert User model to CheckinUserResponse schema

Expand Down
90 changes: 90 additions & 0 deletions seeders/initial_checkin_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
from sqlalchemy.orm import Session
from sqlalchemy import select


def initialize_checkin_data(
db: Session,
):
import uuid

from models.User import User
from models.Ticket import Ticket
from models.Payment import Payment, PaymentStatus
from core.security import generate_hash_password
from core.helper import get_current_time_in_timezone

ticket_id = uuid.UUID("550e8400-e29b-41d4-a716-446655440000")
payment_id = uuid.UUID("550e8400-e29b-41d4-a716-446655440001")
user_id = uuid.UUID("550e8400-e29b-41d4-a716-446655440002")

# Check if data already exists
existing_user = db.execute(
select(User).where(User.id == user_id)
).scalar_one_or_none()
existing_ticket = db.execute(
select(Ticket).where(Ticket.id == ticket_id)
).scalar_one_or_none()
existing_payment = db.execute(
select(Payment).where(Payment.id == payment_id)
).scalar_one_or_none()

if existing_user and existing_ticket and existing_payment:
print("All checkin data already exists. Skipping...")
return

try:
if not existing_user:
user = User(
id=user_id,
username="checkinuser",
email="checkinuser@example.com",
phone="+628123456789",
first_name="test",
last_name="user",
password=generate_hash_password("password"),
is_active=True,
)
db.add(user)
else:
user = existing_user

if not existing_ticket:
ticket = Ticket(
id=ticket_id,
name="Test Conference Ticket",
price=500000,
user_participant_type="In Person",
is_sold_out=False,
is_active=True,
description="Test ticket for payment",
)
db.add(ticket)
else:
ticket = existing_ticket

if not existing_payment:
payment = Payment(
id=payment_id,
user_id=user.id,
ticket_id=ticket.id,
payment_link="https://mayar.id/pay/test-link",
status=PaymentStatus.PAID,
created_at=get_current_time_in_timezone(),
mayar_id="mayar-test-id",
mayar_transaction_id="mayar-test-tx",
amount=500000,
description="Test payment",
)
db.add(payment)
else:
payment = existing_payment

db.commit()
db.refresh(user)
db.refresh(ticket)
db.refresh(payment)
print("Checkin data initialized successfully!")
except Exception as e:
db.rollback()
print(f"Error initializing checkin data: {e}")
raise
Loading