Skip to content

Gastos de envío

Módulo para el manejo de gastos de envío en bPanel 4.

Como añadir métodos de envío

Para añadir nuevas formas de envío al módulo, debe registrarse un nuevo paquete de composer que cumpla algunas condiciones:

Modelos

Interfaces

Por ahora, solo es necesario que el modelo del método de envío que vamos a definir implemente la interfaz ShippingMethod.

Namespace

En el composer.json del plugin debe declararse lo siguiente dentro de autoload: psr-4, aparte del namespace propio del plugin:

"Bittacora\\Bpanel4\\Shipping\\Models\\ShippingMethods\\": "src/Models"

Es imprescindible que el namespace en el que se registren los modelos sea el que se indica, ya que es donde se buscarán los métodos de envío. No importa que estén en paquetes diferentes mientras que se definan en ese namespace.

Luego en el modelo correspondiente a nuestro método de envío, forzaremos el namespace al que hemos indicado antes:

<?php

declare(strict_types=1);

namespace Bittacora\Bpanel4\Shipping\Models\ShippingMethods; // Forzamos el namespace

use ...

class MiModelo extends Model implements ShippingMethod

Habrá que limpiar la caché de Laravel para que encuentre las nuevas clases, ya que el proceso de búsqueda llevaba bastante tiempo y hubo que cachearlo.

Cálculo de precio en el carrito

Para dar más flexibilidad a la hora de calcular los gastos de envío en el carrito, se llamará a una clase que implemente la interfaz ShippingMethodPriceCalculator, que será definida por cada plugin.

Namespace

El namespace para estas clases debe ser Bittacora\Bpanel4\Shipping\Services\PriceCalculators, y también habrá que declararlo en el composer.json de cada plugin, dentro de la sección PSR-4 del apartado autoload:

"Bittacora\\Bpanel4\\Shipping\\Services\\PriceCalculators\\": "src/Services/PriceCalculators"

El nombre de la clase debe acabar con PriceCalculator. Por ejemplo, para el plugin de envío gratuito, la clase sería

Bittacora\Bpanel4\Shipping\Services\PriceCalculators\FreeShipingPriceCalculator

Rutas

// Métodos de envío
Route::prefix('bpanel/envio')->name('bpanel4-shipping.nombre-del-plugin.bpanel.')->middleware(['web', 'auth', 'admin-menu'])
    ->group(static function () {
        Route::get('/metodos-de-envio/NombreDelMetodoDeEnvio/{zone}/crear', [NombreDelMetodoDeEnvioAdminController::class, 'create'])->name('create');
        Route::post('/metodos-de-envio/NombreDelMetodoDeEnvio/{zone}/crear', [NombreDelMetodoDeEnvioAdminController::class, 'store'])->name('store');
        Route::get('/metodos-de-envio/NombreDelMetodoDeEnvio/{model}/editar', [NombreDelMetodoDeEnvioAdminController::class, 'edit'])->name('edit');
        Route::post('/metodos-de-envio/NombreDelMetodoDeEnvio/{model}/editar', [NombreDelMetodoDeEnvioAdminController::class, 'update'])->name('update');
        Route::get('/metodos-de-envio/NombreDelMetodoDeEnvio/{model}/eliminar', [NombreDelMetodoDeEnvioAdminController::class, 'destroy'])->name('destroy');
        //...
    });

nombre-del-plugin debe ser el nombre del plugin en kebab-case. El parámetro de la ruta tendrá que ser {model} para todas las rutas excepto create, que usará zone. {zone} es el id de la zona de envío a la que se debe asignar el método de envío.

En el controlador del plugin en principio no habrá ninguna restricción, aparte de que cuando inyectemos el modelo en el método edit (por ejemplo), la variable tendrá que llamarse $model para que Laravel nos inyecte el modelo correctamente. Eso si, el tipo de $model será el que corresponda al modelo de nuestro plugin, por ejemplo, en el módulo de envío gratis, la función edit tiene como parámetro FreeShipping $model.

public function edit(FreeShipping $model): View

Nota: Esto es así para que el datatable que lista los métodos de envío pueda construir las rutas de cualquier método de envío sin conocer de antemano cuales hay disponibles.

Service providers

En el service provider de cada plugin, habrá que registrar el método de envío para que esté disponible a la hora de construir listados con los métodos de envío disponibles.

Para hacerlo, en el método boot del service provider de cada plugin, llamaremos a registerShippingMethod de ShippingFacade:

ShippingFacade::registerShippingMethod('Nombre del método de envío', ModeloDelPlugin::class);

El primer parámetro será el nombre de cara al usuario del método de envío, y el segundo el nombre completo del modelo (por ejemplo \Bittacora\Bpanel4\Shipping\Models\ShippingMethods\FreeShipping)

Notas

La relación entre zona de envío y los distintos métodos de envío debería haber sido una relación polimórfica, pero cuando empecé a desarrollar estos paquetes, no me venía bien por la estructura que estaba siguiendo así que lo hice de la forma que se ve actualmente. Ahora se podría refactorizar para usar una relación polimórfica sin más, pero de momento no lo hago porque el código funciona y tiene tests. Más adelante nos podríamos plantear corregir esto si lo vemos necesario, pero de momento funciona bien como está y además no habría ninguna ventaja (solo que el código sería más "correcto").