Skip to content
This repository was archived by the owner on Oct 24, 2023. It is now read-only.

Commit 9258a62

Browse files
committed
feat(ProductDiscounts): add endpoint for Matching ProductDiscount
1 parent e75002f commit 9258a62

File tree

6 files changed

+437
-1
lines changed

6 files changed

+437
-1
lines changed

src/Core/Builder/Request/ProductDiscountRequestBuilder.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55

66
namespace Commercetools\Core\Builder\Request;
77

8+
use Commercetools\Core\Model\Common\Price;
89
use Commercetools\Core\Model\ProductDiscount\ProductDiscount;
910
use Commercetools\Core\Model\ProductDiscount\ProductDiscountDraft;
1011
use Commercetools\Core\Request\ProductDiscounts\ProductDiscountByIdGetRequest;
1112
use Commercetools\Core\Request\ProductDiscounts\ProductDiscountCreateRequest;
1213
use Commercetools\Core\Request\ProductDiscounts\ProductDiscountDeleteRequest;
14+
use Commercetools\Core\Request\ProductDiscounts\ProductDiscountMatchingRequest;
1315
use Commercetools\Core\Request\ProductDiscounts\ProductDiscountQueryRequest;
1416
use Commercetools\Core\Request\ProductDiscounts\ProductDiscountUpdateRequest;
1517

@@ -58,4 +60,15 @@ public function getById($id)
5860
{
5961
return ProductDiscountByIdGetRequest::ofId($id);
6062
}
63+
64+
/**
65+
* @param string $productId
66+
* @param int $variantId
67+
* @param Price $price
68+
* @return ProductDiscountMatchingRequest
69+
*/
70+
public function matching($productId, $variantId, Price $price)
71+
{
72+
return ProductDiscountMatchingRequest::ofProductIdVariantIdAndPrice($productId, $variantId, $price);
73+
}
6174
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
/**
3+
*/
4+
5+
namespace Commercetools\Core\Error;
6+
7+
/**
8+
* @package Commercetools\Core\Error
9+
*
10+
* @method string getCode()
11+
* @method NoMatchingProductDiscountFoundError setCode(string $code = null)
12+
* @method string getMessage()
13+
* @method NoMatchingProductDiscountFoundError setMessage(string $message = null)
14+
*/
15+
class NoMatchingProductDiscountFoundError extends ApiError
16+
{
17+
const CODE = 'NoMatchingProductDiscountFound';
18+
}
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
<?php
2+
/**
3+
*/
4+
5+
namespace Commercetools\Core\Request\ProductDiscounts;
6+
7+
use Commercetools\Core\Client\HttpMethod;
8+
use Commercetools\Core\Client\JsonRequest;
9+
use Commercetools\Core\Model\Common\Context;
10+
use Commercetools\Core\Model\Common\Price;
11+
use Commercetools\Core\Model\ProductDiscount\ProductDiscount;
12+
use Commercetools\Core\Request\AbstractApiRequest;
13+
use Commercetools\Core\Response\ApiResponseInterface;
14+
use Commercetools\Core\Response\ResourceResponse;
15+
use Psr\Http\Message\ResponseInterface;
16+
use Commercetools\Core\Model\MapperInterface;
17+
18+
/**
19+
* @package Commercetools\Core\Request\ProductDiscounts
20+
*
21+
* @method ProductDiscount mapResponse(ApiResponseInterface $response)
22+
* @method ProductDiscount mapFromResponse(ApiResponseInterface $response, MapperInterface $mapper = null)
23+
*/
24+
class ProductDiscountMatchingRequest extends AbstractApiRequest
25+
{
26+
protected $resultClass = ProductDiscount::class;
27+
28+
const PRODUCT_ID = 'productId';
29+
const VARIANT_ID = 'variantId';
30+
const STAGED = 'staged';
31+
const PRICE = 'price';
32+
33+
/**
34+
* @var string
35+
*/
36+
protected $productId;
37+
38+
/**
39+
* @var int
40+
*/
41+
protected $variantId;
42+
43+
/**
44+
* @var bool
45+
*/
46+
protected $staged;
47+
48+
/**
49+
* @var Price
50+
*/
51+
protected $price;
52+
53+
/**
54+
* @param Price $price
55+
* @param Context $context
56+
*/
57+
public function __construct(Price $price, Context $context = null)
58+
{
59+
parent::__construct(ProductDiscountsEndpoint::endpoint(), $context);
60+
$this->price = $price;
61+
}
62+
63+
/**
64+
* @return string
65+
*/
66+
public function getProductId()
67+
{
68+
return $this->productId;
69+
}
70+
71+
/**
72+
* @param string $productId
73+
* @return ProductDiscountMatchingRequest
74+
*/
75+
public function setProductId($productId)
76+
{
77+
$this->productId = $productId;
78+
return $this;
79+
}
80+
81+
/**
82+
* @return int
83+
*/
84+
public function getVariantId()
85+
{
86+
return $this->variantId;
87+
}
88+
89+
/**
90+
* @param int $variantId
91+
* @return ProductDiscountMatchingRequest
92+
*/
93+
public function setVariantId($variantId)
94+
{
95+
$this->variantId = $variantId;
96+
return $this;
97+
}
98+
99+
/**
100+
* @return bool
101+
*/
102+
public function getStaged()
103+
{
104+
return $this->staged;
105+
}
106+
107+
/**
108+
* @param bool $staged
109+
* @return ProductDiscountMatchingRequest
110+
*/
111+
public function setStaged($staged)
112+
{
113+
$this->staged = $staged;
114+
return $this;
115+
}
116+
117+
/**
118+
* @return Price
119+
*/
120+
public function getPrice()
121+
{
122+
return $this->price;
123+
}
124+
125+
/**
126+
* @param Price $price
127+
* @return ProductDiscountMatchingRequest
128+
*/
129+
public function setPrice(Price $price)
130+
{
131+
$this->price = $price;
132+
return $this;
133+
}
134+
135+
/**
136+
* @param string $productId
137+
* @param int $variantId
138+
* @param Price $price
139+
* @param Context $context
140+
* @return ProductDiscountMatchingRequest
141+
*/
142+
public static function ofProductIdVariantIdAndPrice($productId, $variantId, Price $price, Context $context = null)
143+
{
144+
$request = new static($price, $context);
145+
$request->setProductId($productId)->setVariantId($variantId);
146+
147+
return $request;
148+
}
149+
150+
/**
151+
* @return string
152+
* @internal
153+
*/
154+
protected function getPath()
155+
{
156+
return (string)$this->getEndpoint() . '/matching' . $this->getParamString();
157+
}
158+
159+
/**
160+
* @return JsonRequest
161+
* @internal
162+
*/
163+
public function httpRequest()
164+
{
165+
$payload = [
166+
static::PRODUCT_ID => $this->getProductId(),
167+
static::VARIANT_ID => $this->getVariantId(),
168+
static::STAGED => ($this->getStaged() == true),
169+
static::PRICE => $this->getPrice()
170+
];
171+
172+
return new JsonRequest(HttpMethod::POST, $this->getPath(), $payload);
173+
}
174+
175+
/**
176+
* @param ResponseInterface $response
177+
* @return ApiResponseInterface
178+
* @internal
179+
*/
180+
public function buildResponse(ResponseInterface $response)
181+
{
182+
return new ResourceResponse($response, $this, $this->getContext());
183+
}
184+
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
<?php
2+
/**
3+
*
4+
*/
5+
6+
namespace Commercetools\Core\ProductDiscount;
7+
8+
use Commercetools\Core\ApiTestCase;
9+
use Commercetools\Core\Model\Common\LocalizedString;
10+
use Commercetools\Core\Model\Common\Money;
11+
use Commercetools\Core\Model\Common\MoneyCollection;
12+
use Commercetools\Core\Model\Common\Price;
13+
use Commercetools\Core\Model\Common\PriceDraft;
14+
use Commercetools\Core\Model\Common\PriceDraftCollection;
15+
use Commercetools\Core\Model\Product\ProductDraft;
16+
use Commercetools\Core\Model\Product\ProductVariant;
17+
use Commercetools\Core\Model\Product\ProductVariantDraft;
18+
use Commercetools\Core\Model\ProductDiscount\ProductDiscount;
19+
use Commercetools\Core\Model\ProductDiscount\ProductDiscountDraft;
20+
use Commercetools\Core\Model\ProductDiscount\ProductDiscountValue;
21+
use Commercetools\Core\Request\ProductDiscounts\ProductDiscountCreateRequest;
22+
use Commercetools\Core\Request\ProductDiscounts\ProductDiscountDeleteRequest;
23+
use Commercetools\Core\Request\ProductDiscounts\ProductDiscountMatchingRequest;
24+
use Commercetools\Core\Request\Products\Command\ProductAddVariantAction;
25+
use Commercetools\Core\Request\Products\ProductCreateRequest;
26+
use Commercetools\Core\Request\Products\ProductDeleteRequest;
27+
use Commercetools\Core\Request\Products\ProductUpdateRequest;
28+
29+
class ProductDiscountMatchingRequestTest extends ApiTestCase
30+
{
31+
/**
32+
* @return ProductDiscountDraft
33+
*/
34+
protected function getProductDiscountDraft()
35+
{
36+
$draft = ProductDiscountDraft::ofNameDiscountPredicateOrderAndActive(
37+
LocalizedString::ofLangAndText('en', 'test-' . $this->getTestRun() . '-discount'),
38+
ProductDiscountValue::of()->setType('absolute')->setMoney(
39+
MoneyCollection::of()
40+
->add(Money::ofCurrencyAndAmount('EUR', 100))
41+
),
42+
'sku="' . $this->getTestRun() . '-sku"',
43+
'0.9' . trim((string)mt_rand(1, 1000), '0'),
44+
true
45+
);
46+
47+
return $draft;
48+
}
49+
50+
protected function createProductDiscount(ProductDiscountDraft $draft)
51+
{
52+
$request = ProductDiscountCreateRequest::ofDraft($draft);
53+
$response = $request->executeWithClient($this->getClient());
54+
// var_export($response);
55+
$productDiscount = $request->mapResponse($response);
56+
57+
$this->cleanupRequests[] = ProductDiscountDeleteRequest::ofIdAndVersion(
58+
$productDiscount->getId(),
59+
$productDiscount->getVersion()
60+
);
61+
62+
return $productDiscount;
63+
}
64+
65+
/**
66+
* @return ProductDraft
67+
*/
68+
protected function getProductDraft()
69+
{
70+
$draft = ProductDraft::ofTypeNameAndSlug(
71+
$this->getProductType()->getReference(),
72+
LocalizedString::ofLangAndText('en', 'test-' . $this->getTestRun() . '-product'),
73+
LocalizedString::ofLangAndText('en', 'test-' . $this->getTestRun() . '-product')
74+
);
75+
76+
return $draft;
77+
}
78+
79+
protected function createProduct(ProductDraft $draft)
80+
{
81+
$request = ProductCreateRequest::ofDraft($draft);
82+
$response = $request->executeWithClient($this->getClient());
83+
$product = $request->mapResponse($response);
84+
85+
$this->cleanupRequests[] = $this->deleteRequest = ProductDeleteRequest::ofIdAndVersion(
86+
$product->getId(),
87+
$product->getVersion()
88+
);
89+
90+
return $product;
91+
}
92+
93+
public function testMatchingProductDiscount()
94+
{
95+
$productDraft = $this->getProductDraft();
96+
$sku = $this->getTestRun() . '-sku';
97+
$productDraft->setMasterVariant(
98+
ProductVariantDraft::of()->setSku($sku)->setKey($sku)->setPrices(
99+
PriceDraftCollection::of()->add(
100+
PriceDraft::ofMoney(Money::ofCurrencyAndAmount('EUR', 100))
101+
)
102+
)
103+
);
104+
$product = $this->createProduct($productDraft);
105+
106+
$productDiscountDraft = $this->getProductDiscountDraft();
107+
$productDiscount = $this->createProductDiscount($productDiscountDraft);
108+
109+
$retries = 0;
110+
do {
111+
$retries++;
112+
sleep(1);
113+
114+
$request = ProductDiscountMatchingRequest::ofProductIdVariantIdAndPrice(
115+
$product->getId(),
116+
$product->getMasterData()->getCurrent()->getMasterVariant()->getId(),
117+
$product->getMasterData()->getCurrent()->getMasterVariant()->getPrices()->current()
118+
);
119+
$response = $request->executeWithClient($this->getClient());
120+
$matchedProductDiscount = $request->mapResponse($response);
121+
} while (is_null($matchedProductDiscount) && $retries <= 9);
122+
123+
if (is_null($matchedProductDiscount)) {
124+
$this->markTestSkipped('Product discount on product, not updated in time');
125+
}
126+
127+
$this->assertInstanceOf(ProductDiscount::class, $matchedProductDiscount);
128+
$this->assertEquals($productDiscount->getId(), $matchedProductDiscount->getId());
129+
$this->assertEquals($productDiscount->getVersion(), $matchedProductDiscount->getVersion());
130+
$this->assertEquals($productDiscount->getValue(), $matchedProductDiscount->getValue());
131+
}
132+
}

tests/integration/ProductDiscount/ProductDiscountQueryRequestTest.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,5 @@ public function testGetById()
7878

7979
$this->assertInstanceOf(ProductDiscount::class, $productDiscount);
8080
$this->assertSame($productDiscount->getId(), $result->getId());
81-
8281
}
8382
}

0 commit comments

Comments
 (0)