Skip to content
Open
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
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ COPY pyproject.toml pyproject.toml

RUN pip install poetry
RUN poetry config virtualenvs.create false
RUN poetry install --no-dev
RUN poetry install --no-root

COPY . /app

Expand Down
4 changes: 4 additions & 0 deletions src/catalogue/views/product.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from src.catalogue.services import get_product_service
from src.common.exceptions.base import ObjectDoesNotExistException
from src.common.schemas.common import ErrorResponse
from src.reviews.services import ProductAnalyticsService


router = APIRouter(prefix=CatalogueRoutesPrefixes.product)
Expand Down Expand Up @@ -51,6 +52,7 @@ async def product_detail(
response: Response,
pk: int,
service: Annotated[get_product_service, Depends()],
analytics_service: Annotated[ProductAnalyticsService, Depends()],
) -> Union[Response, ErrorResponse]:
"""
Retrieve product.
Expand All @@ -60,6 +62,8 @@ async def product_detail(
"""
try:
response = await service.detail(pk=pk)
# track product visit
await analytics_service.track_product_visit(product_id=pk)
except ObjectDoesNotExistException as exc:
response.status_code = status.HTTP_404_NOT_FOUND
return ErrorResponse(message=exc.message)
Expand Down
3 changes: 2 additions & 1 deletion src/common/databases/mongo_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from src.base_settings import base_settings
from src.common.singleton import SingletonMeta
from src.reviews.models.mongo import ProductReview
from src.reviews.models.mongo import ProductReview, ProductAnalytics


class AsyncMongoDBClient(AsyncIOMotorClient, metaclass=SingletonMeta):
Expand All @@ -21,5 +21,6 @@ async def init_mongo_db():
database=client.get_database(),
document_models=[
ProductReview,
ProductAnalytics
],
)
8 changes: 8 additions & 0 deletions src/reviews/models/mongo.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import uuid
from typing import Optional
from datetime import datetime

from beanie import Document
from pydantic import (
Expand Down Expand Up @@ -28,3 +29,10 @@ class ProductReview(Document, BaseProductReview):

class Settings:
name = 'productReviews'

class ProductAnalytics(Document):
product_id: int
timestamp: datetime = Field(default_factory=datetime.now)

class Settings:
name = 'productAnalytics'
5 changes: 4 additions & 1 deletion src/reviews/repositories.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from src.common.repository.beanie import BaseMongoRepository
from src.reviews.models.mongo import ProductReview
from src.reviews.models.mongo import ProductReview, ProductAnalytics


class ProductReviewRepository(BaseMongoRepository[ProductReview]):
__model__ = ProductReview

class ProductAnalyticsRepository(BaseMongoRepository[ProductAnalytics]):
__model__ = ProductAnalytics
16 changes: 15 additions & 1 deletion src/reviews/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
from src.reviews.models.mongo import (
ProductReview,
Reply,
ProductAnalytics
)
from src.reviews.repositories import ProductReviewRepository
from src.reviews.repositories import ProductReviewRepository, ProductAnalyticsRepository


class ProductReviewService(BaseService):
Expand Down Expand Up @@ -44,3 +45,16 @@ async def add_reply(self, pk: str, reply: Reply) -> ProductReview:
review.replies.append(reply.model_dump())

return await review.save()


class ProductAnalyticsService(BaseService):
def __init__(
self,
repository: Annotated[ProductAnalyticsRepository, Depends(ProductAnalyticsRepository)]
):
super().__init__(repository=repository)

async def track_product_visit(self, product_id: int) -> ProductAnalytics:
"""Track a product page visit by creating an analytics record."""
analytics_record = ProductAnalytics(product_id=product_id)
return await self.repository.create(analytics_record)