@@ -149,6 +149,84 @@ def _create_price_from_draft(
149149 )
150150
151151
152+ def _get_target_obj (obj : dict , action : types .ProductUpdateAction ):
153+ staged = getattr (action , "staged" , False )
154+ if not staged and obj ["masterData" ]["current" ]:
155+ return obj ["masterData" ]["current" ]
156+ return obj ["masterData" ]["staged" ]
157+
158+
159+ def _update_productdata_attr (dst : str , src : str ):
160+ def updater (self , obj : dict , action : types .ProductUpdateAction ):
161+ value = getattr (action , src )
162+ target_obj = _get_target_obj (obj , action )
163+
164+ if target_obj [dst ] != value :
165+ new = copy .deepcopy (obj )
166+ new [dst ] = value
167+ return new
168+ return obj
169+
170+ return updater
171+
172+
173+ def _set_attribute_action ():
174+ def updater (self , obj : dict , action : types .ProductSetAttributeAction ):
175+ staged = getattr (action , "staged" , False )
176+ new = copy .deepcopy (obj )
177+
178+ target_obj = _get_target_obj (new , action )
179+
180+ variants = [target_obj ["masterVariant" ]]
181+ if target_obj ["variants" ]:
182+ variants += target_obj ["variants" ]
183+
184+ for variant in variants :
185+ if action .variant_id != variant ["id" ]:
186+ continue
187+
188+ for attr in variant ["attributes" ]:
189+ if attr ["name" ] == action .name :
190+ attr ["value" ] = action .value
191+ return new
192+
193+ # Attribute not found, will add it
194+ attr_schema = schemas .AttributeSchema ()
195+ variant ["attributes" ].append (
196+ attr_schema .dump (types .Attribute (name = action .name , value = action .value ))
197+ )
198+ break
199+
200+ return new
201+
202+ return updater
203+
204+
205+ def _add_variant_action ():
206+ def updater (self , obj : dict , action : types .ProductAddVariantAction ):
207+ variant = self .model ._create_variant_from_draft (
208+ types .ProductVariantDraft (
209+ sku = action .sku ,
210+ key = action .key ,
211+ prices = action .prices ,
212+ attributes = action .attributes ,
213+ images = action .images ,
214+ assets = action .assets ,
215+ )
216+ )
217+ schema = schemas .ProductVariantSchema ()
218+
219+ new = copy .deepcopy (obj )
220+ target_obj = _get_target_obj (new , action )
221+ if not target_obj ["variants" ]:
222+ target_obj ["variants" ] = []
223+ target_obj ["variants" ].append (schema .dump (variant ))
224+
225+ return new
226+
227+ return updater
228+
229+
152230class ProductsBackend (ServiceBackend ):
153231 service_path = "products"
154232 model_class = ProductsModel
@@ -168,24 +246,9 @@ def urls(self):
168246 ("^key=(?P<key>[^/]+)$" , "DELETE" , self .delete_by_key ),
169247 ]
170248
171- def _update_productdata_attr (dst : str , src : str ):
172- def updater (self , obj : dict , action : types .ProductUpdateAction ):
173- value = getattr (action , src )
174- staged = getattr (action , "staged" , False ) or True
175-
176- # Action.staged default is True
177- if staged :
178- target_obj = obj ["masterData" ]["staged" ]
179- else :
180- target_obj = obj ["masterData" ]["current" ]
181-
182- if target_obj [dst ] != value :
183- new = copy .deepcopy (obj )
184- new [dst ] = value
185- return new
186- return obj
187-
188- return updater
189-
190249 # Fixme: use decorator for this
191- _actions = {"changeSlug" : _update_productdata_attr ("slug" , "slug" )}
250+ _actions = {
251+ "changeSlug" : _update_productdata_attr ("slug" , "slug" ),
252+ "setAttribute" : _set_attribute_action (),
253+ "addVariant" : _add_variant_action (),
254+ }
0 commit comments