Feat: Adding Translations to Payment and Shipping Methods, removing unecessary shipping method fulfillment type

This commit is contained in:
2026-09-15 23:51:10 +03:00
parent ea73cc3562
commit 97004234f0
14 changed files with 447 additions and 36 deletions
+60
View File
@@ -0,0 +1,60 @@
<?php
namespace Modules\Core\Shipping\Support;
use Lunar\Shipping\Facades\Shipping;
use Lunar\Shipping\Models\ShippingMethod;
use Modules\Core\Shipping\Contracts\DeclaresFulfillmentType;
/**
* The single source of truth for "is this ShippingMethod a carrier
* delivery or an in-store pickup" — replaces a merchant-facing
* data['fulfillment_type'] Select that used to exist for every method
* regardless of driver. Modules\Core\Shipping\Carriers\Acs\AcsRateDriver
* and BoxNowRateDriver are unambiguously carrier-only (see
* Modules\Core\Shipping\Contracts\DeclaresFulfillmentType's own
* docblock), so asking a merchant to also pick "Carrier delivery" for
* every ACS/Box Now method was redundant, error-prone config with no
* real decision behind it.
*
* table-rate-shipping's own generic drivers (flat-rate, ship-by,
* free-shipping) don't implement DeclaresFulfillmentType — a merchant
* could genuinely configure one for either purpose (e.g. "Flat Rate —
* Athens Store Pickup") — so those still fall back to the merchant-set
* data['fulfillment_type'], defaulting to 'carrier' when unset.
*/
class FulfillmentType
{
public static function resolve(ShippingMethod $method): string
{
$driver = collect(Shipping::getSupportedDrivers())->get($method->driver);
if ($driver instanceof DeclaresFulfillmentType) {
return $driver->fulfillmentType();
}
return $method->data['fulfillment_type'] ?? 'carrier';
}
public static function isStorePickup(ShippingMethod $method): bool
{
return static::resolve($method) === 'store_pickup';
}
/**
* Whether the merchant-facing "Fulfillment type" Select should be
* shown at all for a given driver — hidden entirely for a driver that
* already declares its own fulfillment type, since there is no real
* decision left for the merchant to make.
*/
public static function isConfigurableFor(?string $driverKey): bool
{
if ($driverKey === null) {
return true;
}
$driver = collect(Shipping::getSupportedDrivers())->get($driverKey);
return ! $driver instanceof DeclaresFulfillmentType;
}
}
@@ -0,0 +1,35 @@
<?php
namespace Modules\Core\Shipping\Support;
use Illuminate\Support\Arr;
use Lunar\Shipping\Models\ShippingMethod;
/**
* ShippingMethod.name is a locale-keyed JSON column (see database/
* migrations/..._make_shipping_methods_name_translatable.php, and
* Modules\Core\Shipping\Extensions\ShippingMethodResourceExtension for
* the Filament form/table side), but ShippingMethod is a vendor Eloquent
* model with no cast declared for it — Lunar\Shipping\Models\
* ShippingMethod only casts `data`, and there's no ModelManifest contract
* wired up by the package to swap in a first-party subclass that adds
* one (Contracts\ShippingMethod exists but is never bound). So `$method->
* name` returns the raw JSON string, not a decoded array — this resolves
* it the same way Lunar\Base\Traits\HasTranslations::translate() would,
* shared by every rate driver that builds a Lunar\DataTypes\ShippingOption
* (Modules\Core\Shipping\Concerns\ResolvesFixedPricing, Modules\Core\
* Shipping\Carriers\Acs\AcsRateDriver) plus the Filament table column.
*/
class ShippingMethodName
{
public static function resolve(ShippingMethod $method, ?string $locale = null): ?string
{
$decoded = json_decode((string) $method->getRawOriginal('name'), true);
if (! is_array($decoded)) {
return $method->getRawOriginal('name');
}
return Arr::get($decoded, $locale ?: app()->getLocale()) ?: Arr::first($decoded);
}
}