Fix: Move carrier live-pricing choice onto ShippingMethod.charge_by

Reverts the earlier per-rate pricing_mode column in favor of extending Lunar's existing charge_by field (cart_total/weight) with a third "live" option, gated by a SupportsLivePricing capability check on the driver. Adds a shared ResolvesFixedPricing trait so any carrier driver can fall back to Lunar's normal price-break resolution, matching the vendor ShipBy driver's own charge_by handling instead of introducing a separate mechanism. Also fixes an incorrect Get() path in the admin form that silently hid the new "live" option.
This commit is contained in:
2026-07-19 02:24:10 +03:00
parent 4acabe4185
commit d34e450526
6 changed files with 148 additions and 155 deletions
+7 -25
View File
@@ -4,15 +4,17 @@ namespace Modules\Core\Shipping\Carriers\Acs;
use Lunar\DataTypes\Price;
use Lunar\DataTypes\ShippingOption;
use Lunar\Facades\Pricing;
use Lunar\Shipping\DataTransferObjects\ShippingOptionRequest;
use Lunar\Shipping\Interfaces\ShippingRateInterface;
use Lunar\Shipping\Models\ShippingRate;
use Modules\Core\Shipping\Carriers\Acs\Exceptions\AcsApiException;
use Modules\Core\Shipping\Concerns\ResolvesFixedPricing;
use Modules\Core\Shipping\Contracts\SupportsLivePricing;
class AcsRateDriver implements ShippingRateInterface, SupportsLivePricing
{
use ResolvesFixedPricing;
public ShippingRate $shippingRate;
public function __construct(
@@ -36,39 +38,19 @@ class AcsRateDriver implements ShippingRateInterface, SupportsLivePricing
$shippingMethod = $shippingRate->shippingMethod;
$cart = $shippingOptionRequest->cart;
if (($shippingMethod->data['charge_by'] ?? 'cart_total') !== 'live') {
return $this->resolveFixedPrice($shippingRate, $shippingMethod, $cart);
}
$postcode = $cart->shippingAddress?->postcode;
if (! $postcode) {
return null;
}
if (($shippingRate->pricing_mode ?? 'live') === 'fixed') {
return $this->resolveFixedPrice($shippingRate, $shippingMethod, $cart);
}
return $this->resolveLivePrice($shippingRate, $shippingMethod, $cart, $postcode);
}
private function resolveFixedPrice(ShippingRate $shippingRate, $shippingMethod, $cart): ?ShippingOption
{
$subTotal = $cart->lines->sum('subTotal.value');
$pricing = Pricing::for($shippingRate)->qty($subTotal)->get();
if (! $pricing->matched) {
return null;
}
return new ShippingOption(
name: $shippingMethod->name ?: $this->name(),
description: $shippingMethod->description ?: $this->description(),
identifier: $shippingRate->getIdentifier(),
price: $pricing->matched->price,
taxClass: $shippingRate->getTaxClass(),
taxReference: $shippingRate->getTaxReference(),
);
}
private function resolveLivePrice(ShippingRate $shippingRate, $shippingMethod, $cart, string $postcode): ?ShippingOption
{
try {
@@ -3,19 +3,21 @@
namespace Modules\Core\Shipping\Carriers\BoxNow;
use Lunar\DataTypes\ShippingOption;
use Lunar\Facades\Pricing;
use Lunar\Shipping\DataTransferObjects\ShippingOptionRequest;
use Lunar\Shipping\Interfaces\ShippingRateInterface;
use Lunar\Shipping\Models\ShippingRate;
use Modules\Core\Shipping\Concerns\ResolvesFixedPricing;
/**
* Box Now has no pricing API, so this always resolves the admin-configured
* price/price-breaks on the ShippingRate — the same mechanism the built-in
* flat-rate driver uses. Unlike AcsRateDriver, this does not implement
* SupportsLivePricing: there is nothing to toggle between.
* Box Now has no pricing API, so this always resolves the method's normal
* charge_by + price-break configuration — the same mechanism the built-in
* flat-rate/ship-by drivers use. Does not implement SupportsLivePricing:
* there is no live option to offer.
*/
class BoxNowRateDriver implements ShippingRateInterface
{
use ResolvesFixedPricing;
public ShippingRate $shippingRate;
public function name(): string
@@ -30,25 +32,10 @@ class BoxNowRateDriver implements ShippingRateInterface
public function resolve(ShippingOptionRequest $shippingOptionRequest): ?ShippingOption
{
$shippingRate = $shippingOptionRequest->shippingRate;
$shippingMethod = $shippingRate->shippingMethod;
$cart = $shippingOptionRequest->cart;
$subTotal = $cart->lines->sum('subTotal.value');
$pricing = Pricing::for($shippingRate)->qty($subTotal)->get();
if (! $pricing->matched) {
return null;
}
return new ShippingOption(
name: $shippingMethod->name ?: $this->name(),
description: $shippingMethod->description ?: $this->description(),
identifier: $shippingRate->getIdentifier(),
price: $pricing->matched->price,
taxClass: $shippingRate->getTaxClass(),
taxReference: $shippingRate->getTaxReference(),
return $this->resolveFixedPrice(
$shippingOptionRequest->shippingRate,
$shippingOptionRequest->shippingRate->shippingMethod,
$shippingOptionRequest->cart,
);
}