307 lines
11 KiB
PHP
307 lines
11 KiB
PHP
<?php
|
|
|
|
namespace Koneko\VuexyStoreManager\Livewire\Stores;
|
|
|
|
use Illuminate\Validation\Rule;
|
|
use Koneko\VuexyAdmin\Models\User;
|
|
use Koneko\VuexyAdmin\Livewire\Form\AbstractFormComponent;
|
|
use Koneko\SatCatalogs\Models\{Colonia, Estado, Localidad, Municipio, Pais, RegimenFiscal};
|
|
use Koneko\VuexyStoreManager\Models\Store;
|
|
|
|
/**
|
|
* Class StoreForm
|
|
*
|
|
* Componente Livewire para manejar el formulario CRUD de sucursales en el sistema ERP.
|
|
* Implementa la creación, edición y eliminación de sucursales con validaciones dinámicas.
|
|
*/
|
|
class StoreForm extends AbstractFormComponent
|
|
{
|
|
/**
|
|
* Campos específicos del formulario.
|
|
*/
|
|
public $code, $name, $description, $manager_id, $rfc, $nombre_fiscal, $c_regimen_fiscal,
|
|
$domicilio_fiscal, $serie_ingresos, $serie_egresos, $serie_pagos, $c_codigo_postal,
|
|
$c_pais, $c_estado, $c_localidad, $c_municipio, $c_colonia, $direccion, $num_ext,
|
|
$num_int, $email, $tel, $tel2, $lat, $lng, $show_on_website, $enable_ecommerce, $status;
|
|
|
|
|
|
public $confirmDeletion = false;
|
|
|
|
/**
|
|
* Listas de opciones para selects en el formulario.
|
|
*/
|
|
public $manager_id_options = [],
|
|
$c_regimen_fiscal_options = [],
|
|
$c_pais_options = [],
|
|
$c_estado_options = [],
|
|
$c_localidad_options = [],
|
|
$c_municipio_options = [],
|
|
$c_colonia_options = [];
|
|
|
|
/**
|
|
* Montar el formulario e inicializar datos específicos.
|
|
*
|
|
* @param string $mode Modo del formulario: create, edit, delete.
|
|
* @param Store|null $store El modelo Store si está en modo edición o eliminación.
|
|
*/
|
|
public function mount(string $mode = 'create', mixed $store = null): void
|
|
{
|
|
parent::mount($mode, $store->id ?? null);
|
|
}
|
|
|
|
/**
|
|
* Cargar opciones de formularios según el modo actual.
|
|
*
|
|
* @param string $mode
|
|
*/
|
|
private function loadOptions(string $mode): void
|
|
{
|
|
$this->manager_id_options = User::getUsersListWithInactive($this->manager_id, ['type' => 'user', 'status' => 1]);
|
|
$this->c_regimen_fiscal_options = RegimenFiscal::selectList();
|
|
$this->c_pais_options = Pais::selectList();
|
|
$this->c_estado_options = Estado::selectList($this->c_pais)->toArray();
|
|
|
|
if ($mode !== 'create') {
|
|
$this->c_localidad_options = Localidad::selectList($this->c_estado)->toArray();
|
|
$this->c_municipio_options = Municipio::selectList($this->c_estado, $this->c_municipio)->toArray();
|
|
$this->c_colonia_options = Colonia::selectList($this->c_codigo_postal, $this->c_colonia)->toArray();
|
|
}
|
|
}
|
|
|
|
// ===================== MÉTODOS OBLIGATORIOS =====================
|
|
|
|
/**
|
|
* Devuelve el modelo Eloquent asociado.
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function model(): string
|
|
{
|
|
return Store::class;
|
|
}
|
|
|
|
/**
|
|
* Reglas de validación dinámicas según el modo actual.
|
|
*
|
|
* @param string $mode
|
|
* @return array
|
|
*/
|
|
protected function dynamicRules(string $mode): array
|
|
{
|
|
switch ($mode) {
|
|
case 'create':
|
|
case 'edit':
|
|
return [
|
|
'code' => [
|
|
'required', 'string', 'alpha_num', 'max:16',
|
|
Rule::unique('stores', 'code')->ignore($this->id)
|
|
],
|
|
'name' => 'required|string|max:96',
|
|
'description' => 'nullable|string|max:1024',
|
|
'manager_id' => 'nullable|exists:users,id',
|
|
|
|
// Información fiscal
|
|
'rfc' => ['nullable', 'string', 'regex:/^([A-ZÑ&]{3,4})(\d{6})([A-Z\d]{3})$/i', 'max:13'],
|
|
'nombre_fiscal' => 'nullable|string|max:255',
|
|
'c_regimen_fiscal' => 'nullable|exists:sat_regimen_fiscal,c_regimen_fiscal',
|
|
'domicilio_fiscal' => 'nullable|exists:sat_codigo_postal,c_codigo_postal',
|
|
|
|
// Ubicación
|
|
'c_pais' => 'nullable|exists:sat_pais,c_pais|string|size:3',
|
|
'c_estado' => 'nullable|exists:sat_estado,c_estado|string|min:2|max:3',
|
|
'c_municipio' => 'nullable|exists:sat_municipio,c_municipio|integer',
|
|
'c_localidad' => 'nullable|integer',
|
|
'c_codigo_postal' => 'nullable|exists:sat_codigo_postal,c_codigo_postal|integer',
|
|
'c_colonia' => 'nullable|exists:sat_colonia,c_colonia|integer',
|
|
'direccion' => 'nullable|string|max:255',
|
|
'num_ext' => 'nullable|string|max:50',
|
|
'num_int' => 'nullable|string|max:50',
|
|
'lat' => 'nullable|numeric|between:-90,90',
|
|
'lng' => 'nullable|numeric|between:-180,180',
|
|
|
|
// Contacto
|
|
'email' => ['nullable', 'email', 'required_if:enable_ecommerce,true'],
|
|
'tel' => ['nullable', 'regex:/^[0-9\s\-\+\(\)]+$/', 'max:15'],
|
|
'tel2' => ['nullable', 'regex:/^[0-9\s\-\+\(\)]+$/', 'max:15'],
|
|
|
|
// Configuración web y estado
|
|
'show_on_website' => 'nullable|boolean',
|
|
'enable_ecommerce' => 'nullable|boolean',
|
|
'status' => 'nullable|boolean',
|
|
];
|
|
|
|
case 'delete':
|
|
return [
|
|
'confirmDeletion' => 'accepted', // Asegura que el usuario confirme la eliminación
|
|
];
|
|
|
|
default:
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Inicializa los datos del formulario en función del modo.
|
|
*
|
|
* @param Store|null $store
|
|
* @param string $mode
|
|
*/
|
|
protected function initializeFormData(mixed $store, string $mode): void
|
|
{
|
|
if ($store) {
|
|
$this->code = $store->code;
|
|
$this->name = $store->name;
|
|
$this->description = $store->description;
|
|
$this->manager_id = $store->manager_id;
|
|
$this->rfc = $store->rfc;
|
|
$this->nombre_fiscal = $store->nombre_fiscal;
|
|
$this->c_regimen_fiscal = $store->c_regimen_fiscal;
|
|
$this->domicilio_fiscal = $store->domicilio_fiscal;
|
|
$this->c_pais = $store->c_pais;
|
|
$this->c_estado = $store->c_estado;
|
|
$this->c_municipio = $store->c_municipio;
|
|
$this->c_localidad = $store->c_localidad;
|
|
$this->c_codigo_postal = $store->c_codigo_postal;
|
|
$this->c_colonia = $store->c_colonia;
|
|
$this->direccion = $store->direccion;
|
|
$this->num_ext = $store->num_ext;
|
|
$this->num_int = $store->num_int;
|
|
$this->lat = $store->lat;
|
|
$this->lng = $store->lng;
|
|
$this->email = $store->email;
|
|
$this->tel = $store->tel;
|
|
$this->tel2 = $store->tel2;
|
|
$this->show_on_website = (bool) $store->show_on_website;
|
|
$this->enable_ecommerce = (bool) $store->enable_ecommerce;
|
|
$this->status = (bool) $store->status;
|
|
|
|
} else {
|
|
$this->c_pais = 'MEX';
|
|
$this->status = true;
|
|
$this->show_on_website = false;
|
|
$this->enable_ecommerce = false;
|
|
}
|
|
|
|
$this->loadOptions($mode);
|
|
}
|
|
|
|
/**
|
|
* Prepara los datos validados para su almacenamiento.
|
|
*
|
|
* @param array $validatedData
|
|
* @return array
|
|
*/
|
|
protected function prepareData(array $validatedData): array
|
|
{
|
|
return [
|
|
'code' => $validatedData['code'],
|
|
'name' => $validatedData['name'],
|
|
'description' => strip_tags($validatedData['description']),
|
|
'manager_id' => $validatedData['manager_id'],
|
|
'rfc' => $validatedData['rfc'],
|
|
'nombre_fiscal' => $validatedData['nombre_fiscal'],
|
|
'c_regimen_fiscal' => $validatedData['c_regimen_fiscal'],
|
|
'domicilio_fiscal' => $validatedData['domicilio_fiscal'],
|
|
'c_codigo_postal' => $validatedData['c_codigo_postal'],
|
|
'c_pais' => $validatedData['c_pais'],
|
|
'c_estado' => $validatedData['c_estado'],
|
|
'c_localidad' => $validatedData['c_localidad'],
|
|
'c_municipio' => $validatedData['c_municipio'],
|
|
'c_colonia' => $validatedData['c_colonia'],
|
|
'direccion' => $validatedData['direccion'],
|
|
'num_ext' => $validatedData['num_ext'],
|
|
'num_int' => $validatedData['num_int'],
|
|
'email' => $validatedData['email'],
|
|
'tel' => $validatedData['tel'],
|
|
'tel2' => $validatedData['tel2'],
|
|
'lat' => $validatedData['lat'],
|
|
'lng' => $validatedData['lng'],
|
|
'status' => $validatedData['status'],
|
|
'show_on_website' => $validatedData['show_on_website'],
|
|
'enable_ecommerce' => $validatedData['enable_ecommerce'],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Definición de los contenedores de notificación.
|
|
*
|
|
* @return array
|
|
*/
|
|
protected function targetNotifies(): array
|
|
{
|
|
return [
|
|
"index" => "#bt-stores .notification-container",
|
|
"form" => "#store-form .notification-container",
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Ruta de vista asociada al formulario.
|
|
*
|
|
* @return \Illuminate\Contracts\View\View
|
|
*/
|
|
protected function viewPath(): string
|
|
{
|
|
return 'vuexy-store-manager::livewire.stores.form';
|
|
}
|
|
|
|
// ===================== VALIDACIONES =====================
|
|
|
|
/**
|
|
* Get custom attributes for validator errors.
|
|
*
|
|
* @return array<string, string>
|
|
*/
|
|
public function attributes(): array
|
|
{
|
|
return [
|
|
'code' => 'código de sucursal',
|
|
'name' => 'nombre de la sucursal',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Get the error messages for the defined validation rules.
|
|
*
|
|
* @return array<string, string>
|
|
*/
|
|
public function messages(): array
|
|
{
|
|
return [
|
|
'code.required' => 'El código de la sucursal es obligatorio.',
|
|
'code.unique' => 'Este código ya está en uso por otra sucursal.',
|
|
'name.required' => 'El nombre de la sucursal es obligatorio.',
|
|
];
|
|
}
|
|
|
|
// ===================== PREPARACIÓN DE DATOS =====================
|
|
|
|
// ===================== NOTIFICACIONES Y EVENTOS =====================
|
|
|
|
/**
|
|
* Definición de los eventos del componente.
|
|
*
|
|
* @return array
|
|
*/
|
|
protected function dispatches(): array
|
|
{
|
|
return [
|
|
'on-failed-validation' => 'on-failed-validation-store',
|
|
'on-hydrate' => 'on-hydrate-store-modal',
|
|
];
|
|
}
|
|
|
|
// ===================== REDIRECCIÓN =====================
|
|
|
|
/**
|
|
* Define la ruta de redirección tras guardar o eliminar.
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function getRedirectRoute(): string
|
|
{
|
|
return 'admin.store-manager.stores.index';
|
|
}
|
|
|
|
}
|