From d6cb3978ae56d85e99e98f6aca773004c57d6331 Mon Sep 17 00:00:00 2001 From: Ash <58735196+ash-g-1337@users.noreply.github.com> Date: Thu, 30 Jan 2025 14:48:51 -0500 Subject: [PATCH 01/11] Start of Freight LTL --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 109a0e3..ec81d90 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,12 @@ FedEx Rest API documentation https://developer.fedex.com/api/en-us/get-started.h - [ ] Postal Code Validation API - [x] Rate Quotes API - [ ] Service Availability API +- [ ] Freight LTL API + - [ ] Rate Freight LTL ([docs](https://developer.fedex.com/api/en-us/catalog/ltl-freight/v1/docs.html#operation/Freight%20RateQuote)) + - [ ] Ship Freight LTL ([docs](https://developer.fedex.com/api/en-us/catalog/ltl-freight/v1/docs.html#operation/Freight%20Shipment)) + - [ ] Check Freight LTL Pickup Availability ([docs](https://developer.fedex.com/api/en-us/catalog/ltl-freight/v1/docs.html#operation/Check%20Freight%20Pickup%20Availability)) + - [ ] Create Freight LTL Pickup ([docs](https://developer.fedex.com/api/en-us/catalog/ltl-freight/v1/docs.html#operation/Create%20Freight%20Pickup)) + - [x] Cancel Freight LTL Pickup ([docs](https://developer.fedex.com/api/en-us/catalog/ltl-freight/v1/docs.html#operation/Cancel%20Freight%20Pickup)) ### Other - [x] [oAuth authorization](#authorization) From b725259cfa58f733af08ce7378b17854deac755d Mon Sep 17 00:00:00 2001 From: Ash <58735196+ash-g-1337@users.noreply.github.com> Date: Thu, 30 Jan 2025 14:49:14 -0500 Subject: [PATCH 02/11] Support for Cancel Freight LTL & Unit Tests --- .../FreightLTL/CancelFreightLTLPickup.php | 134 ++++++++++++++++ ...issingAssociatedAccountNumberException.php | 11 ++ .../MissingContactNameException.php | 11 ++ ...MissingPickupConfirmationCodeException.php | 11 ++ .../Exceptions/MissingReasonException.php | 11 ++ .../FreightLTL/CancelFreightLTLPickupTest.php | 144 ++++++++++++++++++ 6 files changed, 322 insertions(+) create mode 100644 src/FedexRest/Services/FreightLTL/CancelFreightLTLPickup.php create mode 100644 src/FedexRest/Services/FreightLTL/Exceptions/MissingAssociatedAccountNumberException.php create mode 100644 src/FedexRest/Services/FreightLTL/Exceptions/MissingContactNameException.php create mode 100644 src/FedexRest/Services/FreightLTL/Exceptions/MissingPickupConfirmationCodeException.php create mode 100644 src/FedexRest/Services/FreightLTL/Exceptions/MissingReasonException.php create mode 100644 tests/FedexRest/Tests/FreightLTL/CancelFreightLTLPickupTest.php diff --git a/src/FedexRest/Services/FreightLTL/CancelFreightLTLPickup.php b/src/FedexRest/Services/FreightLTL/CancelFreightLTLPickup.php new file mode 100644 index 0000000..d4e4b78 --- /dev/null +++ b/src/FedexRest/Services/FreightLTL/CancelFreightLTLPickup.php @@ -0,0 +1,134 @@ +associatedAccountNumber = $associatedAccountNumber; + return $this; + } + + /** + * @param string $pickupConfirmationNumber + * @return $this + */ + public function setPickupConfirmationCode(string $pickupConfirmationCode): CancelFreightLTLPickup + { + $this->pickupConfirmationCode = $pickupConfirmationCode; + return $this; + } + + /** + * @param string $remarks + * @return $this + */ + public function setRemarks(string $remarks): CancelFreightLTLPickup + { + $this->remarks = $remarks; + return $this; + } + + /** + * @param string $reason + * @return $this + */ + public function setReason(string $reason): CancelFreightLTLPickup + { + $this->reason = $reason; + return $this; + } + + /** + * @param string $contactName + * @return $this + */ + public function setContactName(string $contactName): CancelFreightLTLPickup + { + $this->contactName = $contactName; + return $this; + } + + /** + * @param string $scheduledDate + * @return $this + */ + public function setScheduledDate(string $scheduledDate): CancelFreightLTLPickup + { + $this->scheduledDate = $scheduledDate; + return $this; + } + + public function prepare(): array + { + return [ + 'associatedAccountNumber' => + [ + 'value' => $this->associatedAccountNumber + ], + 'pickupConfirmationCode' => $this->pickupConfirmationCode, + 'remarks' => $this->remarks, + 'reason' => $this->reason, + 'contactName' => $this->contactName, + 'scheduledDate' => $this->scheduledDate, + ]; + } + + public function request() + { + parent::request(); + + if(empty($this->associatedAccountNumber)){ + throw new MissingAssociatedAccountNumberException('Associated Account Number is required.'); + } + + if(empty($this->pickupConfirmationCode)){ + throw new MissingPickupConfirmationCodeException('Pickup Confirmation Number is required.'); + } + + if(empty($this->reason)){ + throw new MissingReasonException('Reason is required.'); + } + + if(empty($this->contactName)){ + throw new MissingContactNameException('Contact Name is required.'); + } + + + try { + $query = $this->http_client->put($this->getApiUri($this->api_endpoint), [ + 'json' => $this->prepare(), + 'http_errors' => false, + ]); + return ($this->raw === true) ? $query : json_decode($query->getBody()->getContents()); + } catch (\Exception $e) { + return $e->getMessage(); + } + } + + + +} diff --git a/src/FedexRest/Services/FreightLTL/Exceptions/MissingAssociatedAccountNumberException.php b/src/FedexRest/Services/FreightLTL/Exceptions/MissingAssociatedAccountNumberException.php new file mode 100644 index 0000000..5497a48 --- /dev/null +++ b/src/FedexRest/Services/FreightLTL/Exceptions/MissingAssociatedAccountNumberException.php @@ -0,0 +1,11 @@ +auth = (new Authorize) + ->setClientId('l7749d031872cf4b55a7889376f360d045') + ->setClientSecret('bd59d91084e8482895d4ae2fb4fb79a3'); + } + + public function testHasAssociatedAccountNumber() + { + $request = NULL; + try { + $request = (new CancelFreightLTLPickup()) + ->setAccessToken((string) $this->auth->authorize()->access_token) + ->request(); + + } catch (MissingAssociatedAccountNumberException $e) { + $this->assertEquals('Associated Account Number is required.', $e->getMessage()); + } + $this->assertEmpty($request, 'The request did not fail as it should.'); + } + + public function testHasPickupConfirmationNumber() + { + $request = NULL; + try { + $request = (new CancelFreightLTLPickup()) + ->setAccessToken((string) $this->auth->authorize()->access_token) + ->setAssociatedAccountNumber('740561073') + ->request(); + + } catch (MissingPickupConfirmationCodeException $e) { + $this->assertEquals('Pickup Confirmation Number is required.', $e->getMessage()); + } + $this->assertEmpty($request, 'The request did not fail as it should.'); + } + + public function testHasReason() + { + $request = NULL; + try { + $request = (new CancelFreightLTLPickup()) + ->setAccessToken((string) $this->auth->authorize()->access_token) + ->setAssociatedAccountNumber('740561073') + ->setPickupConfirmationCode('20201007MEM628005') + ->request(); + + } catch (\Exception $e) { + $this->assertEquals('Reason is required.', $e->getMessage()); + } + $this->assertEmpty($request, 'The request did not fail as it should.'); + } + + public function testHasContactName() + { + $request = NULL; + try { + $request = (new CancelFreightLTLPickup()) + ->setAccessToken((string) $this->auth->authorize()->access_token) + ->setAssociatedAccountNumber('740561073') + ->setPickupConfirmationCode('20201007MEM628005') + ->setReason('No longer needed') + ->request(); + + } catch (\Exception $e) { + $this->assertEquals('Contact Name is required.', $e->getMessage()); + } + $this->assertEmpty($request, 'The request did not fail as it should.'); + } + + public function testRequiredData() + { + $cancelFreightLTLPickup = (new CancelFreightLTLPickup()) + ->setAccessToken((string) $this->auth->authorize()->access_token) + ->setAssociatedAccountNumber($associatedAccountNumber = '740561073') + ->setPickupConfirmationCode($pickupConfimrationCode = '20201007MEM628005') + ->setReason($reason = 'No longer needed') + ->setContactName($ContactName = 'John Doe'); + + $prepared = $cancelFreightLTLPickup->prepare(); + $this->assertEquals($associatedAccountNumber, $prepared['associatedAccountNumber']['value']); + $this->assertEquals($pickupConfimrationCode, $prepared['pickupConfirmationCode']); + $this->assertEquals($reason, $prepared['reason']); + $this->assertEquals($ContactName, $prepared['contactName']); + } + + public function testPrepare() + { + $request = (new CancelFreightLTLPickup()) + ->setAccessToken((string) $this->auth->authorize()->access_token) + ->setAssociatedAccountNumber($associatedAccountNumber = '740561073') + ->setPickupConfirmationCode($pickupConfimrationCode = '20201007MEM628005') + ->setRemarks($remarks = 'No longer needed') + ->setReason($reason = 'No longer needed') + ->setContactName($ContactName = 'John Doe') + ->setScheduledDate($scheduledDate = '2020-10-07'); + + $prepared = $request->prepare(); + + $this->assertEquals($associatedAccountNumber, $prepared['associatedAccountNumber']['value']); + $this->assertEquals($pickupConfimrationCode, $prepared['pickupConfirmationCode']); + $this->assertEquals($remarks, $prepared['remarks']); + $this->assertEquals($reason, $prepared['reason']); + $this->assertEquals($ContactName, $prepared['contactName']); + $this->assertEquals($scheduledDate, $prepared['scheduledDate']); + } + + public function testRequest() + { + $request = (new CancelFreightLTLPickup()) + ->setAccessToken((string) $this->auth->authorize()->access_token) + ->setAssociatedAccountNumber('740561073') + ->setPickupConfirmationCode('XXXX1007MEM62XXXX') + ->setReason('No longer needed') + ->setContactName('John Doe') + ->setScheduledDate('2020-10-07') + ->request(); + var_dump($request); + + $this->assertObjectHasProperty('transactionId', $request); + //As per FedEx Rep, Can Freight LTL Pickup will ALWAYS return in an error due to virtulizaed. They may change that in the future. + //This is as far of testing we can do for Cancel. If something changes in future, additional asserts can be done below + //$this->assertObjectNotHasProperty('errors', $request); + //$this->assertObjectHasProperty('output', $request); + //$this->assertObjectHasProperty('pickupConfirmationCode', $request->output); + //$this->assertObjectHasProperty('cancelConfirmationMessage', $request->output); + } + + +} From 159ac6860b664e6d354ae4a9e55a881650a509bd Mon Sep 17 00:00:00 2001 From: Ash <58735196+ash-g-1337@users.noreply.github.com> Date: Thu, 30 Jan 2025 14:59:47 -0500 Subject: [PATCH 03/11] exception details to cancel Freight LTL Pickup --- .../Services/FreightLTL/CancelFreightLTLPickup.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/FedexRest/Services/FreightLTL/CancelFreightLTLPickup.php b/src/FedexRest/Services/FreightLTL/CancelFreightLTLPickup.php index d4e4b78..c683ef1 100644 --- a/src/FedexRest/Services/FreightLTL/CancelFreightLTLPickup.php +++ b/src/FedexRest/Services/FreightLTL/CancelFreightLTLPickup.php @@ -97,6 +97,13 @@ public function prepare(): array ]; } + /** + * @throws MissingAssociatedAccountNumberException + * @throws MissingPickupConfirmationCodeException + * @throws MissingReasonException + * @throws MissingContactNameException + * @throws GuzzleException + */ public function request() { parent::request(); From f23ef3e7a68b2affb386a991ef4843773b675d80 Mon Sep 17 00:00:00 2001 From: Ash <58735196+ash-g-1337@users.noreply.github.com> Date: Thu, 30 Jan 2025 15:19:24 -0500 Subject: [PATCH 04/11] nulls for not required fields --- .../FreightLTL/CancelFreightLTLPickup.php | 32 ++++++++++++------- .../FreightLTL/CancelFreightLTLPickupTest.php | 2 +- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/FedexRest/Services/FreightLTL/CancelFreightLTLPickup.php b/src/FedexRest/Services/FreightLTL/CancelFreightLTLPickup.php index c683ef1..1e0b684 100644 --- a/src/FedexRest/Services/FreightLTL/CancelFreightLTLPickup.php +++ b/src/FedexRest/Services/FreightLTL/CancelFreightLTLPickup.php @@ -12,10 +12,10 @@ class CancelFreightLTLPickup extends AbstractRequest { protected string $associatedAccountNumber = ''; protected string $pickupConfirmationCode = ''; - protected string $remarks = ''; + protected ?string $remarks = null; protected string $reason = ''; protected string $contactName = ''; - protected string $scheduledDate = ''; + protected ?string $scheduledDate = null; public function setApiEndpoint(): string { @@ -84,17 +84,25 @@ public function setScheduledDate(string $scheduledDate): CancelFreightLTLPickup public function prepare(): array { - return [ - 'associatedAccountNumber' => - [ - 'value' => $this->associatedAccountNumber - ], - 'pickupConfirmationCode' => $this->pickupConfirmationCode, - 'remarks' => $this->remarks, - 'reason' => $this->reason, - 'contactName' => $this->contactName, - 'scheduledDate' => $this->scheduledDate, + $data = [ + 'associatedAccountNumber' => + [ + 'value' => $this->associatedAccountNumber + ], + 'pickupConfirmationCode' => $this->pickupConfirmationCode, + 'reason' => $this->reason, + 'contactName' => $this->contactName, ]; + + if(!empty($this->remarks)){ + $data['remarks'] = $this->remarks; + } + + if(!empty($this->scheduledDate)){ + $data['scheduledDate'] = $this->scheduledDate; + } + + return $data; } /** diff --git a/tests/FedexRest/Tests/FreightLTL/CancelFreightLTLPickupTest.php b/tests/FedexRest/Tests/FreightLTL/CancelFreightLTLPickupTest.php index c6b87a2..380ce5e 100644 --- a/tests/FedexRest/Tests/FreightLTL/CancelFreightLTLPickupTest.php +++ b/tests/FedexRest/Tests/FreightLTL/CancelFreightLTLPickupTest.php @@ -129,7 +129,7 @@ public function testRequest() ->setContactName('John Doe') ->setScheduledDate('2020-10-07') ->request(); - var_dump($request); + //var_dump($request); $this->assertObjectHasProperty('transactionId', $request); //As per FedEx Rep, Can Freight LTL Pickup will ALWAYS return in an error due to virtulizaed. They may change that in the future. From 7761ac2c32b9ef526ccf3f8b6744942361029392 Mon Sep 17 00:00:00 2001 From: Ash <58735196+ash-g-1337@users.noreply.github.com> Date: Thu, 30 Jan 2025 23:32:30 -0500 Subject: [PATCH 05/11] little bit of cleanup and added support for Create Freight LTL Pickup --- README.md | 2 +- .../FreightLTL/CancelFreightLTLPickup.php | 7 +- .../FreightLTL/CreateFreightLTLPickup.php | 220 +++++++++++++ .../Services/FreightLTL/Entity/Billing.php | 66 ++++ .../Entity/FreightDirectDataDetails.php | 73 +++++ .../FreightLTL/Entity/FreightDirectDetail.php | 30 ++ .../FreightLTL/Entity/FreightPickupDetail.php | 152 +++++++++ .../Entity/FreightPickupLineItem.php | 290 ++++++++++++++++++ .../FreightLTL/Entity/SubmittedBy.php | 90 ++++++ .../MissingFreightPickupDetailException.php | 11 + .../MissingOriginDetailException.php | 12 + .../Tests/Entity/BillingEntityTest.php | 48 +++ .../Entity/FreightPickupDetailEntityTest.php | 101 ++++++ .../Tests/Entity/SubmittedByEntityTest.php | 33 ++ .../FreightLTL/CreateFreightLTLPickupTest.php | 255 +++++++++++++++ 15 files changed, 1385 insertions(+), 5 deletions(-) create mode 100644 src/FedexRest/Services/FreightLTL/CreateFreightLTLPickup.php create mode 100644 src/FedexRest/Services/FreightLTL/Entity/Billing.php create mode 100644 src/FedexRest/Services/FreightLTL/Entity/FreightDirectDataDetails.php create mode 100644 src/FedexRest/Services/FreightLTL/Entity/FreightDirectDetail.php create mode 100644 src/FedexRest/Services/FreightLTL/Entity/FreightPickupDetail.php create mode 100644 src/FedexRest/Services/FreightLTL/Entity/FreightPickupLineItem.php create mode 100644 src/FedexRest/Services/FreightLTL/Entity/SubmittedBy.php create mode 100644 src/FedexRest/Services/FreightLTL/Exceptions/MissingFreightPickupDetailException.php create mode 100644 src/FedexRest/Services/FreightLTL/Exceptions/MissingOriginDetailException.php create mode 100644 tests/FedexRest/Tests/Entity/BillingEntityTest.php create mode 100644 tests/FedexRest/Tests/Entity/FreightPickupDetailEntityTest.php create mode 100644 tests/FedexRest/Tests/Entity/SubmittedByEntityTest.php create mode 100644 tests/FedexRest/Tests/FreightLTL/CreateFreightLTLPickupTest.php diff --git a/README.md b/README.md index ec81d90..4de4d0c 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ FedEx Rest API documentation https://developer.fedex.com/api/en-us/get-started.h - [ ] Rate Freight LTL ([docs](https://developer.fedex.com/api/en-us/catalog/ltl-freight/v1/docs.html#operation/Freight%20RateQuote)) - [ ] Ship Freight LTL ([docs](https://developer.fedex.com/api/en-us/catalog/ltl-freight/v1/docs.html#operation/Freight%20Shipment)) - [ ] Check Freight LTL Pickup Availability ([docs](https://developer.fedex.com/api/en-us/catalog/ltl-freight/v1/docs.html#operation/Check%20Freight%20Pickup%20Availability)) - - [ ] Create Freight LTL Pickup ([docs](https://developer.fedex.com/api/en-us/catalog/ltl-freight/v1/docs.html#operation/Create%20Freight%20Pickup)) + - [X] Create Freight LTL Pickup ([docs](https://developer.fedex.com/api/en-us/catalog/ltl-freight/v1/docs.html#operation/Create%20Freight%20Pickup)) - [x] Cancel Freight LTL Pickup ([docs](https://developer.fedex.com/api/en-us/catalog/ltl-freight/v1/docs.html#operation/Cancel%20Freight%20Pickup)) ### Other diff --git a/src/FedexRest/Services/FreightLTL/CancelFreightLTLPickup.php b/src/FedexRest/Services/FreightLTL/CancelFreightLTLPickup.php index 1e0b684..02d28f4 100644 --- a/src/FedexRest/Services/FreightLTL/CancelFreightLTLPickup.php +++ b/src/FedexRest/Services/FreightLTL/CancelFreightLTLPickup.php @@ -85,10 +85,9 @@ public function setScheduledDate(string $scheduledDate): CancelFreightLTLPickup public function prepare(): array { $data = [ - 'associatedAccountNumber' => - [ - 'value' => $this->associatedAccountNumber - ], + 'associatedAccountNumber' => [ + 'value' => $this->associatedAccountNumber + ], 'pickupConfirmationCode' => $this->pickupConfirmationCode, 'reason' => $this->reason, 'contactName' => $this->contactName, diff --git a/src/FedexRest/Services/FreightLTL/CreateFreightLTLPickup.php b/src/FedexRest/Services/FreightLTL/CreateFreightLTLPickup.php new file mode 100644 index 0000000..13b43d6 --- /dev/null +++ b/src/FedexRest/Services/FreightLTL/CreateFreightLTLPickup.php @@ -0,0 +1,220 @@ +associatedAccountNumber = $associatedAccountNumber; + return $this; + } + + /** + * @param OriginDetail $originDetail + * @return $this + */ + public function setOriginDetail(OriginDetail $originDetail): CreateFreightLTLPickup + { + $this->originDetail = $originDetail; + return $this; + } + + /** + * @param string $associatedAccountNumber + * @return $this + */ + public function addTotalWeight(Weight $weight): CreateFreightLTLPickup + { + $this->totalWeight[] = $weight; + return $this; + } + + /** + * @param int|null $packageCount + * @return $this + */ + public function setPackageCount(?int $packageCount): CreateFreightLTLPickup + { + $this->packageCount = $packageCount; + return $this; + } + + /** + * @param string|null $remarks + * @return $this + */ + public function setRemarks(?string $remarks): CreateFreightLTLPickup + { + $this->remarks = $remarks; + return $this; + } + + /** + * @param string|null $countryRelationships + * @return $this + */ + public function setCountryRelationships(?string $countryRelationships): CreateFreightLTLPickup + { + $this->countryRelationships = $countryRelationships; + return $this; + } + + /** + * @param string|null $trackingNumber + * @return $this + */ + public function setTrackingNumber(?string $trackingNumber): CreateFreightLTLPickup + { + $this->trackingNumber = $trackingNumber; + return $this; + } + + /** + * @param string|null $commodityDescription + * @return $this + */ + public function setCommodityDescription(?string $commodityDescription): CreateFreightLTLPickup + { + $this->commodityDescription = $commodityDescription; + return $this; + } + + /** + * @param FreightPickupDetail $freightPickupDetail + * @return $this + */ + public function setFreightPickupDetail(FreightPickupDetail $freightPickupDetail): CreateFreightLTLPickup + { + $this->freightPickupDetail = $freightPickupDetail; + return $this; + } + + /** + * @param int|null $oversizePackageCount + * @return $this + */ + public function setOversizePackageCount(?int $oversizePackageCount): CreateFreightLTLPickup + { + $this->oversizePackageCount = $oversizePackageCount; + return $this; + } + + /** + * @param PickupNotificationDetail|null $pickupNotificationDetail + * @return $this + */ + public function setPickupNotificationDetail(?PickupNotificationDetail $pickupNotificationDetail): CreateFreightLTLPickup + { + $this->pickupNotificationDetail = $pickupNotificationDetail; + return $this; + } + + public function prepare(): array + { + $data = [ + 'associatedAccountNumber' => [ + 'value' => $this->associatedAccountNumber, + ], + 'originDetail' => $this->originDetail->prepare(), + 'remarks' => $this->remarks, + 'freightPickupDetail' => $this->freightPickupDetail->prepare(), + ]; + + if(!empty($this->totalWeight)) { + $data['totalWeight'] = array_map(function (Weight $weight) { + return $weight->prepare(); + }, $this->totalWeight); + } + + if(!empty($this->packageCount)){ + $data['packageCount'] = $this->packageCount; + } + + if(!empty($this->remarks)){ + $data['remarks'] = $this->remarks; + } + + if(!empty($this->countryRelationships)){ + $data['countryRelationships'] = $this->countryRelationships; + } + + if(!empty($this->trackingNumber)){ + $data['trackingNumber'] = $this->trackingNumber; + } + + if(!empty($this->commodityDescription)){ + $data['commodityDescription'] = $this->commodityDescription; + } + + if(!empty($this->oversizePackageCount)){ + $data['oversizePackageCount'] = $this->oversizePackageCount; + } + + if(!empty($this->pickupNotificationDetail)){ + $data['pickupNotificationDetail'] = $this->pickupNotificationDetail->prepare(); + } + + + return $data; + } + + public function request() + { + parent::request(); + + if(empty($this->associatedAccountNumber)){ + throw new MissingAssociatedAccountNumberException('Associated Account Number is missing.'); + } + + if(!isset($this->originDetail)){ + throw new MissingOriginDetailException('Origin Detail is missing.'); + } + + if(!isset($this->freightPickupDetail)){ + throw new MissingFreightPickupDetailException('Freight Pickup Detail is missing.'); + } + + + try { + $query = $this->http_client->post($this->getApiUri($this->api_endpoint), [ + 'json' => $this->prepare(), + 'http_errors' => FALSE, + ]); + return ($this->raw === true) ? $query : json_decode($query->getBody()->getContents()); + } catch (\Exception $e) { + return $e->getMessage(); + } + } + +} diff --git a/src/FedexRest/Services/FreightLTL/Entity/Billing.php b/src/FedexRest/Services/FreightLTL/Entity/Billing.php new file mode 100644 index 0000000..ad6229a --- /dev/null +++ b/src/FedexRest/Services/FreightLTL/Entity/Billing.php @@ -0,0 +1,66 @@ +address = $address; + return $this; + } + + /** + * @param Contact $contact + * @return $this + */ + public function setContact(?Contact $contact): Billing + { + $this->contact = $contact; + return $this; + } + + /** + * @param string $accountNumber + * @return $this + */ + public function setAccountNumber(?string $accountNumber): Billing + { + $this->accountNumber = $accountNumber; + return $this; + } + + /** + * @return array[] + */ + public function prepare(): array + { + $data = []; + + if (!empty($this->address)) { + $data['address'] = $this->address->prepare(); + } + + if (!empty($this->contact)) { + $data['contact'] = $this->contact->prepare(); + } + + if (!empty($this->accountNumber)) { + $data['accountNumber'] = $this->accountNumber; + } + + return $data; + } + +} diff --git a/src/FedexRest/Services/FreightLTL/Entity/FreightDirectDataDetails.php b/src/FedexRest/Services/FreightLTL/Entity/FreightDirectDataDetails.php new file mode 100644 index 0000000..b12276f --- /dev/null +++ b/src/FedexRest/Services/FreightLTL/Entity/FreightDirectDataDetails.php @@ -0,0 +1,73 @@ +type = $type; + return $this; + } + + /** + * @param string|null $transportationType + * @return FreightDirectDetail + */ + public function setTransportationType(?string $transportationType): FreightDirectDataDetails + { + $this->transportationType = $transportationType; + return $this; + } + + /** + * @param string|null $emailAddress + * @return FreightDirectDetail + */ + public function setEmailAddress(?string $emailAddress): FreightDirectDataDetails + { + $this->emailAddress = $emailAddress; + return $this; + } + + public function addPhoneNumber($phoneNumber, $type = 'HOME'): FreightDirectDataDetails + { + $this->phoneNumberDetails[] = [ + 'phoneNumber' => $phoneNumber, + 'phoneNumberType' => $type + ]; + return $this; + } + + public function prepare() + { + $data = []; + + if (!empty($this->type)) { + $data['type'] = $this->type; + } + + if (!empty($this->transportationType)) { + $data['transportationType'] = $this->transportationType; + } + + if (!empty($this->emailAddress)) { + $data['emailAddress'] = $this->emailAddress; + } + + if (!empty($this->phoneNumberDetails)) { + $data['phoneNumberDetails'] = $this->phoneNumberDetails; + } + + return $data; + } +} diff --git a/src/FedexRest/Services/FreightLTL/Entity/FreightDirectDetail.php b/src/FedexRest/Services/FreightLTL/Entity/FreightDirectDetail.php new file mode 100644 index 0000000..514b9ad --- /dev/null +++ b/src/FedexRest/Services/FreightLTL/Entity/FreightDirectDetail.php @@ -0,0 +1,30 @@ +freightDirectDataDetails = $freightDirectDataDetails; + return $this; + } + + public function prepare() + { + $data = [ + 'freightDirectDataDetails' => [], + ]; + foreach ($this->freightDirectDataDetails as $freightDirectDataDetail) { + $data['freightDirectDataDetails'][] = $freightDirectDataDetail->prepare(); + } + return $data; + } + +} diff --git a/src/FedexRest/Services/FreightLTL/Entity/FreightPickupDetail.php b/src/FedexRest/Services/FreightLTL/Entity/FreightPickupDetail.php new file mode 100644 index 0000000..ab35024 --- /dev/null +++ b/src/FedexRest/Services/FreightLTL/Entity/FreightPickupDetail.php @@ -0,0 +1,152 @@ +accountNumber = $accountNumber; + return $this; + } + + /** + * @param string $accountNumberKey + * @return $this + */ + public function setAccountNumberKey(?string $accountNumberKey): freightPickupDetail + { + $this->accountNumberKey = $accountNumberKey; + return $this; + } + + /** + * @param string $role + * @return $this + */ + public function setRole(?string $role): freightPickupDetail + { + $this->role = $role; + return $this; + } + + /** + * @param string $payment + * @return $this + */ + public function setPayment(?string $payment): freightPickupDetail + { + $this->payment = $payment; + return $this; + } + + /** + * @param SubmittedBy $submittedBy + * @return $this + */ + public function setSubmittedBy(?SubmittedBy $submittedBy): freightPickupDetail + { + $this->submittedBy = $submittedBy; + return $this; + } + + /** + * @param array $lineItems + * @return $this + */ + public function setLineItems(FreightPickupLineItem ...$lineItems): freightPickupDetail + { + $this->lineItems = $lineItems; + return $this; + } + + /** + * @param Billing $alternateBilling + * @return $this + */ + public function setAlternateBilling(?Billing $alternateBilling): freightPickupDetail + { + $this->alternateBilling = $alternateBilling; + return $this; + } + + /** + * @param string $userMessage + * @return $this + */ + public function setUserMessage(?string $userMessage): freightPickupDetail + { + $this->userMessage = $userMessage; + return $this; + } + + public function prepare(): array + { + $data = []; + + if(!empty($this->accountNumber) || !empty($this->accountNumberKey)) { + $data['accountNumber'] = []; + + if(!empty($this->accountNumber)) { + $data['accountNumber']['value'] = $this->accountNumber; + } + + if(!empty($this->accountNumberKey)) { + $data['accountNumber']['key'] = $this->accountNumberKey; + } + } + + if(!empty($this->role)) { + $data['role'] = $this->role; + } + + if(!empty($this->payment)) { + $data['payment'] = $this->payment; + } + + if(!empty($this->submittedBy)) { + $data['submittedBy'] = $this->submittedBy->prepare(); + } + + if(!empty($this->lineItems)) { + $data['lineItems'] = array_map(function (FreightPickupLineItem $lineItem) { + return $lineItem->prepare(); + }, $this->lineItems); + } + + if(!empty($this->alternateBilling)) { + $data['alternateBilling'] = $this->alternateBilling->prepare(); + } + + if(!empty($this->userMessage)) { + $data['userMessage'] = $this->userMessage; + } + + return $data; + } + + + + + + +} diff --git a/src/FedexRest/Services/FreightLTL/Entity/FreightPickupLineItem.php b/src/FedexRest/Services/FreightLTL/Entity/FreightPickupLineItem.php new file mode 100644 index 0000000..47ff415 --- /dev/null +++ b/src/FedexRest/Services/FreightLTL/Entity/FreightPickupLineItem.php @@ -0,0 +1,290 @@ +trackingNumber = $trackingNumber; + return $this; + } + + /** + * @param string|null $trackingQualifier + * @return FreightPickupLineItem + */ + public function setTrackingQualifier(?string $trackingQualifier): FreightPickupLineItem + { + $this->trackingQualifier = $trackingQualifier; + return $this; + } + + /** + * @param string|null $trackingCarrier + * @return FreightPickupLineItem + */ + public function setTrackingCarrier(?string $trackingCarrier): FreightPickupLineItem + { + $this->trackingCarrier = $trackingCarrier; + return $this; + } + + /** + * @param string|null $trackingUniqueId + * @return FreightPickupLineItem + */ + public function setTrackingUniqueId(?string $trackingUniqueId): FreightPickupLineItem + { + $this->trackingUniqueId = $trackingUniqueId; + return $this; + } + + /** + * @param string|null $service + * @return FreightPickupLineItem + */ + public function setService(?string $service): FreightPickupLineItem + { + $this->service = $service; + return $this; + } + + /** + * @param int|null $sequenceNumber + * @return FreightPickupLineItem + */ + public function setSequenceNumber(?int $sequenceNumber): FreightPickupLineItem + { + $this->sequenceNumber = $sequenceNumber; + return $this; + } + + /** + * @param int|null $totalHandlingUnits + * @return FreightPickupLineItem + */ + public function setTotalHandlingUnits(?int $totalHandlingUnits): FreightPickupLineItem + { + $this->totalHandlingUnits = $totalHandlingUnits; + return $this; + } + + /** + * @param bool|null $justOneMore + * @return FreightPickupLineItem + */ + public function setJustOneMore(?bool $justOneMore): FreightPickupLineItem + { + $this->justOneMore = $justOneMore; + return $this; + } + + /** + * @param string|null $description + * @return FreightPickupLineItem + */ + public function setDescription(?string $description): FreightPickupLineItem + { + $this->description = $description; + return $this; + } + + /** + * @param string|null $packaging + * @return FreightPickupLineItem + */ + public function setPackaging(?string $packaging): FreightPickupLineItem + { + $this->packaging = $packaging; + return $this; + } + + /** + * @param int|null $pieces + * @return FreightPickupLineItem + */ + public function setPieces(?int $pieces): FreightPickupLineItem + { + $this->pieces = $pieces; + return $this; + } + + /** + * @param Weight|null $weight + * @return FreightPickupLineItem + */ + public function setWeight(?Weight $weight): FreightPickupLineItem + { + $this->weight = $weight; + return $this; + } + + /** + * @param Dimensions|null $dimensions + * @return FreightPickupLineItem + */ + public function setDimensions(?Dimensions $dimensions): FreightPickupLineItem + { + $this->dimensions = $dimensions; + return $this; + } + + /** + * @param Address|null $destination + * @return FreightPickupLineItem + */ + public function setDestination(?Address $destination): FreightPickupLineItem + { + $this->destination = $destination; + return $this; + } + + /** + * @param string|null $freightGuarenteeTime + * @return FreightPickupLineItem + */ + public function setFreightGuarenteeTime(?string $freightGuarenteeTime): FreightPickupLineItem + { + $this->freightGuarenteeTime = $freightGuarenteeTime; + return $this; + } + + /** + * @param FreightDirectDetail|null $freightDirectDetail + * @return FreightPickupLineItem + */ + public function setFreightDirectDetail(?FreightDirectDetail $freightDirectDetail): FreightPickupLineItem + { + $this->freightDirectDetail = $freightDirectDetail; + return $this; + } + + /** + * @param array|null $specialServiceTypes + * @return FreightPickupLineItem + */ + public function setSpecialServiceTypes(?array $specialServiceTypes): FreightPickupLineItem + { + $this->specialServiceTypes = $specialServiceTypes; + return $this; + } + + public function prepare() + { + $data = []; + + if (!empty($this->trackingNumber) || !empty($this->trackingQualifier) || !empty($this->trackingCarrier) || !empty($this->trackingUniqueId)) { + $data['trackingNumber'] = []; + if (!empty($this->trackingNumber)) { + $data['trackingNumber']['trackingNumber'] = $this->trackingNumber; + } + if (!empty($this->trackingQualifier)) { + $data['trackingNumber']['trackingQualifier'] = $this->trackingQualifier; + } + if (!empty($this->trackingCarrier)) { + $data['trackingNumber']['trackingCarrier'] = $this->trackingCarrier; + } + if (!empty($this->trackingUniqueId)) { + $data['trackingNumber']['trackingUniqueId'] = $this->trackingUniqueId; + } + } + + if (!empty($this->service)) { + $data['service'] = $this->service; + } + + if(!empty($this->service)) { + $data['service'] = $this->service; + } + + if (!empty($this->service)) { + $data['service'] = $this->service; + } + + if (!empty($this->sequenceNumber)) { + $data['sequenceNumber'] = $this->sequenceNumber; + } + + if (!empty($this->totalHandlingUnits)) { + $data['totalHandlingUnits'] = $this->totalHandlingUnits; + } + + if (!empty($this->justOneMore)) { + $data['justOneMore'] = $this->justOneMore; + } + + if (!empty($this->description)) { + $data['description'] = $this->description; + } + + if (!empty($this->packaging)) { + $data['packaging'] = $this->packaging; + } + + if (!empty($this->pieces)) { + $data['pieces'] = $this->pieces; + } + + if (!empty($this->weight)) { + $data['weight'] = $this->weight->prepare(); + } + + if (!empty($this->dimensions)) { + $data['dimensions'] = $this->dimensions->prepare(); + } + + if (!empty($this->destination)) { + $data['destination'] = $this->destination->prepare(); + } + + if(!empty($this->freightGuarenteeTime) || !empty($this->freightDirectDetail) || !empty($this->specialServiceTypes)) { + $data['shipmentSpecialServicesRequested'] = []; + + if(!empty($this->freightGuarenteeTime)) { + $data['shipmentSpecialServicesRequested']['freightGuaranteeDetail'] = []; + $data['shipmentSpecialServicesRequested']['freightGuaranteeDetail']['time'] = $this->freightGuarenteeTime; + } + + if(!empty($this->freightDirectDetail)) { + $data['shipmentSpecialServicesRequested']['freightDirectDetail'] = $this->freightDirectDetail->prepare(); + } + + if(!empty($this->specialServiceTypes)) { + $data['shipmentSpecialServicesRequested']['specialServiceTypes'] = $this->specialServiceTypes; + } + } + + + return $data; + } + + +} diff --git a/src/FedexRest/Services/FreightLTL/Entity/SubmittedBy.php b/src/FedexRest/Services/FreightLTL/Entity/SubmittedBy.php new file mode 100644 index 0000000..4d05450 --- /dev/null +++ b/src/FedexRest/Services/FreightLTL/Entity/SubmittedBy.php @@ -0,0 +1,90 @@ +companyName = $companyName; + return $this; + } + + /** + * @param string $personName + * @return $this + */ + public function setPersonName(?string $personName): SubmittedBy + { + $this->personName = $personName; + return $this; + } + + /** + * @param string $phoneNumber + * @return $this + */ + public function setPhoneNumber(?string $phoneNumber): SubmittedBy + { + $this->phoneNumber = $phoneNumber; + return $this; + } + + /** + * @param string $phoneExtension + * @return $this + */ + public function setPhoneExtension(?string $phoneExtension): SubmittedBy + { + $this->phoneExtension = $phoneExtension; + return $this; + } + + /** + * @param string $emailAddress + * @return $this + */ + public function setEmailAddress(?string $emailAddress): SubmittedBy + { + $this->emailAddress = $emailAddress; + return $this; + } + + public function prepare(): array + { + $data = []; + + if (!empty($this->companyName)) { + $data['companyName'] = $this->companyName; + } + + if (!empty($this->personName)) { + $data['personName'] = $this->personName; + } + + if (!empty($this->phoneNumber)) { + $data['phoneNumber'] = $this->phoneNumber; + } + + if (!empty($this->phoneExtension)) { + $data['phoneExtension'] = $this->phoneExtension; + } + + if (!empty($this->emailAddress)) { + $data['emailAddress'] = $this->emailAddress; + } + + return $data; + } +} diff --git a/src/FedexRest/Services/FreightLTL/Exceptions/MissingFreightPickupDetailException.php b/src/FedexRest/Services/FreightLTL/Exceptions/MissingFreightPickupDetailException.php new file mode 100644 index 0000000..9c53de5 --- /dev/null +++ b/src/FedexRest/Services/FreightLTL/Exceptions/MissingFreightPickupDetailException.php @@ -0,0 +1,11 @@ +setAddress( + (new Address()) + ->setCity('Harrison') + ->setStateOrProvince('AR') + ->setPostalCode('72601') + ->setCountryCode('US') + ->setResidential(true) + ) + ->setContact( + (new Contact()) + ->setPersonName('John Doe') + ->setPhoneNumber('555-555-5555') + ->setCompanyName('Company Name') + ) + ->setAccountNumber('123456789'); + + $this->assertObjectHasProperty('address', $billing); + $this->assertObjectHasProperty('contact', $billing); + $this->assertObjectHasProperty('accountNumber', $billing); + + $billingPrepared = $billing->prepare(); + $this->assertEquals('Harrison', $billingPrepared['address']['city']); + $this->assertEquals('AR', $billingPrepared['address']['stateOrProvinceCode']); + $this->assertEquals('72601', $billingPrepared['address']['postalCode']); + $this->assertEquals('US', $billingPrepared['address']['countryCode']); + $this->assertEquals(true, $billingPrepared['address']['residential']); + $this->assertEquals('John Doe', $billingPrepared['contact']['personName']); + $this->assertEquals('555-555-5555', $billingPrepared['contact']['phoneNumber']); + $this->assertEquals('Company Name', $billingPrepared['contact']['companyName']); + $this->assertEquals('123456789', $billingPrepared['accountNumber']); + + } + +} diff --git a/tests/FedexRest/Tests/Entity/FreightPickupDetailEntityTest.php b/tests/FedexRest/Tests/Entity/FreightPickupDetailEntityTest.php new file mode 100644 index 0000000..23ddaf9 --- /dev/null +++ b/tests/FedexRest/Tests/Entity/FreightPickupDetailEntityTest.php @@ -0,0 +1,101 @@ +setAccountNumber('123456789') + ->setAccountNumberKey('123456789') + ->setRole('SHIPPER') + ->setPayment('SENDER') + ->setUserMessage('This is a test message') + ->setSubmittedBy( + (new SubmittedBy()) + ->setCompanyName('Test Company') + ->setPersonName('Test Person') + ->setPhoneNumber('1234567890') + ->setPhoneExtension('123') + ->setEmailAddress('abc@abc.com') + ) + ->setLineItems( + (new FreightPickupLineItem()) + ->setTrackingNumber('123456789') + ->setService('FEDEX_FREIGHT_PRIORITY') + ->setTotalHandlingUnits(1) + ->setWeight((new Weight()) + ->setValue(100) + ->setUnit('LB') + ) + ->setDestination((new Address()) + ->setStreetLines('1234 Main St') + ->setCity('Memphis') + ->setStateOrProvince('TN') + ->setPostalCode('38125') + ->setCountryCode('US') + ) + ) + ->setAlternateBilling( + (new Billing()) + ->setAddress( + (new Address()) + ->setCity('Harrison') + ->setStateOrProvince('AR') + ->setPostalCode('72601') + ->setCountryCode('US') + ->setResidential(true) + ) + ->setContact( + (new Contact()) + ->setPersonName('John Doe') + ->setPhoneNumber('555-555-5555') + ->setCompanyName('Company Name') + ) + ->setAccountNumber('123456789') + ); + + $this->assertObjectHasProperty('accountNumber', $freightPickupDetail); + $this->assertObjectHasProperty('role', $freightPickupDetail); + $this->assertObjectHasProperty('payment', $freightPickupDetail); + $this->assertObjectHasProperty('submittedBy', $freightPickupDetail); + $this->assertObjectHasProperty('lineItems', $freightPickupDetail); + $this->assertObjectHasProperty('alternateBilling', $freightPickupDetail); + $this->assertObjectHasProperty('userMessage', $freightPickupDetail); + + $freightPickupDetailPrepared = $freightPickupDetail->prepare(); + + $this->assertEquals('123456789', $freightPickupDetailPrepared['accountNumber']['value']); + $this->assertEquals('123456789', $freightPickupDetailPrepared['accountNumber']['key']); + $this->assertEquals('SHIPPER', $freightPickupDetailPrepared['role']); + $this->assertEquals('SENDER', $freightPickupDetailPrepared['payment']); + $this->assertEquals('This is a test message', $freightPickupDetailPrepared['userMessage']); + $this->assertEquals('Test Company', $freightPickupDetailPrepared['submittedBy']['companyName']); + $this->assertEquals('Test Person', $freightPickupDetailPrepared['submittedBy']['personName']); + $this->assertEquals('1234567890', $freightPickupDetailPrepared['submittedBy']['phoneNumber']); + $this->assertEquals('123', $freightPickupDetailPrepared['submittedBy']['phoneExtension']); + $this->assertEquals('abc@abc.com', $freightPickupDetailPrepared['submittedBy']['emailAddress']); + $this->assertEquals('Harrison', $freightPickupDetailPrepared['alternateBilling']['address']['city']); + $this->assertEquals('AR', $freightPickupDetailPrepared['alternateBilling']['address']['stateOrProvinceCode']); + $this->assertEquals('72601', $freightPickupDetailPrepared['alternateBilling']['address']['postalCode']); + $this->assertEquals('US', $freightPickupDetailPrepared['alternateBilling']['address']['countryCode']); + $this->assertEquals(true, $freightPickupDetailPrepared['alternateBilling']['address']['residential']); + $this->assertEquals('John Doe', $freightPickupDetailPrepared['alternateBilling']['contact']['personName']); + $this->assertEquals('555-555-5555', $freightPickupDetailPrepared['alternateBilling']['contact']['phoneNumber']); + $this->assertEquals('Company Name', $freightPickupDetailPrepared['alternateBilling']['contact']['companyName']); + $this->assertEquals('123456789', $freightPickupDetailPrepared['alternateBilling']['accountNumber']); + } +} diff --git a/tests/FedexRest/Tests/Entity/SubmittedByEntityTest.php b/tests/FedexRest/Tests/Entity/SubmittedByEntityTest.php new file mode 100644 index 0000000..f906b86 --- /dev/null +++ b/tests/FedexRest/Tests/Entity/SubmittedByEntityTest.php @@ -0,0 +1,33 @@ +setCompanyName('Test Company') + ->setPersonName('Test Person') + ->setPhoneNumber('1234567890') + ->setPhoneExtension('123') + ->setEmailAddress('abc@abc.com'); + + $this->assertObjectHasProperty('companyName', $submittedBy); + $this->assertObjectHasProperty('personName', $submittedBy); + $this->assertObjectHasProperty('phoneNumber', $submittedBy); + $this->assertObjectHasProperty('phoneExtension', $submittedBy); + $this->assertObjectHasProperty('emailAddress', $submittedBy); + + $submittedByPrepared = $submittedBy->prepare(); + $this->assertEquals('Test Company', $submittedByPrepared['companyName']); + $this->assertEquals('Test Person', $submittedByPrepared['personName']); + $this->assertEquals('1234567890', $submittedByPrepared['phoneNumber']); + $this->assertEquals('123', $submittedByPrepared['phoneExtension']); + $this->assertEquals('abc@abc.com', $submittedByPrepared['emailAddress']); + } + +} diff --git a/tests/FedexRest/Tests/FreightLTL/CreateFreightLTLPickupTest.php b/tests/FedexRest/Tests/FreightLTL/CreateFreightLTLPickupTest.php new file mode 100644 index 0000000..48ecf9f --- /dev/null +++ b/tests/FedexRest/Tests/FreightLTL/CreateFreightLTLPickupTest.php @@ -0,0 +1,255 @@ +auth = (new Authorize) + ->setClientId('l7749d031872cf4b55a7889376f360d045') + ->setClientSecret('bd59d91084e8482895d4ae2fb4fb79a3'); + } + + public function testHasAssociatedAccountNumber() + { + $request = NULL; + try { + $request = (new CreateFreightLTLPickup()) + ->setAccessToken((string) $this->auth->authorize()->access_token) + ->request(); + + } catch (MissingAssociatedAccountNumberException $e) { + $this->assertEquals('Associated Account Number is missing.', $e->getMessage()); + } + $this->assertEmpty($request, 'The request did not fail as it should.'); + } + + public function testHasOriginDetail() + { + $request = NULL; + try { + $request = (new CreateFreightLTLPickup()) + ->setAccessToken((string) $this->auth->authorize()->access_token) + ->setAssociatedAccountNumber('740561073') + ->request(); + + } catch (MissingOriginDetailException $e) { + $this->assertEquals('Origin Detail is missing.', $e->getMessage()); + } + $this->assertEmpty($request, 'The request did not fail as it should.'); + } + + public function testHasFreightPickupDetail() + { + $request = NULL; + try { + $request = (new CreateFreightLTLPickup()) + ->setAccessToken((string) $this->auth->authorize()->access_token) + ->setAssociatedAccountNumber('740561073') + ->setOriginDetail(new OriginDetail()) + ->request(); + } catch (MissingFreightPickupDetailException $e) { + $this->assertEquals('Freight Pickup Detail is missing.', $e->getMessage()); + } + $this->assertEmpty($request, 'The request did not fail as it should.'); + } + + public function testRequiredData() + { + $createFreightLTLPickup = (new CreateFreightLTLPickup()) + ->setAccessToken((string) $this->auth->authorize()->access_token) + ->setAssociatedAccountNumber($associatedAccountNumber = '740561073') + ->setOriginDetail((new OriginDetail()) + ->setPickupLocation((new PickupLocation()) + ->setAddress((new Address()) + ->setStreetLines('1234 Main St') + ->setCity('Memphis') + ->setStateOrProvince('TN') + ->setPostalCode('38125') + ->setCountryCode('US') + ) + ->setContact((new Contact()) + ->setPersonName('John Doe') + ->setPhoneNumber('9015551234') + ) + ) + ->setReadyDateTimestamp('2021-10-07T08:00:00') + ->setCustomerCloseTime('2021-10-07T08:00:00') + ) + ->setFreightPickupDetail(new FreightPickupDetail()); + + $prepared = $createFreightLTLPickup->prepare(); + $this->assertArrayHasKey('originDetail', $prepared); + $this->assertArrayHasKey('freightPickupDetail', $prepared); + + $this->assertEquals($associatedAccountNumber, $prepared['associatedAccountNumber']['value']); + $this->assertEquals('1234 Main St', $prepared['originDetail']['pickupLocation']['address']['streetLines'][0]); + $this->assertEquals('Memphis', $prepared['originDetail']['pickupLocation']['address']['city']); + $this->assertEquals('TN', $prepared['originDetail']['pickupLocation']['address']['stateOrProvinceCode']); + $this->assertEquals('38125', $prepared['originDetail']['pickupLocation']['address']['postalCode']); + $this->assertEquals('US', $prepared['originDetail']['pickupLocation']['address']['countryCode']); + $this->assertEquals('John Doe', $prepared['originDetail']['pickupLocation']['contact']['personName']); + $this->assertEquals('9015551234', $prepared['originDetail']['pickupLocation']['contact']['phoneNumber']); + $this->assertEquals('2021-10-07T08:00:00', $prepared['originDetail']['readyDateTimestamp']); + $this->assertEquals('2021-10-07T08:00:00', $prepared['originDetail']['customerCloseTime']); + + + } + + public function testPrepare() + { + $createFreightLTLPickup = (new CreateFreightLTLPickup()) + ->setAccessToken((string) $this->auth->authorize()->access_token) + ->setAssociatedAccountNumber($associatedAccountNumber = '740561073') + ->setOriginDetail((new OriginDetail()) + ->setPickupLocation((new PickupLocation()) + ->setAddress((new Address()) + ->setStreetLines('1234 Main St') + ->setCity('Memphis') + ->setStateOrProvince('TN') + ->setPostalCode('38125') + ->setCountryCode('US') + ) + ->setContact((new Contact()) + ->setPersonName('John Doe') + ->setPhoneNumber('9015551234') + ) + ) + ->setReadyDateTimestamp('2021-10-07T08:00:00') + ->setCustomerCloseTime('2021-10-07T08:00:00') + ) + ->addTotalWeight((new Weight()) + ->setValue(100) + ->setUnit('LB') + ) + ->setPackageCount(1) + ->setRemarks('Some Remarks') + ->setCountryRelationships('DOMESTIC') + ->setTrackingNumber('123456789') + ->setCommodityDescription('Some Commodity Description') + ->setFreightPickupDetail(new FreightPickupDetail()) + ->setOversizePackageCount(1) + ->setPickupNotificationDetail((new PickupNotificationDetail()) + ->setEmailAddresses([ + (new EmailAddress()) + ->setAddress('abc@abc.com') + ->setLocale('en_US') + ]) + ->setFormat('HTML') + ->setUserMessage('Some User Message') + ); + + + $prepared = $createFreightLTLPickup->prepare(); + $this->assertArrayHasKey('originDetail', $prepared); + $this->assertArrayHasKey('freightPickupDetail', $prepared); + + $this->assertEquals($associatedAccountNumber, $prepared['associatedAccountNumber']['value']); + $this->assertEquals('1234 Main St', $prepared['originDetail']['pickupLocation']['address']['streetLines'][0]); + $this->assertEquals('Memphis', $prepared['originDetail']['pickupLocation']['address']['city']); + $this->assertEquals('TN', $prepared['originDetail']['pickupLocation']['address']['stateOrProvinceCode']); + $this->assertEquals('38125', $prepared['originDetail']['pickupLocation']['address']['postalCode']); + $this->assertEquals('US', $prepared['originDetail']['pickupLocation']['address']['countryCode']); + $this->assertEquals('John Doe', $prepared['originDetail']['pickupLocation']['contact']['personName']); + $this->assertEquals('9015551234', $prepared['originDetail']['pickupLocation']['contact']['phoneNumber']); + $this->assertEquals('2021-10-07T08:00:00', $prepared['originDetail']['readyDateTimestamp']); + $this->assertEquals('2021-10-07T08:00:00', $prepared['originDetail']['customerCloseTime']); + $this->assertEquals(100, $prepared['totalWeight'][0]['value']); + $this->assertEquals('LB', $prepared['totalWeight'][0]['units']); + $this->assertEquals(1, $prepared['packageCount']); + $this->assertEquals('Some Remarks', $prepared['remarks']); + $this->assertEquals('DOMESTIC', $prepared['countryRelationships']); + $this->assertEquals('123456789', $prepared['trackingNumber']); + $this->assertEquals('Some Commodity Description', $prepared['commodityDescription']); + $this->assertEquals(1, $prepared['oversizePackageCount']); + $this->assertEquals('abc@abc.com', $prepared['pickupNotificationDetail']['emailDetails'][0]['address']); + $this->assertEquals('en_US', $prepared['pickupNotificationDetail']['emailDetails'][0]['locale']); + $this->assertEquals('HTML', $prepared['pickupNotificationDetail']['format']); + $this->assertEquals('Some User Message', $prepared['pickupNotificationDetail']['userMessage']); + + } + + public function testRequest() + { + $nextDayforPickup = date('Y-m-d', strtotime('+1 day')) . 'T08:00:00Z'; + $request = (new CreateFreightLTLPickup()) + ->setAccessToken((string) $this->auth->authorize()->access_token) + ->setAssociatedAccountNumber('740561073') + ->setOriginDetail((new OriginDetail()) + ->setPickupLocation((new PickupLocation()) + ->setAddress((new Address()) + ->setStreetLines('1234 Main St') + ->setCity('Memphis') + ->setStateOrProvince('TN') + ->setPostalCode('38125') + ->setCountryCode('US') + ) + ->setContact((new Contact()) + ->setCompanyName('Company Name') + ->setPersonName('John Doe') + ->setPhoneNumber('9015551234') + ) + ) + ->setReadyDateTimestamp($nextDayforPickup) + ->setCustomerCloseTime('18:00:00') + ) + ->setFreightPickupDetail((new FreightPickupDetail()) + ->setRole('SHIPPER') + ->setPayment('SENDER') + ->setLineItems( (new FreightPickupLineItem()) + ->setTrackingNumber('123456789') + ->setService('FEDEX_FREIGHT_PRIORITY') + ->setTotalHandlingUnits(1) + ->setWeight((new Weight()) + ->setValue(100) + ->setUnit('LB') + ) + ->setDestination((new Address()) + ->setStreetLines('1234 Main St') + ->setCity('Memphis') + ->setStateOrProvince('TN') + ->setPostalCode('38125') + ->setCountryCode('US') + ) + ) + ) + ->setOversizePackageCount(1) + ->setPickupNotificationDetail((new PickupNotificationDetail()) + ->setEmailAddresses([ + (new EmailAddress()) + ->setAddress('abc@abc.com') + ->setLocale('en_US') + ]) + ->setFormat('HTML') + ->setUserMessage('Some User Message') + ); + $request = $request->request(); + + $this->assertObjectHasProperty('transactionId', $request); + $this->assertObjectNotHasProperty('errors', $request); + $this->assertObjectHasProperty('output', $request); + $this->assertObjectHasProperty('pickupConfirmationCode', $request->output); + } +} From a0ee295b354e0bebde430826e4ea1e719dae06cc Mon Sep 17 00:00:00 2001 From: Ash <58735196+ash-g-1337@users.noreply.github.com> Date: Fri, 31 Jan 2025 00:41:21 -0500 Subject: [PATCH 06/11] added support for Check Freight LTL Pickup Availability --- README.md | 2 +- .../CheckFreightLTLPickupAvailability.php | 236 ++++++++++++++++++ .../CheckFreightLTLPickupAvailabilityTest.php | 162 ++++++++++++ 3 files changed, 399 insertions(+), 1 deletion(-) create mode 100644 src/FedexRest/Services/FreightLTL/CheckFreightLTLPickupAvailability.php create mode 100644 tests/FedexRest/Tests/FreightLTL/CheckFreightLTLPickupAvailabilityTest.php diff --git a/README.md b/README.md index 4de4d0c..784e6ad 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ FedEx Rest API documentation https://developer.fedex.com/api/en-us/get-started.h - [ ] Freight LTL API - [ ] Rate Freight LTL ([docs](https://developer.fedex.com/api/en-us/catalog/ltl-freight/v1/docs.html#operation/Freight%20RateQuote)) - [ ] Ship Freight LTL ([docs](https://developer.fedex.com/api/en-us/catalog/ltl-freight/v1/docs.html#operation/Freight%20Shipment)) - - [ ] Check Freight LTL Pickup Availability ([docs](https://developer.fedex.com/api/en-us/catalog/ltl-freight/v1/docs.html#operation/Check%20Freight%20Pickup%20Availability)) + - [X] Check Freight LTL Pickup Availability ([docs](https://developer.fedex.com/api/en-us/catalog/ltl-freight/v1/docs.html#operation/Check%20Freight%20Pickup%20Availability)) - [X] Create Freight LTL Pickup ([docs](https://developer.fedex.com/api/en-us/catalog/ltl-freight/v1/docs.html#operation/Create%20Freight%20Pickup)) - [x] Cancel Freight LTL Pickup ([docs](https://developer.fedex.com/api/en-us/catalog/ltl-freight/v1/docs.html#operation/Cancel%20Freight%20Pickup)) diff --git a/src/FedexRest/Services/FreightLTL/CheckFreightLTLPickupAvailability.php b/src/FedexRest/Services/FreightLTL/CheckFreightLTLPickupAvailability.php new file mode 100644 index 0000000..71cd4cf --- /dev/null +++ b/src/FedexRest/Services/FreightLTL/CheckFreightLTLPickupAvailability.php @@ -0,0 +1,236 @@ +pickupAddress = $pickupAddress; + return $this; + } + + /** + * @param string|null $packageReadyTime + * @return CheckFreightLTLPickupAvailability + */ + public function setPackageReadyTime(?string $packageReadyTime): CheckFreightLTLPickupAvailability + { + $this->packageReadyTime = $packageReadyTime; + return $this; + } + + /** + * @param string|null $customerCloseTime + * @return CheckFreightLTLPickupAvailability + */ + public function setCustomerCloseTime(?string $customerCloseTime): CheckFreightLTLPickupAvailability + { + $this->customerCloseTime = $customerCloseTime; + return $this; + } + + /** + * @param string|null $ServiceType + * @return CheckFreightLTLPickupAvailability + */ + public function setServiceType(?string $serviceType): CheckFreightLTLPickupAvailability + { + $this->serviceType = $serviceType; + return $this; + } + + /** + * @param Weight|null $weight + * @return CheckFreightLTLPickupAvailability + */ + public function setWeight(?Weight $weight): CheckFreightLTLPickupAvailability + { + $this->weight = $weight; + return $this; + } + + /** + * @param string|null $packagingType + * @return CheckFreightLTLPickupAvailability + */ + public function setPackagingType(?string $packagingType): CheckFreightLTLPickupAvailability + { + $this->packagingType = $packagingType; + return $this; + } + + /** + * @param Dimensions|null $dimensions + * @return CheckFreightLTLPickupAvailability + */ + public function setDimensions(?Dimensions $dimensions): CheckFreightLTLPickupAvailability + { + $this->dimensions = $dimensions; + return $this; + } + + /** + * @param string|null $freightGuaranteeTime + * @return CheckFreightLTLPickupAvailability + */ + public function setFreightGuaranteeTime(?string $freightGuaranteeTime): CheckFreightLTLPickupAvailability + { + $this->freightGuaranteeTime = $freightGuaranteeTime; + return $this; + } + + /** + * @param FreightDirectDetail|null $freightDirectDetail + * @return CheckFreightLTLPickupAvailability + */ + public function setFreightDirectDetail(?FreightDirectDetail $freightDirectDetail): CheckFreightLTLPickupAvailability + { + $this->freightDirectDetail = $freightDirectDetail; + return $this; + } + + /** + * @param array|null $specialServiceTypes + * @return CheckFreightLTLPickupAvailability + */ + public function setSpecialServiceTypes(?string ...$specialServiceTypes): CheckFreightLTLPickupAvailability + { + $this->specialServiceTypes = $specialServiceTypes; + return $this; + } + + /** + * @param string|null $dispatchDate + * @return CheckFreightLTLPickupAvailability + */ + public function setDispatchDate(?string $dispatchDate): CheckFreightLTLPickupAvailability + { + $this->dispatchDate = $dispatchDate; + return $this; + } + + /** + * @param int|null $numberOfBusinessDays + * @return CheckFreightLTLPickupAvailability + */ + public function setNumberOfBusinessDays(?int $numberOfBusinessDays): CheckFreightLTLPickupAvailability + { + $this->numberOfBusinessDays = $numberOfBusinessDays; + return $this; + } + + + public function prepare(): array + { + $data = []; + + if (!empty($this->pickupAddress)) { + $data['pickupAddress'] = $this->pickupAddress->prepare(); + } + + if (!empty($this->packageReadyTime)) { + $data['packageReadyTime'] = $this->packageReadyTime; + } + + if (!empty($this->customerCloseTime)) { + $data['customerCloseTime'] = $this->customerCloseTime; + } + + if (!empty($this->serviceType) || !empty($this->weight) || !empty($this->packagingType) || !empty($this->dimensions)) { + $data['shipmentAttributes'] = []; + + if (!empty($this->serviceType)) { + $data['shipmentAttributes']['serviceType'] = $this->serviceType; + } + + if (!empty($this->weight)) { + $data['shipmentAttributes']['weight'] = $this->weight->prepare(); + } + + if (!empty($this->packagingType)) { + $data['shipmentAttributes']['packagingType'] = $this->packagingType; + } + + if (!empty($this->dimensions)) { + $data['shipmentAttributes']['dimensions'] = $this->dimensions->prepare(); + } + } + + if (!empty($this->freightGuaranteeTime) || !empty($this->freightDirectDetail) || !empty($this->specialServiceTypes)) { + $data['freightPickupSpecialServiceDetail'] = []; + $data['freightPickupSpecialServiceDetail']['shipmentSpecialServicesRequested'] = []; + + if (!empty($this->freightGuaranteeTime)) { + $data['freightPickupSpecialServiceDetail']['shipmentSpecialServicesRequested']['freightGuaranteeDetail'] = ['time'=>$this->freightGuaranteeTime]; + } + + if (!empty($this->freightDirectDetail)) { + $data['freightPickupSpecialServiceDetail']['shipmentSpecialServicesRequested']['freightDirectDetail'] = $this->freightDirectDetail->prepare(); + } + + if (!empty($this->specialServiceTypes)) { + $data['freightPickupSpecialServiceDetail']['shipmentSpecialServicesRequested']['specialServiceTypes'] = $this->specialServiceTypes; + } + } + + if (!empty($this->dispatchDate)) { + $data['dispatchDate'] = $this->dispatchDate; + } + + if (!empty($this->numberOfBusinessDays)) { + $data['numberOfBusinessDays'] = $this->numberOfBusinessDays; + } + + return $data; + } + + + public function request() + { + parent::request(); + + if (empty($this->pickupAddress)) { + throw new MissingFreightPickupDetailException('Pickup Address is required.'); + } + + try { + $query = $this->http_client->post($this->getApiUri($this->api_endpoint), [ + 'json' => $this->prepare(), + 'http_errors' => FALSE, + ]); + return ($this->raw === true) ? $query : json_decode($query->getBody()->getContents()); + } catch (\Exception $e) { + return $e->getMessage(); + } + } +} diff --git a/tests/FedexRest/Tests/FreightLTL/CheckFreightLTLPickupAvailabilityTest.php b/tests/FedexRest/Tests/FreightLTL/CheckFreightLTLPickupAvailabilityTest.php new file mode 100644 index 0000000..3573c4f --- /dev/null +++ b/tests/FedexRest/Tests/FreightLTL/CheckFreightLTLPickupAvailabilityTest.php @@ -0,0 +1,162 @@ +auth = (new Authorize) + ->setClientId('l7749d031872cf4b55a7889376f360d045') + ->setClientSecret('bd59d91084e8482895d4ae2fb4fb79a3'); + } + + public function testHasPickupAddress() + { + $request = NULL; + try { + $request = (new CheckFreightLTLPickupAvailability()) + ->setAccessToken((string) $this->auth->authorize()->access_token) + ->request(); + + } catch (MissingFreightPickupDetailException $e) { + $this->assertEquals('Pickup Address is required.', $e->getMessage()); + } + $this->assertEmpty($request, 'The request did not fail as it should.'); + } + + public function testPrepare() + { + $request = (new CheckFreightLTLPickupAvailability()) + ->setAccessToken((string) $this->auth->authorize()->access_token) + ->setPickupAddress((new Address()) + ->setStreetLines('1234 Main St') + ->setCity('Memphis') + ->setStateOrProvince('TN') + ->setPostalCode('38120') + ->setCountryCode('US') + ->setResidential(true) + ) + ->setPackageReadyTime('09:00') + ->setCustomerCloseTime('17:00') + ->setServiceType('FEDEX_FREIGHT_PRIORITY') + ->setWeight((new Weight()) + ->setUnit('LB') + ->setValue(200) + ) + ->setPackagingType(SubPackagingType::_PALLET) + ->setDimensions((new Dimensions()) + ->setLength(48) + ->setWidth(40) + ->setHeight(30) + ->setUnits('IN') + ) + ->setFreightGuaranteeTime('10:00') + ->setFreightDirectDetail((new FreightDirectDetail()) + ->setFreightDirectDataDetails((new FreightDirectDataDetails()) + ->setType('BASIC') + ->setTransportationType('PICKUP') + ->setEmailAddress('abc@abc.com') + ->addPhoneNumber('9015551234', 'MOBILE') + ) + ) + ->setSpecialServiceTypes(ShipmentSpecialServiceType::_FREIGHT_GUARANTEE) + ->setDispatchDate(date('Y-m-d')) + ->setNumberOfBusinessDays(3); + + $prepared = $request->prepare(); + + $this->assertEquals('1234 Main St', $prepared['pickupAddress']['streetLines'][0]); + $this->assertEquals('Memphis', $prepared['pickupAddress']['city']); + $this->assertEquals('TN', $prepared['pickupAddress']['stateOrProvinceCode']); + $this->assertEquals('38120', $prepared['pickupAddress']['postalCode']); + $this->assertEquals('US', $prepared['pickupAddress']['countryCode']); + $this->assertEquals(true, $prepared['pickupAddress']['residential']); + $this->assertEquals('09:00', $prepared['packageReadyTime']); + $this->assertEquals('17:00', $prepared['customerCloseTime']); + $this->assertEquals('FEDEX_FREIGHT_PRIORITY', $prepared['shipmentAttributes']['serviceType']); + $this->assertEquals('LB', $prepared['shipmentAttributes']['weight']['units']); + $this->assertEquals(200, $prepared['shipmentAttributes']['weight']['value']); + $this->assertEquals('PALLET', $prepared['shipmentAttributes']['packagingType']); + $this->assertEquals(48, $prepared['shipmentAttributes']['dimensions']['length']); + $this->assertEquals(40, $prepared['shipmentAttributes']['dimensions']['width']); + $this->assertEquals(30, $prepared['shipmentAttributes']['dimensions']['height']); + $this->assertEquals('IN', $prepared['shipmentAttributes']['dimensions']['units']); + $this->assertEquals('10:00', $prepared['freightPickupSpecialServiceDetail']['shipmentSpecialServicesRequested']['freightGuaranteeDetail']['time']); + $this->assertEquals('BASIC', $prepared['freightPickupSpecialServiceDetail']['shipmentSpecialServicesRequested']['freightDirectDetail']['freightDirectDataDetails'][0]['type']); + $this->assertEquals('PICKUP', $prepared['freightPickupSpecialServiceDetail']['shipmentSpecialServicesRequested']['freightDirectDetail']['freightDirectDataDetails'][0]['transportationType']); + $this->assertEquals('abc@abc.com', $prepared['freightPickupSpecialServiceDetail']['shipmentSpecialServicesRequested']['freightDirectDetail']['freightDirectDataDetails'][0]['emailAddress']); + $this->assertEquals('9015551234', $prepared['freightPickupSpecialServiceDetail']['shipmentSpecialServicesRequested']['freightDirectDetail']['freightDirectDataDetails'][0]['phoneNumberDetails'][0]['phoneNumber']); + $this->assertEquals('MOBILE', $prepared['freightPickupSpecialServiceDetail']['shipmentSpecialServicesRequested']['freightDirectDetail']['freightDirectDataDetails'][0]['phoneNumberDetails'][0]['phoneNumberType']); + $this->assertEquals(ShipmentSpecialServiceType::_FREIGHT_GUARANTEE, $prepared['freightPickupSpecialServiceDetail']['shipmentSpecialServicesRequested']['specialServiceTypes'][0]); + $this->assertEquals(date('Y-m-d'), $prepared['dispatchDate']); + $this->assertEquals(3, $prepared['numberOfBusinessDays']); + + } + + public function testRequest() + { + $request = (new CheckFreightLTLPickupAvailability()) + ->setAccessToken((string) $this->auth->authorize()->access_token) + ->setPickupAddress((new Address()) + ->setStreetLines('1234 Main St') + ->setCity('Memphis') + ->setStateOrProvince('TN') + ->setPostalCode('38120') + ->setCountryCode('US') + ->setResidential(true) + ) + ->setPackageReadyTime('09:00') + ->setCustomerCloseTime('17:00') + ->setServiceType('FEDEX_FREIGHT_PRIORITY') + ->setWeight((new Weight()) + ->setUnit('LB') + ->setValue(200) + ) + ->setPackagingType(SubPackagingType::_PALLET) + ->setDimensions((new Dimensions()) + ->setLength(48) + ->setWidth(40) + ->setHeight(30) + ->setUnits('IN') + ) + ->setFreightGuaranteeTime('10:00') + ->setFreightDirectDetail((new FreightDirectDetail()) + ->setFreightDirectDataDetails((new FreightDirectDataDetails()) + ->setType('BASIC') + ->setTransportationType('PICKUP') + ->setEmailAddress('abc@abc.com') + ->addPhoneNumber('9015551234', 'MOBILE') + ) + ) + ->setSpecialServiceTypes(ShipmentSpecialServiceType::_FREIGHT_GUARANTEE) + ->setDispatchDate(date('Y-m-d')) + ->setNumberOfBusinessDays(3) + ->request(); + + $this->assertObjectHasProperty('transactionId', $request); + $this->assertObjectNotHasProperty('errors', $request); + $this->assertObjectHasProperty('output', $request); + $this->assertObjectHasProperty('closeTime', $request->output); + $this->assertObjectHasProperty('closeTimeType', $request->output); + $this->assertObjectHasProperty('localTime', $request->output); + $this->assertObjectHasProperty('options', $request->output); + $this->assertIsArray($request->output->options); + } + +} From d7af775e778bc4f387fddc50a216eb23343cb0ac Mon Sep 17 00:00:00 2001 From: Ash <58735196+ash-g-1337@users.noreply.github.com> Date: Fri, 31 Jan 2025 00:44:35 -0500 Subject: [PATCH 07/11] Fixed Create Freight Pickup Unit test failing due to logic error caused by date falling on weekend --- tests/FedexRest/Tests/FreightLTL/CreateFreightLTLPickupTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/FedexRest/Tests/FreightLTL/CreateFreightLTLPickupTest.php b/tests/FedexRest/Tests/FreightLTL/CreateFreightLTLPickupTest.php index 48ecf9f..73dc85b 100644 --- a/tests/FedexRest/Tests/FreightLTL/CreateFreightLTLPickupTest.php +++ b/tests/FedexRest/Tests/FreightLTL/CreateFreightLTLPickupTest.php @@ -193,7 +193,7 @@ public function testPrepare() public function testRequest() { - $nextDayforPickup = date('Y-m-d', strtotime('+1 day')) . 'T08:00:00Z'; + $nextDayforPickup = date('Y-m-d', strtotime('+2 weekdays')) . 'T08:00:00Z'; $request = (new CreateFreightLTLPickup()) ->setAccessToken((string) $this->auth->authorize()->access_token) ->setAssociatedAccountNumber('740561073') From 9a86ec30b36911f5e79b7fe5765fffe84e213181 Mon Sep 17 00:00:00 2001 From: Ash <58735196+ash-g-1337@users.noreply.github.com> Date: Sat, 1 Feb 2025 19:35:04 -0500 Subject: [PATCH 08/11] minor issues and cleanup --- .../Services/FreightLTL/Entity/FreightDirectDataDetails.php | 2 +- .../Services/FreightLTL/Entity/FreightDirectDetail.php | 2 +- .../Services/FreightLTL/Entity/FreightPickupLineItem.php | 2 +- .../Exceptions/MissingFreightPickupDetailException.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/FedexRest/Services/FreightLTL/Entity/FreightDirectDataDetails.php b/src/FedexRest/Services/FreightLTL/Entity/FreightDirectDataDetails.php index b12276f..074404a 100644 --- a/src/FedexRest/Services/FreightLTL/Entity/FreightDirectDataDetails.php +++ b/src/FedexRest/Services/FreightLTL/Entity/FreightDirectDataDetails.php @@ -48,7 +48,7 @@ public function addPhoneNumber($phoneNumber, $type = 'HOME'): FreightDirectDataD return $this; } - public function prepare() + public function prepare(): array { $data = []; diff --git a/src/FedexRest/Services/FreightLTL/Entity/FreightDirectDetail.php b/src/FedexRest/Services/FreightLTL/Entity/FreightDirectDetail.php index 514b9ad..30ced41 100644 --- a/src/FedexRest/Services/FreightLTL/Entity/FreightDirectDetail.php +++ b/src/FedexRest/Services/FreightLTL/Entity/FreightDirectDetail.php @@ -16,7 +16,7 @@ public function setFreightDirectDataDetails(FreightDirectDataDetails ...$freight return $this; } - public function prepare() + public function prepare(): array { $data = [ 'freightDirectDataDetails' => [], diff --git a/src/FedexRest/Services/FreightLTL/Entity/FreightPickupLineItem.php b/src/FedexRest/Services/FreightLTL/Entity/FreightPickupLineItem.php index 47ff415..e0d0dea 100644 --- a/src/FedexRest/Services/FreightLTL/Entity/FreightPickupLineItem.php +++ b/src/FedexRest/Services/FreightLTL/Entity/FreightPickupLineItem.php @@ -197,7 +197,7 @@ public function setSpecialServiceTypes(?array $specialServiceTypes): FreightPick return $this; } - public function prepare() + public function prepare(): array { $data = []; diff --git a/src/FedexRest/Services/FreightLTL/Exceptions/MissingFreightPickupDetailException.php b/src/FedexRest/Services/FreightLTL/Exceptions/MissingFreightPickupDetailException.php index 9c53de5..eecdb79 100644 --- a/src/FedexRest/Services/FreightLTL/Exceptions/MissingFreightPickupDetailException.php +++ b/src/FedexRest/Services/FreightLTL/Exceptions/MissingFreightPickupDetailException.php @@ -2,7 +2,7 @@ namespace FedexRest\Services\FreightLTL\Exceptions; -class MissingFreightPickupDetailException extends \Exception +class MissingFreightPickupDetailException extends \Exception { public function __construct($message, $code = 0, \Exception $previous = null) { From 6cea37fef4890b33d275e740d8c8dd49c74cbd73 Mon Sep 17 00:00:00 2001 From: Ash <58735196+ash-g-1337@users.noreply.github.com> Date: Sat, 1 Feb 2025 21:45:37 -0500 Subject: [PATCH 09/11] Identified GAP in existing process. wrote TODO for future impact assessment and fixes --- src/FedexRest/Services/Ship/Entity/ShippingChargesPayment.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/FedexRest/Services/Ship/Entity/ShippingChargesPayment.php b/src/FedexRest/Services/Ship/Entity/ShippingChargesPayment.php index 6656d52..2454fb1 100644 --- a/src/FedexRest/Services/Ship/Entity/ShippingChargesPayment.php +++ b/src/FedexRest/Services/Ship/Entity/ShippingChargesPayment.php @@ -5,6 +5,7 @@ class ShippingChargesPayment { public ?string $paymentType; + //TODO: Missing Payor Element <- Works without in most cases, but should be added in the future for 3rd party payor scenario. /** * @param string $paymentType * @return $this From 9446eefed4927e6ef8343f1bdbc77c1c5d03cb68 Mon Sep 17 00:00:00 2001 From: Ash <58735196+ash-g-1337@users.noreply.github.com> Date: Sat, 1 Feb 2025 22:29:44 -0500 Subject: [PATCH 10/11] Almost Done Rate Freight; need to finish up a sub entity. setup the Ship Freight; will re-use a lot of items from Rate --- .../Entity/AssociatedFreightLineItems.php | 27 +++ .../FreightLTL/Entity/ContentRecord.php | 68 ++++++ .../FreightRateRequestedPackageLineItems.php | 144 ++++++++++++ .../Entity/FreightRequestedShipment.php | 13 ++ .../Entity/FreightShipmentSpecialServices.php | 88 ++++++++ .../Entity/RateFreightRequestedShipment.php | 206 ++++++++++++++++++ .../Entity/RateRequestControlParameters.php | 79 +++++++ .../MissingFreightRequestedShipment.php | 11 + .../Services/FreightLTL/RateFreightLTL.php | 93 ++++++++ .../Services/FreightLTL/ShipFreightLTL.php | 102 +++++++++ .../Tests/FreightLTL/RateFreightLTLTest.php | 101 +++++++++ .../Tests/FreightLTL/ShipFreightLTLTest.php | 29 +++ 12 files changed, 961 insertions(+) create mode 100644 src/FedexRest/Services/FreightLTL/Entity/AssociatedFreightLineItems.php create mode 100644 src/FedexRest/Services/FreightLTL/Entity/ContentRecord.php create mode 100644 src/FedexRest/Services/FreightLTL/Entity/FreightRateRequestedPackageLineItems.php create mode 100644 src/FedexRest/Services/FreightLTL/Entity/FreightRequestedShipment.php create mode 100644 src/FedexRest/Services/FreightLTL/Entity/FreightShipmentSpecialServices.php create mode 100644 src/FedexRest/Services/FreightLTL/Entity/RateFreightRequestedShipment.php create mode 100644 src/FedexRest/Services/FreightLTL/Entity/RateRequestControlParameters.php create mode 100644 src/FedexRest/Services/FreightLTL/Exceptions/MissingFreightRequestedShipment.php create mode 100644 src/FedexRest/Services/FreightLTL/RateFreightLTL.php create mode 100644 src/FedexRest/Services/FreightLTL/ShipFreightLTL.php create mode 100644 tests/FedexRest/Tests/FreightLTL/RateFreightLTLTest.php create mode 100644 tests/FedexRest/Tests/FreightLTL/ShipFreightLTLTest.php diff --git a/src/FedexRest/Services/FreightLTL/Entity/AssociatedFreightLineItems.php b/src/FedexRest/Services/FreightLTL/Entity/AssociatedFreightLineItems.php new file mode 100644 index 0000000..5bfc8f8 --- /dev/null +++ b/src/FedexRest/Services/FreightLTL/Entity/AssociatedFreightLineItems.php @@ -0,0 +1,27 @@ +id = $id; + + return $this; + } + + public function prepare(): array + { + return [ + 'id' => $this->id, + ]; + } +} diff --git a/src/FedexRest/Services/FreightLTL/Entity/ContentRecord.php b/src/FedexRest/Services/FreightLTL/Entity/ContentRecord.php new file mode 100644 index 0000000..c981eeb --- /dev/null +++ b/src/FedexRest/Services/FreightLTL/Entity/ContentRecord.php @@ -0,0 +1,68 @@ +itemNumber = $itemNumber; + + return $this; + } + + /** + * Set the value of receivedQuantity + * @param string|null $receivedQuantity + * @return $this + */ + public function setReceivedQuantity(?string $receivedQuantity): self + { + $this->receivedQuantity = $receivedQuantity; + + return $this; + } + /** + * Set the value of description + * @param string|null $description + * @return $this + */ + public function setDescription(?string $description): self + { + $this->description = $description; + + return $this; + } + + /** + * Set the value of partNumber + * @param string|null $partNumber + * @return $this + */ + public function setPartNumber(?string $partNumber): self + { + $this->partNumber = $partNumber; + + return $this; + } + + public function prepare(): array + { + return [ + 'itemNumber' => $this->itemNumber, + 'receivedQuantity' => $this->receivedQuantity, + 'description' => $this->description, + 'partNumber' => $this->partNumber, + ]; + } +} diff --git a/src/FedexRest/Services/FreightLTL/Entity/FreightRateRequestedPackageLineItems.php b/src/FedexRest/Services/FreightLTL/Entity/FreightRateRequestedPackageLineItems.php new file mode 100644 index 0000000..192898a --- /dev/null +++ b/src/FedexRest/Services/FreightLTL/Entity/FreightRateRequestedPackageLineItems.php @@ -0,0 +1,144 @@ +subPackagingType = $subPackagingType; + + return $this; + } + + /** + * Set the value of groupPackageCount + * @param int|null $groupPackageCount + * @return $this + */ + public function setGroupPackageCount(?int $groupPackageCount): self + { + $this->groupPackageCount = $groupPackageCount; + + return $this; + } + + /** + * Set the value of contentRecords + * @param array|null $contentRecords + * @return $this + */ + public function setContentRecords(ContentRecord ...$contentRecords): self + { + $this->contentRecords = $contentRecords; + + return $this; + } + + /** + * Set the value of declaredValue + * @param Value|null $declaredValue + * @return $this + */ + public function setDeclaredValue(?Value $declaredValue): self + { + $this->declaredValue = $declaredValue; + + return $this; + } + + /** + * Set the value of weight + * @param Weight $weight + * @return $this + */ + public function setWeight(Weight $weight): self + { + $this->weight = $weight; + + return $this; + } + + /** + * Set the value of dimensions + * @param Dimensions|null $dimensions + * @return $this + */ + public function setDimensions(?Dimensions $dimensions): self + { + $this->dimensions = $dimensions; + + return $this; + } + + /** + * Set the value of associatedFreightLineItems + * @param array $associatedFreightLineItems + * @return $this + */ + public function setAssociatedFreightLineItems(AssociatedFreightLineItems ...$associatedFreightLineItems): self + { + $this->associatedFreightLineItems = $associatedFreightLineItems; + + return $this; + } + + public function prepare(): array + { + $data = []; + + if (!empty($this->subPackagingType)) { + $data['subPackagingType'] = $this->subPackagingType; + } + + if (!empty($this->groupPackageCount)) { + $data['groupPackageCount'] = $this->groupPackageCount; + } + + if (!empty($this->contentRecords)) { + $data['contentRecords'] = []; + foreach ($this->contentRecords as $contentRecord) { + $data['contentRecords'][] = $contentRecord->prepare(); + } + } + + if (!empty($this->declaredValue)) { + $data['declaredValue'] = $this->declaredValue->prepare(); + } + + if (!empty($this->weight)) { + $data['weight'] = $this->weight->prepare(); + } + + if (!empty($this->dimensions)) { + $data['dimensions'] = $this->dimensions->prepare(); + } + + if (!empty($this->associatedFreightLineItems)) { + $data['associatedFreightLineItems'] = []; + foreach ($this->associatedFreightLineItems as $associatedFreightLineItem) { + $data['associatedFreightLineItems'][] = $associatedFreightLineItem->prepare(); + } + } + + return $data; + } +} diff --git a/src/FedexRest/Services/FreightLTL/Entity/FreightRequestedShipment.php b/src/FedexRest/Services/FreightLTL/Entity/FreightRequestedShipment.php new file mode 100644 index 0000000..46af08e --- /dev/null +++ b/src/FedexRest/Services/FreightLTL/Entity/FreightRequestedShipment.php @@ -0,0 +1,13 @@ +freightGuaranteeType = $freightGuaranteeType; + + return $this; + } + + /** + * Set the value of guaranteeTimestamp + * @param string|null $guaranteeTimestamp + * @return $this + */ + public function setGuaranteeTimestamp(?string $guaranteeTimestamp): self + { + $this->guaranteeTimestamp = $guaranteeTimestamp; + + return $this; + } + + /** + * Set the value of specialServiceTypes + * @param string|null $specialServiceTypes + * @return $this + */ + public function setSpecialServiceTypes(?string ...$specialServiceTypes): self + { + $this->specialServiceTypes = $specialServiceTypes; + + return $this; + } + + /** + * Set the value of freightDirectDetail + * @param FreightDirectDetail|null $freightDirectDetail + * @return $this + */ + public function setFreightDirectDetail(?FreightDirectDetail $freightDirectDetail): self + { + $this->freightDirectDetail = $freightDirectDetail; + + return $this; + } + + + + public function prepare(): array + { + $data = []; + + if(!empty($this->freightGuaranteeType) || !empty($this->guaranteeTimestamp)) { + $data['freightGuaranteeDetail'] = []; + if (!empty($this->freightGuaranteeType)) { + $data['freightGuaranteeDetail']['freightGuaranteeType'] = $this->freightGuaranteeType; + } + if (!empty($this->guaranteeTimestamp)) { + $data['freightGuaranteeDetail']['guaranteeTimestamp'] = $this->guaranteeTimestamp; + } + } + + + if (!empty($this->specialServiceTypes)) { + $data['specialServiceTypes'] = $this->specialServiceTypes; + } + + if (!empty($this->freightDirectDetail)) { + $data['freightDirectDetail'] = $this->freightDirectDetail->prepare(); + } + + return $data; + } +} diff --git a/src/FedexRest/Services/FreightLTL/Entity/RateFreightRequestedShipment.php b/src/FedexRest/Services/FreightLTL/Entity/RateFreightRequestedShipment.php new file mode 100644 index 0000000..dce014a --- /dev/null +++ b/src/FedexRest/Services/FreightLTL/Entity/RateFreightRequestedShipment.php @@ -0,0 +1,206 @@ +shipper = $shipper; + return $this; + } + + /** + * Set the value of recipient + * @param Address $recipient + * @return $this + */ + public function setRecipientAddress(Address $recipient): self + { + $this->recipient = $recipient; + return $this; + } + + /** + * Set the value of serviceType + * @param string|null $serviceType + * @return $this + */ + public function setServiceType(?string $serviceType): self + { + $this->serviceType = $serviceType; + return $this; + } + + /** + * Set the value of preferredCurrency + * @param string|null $preferredCurrency + * @return $this + */ + public function setPreferredCurrency(?string $preferredCurrency): self + { + $this->preferredCurrency = $preferredCurrency; + return $this; + } + + /** + * Set the value of shippingChargesPayment + * @param ShippingChargesPayment|null $shippingChargesPayment + * @return $this + */ + public function setShippingChargesPayment(?ShippingChargesPayment $shippingChargesPayment): self + { + $this->shippingChargesPayment = $shippingChargesPayment; + return $this; + } + + /** + * Set the value of rateRequestType + * @param string|null $rateRequestType + * @return $this + */ + public function setRateRequestType(?string ...$rateRequestType): self + { + $this->rateRequestType = $rateRequestType; + return $this; + } + + /** + * Set the value of shipDateStamp + * @param string|null $shipDateStamp + * @return $this + */ + public function setShipDateStamp(?string $shipDateStamp): self + { + $this->shipDateStamp = $shipDateStamp; + return $this; + } + + /** + * Set the value of requestedPackageLineItems + * @param array $requestedPackageLineItems + * @return $this + */ + public function setRequestedPackageLineItems(FreightRateRequestedPackageLineItems ...$requestedPackageLineItems): self + { + $this->requestedPackageLineItems = $requestedPackageLineItems; + return $this; + } + + /** + * Set the value of totalPackageCount + * @param int|null $totalPackageCount + * @return $this + */ + public function setTotalPackageCount(?int $totalPackageCount): self + { + $this->totalPackageCount = $totalPackageCount; + return $this; + } + + /** + * Set the value of totalWeight + * @param int|null $totalWeight + * @return $this + */ + public function setTotalWeight(?int $totalWeight): self + { + $this->totalWeight = $totalWeight; + return $this; + } + + //TODO: freightShipmentDetail + + + /** + * Set the value of freightShipmentSpecialServices + * @param FreightShipmentSpecialServices|null $freightShipmentSpecialServices + * @return $this + */ + public function setFreightShipmentSpecialServices(?FreightShipmentSpecialServices $freightShipmentSpecialServices): self + { + $this->freightShipmentSpecialServices = $freightShipmentSpecialServices; + return $this; + } + + + + + public function prepare(): array + { + $data = []; + + if (!empty($this->shipper)) { + $data['shipper'] = []; + $data['shipper']['address'] = $this->shipper->prepare(); + } + + if (!empty($this->recipient)) { + $data['recipient'] = []; + $data['recipient']['address'] = $this->recipient->prepare(); + } + + if (!empty($this->serviceType)) { + $data['serviceType'] = $this->serviceType; + } + + if (!empty($this->preferredCurrency)) { + $data['preferredCurrency'] = $this->preferredCurrency; + } + + if (!empty($this->shippingChargesPayment)) { + $data['shippingChargesPayment'] = $this->shippingChargesPayment->prepare(); + } + + if (!empty($this->rateRequestType)) { + $data['rateRequestType'] = $this->rateRequestType; + } + + if (!empty($this->shipDateStamp)) { + $data['shipDateStamp'] = $this->shipDateStamp; + } + + //TODO: requestedPackageLineItems + + if (!empty($this->totalPackageCount)) { + $data['totalPackageCount'] = $this->totalPackageCount; + } + + if (!empty($this->totalWeight)) { + $data['totalWeight'] = $this->totalWeight; + } + + //TODO: freightShipmentDetail + + if (!empty($this->freightShipmentSpecialServices)) { + $data['freightShipmentSpecialServices'] = $this->freightShipmentSpecialServices->prepare(); + } + + + return $data; + } +} diff --git a/src/FedexRest/Services/FreightLTL/Entity/RateRequestControlParameters.php b/src/FedexRest/Services/FreightLTL/Entity/RateRequestControlParameters.php new file mode 100644 index 0000000..3ce4c52 --- /dev/null +++ b/src/FedexRest/Services/FreightLTL/Entity/RateRequestControlParameters.php @@ -0,0 +1,79 @@ +returnTransitTimes = $returnTransitTimes; + + return $this; + } + + /** + * Set the value of serviceNeededOnRateFailure + * @param bool|null $serviceNeededOnRateFailure + * @return $this + */ + public function setServiceNeededOnRateFailure(?bool $serviceNeededOnRateFailure): self + { + $this->serviceNeededOnRateFailure = $serviceNeededOnRateFailure; + + return $this; + } + + /** + * Set the value of variableOptions + * @param string|null $variableOptions + * @return $this + */ + public function setVariableOptions(?string $variableOptions): self + { + $this->variableOptions = $variableOptions; + + return $this; + } + + /** + * Set the value of rateSortOrder + * @param string|null $rateSortOrder + * @return $this + */ + public function setRateSortOrder(?string $rateSortOrder): self + { + $this->rateSortOrder = $rateSortOrder; + + return $this; + } + + + public function prepare(): array + { + $data = []; + if (!empty($this->returnTransitTimes)) { + $data['returnTransitTimes'] = $this->returnTransitTimes; + } + if (!empty($this->serviceNeededOnRateFailure)) { + $data['serviceNeededOnRateFailure'] = $this->serviceNeededOnRateFailure; + } + if (!empty($this->variableOptions)) { + $data['variableOptions'] = $this->variableOptions; + } + if (!empty($this->rateSortOrder)) { + $data['rateSortOrder'] = $this->rateSortOrder; + } + return $data; + } +} diff --git a/src/FedexRest/Services/FreightLTL/Exceptions/MissingFreightRequestedShipment.php b/src/FedexRest/Services/FreightLTL/Exceptions/MissingFreightRequestedShipment.php new file mode 100644 index 0000000..8b49cb4 --- /dev/null +++ b/src/FedexRest/Services/FreightLTL/Exceptions/MissingFreightRequestedShipment.php @@ -0,0 +1,11 @@ + [ + 'value' => $this->accountNumber, + ], + 'rateRequestControlParameters' => $this->rateRequestControlParameters->prepare(), + 'freightRequestedShipment' => $this->freightRequestedShipment->prepare(), + ]; + return $data; + } + + /** + * Set the value of accountNumber + * @param string $accountNumber + * @return $this + */ + public function setAccountNumber(string $accountNumber): self + { + $this->accountNumber = $accountNumber; + + return $this; + } + + /** + * Set the value of rateRequestControlParameters + * @param RateRequestControlParameters|null $rateRequestControlParameters + * @return $this + */ + public function setRateRequestControlParameters(?RateRequestControlParameters $rateRequestControlParameters): self + { + $this->rateRequestControlParameters = $rateRequestControlParameters; + + return $this; + } + + /** + * Set the value of freightRequestedShipment + * @param RateFreightRequestedShipment $freightRequestedShipment + * @return $this + */ + public function setFreightRequestedShipment(RateFreightRequestedShipment $freightRequestedShipment): self + { + $this->freightRequestedShipment = $freightRequestedShipment; + + return $this; + } + + + public function request() + { + parent::request(); + + if (empty($this->accountNumber)) { + throw new MissingAccountNumberException('Account Number is missing.'); + } + + if (empty($this->freightRequestedShipment)) { + throw new MissingFreightRequestedShipment('Freight Requested Shipment is missing.'); + } + + try { + $query = $this->http_client->post($this->getApiUri($this->api_endpoint), [ + 'json' => $this->prepare(), + 'http_errors' => FALSE, + ]); + return ($this->raw === true) ? $query : json_decode($query->getBody()->getContents()); + } catch (\Exception $e) { + return $e->getMessage(); + } + } +} diff --git a/src/FedexRest/Services/FreightLTL/ShipFreightLTL.php b/src/FedexRest/Services/FreightLTL/ShipFreightLTL.php new file mode 100644 index 0000000..548d96b --- /dev/null +++ b/src/FedexRest/Services/FreightLTL/ShipFreightLTL.php @@ -0,0 +1,102 @@ +freightRequestedShipment = $freightRequestedShipment; + + return $this; + } + + /** + * Set the value of labelResponseOptions + * @param string $labelResponseOptions + * @return $this + */ + public function setLabelResponseOptions(string $labelResponseOptions): self + { + $this->labelResponseOptions = $labelResponseOptions; + + return $this; + } + + /** + * Set the value of accountNumber + * @param string $accountNumber + * @return $this + */ + public function setAccountNumber(string $accountNumber): self + { + $this->accountNumber = $accountNumber; + + return $this; + } + + /** + * Set the value of oneLabelAtATime + * @param bool|null $oneLabelAtATime + * @return $this + */ + public function setOneLabelAtATime(?bool $oneLabelAtATime): self + { + $this->oneLabelAtATime = $oneLabelAtATime; + + return $this; + } + + public function prepare() + { + $data = [ + 'freightRequestedShipment' => $this->freightRequestedShipment->prepare(), + 'labelResponseOptions' => $this->labelResponseOptions, + 'accountNumber' => $this->accountNumber, + ]; + + if ($this->oneLabelAtATime) { + $data['oneLabelAtATime'] = $this->oneLabelAtATime; + } + return $data; + } + + public function request() + { + parent::request(); + + if (empty($this->accountNumber)) { + throw new MissingAccountNumberException('The account number is required'); + } + + try { + $query = $this->http_client->post($this->getApiUri($this->api_endpoint), [ + 'json' => $this->prepare(), + 'http_errors' => FALSE, + ]); + return ($this->raw === true) ? $query : json_decode($query->getBody()->getContents()); + } catch (\Exception $e) { + return $e->getMessage(); + } + } +} diff --git a/tests/FedexRest/Tests/FreightLTL/RateFreightLTLTest.php b/tests/FedexRest/Tests/FreightLTL/RateFreightLTLTest.php new file mode 100644 index 0000000..2612d4f --- /dev/null +++ b/tests/FedexRest/Tests/FreightLTL/RateFreightLTLTest.php @@ -0,0 +1,101 @@ +auth = (new Authorize) + ->setClientId('l7749d031872cf4b55a7889376f360d045') + ->setClientSecret('bd59d91084e8482895d4ae2fb4fb79a3'); + } + + public function testHasAccountNumber() + { + $request = NULL; + try { + $request = (new RateFreightLTL()) + ->setAccessToken((string) $this->auth->authorize()->access_token) + ->request(); + + } catch (MissingAccountNumberException $e) { + $this->assertEquals('Account Number is missing.', $e->getMessage()); + } + $this->assertEmpty($request, 'The request did not fail as it should.'); + } + + public function testHasFreightRequestedShipment() + { + $request = NULL; + try { + $request = (new RateFreightLTL()) + ->setAccessToken((string) $this->auth->authorize()->access_token) + ->setAccountNumber('510087503') + ->request(); + + } catch (MissingFreightRequestedShipment $e) { + $this->assertEquals('Freight Requested Shipment is missing.', $e->getMessage()); + } + $this->assertEmpty($request, 'The request did not fail as it should.'); + } + + public function testPrepare() + { + $request = (new RateFreightLTL()) + ->setAccessToken((string) $this->auth->authorize()->access_token) + ->setAccountNumber('510087503') + ->setRateRequestControlParameters((new RateRequestControlParameters()) + ->setReturnTransitTimes(true) + ->setServiceNeededOnRateFailure(true) + ->setVariableOptions('FREIGHT_GUARANTEE') + ->setRateSortOrder('SERVICENAMETRADITIONAL')) + ->setFreightRequestedShipment((new RateFreightRequestedShipment()) + ->setShipperAddress((new Address()) + ->setStreetLines(['1234 Main Street']) + ->setCity('Anytown') + ->setStateOrProvince('NC') + ->setPostalCode('12345') + ->setCountryCode('US') + ->setResidential(false)) + ->setRecipientAddress((new Address()) + ->setStreetLines(['1234 Main Street']) + ->setCity('Anytown') + ->setStateOrProvince('NC') + ->setPostalCode('12345') + ->setCountryCode('US') + ->setResidential(false))); + + $prepared = $request->prepare(); + + $this->assertIsArray($prepared); + $this->assertArrayHasKey('accountNumber', $prepared); + $this->assertArrayHasKey('rateRequestControlParameters', $prepared); + $this->assertArrayHasKey('freightRequestedShipment', $prepared); + $this->assertEquals('510087503', $prepared['accountNumber']['value']); + $this->assertEquals([ + 'returnTransitTimes' => true, + 'serviceNeededOnRateFailure' => true, + 'variableOptions' => 'FREIGHT_GUARANTEE', + 'rateSortOrder' => 'SERVICENAMETRADITIONAL' + ], $prepared['rateRequestControlParameters']); + + } + + public function testRequest() + { + + } +} diff --git a/tests/FedexRest/Tests/FreightLTL/ShipFreightLTLTest.php b/tests/FedexRest/Tests/FreightLTL/ShipFreightLTLTest.php new file mode 100644 index 0000000..0de15b4 --- /dev/null +++ b/tests/FedexRest/Tests/FreightLTL/ShipFreightLTLTest.php @@ -0,0 +1,29 @@ +auth = (new Authorize) + ->setClientId('l7749d031872cf4b55a7889376f360d045') + ->setClientSecret('bd59d91084e8482895d4ae2fb4fb79a3'); + } + + public function testPrepare() + { + + } + + public function testRequest() + { + + } +} From 85c0c50c98088d66b79de7ddf29ef3bcb59e60a9 Mon Sep 17 00:00:00 2001 From: ash <58735196+ash-g-1337@users.noreply.github.com> Date: Tue, 3 Mar 2026 12:31:05 -0500 Subject: [PATCH 11/11] Placeholder FreightShipmentDetail entity for completing the Rates request --- .../Services/FreightLTL/Entity/FreightShipmentDetail.php | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/FedexRest/Services/FreightLTL/Entity/FreightShipmentDetail.php diff --git a/src/FedexRest/Services/FreightLTL/Entity/FreightShipmentDetail.php b/src/FedexRest/Services/FreightLTL/Entity/FreightShipmentDetail.php new file mode 100644 index 0000000..df5886d --- /dev/null +++ b/src/FedexRest/Services/FreightLTL/Entity/FreightShipmentDetail.php @@ -0,0 +1,8 @@ +