55from sqlalchemy .exc import IntegrityError
66from sqlalchemy .ext .asyncio import AsyncSession
77
8+ from app .core .audit_log .service import audit_log_service
89from app .core .config import settings
910from app .core .exceptions import (
1011 ConflictError ,
1516from app .services .inventory .models import Product , ProductStatus , Reservation
1617from app .services .inventory .schemas import (
1718 ProductCreate ,
19+ ProductRead ,
1820 ProductUpdate ,
1921 ReservationCreate ,
2022)
@@ -41,25 +43,65 @@ async def _get_product(
4143 check_ownership (current_user , product )
4244 return product
4345
46+ @staticmethod
47+ async def _log_product_change (
48+ session : AsyncSession ,
49+ user : User ,
50+ product : Product ,
51+ old_snapshot : ProductRead | None ,
52+ action : str ,
53+ ) -> None :
54+ await audit_log_service .log_object_change (
55+ session = session ,
56+ actor_id = user .id ,
57+ target_id = product .id ,
58+ target_type = 'product' ,
59+ action = action ,
60+ old_obj = old_snapshot ,
61+ new_obj = ProductRead .model_validate (product ),
62+ )
63+
4464 @staticmethod
4565 async def change_status (
46- session : AsyncSession , product_id : UUID , status : ProductStatus
66+ session : AsyncSession ,
67+ product_id : UUID ,
68+ status : ProductStatus ,
69+ current_user : User ,
4770 ) -> Product :
4871 product = await InventoryService ._get_product (
4972 session , product_id , for_update = True
5073 )
74+ old_snapshot = ProductRead .model_validate (product )
5175 product .status = status
76+ await InventoryService ._log_product_change (
77+ session = session ,
78+ user = current_user ,
79+ product = product ,
80+ old_snapshot = old_snapshot ,
81+ action = 'update' ,
82+ )
5283 await session .commit ()
5384 await session .refresh (product )
5485 return product
5586
5687 @staticmethod
5788 async def create_product (
58- session : AsyncSession , owner_id : UUID , product_data : ProductCreate
89+ session : AsyncSession ,
90+ owner_id : UUID ,
91+ product_data : ProductCreate ,
92+ current_user : User ,
5993 ) -> Product :
6094 new_product = Product (** product_data .model_dump ())
6195 new_product .owner_id = owner_id
6296 session .add (new_product )
97+ await session .flush ()
98+ await InventoryService ._log_product_change (
99+ session = session ,
100+ user = current_user ,
101+ product = new_product ,
102+ old_snapshot = None ,
103+ action = 'create' ,
104+ )
63105 await session .commit ()
64106 await session .refresh (new_product )
65107 return new_product
@@ -74,8 +116,16 @@ async def update_product(
74116 product = await InventoryService ._get_product (
75117 session , product_id , for_update = True , current_user = current_user
76118 )
119+ old_snapshot = ProductRead .model_validate (product )
77120 for field , value in product_data .model_dump (exclude_unset = True ).items ():
78121 setattr (product , field , value )
122+ await InventoryService ._log_product_change (
123+ session = session ,
124+ user = current_user ,
125+ product = product ,
126+ old_snapshot = old_snapshot ,
127+ action = 'update' ,
128+ )
79129 await session .commit ()
80130 await session .refresh (product )
81131 return product
@@ -89,6 +139,13 @@ async def delete_product(
89139 product = await InventoryService ._get_product (
90140 session , product_id , for_update = True , current_user = current_user
91141 )
142+ await InventoryService ._log_product_change (
143+ session = session ,
144+ user = current_user ,
145+ product = product ,
146+ old_snapshot = ProductRead .model_validate (product ),
147+ action = 'delete' ,
148+ )
92149 await session .delete (product )
93150 await session .commit ()
94151
0 commit comments