Skip to content

Commit 25b5361

Browse files
Implement publish and set prices action for products (#87)
* Implement publish and set prices action for products * Always set hasStagedChanges to False when publishing * Added tests for product update actions
1 parent 128aec7 commit 25b5361

File tree

3 files changed

+93
-4
lines changed

3 files changed

+93
-4
lines changed

src/commercetools/testing/products.py

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from commercetools import schemas, types
77
from commercetools.testing.abstract import BaseModel, ServiceBackend
8-
from commercetools.testing.utils import custom_fields_from_draft
8+
from commercetools.testing.utils import custom_fields_from_draft, get_product_variants
99

1010

1111
class ProductsModel(BaseModel):
@@ -149,8 +149,8 @@ def _create_price_from_draft(
149149
)
150150

151151

152-
def _get_target_obj(obj: dict, action: types.ProductUpdateAction):
153-
staged = getattr(action, "staged", False)
152+
def _get_target_obj(obj: dict, action: types.ProductUpdateAction, default_staged=False):
153+
staged = getattr(action, "staged", default_staged)
154154
if not staged and obj["masterData"]["current"]:
155155
return obj["masterData"]["current"]
156156
return obj["masterData"]["staged"]
@@ -227,6 +227,54 @@ def updater(self, obj: dict, action: types.ProductAddVariantAction):
227227
return updater
228228

229229

230+
def _publish_product_action():
231+
def updater(self, obj: dict, action: types.ProductPublishAction):
232+
new = copy.deepcopy(obj)
233+
# not implemented scopes right now.
234+
if "staged" in new["masterData"]:
235+
new["masterData"]["current"] = new["masterData"]["staged"]
236+
new["masterData"]["hasStagedChanges"] = False
237+
new["masterData"]["published"] = True
238+
return new
239+
240+
return updater
241+
242+
243+
def _set_product_prices():
244+
def updater(self, obj: dict, action: types.ProductSetPricesAction):
245+
new = copy.deepcopy(obj)
246+
target_obj = _get_target_obj(new, action, default_staged=True)
247+
prices = []
248+
for price_draft in action.prices:
249+
price = types.Price(
250+
id=str(uuid.uuid4()),
251+
country=price_draft.country,
252+
channel=price_draft.channel,
253+
value=types.TypedMoney(
254+
fraction_digits=2,
255+
cent_amount=price_draft.value.cent_amount,
256+
currency_code=price_draft.value.currency_code,
257+
type=types.MoneyType.CENT_PRECISION,
258+
),
259+
valid_from=price_draft.valid_from,
260+
valid_until=price_draft.valid_until,
261+
discounted=price_draft.discounted,
262+
custom=price_draft.custom,
263+
tiers=price_draft.tiers,
264+
)
265+
prices.append(price)
266+
267+
schema = schemas.PriceSchema()
268+
for variant in get_product_variants(target_obj):
269+
if variant["sku"] == action.sku:
270+
variant["prices"] = schema.dump(prices, many=True)
271+
if action.staged:
272+
new["masterData"]["hasStagedChanges"] = True
273+
return new
274+
275+
return updater
276+
277+
230278
class ProductsBackend(ServiceBackend):
231279
service_path = "products"
232280
model_class = ProductsModel
@@ -251,4 +299,6 @@ def urls(self):
251299
"changeSlug": _update_productdata_attr("slug", "slug"),
252300
"setAttribute": _set_attribute_action(),
253301
"addVariant": _add_variant_action(),
302+
"setPrices": _set_product_prices(),
303+
"publish": _publish_product_action(),
254304
}

src/commercetools/testing/utils.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ def flatten_multivaluedict(data: dict) -> dict:
3232
return result
3333

3434

35+
def get_product_variants(product_catalog_data: dict) -> typing.List[dict]:
36+
variants = []
37+
if product_catalog_data.get("masterVariant"):
38+
variants.append(product_catalog_data["masterVariant"])
39+
if product_catalog_data.get("variants"):
40+
variants += product_catalog_data["variants"]
41+
return variants
42+
43+
3544
def create_from_draft(draft):
3645
"""Utility method to create normal objects out of draft objects.
3746

tests/test_service_products.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,12 @@ def test_product_update(client):
145145
It doesn't test the actual update itself.
146146
TODO: See if this is worth testing since we're using a mocking backend
147147
"""
148-
product = client.products.create(types.ProductDraft(key="test-product"))
148+
product = client.products.create(
149+
types.ProductDraft(
150+
key="test-product",
151+
master_variant=types.ProductVariantDraft(sku="1", key="1"),
152+
)
153+
)
149154

150155
assert uuid.UUID(product.id)
151156
assert product.key == "test-product"
@@ -158,6 +163,31 @@ def test_product_update(client):
158163
],
159164
)
160165
assert product.key == "test-product"
166+
assert product.master_data.published is False
167+
168+
product = client.products.update_by_id(
169+
id=product.id, version=product.version, actions=[types.ProductPublishAction()]
170+
)
171+
assert product.master_data.published is True
172+
173+
assert not product.master_data.current.master_variant.prices
174+
product = client.products.update_by_id(
175+
id=product.id,
176+
version=product.version,
177+
actions=[
178+
types.ProductSetPricesAction(
179+
sku="1",
180+
prices=[
181+
types.PriceDraft(
182+
value=types.Money(cent_amount=1000, currency_code="GBP")
183+
)
184+
],
185+
staged=False,
186+
)
187+
],
188+
)
189+
190+
assert len(product.master_data.current.master_variant.prices) == 1
161191

162192
product = client.products.update_by_key(
163193
key="test-product",

0 commit comments

Comments
 (0)