88from api .utils .pagination import paginated_response
99from api .utils .success_response import success_response
1010from api .db .database import get_db
11- from api .v1 .models .product import Product , ProductFilterStatusEnum , ProductStatusEnum
11+ from api .v1 .models .product import (
12+ Product ,
13+ ProductFilterStatusEnum ,
14+ ProductStatusEnum ,
15+ )
1216from api .v1 .services .product import product_service , ProductCategoryService
1317from api .v1 .schemas .product import (
1418 ProductCategoryCreate ,
3034non_organisation_product = APIRouter (prefix = "/products" , tags = ["Products" ])
3135
3236
33- @non_organisation_product .get ("" , response_model = success_response , status_code = 200 )
37+ @non_organisation_product .get (
38+ "" , response_model = success_response , status_code = 200
39+ )
3440async def get_all_products (
35- current_user : Annotated [User , Depends (user_service .get_current_super_admin )],
36- limit : Annotated [int , Query (
37- ge = 1 , description = "Number of products per page" )] = 10 ,
38- skip : Annotated [int , Query (
39- ge = 1 , description = "Page number (starts from 1)" )] = 0 ,
41+ current_user : Annotated [
42+ User , Depends (user_service .get_current_super_admin )
43+ ],
44+ limit : Annotated [
45+ int , Query (ge = 1 , description = "Number of products per page" )
46+ ] = 10 ,
47+ skip : Annotated [
48+ int , Query (ge = 1 , description = "Page number (starts from 1)" )
49+ ] = 0 ,
4050 db : Session = Depends (get_db ),
4151):
4252 """Endpoint to get all products. Only accessible to superadmin"""
@@ -45,7 +55,9 @@ async def get_all_products(
4555
4656
4757# categories
48- @non_organisation_product .post ("/categories" , status_code = status .HTTP_201_CREATED )
58+ @non_organisation_product .post (
59+ "/categories" , status_code = status .HTTP_201_CREATED
60+ )
4961def create_product_category (
5062 category_schema : ProductCategoryCreate ,
5163 current_user : User = Depends (user_service .get_current_user ),
@@ -65,7 +77,8 @@ def create_product_category(
6577 """
6678
6779 new_category = ProductCategoryService .create (
68- db , category_schema , current_user )
80+ db , category_schema , current_user
81+ )
6982
7083 return success_response (
7184 status_code = status .HTTP_201_CREATED ,
@@ -101,8 +114,87 @@ def retrieve_categories(
101114 )
102115
103116
117+ @non_organisation_product .delete (
118+ "/categories/{category_name}" , status_code = status .HTTP_204_NO_CONTENT
119+ )
120+ def soft_delete_product_category (
121+ category_name : str ,
122+ current_user : User = Depends (user_service .get_current_user ),
123+ db : Session = Depends (get_db ),
124+ ):
125+ """Endpoint to soft delete a product category using its unique name.
126+
127+ This endpoint checks if the current user is an admin.
128+ If so, it marks the category as deleted (soft delete)
129+ rather than permanently removing it.
130+
131+ Args:
132+ category_name (str): The unique name of the product category to delete.
133+ current_user (User): The currently authenticated user.
134+ db (Session): The database session.
135+
136+ Returns:
137+ A success response with the soft-deleted product category data.
138+ """
139+ user_service .require_admin (current_user )
140+ ProductCategoryService .soft_delete (db , category_name )
141+ return success_response (
142+ status_code = status .HTTP_204_NO_CONTENT ,
143+ message = "Category deleted successfully" ,
144+ )
145+
146+
147+ @non_organisation_product .patch (
148+ "/categories/{category_name}/restore" , status_code = status .HTTP_200_OK
149+ )
150+ def restore_deleted_category (
151+ category_name : str ,
152+ current_user : User = Depends (user_service .get_current_user ),
153+ db : Session = Depends (get_db ),
154+ ):
155+ """
156+ Endpoint to restore a soft-deleted product category using its name.
157+
158+ Checks if the current user is an admin and, if so, restores the
159+ category (sets is_deleted to False).
160+ """
161+ user_service .require_admin (current_user )
162+ restored_category = ProductCategoryService .restore_deleted (
163+ db , category_name
164+ )
165+ return success_response (
166+ status_code = status .HTTP_200_OK ,
167+ message = "Category restored successfully" ,
168+ data = jsonable_encoder (restored_category ),
169+ )
170+
171+
172+ @non_organisation_product .delete (
173+ "/categories/{category_name}/permanent" ,
174+ status_code = status .HTTP_204_NO_CONTENT ,
175+ )
176+ def permanent_delete_product_category (
177+ category_name : str ,
178+ current_user : User = Depends (user_service .get_current_user ),
179+ db : Session = Depends (get_db ),
180+ ):
181+ """
182+ Endpoint to permanently delete a product category using its unique name.
183+
184+ This endpoint checks if the current user is an admin. If so, it permanently
185+ removes the category from the database.
186+ """
187+ user_service .require_admin (current_user )
188+ ProductCategoryService .permanent_delete (db , category_name )
189+ return success_response (
190+ status_code = status .HTTP_204_NO_CONTENT ,
191+ message = "Category permanently deleted successfully" ,
192+ )
193+
194+
104195product = APIRouter (
105- prefix = "/organisations/{org_id}/products" , tags = ["Products" ])
196+ prefix = "/organisations/{org_id}/products" , tags = ["Products" ]
197+ )
106198
107199
108200# create
@@ -253,10 +345,12 @@ def delete_product(
253345def get_organisation_products (
254346 org_id : str ,
255347 current_user : Annotated [User , Depends (user_service .get_current_user )],
256- limit : Annotated [int , Query (
257- ge = 1 , description = "Number of products per page" )] = 10 ,
258- page : Annotated [int , Query (
259- ge = 1 , description = "Page number (starts from 1)" )] = 1 ,
348+ limit : Annotated [
349+ int , Query (ge = 1 , description = "Number of products per page" )
350+ ] = 10 ,
351+ page : Annotated [
352+ int , Query (ge = 1 , description = "Page number (starts from 1)" )
353+ ] = 1 ,
260354 db : Session = Depends (get_db ),
261355):
262356 """
@@ -329,11 +423,14 @@ async def get_products_by_filter_status(
329423 db = db , org_id = org_id , filter_status = filter_status
330424 )
331425 return SuccessResponse (
332- message = "Products retrieved successfully" , status_code = 200 , data = products
426+ message = "Products retrieved successfully" ,
427+ status_code = 200 ,
428+ data = products ,
333429 )
334430 except Exception as e :
335431 raise HTTPException (
336- status_code = 500 , detail = "Failed to retrieve products" )
432+ status_code = 500 , detail = "Failed to retrieve products"
433+ )
337434
338435
339436@product .get (
@@ -350,30 +447,41 @@ async def get_products_by_status(
350447 """Endpoint to get products by status"""
351448 try :
352449 products = product_service .fetch_by_status (
353- db = db , org_id = org_id , status = status )
450+ db = db , org_id = org_id , status = status
451+ )
354452 return SuccessResponse (
355- message = "Products retrieved successfully" , status_code = 200 , data = products
453+ message = "Products retrieved successfully" ,
454+ status_code = 200 ,
455+ data = products ,
356456 )
357457 except Exception as e :
358458 raise HTTPException (
359- status_code = 500 , detail = "Failed to retrieve products" )
459+ status_code = 500 , detail = "Failed to retrieve products"
460+ )
360461
361462
362- @product .get ("/search" , status_code = status .HTTP_200_OK , response_model = ProductList )
463+ @product .get (
464+ "/search" , status_code = status .HTTP_200_OK , response_model = ProductList
465+ )
363466def search_products (
364467 org_id : str ,
365468 name : Optional [str ] = Query (None , description = "Search by product name" ),
366469 category : Optional [str ] = Query (None , description = "Filter by category" ),
367470 min_price : Optional [float ] = Query (
368- None , description = "Filter by minimum price" ),
471+ None , description = "Filter by minimum price"
472+ ),
369473 max_price : Optional [float ] = Query (
370- None , description = "Filter by maximum price" ),
371- limit : Annotated [int , Query (
372- ge = 1 , description = "Number of products per page" )] = 10 ,
373- page : Annotated [int , Query (
374- ge = 1 , description = "Page number (starts from 1)" )] = 1 ,
375- current_user : Annotated [User , Depends (
376- user_service .get_current_user )] = None ,
474+ None , description = "Filter by maximum price"
475+ ),
476+ limit : Annotated [
477+ int , Query (ge = 1 , description = "Number of products per page" )
478+ ] = 10 ,
479+ page : Annotated [
480+ int , Query (ge = 1 , description = "Page number (starts from 1)" )
481+ ] = 1 ,
482+ current_user : Annotated [
483+ User , Depends (user_service .get_current_user )
484+ ] = None ,
377485 db : Session = Depends (get_db ),
378486):
379487 """
0 commit comments