Skip to content

Commit 556cc3f

Browse files
authored
Najwiekszy bugfix w miescie (#56)
* Najwiekszy bugfix w miescie * Visual fixes * Fixed marketplace confirmation * compile fix * Fix * Error display fix * tests
1 parent 1558c28 commit 556cc3f

33 files changed

Lines changed: 7792 additions & 1019 deletions

.concat.conf

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
frontend/lib
2-
bbackend/tests
1+
Afrontend/lib
2+
backend/tests
33
backend/user_auth_service/app
4-
bbackend/event_ticketing_service/app
4+
backend/event_ticketing_service/app
55

\

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
frontend/lib
2+
Abackend/tests
3+
Abackend/user_auth_service/app
4+
backend/event_ticketing_service/app
5+

backend/event_ticketing_service/app/repositories/cart_repository.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,12 @@ def add_item_from_resell(self, customer_id: int, ticket_id: int) -> CartItemMode
160160

161161
def remove_item(self, customer_id: int, cart_item_id: int) -> bool:
162162
# Get the shopping cart for the customer
163-
cart = self.db.query(ShoppingCartModel).filter(ShoppingCartModel.customer_id == customer_id).first()
163+
cart = self.db.query(ShoppingCartModel).filter(
164+
ShoppingCartModel.customer_id == customer_id).first()
164165
if not cart:
165-
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Shopping cart not found")
166+
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
167+
detail="Shopping cart not found")
166168

167-
# Find the cart item to remove
168169
cart_item_to_remove = (
169170
self.db.query(CartItemModel)
170171
.filter(CartItemModel.cart_item_id == cart_item_id, CartItemModel.cart_id == cart.cart_id)
@@ -179,7 +180,6 @@ def remove_item(self, customer_id: int, cart_item_id: int) -> bool:
179180

180181
self.db.delete(cart_item_to_remove)
181182
self.db.commit()
182-
logger.info(f"Removed cart_item_id {cart_item_id} from cart_id {cart.cart_id} of customer_id {customer_id}")
183183
return True
184184

185185
#----------------------------------------------------------

backend/event_ticketing_service/app/routers/cart.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,16 @@ async def get_shopping_cart(
3232
cart_repo: CartRepository = Depends(get_cart_repository)
3333
):
3434
"""Get items in the user's shopping cart"""
35-
logger.info(f"Get shopping cart of {user}")
35+
logger.info(f"Get shopping cart for user_id {user['user_id']}")
3636
user_id = user["user_id"]
37-
logger.info(f"Get shopping cart for user_id {user_id}")
3837

3938
cart_items_models = cart_repo.get_cart_items_details(customer_id=user_id)
4039

4140
response_items: List[CartItemWithDetails] = []
4241
for item_model in cart_items_models:
4342
if item_model.ticket_type:
4443
cart_item_detail = CartItemWithDetails(
44+
cart_item_id=item_model.cart_item_id,
4545
ticket_type=TicketType.model_validate(item_model.ticket_type),
4646
quantity=item_model.quantity
4747
)
@@ -72,10 +72,15 @@ async def add_to_cart(
7272
)
7373

7474
return CartItemWithDetails(
75+
cart_item_id=cart_item_model.cart_item_id,
7576
ticket_type=TicketType.model_validate(cart_item_model.ticket_type),
7677
quantity=cart_item_model.quantity
7778
)
7879

80+
raise HTTPException(
81+
status_code=status.HTTP_400_BAD_REQUEST,
82+
detail="Ticket type ID is required."
83+
)
7984

8085
@router.delete(
8186
"/items/{cart_item_id}",

backend/event_ticketing_service/app/routers/events.py

Lines changed: 142 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,36 @@
1-
from typing import List
2-
from datetime import datetime, timedelta
1+
from typing import List, Optional
2+
from datetime import datetime
33

44
from app.database import get_db
55
from sqlalchemy.orm import Session
6-
from fastapi import Path, Depends, APIRouter
6+
from sqlalchemy import or_, and_, desc, asc
7+
from fastapi import Path, Depends, APIRouter, Query, HTTPException, status
78
from app.filters.events_filter import EventsFilter
89
from app.repositories.event_repository import EventRepository, get_event_repository
910
from app.schemas.event import EventBase, EventUpdate, EventDetails, NotificationRequest
1011
from app.utils.jwt_auth import get_current_organizer, get_current_admin
12+
from app.models.events import EventModel
13+
from app.models.location import LocationModel
14+
from app.models.ticket_type import TicketTypeModel
1115

1216
router = APIRouter(prefix="/events", tags=["events"])
1317

1418

1519
@router.post("/", response_model=EventDetails)
1620
async def create_event(
17-
event_data: EventBase,
18-
event_repo: EventRepository = Depends(get_event_repository),
19-
current_organizer = Depends(get_current_organizer)
21+
event_data: EventBase,
22+
event_repo: EventRepository = Depends(get_event_repository),
23+
current_organizer=Depends(get_current_organizer)
2024
):
2125
"""Create a new event (requires authentication)"""
2226
return event_repo.create_event(event_data, current_organizer["role_id"])
2327

2428

2529
@router.post("/authorize/{event_id}", response_model=bool)
2630
async def authorize_event(
27-
event_id: int = Path(..., title="Event ID"),
28-
event_repo: EventRepository = Depends(get_event_repository),
29-
current_admin = Depends(get_current_admin)
31+
event_id: int = Path(..., title="Event ID"),
32+
event_repo: EventRepository = Depends(get_event_repository),
33+
current_admin=Depends(get_current_admin)
3034
):
3135
"""Authorize an event (requires admin authentication)"""
3236
event_repo.authorize_event(event_id)
@@ -35,9 +39,9 @@ async def authorize_event(
3539

3640
@router.post("/reject/{event_id}", response_model=bool)
3741
async def reject_event(
38-
event_id: int = Path(..., title="Event ID"),
39-
event_repo: EventRepository = Depends(get_event_repository),
40-
current_admin = Depends(get_current_admin)
42+
event_id: int = Path(..., title="Event ID"),
43+
event_repo: EventRepository = Depends(get_event_repository),
44+
current_admin=Depends(get_current_admin)
4145
):
4246
"""Reject an event (requires admin authentication)"""
4347
event_repo.reject_event(event_id)
@@ -46,38 +50,151 @@ async def reject_event(
4650

4751
@router.get("", response_model=List[EventDetails])
4852
def get_events_endpoint(
49-
filters: EventsFilter = Depends(),
50-
event_repo: EventRepository = Depends(get_event_repository),
53+
page: int = Query(1, ge=1, description="Page number"),
54+
limit: int = Query(50, ge=1, le=100, description="Items per page"),
55+
search: Optional[str] = Query(None, description="Search by event name or description"),
56+
location: Optional[str] = Query(None, description="Filter by location name"),
57+
start_date_from: Optional[datetime] = Query(None,
58+
description="Events starting after this date"),
59+
start_date_to: Optional[datetime] = Query(None,
60+
description="Events starting before this date"),
61+
min_price: Optional[float] = Query(None, ge=0,
62+
description="Minimum ticket price available"),
63+
max_price: Optional[float] = Query(None, ge=0,
64+
description="Maximum ticket price available"),
65+
organizer_id: Optional[int] = Query(None, description="Filter by specific organizer"),
66+
minimum_age: Optional[int] = Query(None, ge=0,
67+
description="Minimum required age for attendees"),
68+
status: Optional[str] = Query(None, description="Filter by event status"),
69+
categories: Optional[str] = Query(None,
70+
description="Filter by categories (comma-separated)"),
71+
sort_by: str = Query("start_date",
72+
description="Sort field (start_date, name, creation_date)"),
73+
sort_order: str = Query("asc", description="Sort order (asc/desc)"),
74+
db: Session = Depends(get_db),
5175
):
52-
events = event_repo.get_events(filters)
76+
"""
77+
Get list of events with advanced filtering, searching, and pagination
78+
"""
79+
# Build the query with joins for filtering
80+
query = db.query(EventModel).join(LocationModel,
81+
EventModel.location_id == LocationModel.location_id)
82+
83+
# Apply search filter
84+
if search:
85+
search_filter = f"%{search}%"
86+
query = query.filter(
87+
or_(
88+
EventModel.name.ilike(search_filter),
89+
EventModel.description.ilike(search_filter)
90+
)
91+
)
92+
93+
# Apply location filter
94+
if location:
95+
query = query.filter(LocationModel.name.ilike(f"%{location}%"))
96+
97+
# Apply date filters
98+
if start_date_from:
99+
query = query.filter(EventModel.start_date >= start_date_from)
100+
if start_date_to:
101+
query = query.filter(EventModel.start_date <= start_date_to)
102+
103+
# Apply organizer filter
104+
if organizer_id:
105+
query = query.filter(EventModel.organizer_id == organizer_id)
106+
107+
# Apply minimum age filter
108+
if minimum_age:
109+
query = query.filter(EventModel.minimum_age >= minimum_age)
110+
111+
# Apply status filter
112+
if status:
113+
if status not in ["pending", "created", "rejected", "cancelled"]:
114+
raise HTTPException(
115+
status_code=status.HTTP_400_BAD_REQUEST,
116+
detail="Invalid status. Must be one of: pending, created, rejected, cancelled"
117+
)
118+
query = query.filter(EventModel.status == status)
119+
120+
# Apply price filters (requires subquery on ticket types)
121+
if min_price is not None or max_price is not None:
122+
price_subquery = db.query(TicketTypeModel.event_id).distinct()
123+
if min_price is not None:
124+
price_subquery = price_subquery.filter(TicketTypeModel.price >= min_price)
125+
if max_price is not None:
126+
price_subquery = price_subquery.filter(TicketTypeModel.price <= max_price)
127+
128+
query = query.filter(EventModel.event_id.in_(price_subquery))
129+
130+
# Apply categories filter (simplified - assuming categories are stored as comma-separated values in description or using JSON)
131+
if categories:
132+
category_list = [cat.strip() for cat in categories.split(",")]
133+
category_filters = [EventModel.description.ilike(f"%{cat}%") for cat in category_list]
134+
query = query.filter(or_(*category_filters))
135+
136+
# Apply sorting
137+
if sort_by not in ["start_date", "name", "creation_date"]:
138+
raise HTTPException(
139+
status_code=status.HTTP_400_BAD_REQUEST,
140+
detail="Invalid sort_by. Must be one of: start_date, name, creation_date"
141+
)
142+
143+
if sort_order not in ["asc", "desc"]:
144+
raise HTTPException(
145+
status_code=status.HTTP_400_BAD_REQUEST,
146+
detail="Invalid sort_order. Must be 'asc' or 'desc'"
147+
)
148+
149+
# Map sort fields
150+
sort_field_map = {
151+
"start_date": EventModel.start_date,
152+
"name": EventModel.name,
153+
"creation_date": EventModel.event_id # Assuming event_id correlates with creation order
154+
}
155+
156+
sort_field = sort_field_map[sort_by]
157+
if sort_order == "desc":
158+
query = query.order_by(desc(sort_field))
159+
else:
160+
query = query.order_by(asc(sort_field))
161+
162+
# Apply pagination
163+
offset = (page - 1) * limit
164+
query = query.offset(offset).limit(limit)
165+
166+
# Execute query and get results
167+
events = query.all()
168+
169+
# Convert to response models
53170
return [EventDetails.model_validate(e) for e in events]
54171

55172

56173
@router.put("/{event_id}", response_model=EventDetails)
57174
def update_event_endpoint(
58-
event_id: int = Path(..., title="Event ID"),
59-
update_data: EventUpdate = Depends(),
60-
event_repo: EventRepository = Depends(get_event_repository),
61-
current_organizer = Depends(get_current_organizer)
175+
event_id: int = Path(..., title="Event ID"),
176+
update_data: EventUpdate = Depends(),
177+
event_repo: EventRepository = Depends(get_event_repository),
178+
current_organizer=Depends(get_current_organizer)
62179
):
63180
return event_repo.update_event(event_id, update_data, current_organizer["role_id"])
64181

65182

66183
@router.delete("/{event_id}", response_model=bool)
67184
def cancel_event_endpoint(
68-
event_id: int = Path(..., title="Event ID"),
69-
event_repo: EventRepository = Depends(get_event_repository),
70-
current_organizer = Depends(get_current_organizer)
185+
event_id: int = Path(..., title="Event ID"),
186+
event_repo: EventRepository = Depends(get_event_repository),
187+
current_organizer=Depends(get_current_organizer)
71188
):
72189
event_repo.cancel_event(event_id, current_organizer["role_id"])
73190
return True
74191

75192

76193
@router.post("/{event_id}/notify")
77194
async def notify_participants(
78-
event_id: int = Path(..., title="Event ID"),
79-
notification: NotificationRequest = None,
80-
current_organizer = Depends(get_current_organizer),
195+
event_id: int = Path(..., title="Event ID"),
196+
notification: NotificationRequest = None,
197+
current_organizer=Depends(get_current_organizer),
81198
):
82199
"""Notify participants of an event (requires organizer authentication)"""
83200
return {

0 commit comments

Comments
 (0)