MukeshKapoor25 commited on
Commit
e31a512
Β·
1 Parent(s): dba1656

get catalogue details

Browse files
app/product_catalogue/controllers/router.py CHANGED
@@ -109,6 +109,65 @@ async def list_products(payload: ProductListRequest):
109
  )
110
 
111
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  # Legacy GET endpoint for backward compatibility (if needed)
113
  @router.get("/", response_model=ProductListResponse)
114
  async def list_products_get(
 
109
  )
110
 
111
 
112
+ @router.get("/{catalogue_id}", response_model=CustomerProductResponse)
113
+ async def get_product_details(catalogue_id: str = Path(..., description="Catalogue ID of the product")):
114
+ """
115
+ Get detailed information for a specific product.
116
+
117
+ **Customer-facing endpoint** - Returns detailed product information.
118
+ **Company-level products** - Products are shared across the platform.
119
+
120
+ - **catalogue_id**: The unique catalogue identifier for the product
121
+
122
+ Returns detailed product information including:
123
+ - Complete product details (name, category, brand, description)
124
+ - Pricing information (MRP, currency, GST rate)
125
+ - Stock availability status
126
+ - All product images and media
127
+ - Product specifications and attributes
128
+
129
+ **Data Source**: MongoDB collection `scm_catalogues`
130
+ **Filters Applied**:
131
+ - `catalogue_type = "Product"`
132
+ - `meta.status = "active" or "Active"`
133
+ - `allow_ecommerce = true`
134
+ - `catalogue_id = {catalogue_id}`
135
+
136
+ **Customer-Safe Fields Only**:
137
+ - No pricing levels beyond MRP
138
+ - No inventory numbers exposed
139
+ - No internal procurement data
140
+ - No commission or loyalty data
141
+ """
142
+ try:
143
+ logger.info("Getting product details", extra={
144
+ "catalogue_id": catalogue_id
145
+ })
146
+
147
+ # Get product details
148
+ product = await product_catalogue_service.get_product_details(catalogue_id)
149
+
150
+ if not product:
151
+ raise HTTPException(
152
+ status_code=status.HTTP_404_NOT_FOUND,
153
+ detail=f"Product with catalogue_id '{catalogue_id}' not found"
154
+ )
155
+
156
+ return product
157
+
158
+ except HTTPException:
159
+ # Re-raise HTTP exceptions as-is
160
+ raise
161
+ except Exception as e:
162
+ logger.error("Error getting product details", exc_info=e, extra={
163
+ "catalogue_id": catalogue_id
164
+ })
165
+ raise HTTPException(
166
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
167
+ detail="Failed to get product details"
168
+ )
169
+
170
+
171
  # Legacy GET endpoint for backward compatibility (if needed)
172
  @router.get("/", response_model=ProductListResponse)
173
  async def list_products_get(
app/product_catalogue/services/service.py CHANGED
@@ -329,6 +329,57 @@ class ProductCatalogueService:
329
  logger.error("Error getting company products count", exc_info=e)
330
  raise
331
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
332
 
333
 
334
  # Global service instance
 
329
  logger.error("Error getting company products count", exc_info=e)
330
  raise
331
 
332
+ async def get_product_details(
333
+ self,
334
+ catalogue_id: str
335
+ ) -> Optional[CustomerProductResponse]:
336
+ """
337
+ Get detailed information for a specific product by catalogue ID.
338
+
339
+ Args:
340
+ catalogue_id: The catalogue ID to fetch details for
341
+
342
+ Returns:
343
+ Product details if found, None otherwise
344
+ """
345
+ try:
346
+ logger.info("Getting product details", extra={
347
+ "catalogue_id": catalogue_id
348
+ })
349
+
350
+ # Build query for specific product
351
+ query = {
352
+ "catalogue_id": catalogue_id,
353
+ "catalogue_type": "Product",
354
+ "meta.status": {"$in": ["active", "Active"]},
355
+ "allow_ecommerce": True
356
+ }
357
+
358
+ # Find the product
359
+ doc = await self.collection.find_one(query)
360
+
361
+ if not doc:
362
+ logger.warning("Product not found", extra={
363
+ "catalogue_id": catalogue_id
364
+ })
365
+ return None
366
+
367
+ # Transform to customer-safe response
368
+ product_response = self._transform_product_data(doc)
369
+
370
+ logger.info("Successfully retrieved product details", extra={
371
+ "catalogue_id": catalogue_id,
372
+ "product_name": product_response.name
373
+ })
374
+
375
+ return product_response
376
+
377
+ except Exception as e:
378
+ logger.error("Error getting product details", exc_info=e, extra={
379
+ "catalogue_id": catalogue_id
380
+ })
381
+ raise
382
+
383
 
384
 
385
  # Global service instance
test_product_details.py ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Test the product details API endpoint.
4
+ """
5
+ import asyncio
6
+
7
+ async def test_product_details():
8
+ """Test the product details API"""
9
+
10
+ try:
11
+ # Import the service
12
+ from app.product_catalogue.services.service import product_catalogue_service
13
+ from app.nosql import connect_to_mongo
14
+
15
+ print("πŸ”— Connecting to database...")
16
+ await connect_to_mongo()
17
+ print("βœ… Connected to database")
18
+
19
+ # First, get a sample product ID from the list
20
+ print("\nπŸ” Getting sample product ID...")
21
+ products = await product_catalogue_service.list_products(
22
+ limit=1,
23
+ offset=0,
24
+ projection_list=None
25
+ )
26
+
27
+ if not products:
28
+ print("❌ No products found to test with")
29
+ return
30
+
31
+ sample_product = products[0]
32
+ catalogue_id = sample_product.catalogue_id
33
+ print(f"πŸ“¦ Using product: {sample_product.name} (ID: {catalogue_id})")
34
+
35
+ # Test the get_product_details method
36
+ print(f"\nπŸ§ͺ Testing get_product_details for ID: {catalogue_id}")
37
+ product_details = await product_catalogue_service.get_product_details(catalogue_id)
38
+
39
+ if product_details:
40
+ print("βœ… Product details retrieved successfully")
41
+ print(f" Name: {product_details.name}")
42
+ print(f" Brand: {product_details.brand}")
43
+ print(f" Category: {product_details.category}")
44
+ print(f" Price: {product_details.price} {product_details.currency}")
45
+ print(f" In Stock: {product_details.in_stock}")
46
+ print(f" Images: {len(product_details.images)} images")
47
+ if product_details.description:
48
+ print(f" Description: {product_details.description[:100]}...")
49
+ else:
50
+ print("❌ Product details not found")
51
+
52
+ # Test with non-existent ID
53
+ print(f"\nπŸ§ͺ Testing with non-existent ID...")
54
+ fake_id = "00000000-0000-0000-0000-000000000000"
55
+ fake_product = await product_catalogue_service.get_product_details(fake_id)
56
+
57
+ if fake_product is None:
58
+ print("βœ… Correctly returned None for non-existent product")
59
+ else:
60
+ print("❌ Unexpectedly found product for fake ID")
61
+
62
+ print("\nβœ… Product details API test completed successfully")
63
+
64
+ except Exception as e:
65
+ print(f"❌ Error testing product details API: {e}")
66
+ import traceback
67
+ traceback.print_exc()
68
+
69
+ if __name__ == "__main__":
70
+ asyncio.run(test_product_details())