Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(checkout): fix incorrect shipping price being used in checkout #272

Merged
merged 7 commits into from
Sep 26, 2024
Merged
17 changes: 16 additions & 1 deletion src/Hooks/HasPsShippingCostHooks.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use MyParcelNL\Pdk\Facade\Pdk;
use MyParcelNL\Pdk\Shipment\Model\DeliveryOptions;
use MyParcelNL\PrestaShop\Contract\PsCarrierServiceInterface;
use MyParcelNL\PrestaShop\Repository\PsCartDeliveryOptionsRepository;
use Tools;

trait HasPsShippingCostHooks
Expand Down Expand Up @@ -87,7 +88,8 @@ private function calculateShippingCost(DeliveryOptions $deliveryOptions, float $
}

/**
* Get the actual delivery options from the checkout hidden input, or get the default delivery options for the current carrier, without any options.
* Get the actual delivery options from the checkout hidden input, or from the database using the cart id,
* or get the default delivery options for the current carrier, without any options.
*
* @param \MyParcelNL\Pdk\Carrier\Model\Carrier $carrier
*
Expand All @@ -101,6 +103,19 @@ private function getDeliveryOptions(Carrier $carrier): DeliveryOptions
return new DeliveryOptions(json_decode($deliveryOptions, true));
}

/** @var \MyParcelNL\PrestaShop\Repository\PsCartDeliveryOptionsRepository $cartDeliveryOptionsRepository */
$cartDeliveryOptionsRepository = Pdk::get(PsCartDeliveryOptionsRepository::class);
$dbDeliveryOptions = $cartDeliveryOptionsRepository->findOneBy(
['cartId' => $this->context->cart->id]
);

if (
$dbDeliveryOptions
&& $dbDeliveryOptions->getData()['carrier']['externalIdentifier'] === $carrier->externalIdentifier
) {
return new DeliveryOptions($dbDeliveryOptions->getData());
}

return new DeliveryOptions(['carrier' => $carrier]);
}
}
5 changes: 5 additions & 0 deletions tests/Mock/MockPsTools.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ public static function getValue(string $key)
return self::$values[$key] ?? null;
}

public static function reset(): void
{
self::$values = [];
}

/**
* @param array $values
*
Expand Down
13 changes: 12 additions & 1 deletion tests/Pest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* @see https://pestphp.com/docs/underlying-test-case#testspestphp
*/

use MyParcelNL\PrestaShop\Tests\Mock\MockPsTools;
use MyParcelNL\PrestaShop\Tests\TestCase;

/** @see \MyParcelNL\PrestaShop\bootPdk() */
Expand All @@ -29,7 +30,17 @@
const _PS_VERSION_ = '8.0.0';
const _PS_USE_SQL_SLAVE_ = false;

uses(TestCase::class)->in(__DIR__);
uses(TestCase::class)
->afterEach(function () {
$resetInterfaces = [
MockPsTools::class,
];

foreach ($resetInterfaces as $resetInterface) {
$resetInterface::reset();
}
})
->in(__DIR__);

uses()
->group('migrations')
Expand Down
85 changes: 85 additions & 0 deletions tests/Unit/Hooks/HasPsShippingCostHooksTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use MyParcelNL\Pdk\Shipment\Model\ShipmentOptions;
use MyParcelNL\Pdk\Tests\Factory\Collection\FactoryCollection;
use MyParcelNL\PrestaShop\Entity\MyparcelnlCarrierMapping;
use MyParcelNL\PrestaShop\Repository\PsCartDeliveryOptionsRepository;
use MyParcelNL\PrestaShop\Tests\Mock\MockPsTools;
use MyParcelNL\PrestaShop\Tests\Uses\UsesMockPsPdkInstance;
use function MyParcelNL\Pdk\Tests\factory;
Expand All @@ -44,6 +45,11 @@ public function setIdCarrier(int $idCarrier): void
{
$this->id_carrier = $idCarrier;
}

public function setCart(Cart $cart): void
{
$this->context->cart = $cart;
}
}

usesShared(new UsesMockPsPdkInstance());
Expand Down Expand Up @@ -136,4 +142,83 @@ function () {
expect($result)->toBe(123.45);
});

it(
'calculates shipping costs using database',
function (CartFactory $cartFactory, array $deliveryOptions = [], float $addedCost = 0) {
$cart = $cartFactory->make();

/** @var PsCartDeliveryOptionsRepository $cartDeliveryOptionsRepository */
$cartDeliveryOptionsRepository = Pdk::get(PsCartDeliveryOptionsRepository::class);

$deliveryOptions = new DeliveryOptions($deliveryOptions);

$cartDeliveryOptionsRepository->updateOrCreate(
[
'cartId' => $cart->id,
],
[
'data' => json_encode($deliveryOptions->toStorableArray()),
]
);

$instance = new ClassWithTrait();
$instance->setIdCarrier(93);
$instance->setCart($cart);

$baseCost = 10;
$cost = $instance->getOrderShippingCost($cart, $baseCost);

expect(number_format($cost, 2))->toEqual(number_format($baseCost + $addedCost, 2));
}
)->with([
'standard delivery with delivery options in values' => [
function () {
$psCarrier = psFactory(PsCarrier::class)->withId(93);

(new FactoryCollection([
$psCarrier,
psFactory(MyparcelnlCarrierMapping::class)
->withCarrierId(93)
->withMyparcelCarrier(Carrier::CARRIER_POSTNL_NAME),
factory(Settings::class)->withCarrierPostNl([
CarrierSettings::PRICE_DELIVERY_TYPE_STANDARD => 2.95,
]),
]))->store();

return psFactory(Cart::class)->withCarrier($psCarrier);
},
'values' => [
DeliveryOptions::CARRIER => Carrier::CARRIER_POSTNL_NAME,
DeliveryOptions::DELIVERY_TYPE => DeliveryOptions::DELIVERY_TYPE_STANDARD_NAME,
],
'cost' => 2.95,
],

'carrier with linked myparcel carrier and delivery options in values' => [
function () {
$psCarrier = psFactory(PsCarrier::class)->withId(93);

(new FactoryCollection([
$psCarrier,
psFactory(MyparcelnlCarrierMapping::class)
->withCarrierId(93)
->withMyparcelCarrier(Carrier::CARRIER_POSTNL_NAME),
factory(Settings::class)
->withCarrierPostNl([
CarrierSettings::PRICE_SIGNATURE => 0.45,
CarrierSettings::PRICE_DELIVERY_TYPE_STANDARD => 4.95,
]),
]))->store();

return psFactory(Cart::class)->withCarrier($psCarrier);
},
'values' => [
DeliveryOptions::CARRIER => Carrier::CARRIER_POSTNL_NAME,
DeliveryOptions::DELIVERY_TYPE => DeliveryOptions::DELIVERY_TYPE_STANDARD_NAME,
DeliveryOptions::SHIPMENT_OPTIONS => [
ShipmentOptions::SIGNATURE => true,
],
],
'cost' => 5.4,
],
]);
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import {debounce, type DeliveryOptionsStoreState, type StoreCallbackUpdate} from '@myparcel-pdk/checkout';
import {
debounce,
useDeliveryOptionsStore,
type DeliveryOptionsStoreState,
type StoreCallbackUpdate,
} from '@myparcel-pdk/checkout';
import {objectIsEqual} from '@myparcel/ts-utils';
import {getCurrentShippingMethod} from '../../utils';

const CHECKOUT_UPDATE_DELAY = 200;

/**
* Only do this once to avoid excessive animations.
*/
let done = false;

export const onDeliveryOptionsOutputChange: StoreCallbackUpdate<DeliveryOptionsStoreState> = debounce(
(newState, oldState) => {
if (objectIsEqual(newState.output, oldState?.output)) {
Expand All @@ -21,13 +21,12 @@ export const onDeliveryOptionsOutputChange: StoreCallbackUpdate<DeliveryOptionsS
return;
}

if (done) {
return;
}
const deliveryOptions = useDeliveryOptionsStore();

// Trigger a change event on the shipping method input to let PrestaShop fetch the new price.
currentShippingMethod.input.trigger('change');
done = true;
// Update the hidden input.
if (deliveryOptions.state.hiddenInput) {
$(deliveryOptions.state.hiddenInput).trigger('change');
}
},
CHECKOUT_UPDATE_DELAY,
);
Loading