Skip to content
Merged
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
22 changes: 20 additions & 2 deletions apps/api/backend/api/routes/reviews.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
from uuid import UUID

from fastapi import APIRouter, status

from backend.schemas.review import (
ProductReviewListResponse,
ReviewCreateRequest,
ReviewCreateResponse,
ReviewDeleteRequest,
ReviewDeleteResponse,
ReviewUpdateRequest,
ReviewUpdateResponse,
)
from backend.services.review_service import create_review, delete_review, update_review
from backend.services.review_service import (
create_review,
delete_review,
list_product_reviews,
update_review,
)

router = APIRouter(prefix="/reviews", tags=["reviews"])

Expand Down Expand Up @@ -42,4 +50,14 @@ def delete_product_review(
payload: ReviewDeleteRequest,
) -> ReviewDeleteResponse:
result = delete_review(review_id, payload)
return ReviewDeleteResponse(**result)
return ReviewDeleteResponse(**result)


@router.get(
"/products/{product_id}/reviews",
response_model=ProductReviewListResponse,
status_code=status.HTTP_200_OK,
)
def get_product_reviews(product_id: UUID) -> ProductReviewListResponse:
result = list_product_reviews(product_id)
return ProductReviewListResponse(**result)
4 changes: 4 additions & 0 deletions apps/api/backend/schemas/order_history.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@ class OrderHistoryItemResponse(BaseModel):


class OrderHistorySummaryResponse(BaseModel):
order_history_id: str
history_event_type: str
history_event_at: datetime
order_id: UUID
cart_id: UUID | None = None
order_status: str
payment_id: UUID | None = None
payment_status: str | None = None
subtotal_amount: Decimal
discount_amount: Decimal
Expand Down
24 changes: 23 additions & 1 deletion apps/api/backend/schemas/review.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from datetime import datetime
from decimal import Decimal
from uuid import UUID

from pydantic import BaseModel, Field
Expand Down Expand Up @@ -50,4 +51,25 @@ class ReviewDeleteResponse(BaseModel):
user_id: UUID
review_status: str
updated_at: datetime
message: str
message: str


class ProductReviewItemResponse(BaseModel):
review_id: UUID
user_id: UUID
product_id: UUID
order_item_id: UUID
rating: int
review_title: str
review_content: str
review_status: str
created_at: datetime
updated_at: datetime | None = None
user_name: str | None = None


class ProductReviewListResponse(BaseModel):
product_id: UUID
total_reviews: int
average_rating: Decimal | None = None
reviews: list[ProductReviewItemResponse]
54 changes: 43 additions & 11 deletions apps/api/backend/services/order_history_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,56 @@ def get_order_history(user_id: UUID) -> dict[str, Any]:

orders_query = text("""
SELECT
CONCAT(o.order_id::text, CHR(58), 'created') AS order_history_id,
'order_created' AS history_event_type,
o.ordered_at AS history_event_at,
o.order_id,
o.user_id,
o.cart_id,
o.order_status,
'created' AS order_status,
NULL AS payment_id,
NULL AS payment_status,
o.subtotal_amount,
o.discount_amount,
o.total_amount,
o.currency,
c.coupon_name,
o.ordered_at,
(
SELECT p.payment_status
FROM payments p
WHERE p.order_id = o.order_id
ORDER BY p.created_at DESC
LIMIT 1
) AS payment_status
o.ordered_at
FROM orders o
LEFT JOIN coupons c
ON c.coupon_id = o.coupon_id
ON c.coupon_id = o.coupon_id
WHERE o.user_id = :user_id
ORDER BY o.ordered_at DESC, o.created_at DESC

UNION ALL

SELECT
CONCAT(o.order_id::text, CHR(58), 'payment', CHR(58), p.payment_id::text) AS order_history_id,
'payment_simulated' AS history_event_type,
COALESCE(p.paid_at, p.created_at) AS history_event_at,
o.order_id,
o.user_id,
o.cart_id,
CASE
WHEN p.payment_status = 'paid' THEN 'paid'
WHEN p.payment_status = 'failed' THEN 'payment_failed'
ELSE o.order_status
END AS order_status,
p.payment_id,
p.payment_status,
o.subtotal_amount,
o.discount_amount,
o.total_amount,
o.currency,
c.coupon_name,
o.ordered_at
FROM orders o
JOIN payments p
ON p.order_id = o.order_id
LEFT JOIN coupons c
ON c.coupon_id = o.coupon_id
WHERE o.user_id = :user_id

ORDER BY history_event_at DESC
""")

order_items_query = text("""
Expand Down Expand Up @@ -100,9 +128,13 @@ def get_order_history(user_id: UUID) -> dict[str, Any]:

orders.append(
{
"order_history_id": order_row["order_history_id"],
"history_event_type": order_row["history_event_type"],
"history_event_at": order_row["history_event_at"],
"order_id": order_row["order_id"],
"cart_id": order_row["cart_id"],
"order_status": order_row["order_status"],
"payment_id": order_row["payment_id"],
"payment_status": order_row["payment_status"],
"subtotal_amount": Decimal(str(order_row["subtotal_amount"])),
"discount_amount": Decimal(str(order_row["discount_amount"])),
Expand Down
21 changes: 16 additions & 5 deletions apps/api/backend/services/order_service.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from datetime import datetime, timedelta, timezone
from decimal import Decimal, ROUND_HALF_UP
from typing import Any
from uuid import UUID
Expand All @@ -9,6 +10,12 @@
from backend.schemas.order import OrderCreateRequest


KST = timezone(timedelta(hours=9))


def now_kst_naive() -> datetime:
return datetime.now(KST).replace(tzinfo=None)

def create_order_from_cart(payload: OrderCreateRequest) -> dict[str, Any]:
cart_query = text("""
SELECT
Expand Down Expand Up @@ -88,9 +95,9 @@ def create_order_from_cart(payload: OrderCreateRequest) -> dict[str, Any]:
:discount_amount,
:total_amount,
:currency,
CURRENT_TIMESTAMP,
CURRENT_TIMESTAMP,
CURRENT_TIMESTAMP
:now,
:now,
:now
)
RETURNING
order_id,
Expand Down Expand Up @@ -126,8 +133,8 @@ def create_order_from_cart(payload: OrderCreateRequest) -> dict[str, Any]:
:final_item_amount,
:currency,
:line_total,
CURRENT_TIMESTAMP,
CURRENT_TIMESTAMP
:now,
:now
)
RETURNING
order_item_id,
Expand Down Expand Up @@ -244,6 +251,8 @@ def create_order_from_cart(payload: OrderCreateRequest) -> dict[str, Any]:

total_amount = subtotal_amount - discount_amount

now = now_kst_naive()

created_order = connection.execute(
insert_order_query,
{
Expand All @@ -254,6 +263,7 @@ def create_order_from_cart(payload: OrderCreateRequest) -> dict[str, Any]:
"discount_amount": discount_amount,
"total_amount": total_amount,
"currency": currency,
"now": now
},
).mappings().first()

Expand All @@ -277,6 +287,7 @@ def create_order_from_cart(payload: OrderCreateRequest) -> dict[str, Any]:
"final_item_amount": item["final_item_amount"],
"line_total": item["line_total"],
"currency": item["currency"],
"now": now
},
).mappings().first()

Expand Down
42 changes: 30 additions & 12 deletions apps/api/backend/services/payment_service.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from datetime import datetime
from datetime import datetime, timedelta, timezone
from decimal import Decimal
from typing import Any

Expand All @@ -9,6 +9,12 @@
from backend.schemas.payment import PaymentSimulationRequest


KST = timezone(timedelta(hours=9))


def now_kst_naive() -> datetime:
return datetime.now(KST).replace(tzinfo=None)

def simulate_payment(payload: PaymentSimulationRequest) -> dict[str, Any]:
order_query = text("""
SELECT
Expand Down Expand Up @@ -46,10 +52,10 @@ def simulate_payment(payload: PaymentSimulationRequest) -> dict[str, Any]:
:pg_provider,
:transaction_id,
:failure_code,
CURRENT_TIMESTAMP,
:now,
:paid_at,
CURRENT_TIMESTAMP,
CURRENT_TIMESTAMP
:now,
:now
)
RETURNING
payment_id,
Expand All @@ -70,24 +76,24 @@ def simulate_payment(payload: PaymentSimulationRequest) -> dict[str, Any]:
UPDATE orders
SET
order_status = 'paid',
updated_at = CURRENT_TIMESTAMP
updated_at = :now
WHERE order_id = :order_id
""")

update_order_failed_query = text("""
UPDATE orders
SET
order_status = 'payment_failed',
updated_at = CURRENT_TIMESTAMP
updated_at = :now
WHERE order_id = :order_id
""")

update_cart_checked_out_query = text("""
UPDATE carts
SET
cart_status = 'checked_out',
checked_out_at = CURRENT_TIMESTAMP,
updated_at = CURRENT_TIMESTAMP
checked_out_at = :now,
updated_at = :now
WHERE cart_id = :cart_id
AND cart_status = 'active'
""")
Expand All @@ -112,23 +118,30 @@ def simulate_payment(payload: PaymentSimulationRequest) -> dict[str, Any]:

requested_amount = Decimal(str(order["total_amount"]))
currency = order["currency"]
now = now_kst_naive()

if payload.simulate_result == "success":
payment_status = "paid"
paid_amount = requested_amount
failure_code = None
paid_at = datetime.now()
paid_at = now
pg_provider = "mock_pg"
transaction_id = f"tx-{payload.order_id}"

connection.execute(
update_order_success_query,
{"order_id": payload.order_id},
{
"order_id": payload.order_id,
"now": now,
},
)

connection.execute(
update_cart_checked_out_query,
{"cart_id": order["cart_id"]},
{
"cart_id": order["cart_id"],
"now": now,
},
)
else:
payment_status = "failed"
Expand All @@ -137,9 +150,13 @@ def simulate_payment(payload: PaymentSimulationRequest) -> dict[str, Any]:
paid_at = None
pg_provider = "mock_pg"
transaction_id = None

connection.execute(
update_order_failed_query,
{"order_id": payload.order_id},
{
"order_id": payload.order_id,
"now": now,
},
)

created_payment = connection.execute(
Expand All @@ -154,6 +171,7 @@ def simulate_payment(payload: PaymentSimulationRequest) -> dict[str, Any]:
"transaction_id": transaction_id,
"failure_code": failure_code,
"paid_at": paid_at,
"now": now,
},
).mappings().first()

Expand Down
Loading
Loading