Skip to content

Commit a7e2494

Browse files
authored
Add Claims service (#344)
* Add Claims service * fix lint
1 parent 76d7643 commit a7e2494

15 files changed

+1312
-2
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# CHANGELOG
22

3+
## Next Release
4+
5+
- Adds new `Claim` service for filing claims on EasyPost shipments and insurances
6+
37
## v7.3.0 (2024-07-12)
48

59
- Adds new `shipment.recommendShipDate`, `smartrate.recommendShipDate`, and `smartrate.estimateDeliveryDate` functions

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"squizlabs/php_codesniffer": "^3.7",
3131
"roave/security-advisories": "dev-latest",
3232
"rregeer/phpunit-coverage-check": "^0.3.1",
33-
"phpstan/phpstan": "^1.10"
33+
"phpstan/phpstan": "^1.11"
3434
},
3535
"scripts": {
3636
"coverage": "XDEBUG_MODE=coverage ./bin/phpunit --coverage-html clover.html --coverage-clover build/logs/clover.xml && ./bin/coverage-check build/logs/clover.xml 85 --only-percentage",

examples

Submodule examples updated 225 files

lib/EasyPost/Claim.php

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace EasyPost;
4+
5+
/**
6+
* @package EasyPost
7+
* @property string $id
8+
* @property string $approved_amount
9+
* @property string[] $attachments
10+
* @property string $check_delivery_address
11+
* @property string $contact_email
12+
* @property string $description
13+
* @property object $history
14+
* @property string $insurance_amount
15+
* @property string $insurance_id
16+
* @property string $payment_method
17+
* @property string $recipient_name
18+
* @property string $requested_amount
19+
* @property string $salvage_value
20+
* @property string $shipment_id
21+
* @property string $status
22+
* @property string $status_detail
23+
* @property string $status_timestamp
24+
* @property string $tracking_code
25+
* @property string $type
26+
*/
27+
class Claim extends EasyPostObject
28+
{
29+
}

lib/EasyPost/EasyPostClient.php

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use EasyPost\Service\BillingService;
1616
use EasyPost\Service\CarrierAccountService;
1717
use EasyPost\Service\CarrierMetadataService;
18+
use EasyPost\Service\ClaimService;
1819
use EasyPost\Service\CustomsInfoService;
1920
use EasyPost\Service\CustomsItemService;
2021
use EasyPost\Service\EndShipperService;
@@ -47,6 +48,7 @@
4748
* @property BillingService $billing
4849
* @property CarrierAccountService $carrierAccount
4950
* @property CarrierMetadataService $carrierMetadata
51+
* @property ClaimService $claim
5052
* @property CustomsInfoService $customsInfo
5153
* @property CustomsItemService $customsItem
5254
* @property EndShipperService $endShipper
@@ -119,6 +121,7 @@ public function __get(string $serviceName)
119121
'billing' => BillingService::class,
120122
'carrierAccount' => CarrierAccountService::class,
121123
'carrierMetadata' => CarrierMetadataService::class,
124+
'claim' => ClaimService::class,
122125
'customsInfo' => CustomsInfoService::class,
123126
'customsItem' => CustomsItemService::class,
124127
'endShipper' => EndShipperService::class,

lib/EasyPost/Service/ClaimService.php

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
namespace EasyPost\Service;
4+
5+
use EasyPost\Http\Requestor;
6+
use EasyPost\Util\InternalUtil;
7+
8+
/**
9+
* Claim service containing all the logic to make API calls.
10+
*/
11+
class ClaimService extends BaseService
12+
{
13+
/**
14+
* Create an claim object.
15+
*
16+
* @param mixed $params
17+
* @return mixed
18+
*/
19+
public function create(mixed $params = null): mixed
20+
{
21+
return self::createResource(self::serviceModelClassName(self::class), $params);
22+
}
23+
24+
/**
25+
* Retrieve an claim object.
26+
*
27+
* @param string $id
28+
* @return mixed
29+
*/
30+
public function retrieve(string $id): mixed
31+
{
32+
return self::retrieveResource(self::serviceModelClassName(self::class), $id);
33+
}
34+
35+
/**
36+
* Retrieve all claim objects.
37+
*
38+
* @param mixed $params
39+
* @return mixed
40+
*/
41+
public function all(mixed $params = null): mixed
42+
{
43+
return self::allResources(self::serviceModelClassName(self::class), $params);
44+
}
45+
46+
/**
47+
* Retrieve the next page of claim collection.
48+
*
49+
* @param mixed $claims
50+
* @param int|null $pageSize
51+
* @return mixed
52+
*/
53+
public function getNextPage(mixed $claims, ?int $pageSize = null): mixed
54+
{
55+
return $this->getNextPageResources(self::serviceModelClassName(self::class), $claims, $pageSize);
56+
}
57+
58+
/**
59+
* Cancel a claim object.
60+
*
61+
* @param string $id
62+
* @return mixed
63+
*/
64+
public function cancel(string $id): mixed
65+
{
66+
$response = Requestor::request($this->client, 'post', "/claims/{$id}/cancel");
67+
68+
return InternalUtil::convertToEasyPostObject($this->client, $response);
69+
}
70+
}

lib/EasyPost/Util/InternalUtil.php

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use EasyPost\Brand;
99
use EasyPost\CarrierAccount;
1010
use EasyPost\CarrierDetail;
11+
use EasyPost\Claim;
1112
use EasyPost\Constant\Constants;
1213
use EasyPost\CustomsInfo;
1314
use EasyPost\CustomsItem;
@@ -43,6 +44,7 @@
4344
'Brand' => Brand::class,
4445
'CarrierAccount' => CarrierAccount::class,
4546
'CarrierDetail' => CarrierDetail::class,
47+
'Claim' => Claim::class,
4648
'CustomsInfo' => CustomsInfo::class,
4749
'CustomsItem' => CustomsItem::class,
4850
'EndShipper' => EndShipper::class,

lib/easypost.php

+2
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
require_once(dirname(__FILE__) . '/EasyPost/Brand.php');
6262
require_once(dirname(__FILE__) . '/EasyPost/CarrierAccount.php');
6363
require_once(dirname(__FILE__) . '/EasyPost/CarrierDetail.php');
64+
require_once(dirname(__FILE__) . '/EasyPost/Claim.php');
6465
require_once(dirname(__FILE__) . '/EasyPost/CustomsInfo.php');
6566
require_once(dirname(__FILE__) . '/EasyPost/CustomsItem.php');
6667
require_once(dirname(__FILE__) . '/EasyPost/EndShipper.php');
@@ -96,6 +97,7 @@
9697
require_once(dirname(__FILE__) . '/EasyPost/Service/BatchService.php');
9798
require_once(dirname(__FILE__) . '/EasyPost/Service/BillingService.php');
9899
require_once(dirname(__FILE__) . '/EasyPost/Service/CarrierAccountService.php');
100+
require_once(dirname(__FILE__) . '/EasyPost/Service/ClaimService.php');
99101
require_once(dirname(__FILE__) . '/EasyPost/Service/CustomsInfoService.php');
100102
require_once(dirname(__FILE__) . '/EasyPost/Service/CustomsItemService.php');
101103
require_once(dirname(__FILE__) . '/EasyPost/Service/EndShipperService.php');

test/EasyPost/ClaimTest.php

+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
<?php
2+
3+
namespace EasyPost\Test;
4+
5+
use EasyPost\EasyPostClient;
6+
use EasyPost\Exception\General\EndOfPaginationException;
7+
use EasyPost\Claim;
8+
use Exception;
9+
10+
class ClaimTest extends \PHPUnit\Framework\TestCase
11+
{
12+
private static EasyPostClient $client;
13+
14+
/**
15+
* Setup the testing environment for this file.
16+
*/
17+
public static function setUpBeforeClass(): void
18+
{
19+
TestUtil::setupVcrTests();
20+
self::$client = new EasyPostClient(getenv('EASYPOST_TEST_API_KEY'));
21+
}
22+
23+
/**
24+
* Cleanup the testing environment once finished.
25+
*/
26+
public static function tearDownAfterClass(): void
27+
{
28+
TestUtil::teardownVcrTests();
29+
}
30+
31+
/**
32+
* Helper method to create and purchase an insured shipment.
33+
*
34+
* @param string $amount The amount of insurance for the shipment.
35+
* @return \EasyPost\Shipment The purchased shipment object.
36+
*/
37+
private static function createAndBuyShipment(string $amount): \EasyPost\Shipment
38+
{
39+
$shipment = self::$client->shipment->create(Fixture::fullShipment());
40+
return self::$client->shipment->buy(
41+
$shipment->id,
42+
[
43+
'rate' => $shipment->lowestRate(),
44+
'insurance' => $amount,
45+
]
46+
);
47+
}
48+
49+
50+
/**
51+
* Test creating an claim object.
52+
*/
53+
public function testCreate(): void
54+
{
55+
TestUtil::setupCassette('claim/create.yml');
56+
$amount = '100';
57+
$purchasedShipment = self::createAndBuyShipment($amount);
58+
59+
$claimData = Fixture::basicClaimData();
60+
$claimData['tracking_code'] = $purchasedShipment->tracking_code;
61+
$claimData['amount'] = $amount;
62+
63+
$claim = self::$client->claim->create($claimData);
64+
65+
$this->assertInstanceOf(Claim::class, $claim);
66+
$this->assertStringMatchesFormat('clm_%s', $claim->id);
67+
}
68+
69+
/**
70+
* Test retrieving an claim object.
71+
*/
72+
public function testRetrieve(): void
73+
{
74+
TestUtil::setupCassette('claim/retrieve.yml');
75+
$amount = '100';
76+
$purchasedShipment = self::createAndBuyShipment($amount);
77+
78+
$claimData = Fixture::basicClaimData();
79+
$claimData['tracking_code'] = $purchasedShipment->tracking_code;
80+
$claimData['amount'] = $amount;
81+
82+
$claim = self::$client->claim->create($claimData);
83+
$retrievedClaim = self::$client->claim->retrieve($claim->id);
84+
85+
$this->assertInstanceOf(Claim::class, $claim);
86+
$this->assertStringMatchesFormat('clm_%s', $claim->id);
87+
$this->assertEquals($claim->id, $retrievedClaim->id);
88+
}
89+
90+
/**
91+
* Test retrieving all claims.
92+
*/
93+
public function testAll(): void
94+
{
95+
TestUtil::setupCassette('claim/all.yml');
96+
97+
$claim = self::$client->claim->all([
98+
'page_size' => Fixture::pageSize(),
99+
]);
100+
101+
$claimArray = $claim['claims'];
102+
103+
$this->assertLessThanOrEqual($claimArray, Fixture::pageSize());
104+
$this->assertNotNull($claim['has_more']);
105+
$this->assertContainsOnlyInstancesOf(Claim::class, $claimArray);
106+
}
107+
108+
/**
109+
* Test retrieving next page.
110+
*/
111+
public function testGetNextPage(): void
112+
{
113+
TestUtil::setupCassette('claim/getNextPage.yml');
114+
115+
try {
116+
$claims = self::$client->claim->all([
117+
'page_size' => Fixture::pageSize(),
118+
]);
119+
$nextPage = self::$client->claim->getNextPage($claims, Fixture::pageSize());
120+
121+
$firstIdOfFirstPage = $claims['claims'][0]->id;
122+
$secondIdOfSecondPage = $nextPage['claims'][0]->id;
123+
124+
$this->assertNotEquals($firstIdOfFirstPage, $secondIdOfSecondPage);
125+
$this->assertNotNull($nextPage['_params']);
126+
} catch (EndOfPaginationException $error) {
127+
// There's no second page, that's not a failure
128+
$this->assertTrue(true);
129+
} catch (Exception $error) {
130+
throw $error;
131+
}
132+
}
133+
134+
/**
135+
* Test cancelling a filed claim.
136+
*/
137+
public function testRefund(): void
138+
{
139+
TestUtil::setupCassette('claim/cancel.yml');
140+
$amount = '100';
141+
$purchasedShipment = self::createAndBuyShipment($amount);
142+
143+
$claimData = Fixture::basicClaimData();
144+
$claimData['tracking_code'] = $purchasedShipment->tracking_code;
145+
$claimData['amount'] = $amount;
146+
147+
$claim = self::$client->claim->create($claimData);
148+
$cancelledClaim = self::$client->claim->cancel($claim->id);
149+
150+
$this->assertInstanceOf(Claim::class, $cancelledClaim);
151+
$this->assertStringMatchesFormat('clm_%s', $cancelledClaim->id);
152+
$this->assertEquals('cancelled', $cancelledClaim->status);
153+
}
154+
}

test/EasyPost/Fixture.php

+14
Original file line numberDiff line numberDiff line change
@@ -229,13 +229,27 @@ public static function rmaFormOtions(): array
229229
return self::readFixtureData()['form_options']['rma'];
230230
}
231231

232+
/**
233+
* @return string
234+
*/
232235
public static function plannedShipDate(): string
233236
{
234237
return '2024-07-16';
235238
}
236239

240+
/**
241+
* @return string
242+
*/
237243
public static function desiredDeliveryDate(): string
238244
{
239245
return '2024-07-16';
240246
}
247+
248+
/**
249+
* @return array<mixed>
250+
*/
251+
public static function basicClaimData(): array
252+
{
253+
return self::readFixtureData()['claims']['basic'];
254+
}
241255
}

0 commit comments

Comments
 (0)