Skip to content

Commit 36c61ce

Browse files
feat: Add support for discount group include and mode filter (#124)
1 parent d193d08 commit 36c61ce

File tree

8 files changed

+175
-9
lines changed

8 files changed

+175
-9
lines changed

src/Entities/Discount.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ private function __construct(
4141
public ImportMeta|null $importMeta,
4242
public DiscountMode $mode,
4343
public string|null $discountGroupId,
44+
public DiscountGroup|null $discountGroup,
4445
) {
4546
}
4647

@@ -67,6 +68,7 @@ public static function from(array $data): self
6768
importMeta: isset($data['import_meta']) ? ImportMeta::from($data['import_meta']) : null,
6869
mode: DiscountMode::from($data['mode']),
6970
discountGroupId: $data['discount_group_id'] ?? null,
71+
discountGroup: isset($data['discount_group']) ? DiscountGroup::from($data['discount_group']) : null,
7072
);
7173
}
7274
}

src/Resources/Discounts/DiscountsClient.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Paddle\SDK\Exceptions\ApiError;
2020
use Paddle\SDK\Exceptions\SdkExceptions\MalformedResponse;
2121
use Paddle\SDK\Resources\Discounts\Operations\CreateDiscount;
22+
use Paddle\SDK\Resources\Discounts\Operations\GetDiscount;
2223
use Paddle\SDK\Resources\Discounts\Operations\ListDiscounts;
2324
use Paddle\SDK\Resources\Discounts\Operations\UpdateDiscount;
2425
use Paddle\SDK\ResponseParser;
@@ -50,10 +51,10 @@ public function list(ListDiscounts $listOperation = new ListDiscounts()): Discou
5051
* @throws ApiError On a generic API error
5152
* @throws MalformedResponse If the API response was not parsable
5253
*/
53-
public function get(string $id): Discount
54+
public function get(string $id, GetDiscount $operation = new GetDiscount()): Discount
5455
{
5556
$parser = new ResponseParser(
56-
$this->client->getRaw("/discounts/{$id}"),
57+
$this->client->getRaw("/discounts/{$id}", $operation),
5758
);
5859

5960
return Discount::from($parser->getData());
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Paddle\SDK\Resources\Discounts\Operations;
6+
7+
use Paddle\SDK\PaddleEnum;
8+
9+
/**
10+
* @method static DiscountInclude DiscountGroup()
11+
*/
12+
class DiscountInclude extends PaddleEnum
13+
{
14+
private const DiscountGroup = 'discount_group';
15+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Paddle\SDK\Resources\Discounts\Operations;
6+
7+
use Paddle\SDK\Exceptions\SdkExceptions\InvalidArgumentException;
8+
use Paddle\SDK\HasParameters;
9+
10+
class GetDiscount implements HasParameters
11+
{
12+
/**
13+
* @param array<DiscountInclude> $includes
14+
*
15+
* @throws InvalidArgumentException On invalid array contents
16+
*/
17+
public function __construct(
18+
private readonly array $includes = [],
19+
) {
20+
if ($invalid = array_filter($this->includes, fn ($value): bool => ! $value instanceof DiscountInclude)) {
21+
throw InvalidArgumentException::arrayContainsInvalidTypes('includes', DiscountInclude::class, implode(', ', $invalid));
22+
}
23+
}
24+
25+
public function getParameters(): array
26+
{
27+
return array_filter([
28+
'include' => implode(',', $this->includes),
29+
]);
30+
}
31+
}

src/Resources/Discounts/Operations/ListDiscounts.php

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Paddle\SDK\Resources\Discounts\Operations;
66

7+
use Paddle\SDK\Entities\Discount\DiscountMode;
78
use Paddle\SDK\Entities\Shared\Status;
89
use Paddle\SDK\Exceptions\SdkExceptions\InvalidArgumentException;
910
use Paddle\SDK\HasParameters;
@@ -12,10 +13,11 @@
1213
class ListDiscounts implements HasParameters
1314
{
1415
/**
15-
* @param array<string> $ids
16-
* @param array<Status> $statuses
17-
* @param array<string> $codes
18-
* @param array<string> $discountGroupIds
16+
* @param array<string> $ids
17+
* @param array<Status> $statuses
18+
* @param array<string> $codes
19+
* @param array<string> $discountGroupIds
20+
* @param array<DiscountInclude> $includes
1921
*
2022
* @throws InvalidArgumentException On invalid array contents
2123
*/
@@ -25,6 +27,8 @@ public function __construct(
2527
private readonly array $statuses = [],
2628
private readonly array $codes = [],
2729
private readonly array $discountGroupIds = [],
30+
private readonly DiscountMode|null $mode = null,
31+
private readonly array $includes = [],
2832
) {
2933
if ($invalid = array_filter($this->ids, fn ($value): bool => ! is_string($value))) {
3034
throw InvalidArgumentException::arrayContainsInvalidTypes('ids', 'string', implode(', ', $invalid));
@@ -41,6 +45,10 @@ public function __construct(
4145
if ($invalid = array_filter($this->discountGroupIds, fn ($value): bool => ! is_string($value))) {
4246
throw InvalidArgumentException::arrayContainsInvalidTypes('discountGroupIds', 'string', implode(', ', $invalid));
4347
}
48+
49+
if ($invalid = array_filter($this->includes, fn ($value): bool => ! $value instanceof DiscountInclude)) {
50+
throw InvalidArgumentException::arrayContainsInvalidTypes('includes', DiscountInclude::class, implode(', ', $invalid));
51+
}
4452
}
4553

4654
public function getParameters(): array
@@ -54,6 +62,8 @@ public function getParameters(): array
5462
'status' => implode(',', array_map($enumStringify, $this->statuses)),
5563
'code' => implode(',', $this->codes),
5664
'discount_group_id' => implode(',', $this->discountGroupIds),
65+
'mode' => $this->mode?->getValue(),
66+
'include' => implode(',', $this->includes),
5767
]),
5868
);
5969
}

tests/Functional/Resources/Discounts/DiscountsClientTest.php

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@
1313
use Paddle\SDK\Entities\Shared\CurrencyCode;
1414
use Paddle\SDK\Entities\Shared\Status;
1515
use Paddle\SDK\Environment;
16+
use Paddle\SDK\JsonEncoder;
1617
use Paddle\SDK\Options;
1718
use Paddle\SDK\Resources\Discounts\Operations\CreateDiscount;
19+
use Paddle\SDK\Resources\Discounts\Operations\DiscountInclude;
20+
use Paddle\SDK\Resources\Discounts\Operations\GetDiscount;
1821
use Paddle\SDK\Resources\Discounts\Operations\ListDiscounts;
1922
use Paddle\SDK\Resources\Discounts\Operations\UpdateDiscount;
2023
use Paddle\SDK\Resources\Shared\Operations\List\Pager;
@@ -165,12 +168,17 @@ public function list_hits_expected_uri(
165168
string $expectedUri,
166169
): void {
167170
$this->mockClient->addResponse($response);
168-
$this->client->discounts->list($operation);
171+
$discounts = $this->client->discounts->list($operation);
169172
$request = $this->mockClient->getLastRequest();
170173

171174
self::assertInstanceOf(RequestInterface::class, $request);
172175
self::assertEquals('GET', $request->getMethod());
173176
self::assertEquals($expectedUri, urldecode((string) $request->getUri()));
177+
178+
self::assertJsonStringEqualsJsonString(
179+
json_encode(json_decode((string) $response->getBody(), true)['data'][0]),
180+
JsonEncoder::default()->encode($discounts->current()),
181+
);
174182
}
175183

176184
public static function listOperationsProvider(): \Generator
@@ -246,6 +254,33 @@ public static function listOperationsProvider(): \Generator
246254
Environment::SANDBOX->baseUrl(),
247255
),
248256
];
257+
258+
yield 'Discount filtered by standard mode' => [
259+
new ListDiscounts(mode: DiscountMode::Standard()),
260+
new Response(200, body: self::readRawJsonFixture('response/list_default')),
261+
sprintf(
262+
'%s/discounts?mode=standard',
263+
Environment::SANDBOX->baseUrl(),
264+
),
265+
];
266+
267+
yield 'Discount filtered by custom mode' => [
268+
new ListDiscounts(mode: DiscountMode::Custom()),
269+
new Response(200, body: self::readRawJsonFixture('response/list_default')),
270+
sprintf(
271+
'%s/discounts?mode=custom',
272+
Environment::SANDBOX->baseUrl(),
273+
),
274+
];
275+
276+
yield 'Discount with discount group include' => [
277+
new ListDiscounts(includes: [DiscountInclude::DiscountGroup()]),
278+
new Response(200, body: self::readRawJsonFixture('response/list_default')),
279+
sprintf(
280+
'%s/discounts?include=discount_group',
281+
Environment::SANDBOX->baseUrl(),
282+
),
283+
];
249284
}
250285

251286
/** @test */
@@ -263,4 +298,26 @@ public function get_hits_expected_uri(): void
263298
urldecode((string) $request->getUri()),
264299
);
265300
}
301+
302+
/** @test */
303+
public function get_hits_expected_uri_with_discount_group_included(): void
304+
{
305+
$responseBody = self::readRawJsonFixture('response/full_entity_include_discount_group');
306+
$response = new Response(200, body: $responseBody);
307+
$this->mockClient->addResponse($response);
308+
$discount = $this->client->discounts->get('dsc_01h83xenpcfjyhkqr4x214m02x', new GetDiscount(includes: [DiscountInclude::DiscountGroup()]));
309+
$request = $this->mockClient->getLastRequest();
310+
311+
self::assertInstanceOf(RequestInterface::class, $request);
312+
self::assertEquals('GET', $request->getMethod());
313+
self::assertEquals(
314+
sprintf('%s/discounts/dsc_01h83xenpcfjyhkqr4x214m02x?include=discount_group', Environment::SANDBOX->baseUrl()),
315+
urldecode((string) $request->getUri()),
316+
);
317+
318+
self::assertJsonStringEqualsJsonString(
319+
json_encode(json_decode($responseBody, true)['data']),
320+
JsonEncoder::default()->encode($discount),
321+
);
322+
}
266323
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"data": {
3+
"id": "dsc_01h83xenpcfjyhkqr4x214m02x",
4+
"status": "active",
5+
"description": "Nonprofit discount",
6+
"enabled_for_checkout": true,
7+
"code": "ABCDE12345",
8+
"type": "percentage",
9+
"mode": "standard",
10+
"amount": "10",
11+
"currency_code": "USD",
12+
"recur": true,
13+
"maximum_recurring_intervals": 5,
14+
"usage_limit": 1000,
15+
"restrict_to": [
16+
"pro_01gsz4t5hdjse780zja8vvr7jg",
17+
"pro_01gsz4s0w61y0pp88528f1wvvb"
18+
],
19+
"expires_at": "2025-01-01T10:00:00.000000Z",
20+
"times_used": 0,
21+
"created_at": "2023-08-18T08:51:07.596000Z",
22+
"updated_at": "2023-08-18T08:51:07.596000Z",
23+
"custom_data": {
24+
"key": "value"
25+
},
26+
"discount_group_id": "dsg_01gtf15svsqzgp9325ss4ebmwt",
27+
"discount_group": {
28+
"id": "dsg_01gtf15svsqzgp9325ss4ebmwt",
29+
"name": "Black Friday 2024",
30+
"status": "active",
31+
"created_at": "2024-11-28T14:36:14.695000Z",
32+
"updated_at": "2024-11-28T14:36:14.695000Z",
33+
"import_meta": null
34+
},
35+
"import_meta": null
36+
},
37+
"meta": {
38+
"request_id": "badf3eb7-3eb8-4d4a-92f9-bc798790b7bc"
39+
}
40+
}

tests/Functional/Resources/Discounts/_fixtures/response/list_default.json

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,18 @@
1717
"expires_at": null,
1818
"times_used": 0,
1919
"custom_data": null,
20-
"created_at": "2023-03-01T16:48:04.473Z",
21-
"updated_at": "2023-08-18T09:22:14.563Z"
20+
"created_at": "2023-03-01T16:48:04.473000Z",
21+
"updated_at": "2023-08-18T09:22:14.563000Z",
22+
"discount_group_id": "dsg_01gtf15svsqzgp9325ss4ebmwt",
23+
"discount_group": {
24+
"id": "dsg_01gtf15svsqzgp9325ss4ebmwt",
25+
"name": "Black Friday 2024",
26+
"status": "active",
27+
"created_at": "2024-11-28T14:36:14.695000Z",
28+
"updated_at": "2024-11-28T14:36:14.695000Z",
29+
"import_meta": null
30+
},
31+
"import_meta": null
2232
},
2333
{
2434
"id": "dsc_01gtgraak4chyhnp47rrdv89ad",

0 commit comments

Comments
 (0)