first commit
This commit is contained in:
306
Livewire/Contacts/ContactForm.php
Normal file
306
Livewire/Contacts/ContactForm.php
Normal file
@ -0,0 +1,306 @@
|
||||
<?php
|
||||
|
||||
namespace Koneko\VuexyContacts\Livewire\Contacts;
|
||||
|
||||
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\VuexyContacts\Models\Store;
|
||||
|
||||
/**
|
||||
* Class ContactForm
|
||||
*
|
||||
* 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 ContactForm 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';
|
||||
}
|
||||
|
||||
}
|
236
Livewire/Contacts/ContactIndex.php
Normal file
236
Livewire/Contacts/ContactIndex.php
Normal file
@ -0,0 +1,236 @@
|
||||
<?php
|
||||
|
||||
namespace Koneko\VuexyContacts\Livewire\Contacts;
|
||||
|
||||
use Koneko\VuexyAdmin\Models\User;
|
||||
use Koneko\VuexyAdmin\Livewire\Table\AbstractIndexComponent;
|
||||
|
||||
class ContactIndex extends AbstractIndexComponent
|
||||
{
|
||||
/**
|
||||
* Almacena rutas útiles para la funcionalidad de edición o eliminación.
|
||||
*/
|
||||
public $routes = [];
|
||||
|
||||
/**
|
||||
* Método que define la clase o instancia del modelo a usar en este Index.
|
||||
*/
|
||||
protected function model(): string
|
||||
{
|
||||
return User::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retorna las columnas (header) de la tabla.
|
||||
*/
|
||||
protected function columns(): array
|
||||
{
|
||||
return [
|
||||
'action' => 'Acciones',
|
||||
'code' => 'Código personal',
|
||||
'full_name' => 'Nombre Completo',
|
||||
'email' => 'Correo Electrónico',
|
||||
'parent_name' => 'Responsable',
|
||||
'parent_email' => 'Correo Responsable',
|
||||
'company' => 'Empresa',
|
||||
'birth_date' => 'Fecha de Nacimiento',
|
||||
'hire_date' => 'Fecha de Contratación',
|
||||
'curp' => 'CURP',
|
||||
'nss' => 'NSS',
|
||||
'job_title' => 'Puesto',
|
||||
'rfc' => 'RFC',
|
||||
'nombre_fiscal' => 'Nombre Fiscal',
|
||||
'tipo_persona' => 'Tipo de Persona',
|
||||
'c_regimen_fiscal'=> 'Régimen Fiscal',
|
||||
'domicilio_fiscal'=> 'Domicilio Fiscal',
|
||||
'c_uso_cfdi' => 'Clave Uso CFDI',
|
||||
'uso_cfdi' => 'Uso CFDI',
|
||||
'profile_photo_path' => 'Foto de Perfil',
|
||||
'is_partner' => 'Socio',
|
||||
'is_employee' => 'Empleado',
|
||||
'is_prospect' => 'Prospecto',
|
||||
'is_customer' => 'Cliente',
|
||||
'is_provider' => 'Proveedor',
|
||||
'is_user' => 'Usuario',
|
||||
'status' => 'Estatus',
|
||||
'creator' => 'Creado Por',
|
||||
'creator_email' => 'Correo Creador',
|
||||
'created_at' => 'Fecha de Creación',
|
||||
'updated_at' => 'Última Modificación',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retorna el formato (formatter) para cada columna.
|
||||
*/
|
||||
protected function format(): array
|
||||
{
|
||||
return [
|
||||
'action' => [
|
||||
'formatter' => 'contactActionFormatter',
|
||||
'onlyFormatter' => true,
|
||||
],
|
||||
'code' => [
|
||||
'formatter' => [
|
||||
'name' => 'dynamicBadgeFormatter',
|
||||
'params' => ['color' => 'secondary'],
|
||||
],
|
||||
'align' => 'center',
|
||||
'switchable' => false,
|
||||
],
|
||||
'full_name' => [
|
||||
'formatter' => 'contactProfileFormatter',
|
||||
],
|
||||
'email' => [
|
||||
'formatter' => 'emailFormatter',
|
||||
'visible' => false,
|
||||
],
|
||||
'parent_name' => [
|
||||
'formatter' => 'contactParentFormatter',
|
||||
'visible' => false,
|
||||
],
|
||||
'agent_name' => [
|
||||
'formatter' => 'agentFormatter',
|
||||
'visible' => false,
|
||||
],
|
||||
'company' => [
|
||||
'formatter' => 'textNowrapFormatter',
|
||||
],
|
||||
'curp' => [
|
||||
'visible' => false,
|
||||
],
|
||||
'nss' => [
|
||||
'visible' => false,
|
||||
],
|
||||
'job_title' => [
|
||||
'formatter' => 'textNowrapFormatter',
|
||||
'visible' => false,
|
||||
],
|
||||
'rfc' => [
|
||||
'visible' => false,
|
||||
],
|
||||
'nombre_fiscal' => [
|
||||
'formatter' => 'textNowrapFormatter',
|
||||
'visible' => false,
|
||||
],
|
||||
'domicilio_fiscal' => [
|
||||
'visible' => false,
|
||||
],
|
||||
'c_uso_cfdi' => [
|
||||
'formatter' => 'usoCfdiFormatter',
|
||||
'visible' => false,
|
||||
],
|
||||
'tipo_persona' => [
|
||||
'formatter' => 'dynamicBadgeFormatter',
|
||||
'align' => 'center',
|
||||
'visible' => false,
|
||||
],
|
||||
'c_regimen_fiscal' => [
|
||||
'formatter' => 'regimenFiscalFormatter',
|
||||
'visible' => false,
|
||||
],
|
||||
'birth_date' => [
|
||||
'align' => 'center',
|
||||
'visible' => false,
|
||||
],
|
||||
'hire_date' => [
|
||||
'align' => 'center',
|
||||
'visible' => false,
|
||||
],
|
||||
'estado' => [
|
||||
'formatter' => 'textNowrapFormatter',
|
||||
],
|
||||
'municipio' => [
|
||||
'formatter' => 'textNowrapFormatter',
|
||||
],
|
||||
'localidad' => [
|
||||
'formatter' => 'textNowrapFormatter',
|
||||
'visible' => false,
|
||||
],
|
||||
'is_partner' => [
|
||||
'formatter' => [
|
||||
'name' => 'dynamicBooleanFormatter',
|
||||
'params' => ['tag' => 'checkSI'],
|
||||
],
|
||||
'align' => 'center',
|
||||
],
|
||||
'is_employee' => [
|
||||
'formatter' => [
|
||||
'name' => 'dynamicBooleanFormatter',
|
||||
'params' => ['tag' => 'checkSI'],
|
||||
],
|
||||
'align' => 'center',
|
||||
],
|
||||
'is_prospect' => [
|
||||
'formatter' => [
|
||||
'name' => 'dynamicBooleanFormatter',
|
||||
'params' => ['tag' => 'checkSI'],
|
||||
],
|
||||
'align' => 'center',
|
||||
],
|
||||
'is_customer' => [
|
||||
'formatter' => [
|
||||
'name' => 'dynamicBooleanFormatter',
|
||||
'params' => ['tag' => 'checkSI'],
|
||||
],
|
||||
'align' => 'center',
|
||||
],
|
||||
'is_provider' => [
|
||||
'formatter' => [
|
||||
'name' => 'dynamicBooleanFormatter',
|
||||
'params' => ['tag' => 'checkSI'],
|
||||
],
|
||||
'align' => 'center',
|
||||
],
|
||||
'is_user' => [
|
||||
'formatter' => [
|
||||
'name' => 'dynamicBooleanFormatter',
|
||||
'params' => ['tag' => 'checkSI'],
|
||||
],
|
||||
'align' => 'center',
|
||||
],
|
||||
'status' => [
|
||||
'formatter' => 'statusIntBadgeBgFormatter',
|
||||
'align' => 'center',
|
||||
],
|
||||
'creator' => [
|
||||
'formatter' => 'creatorFormatter',
|
||||
'visible' => false,
|
||||
],
|
||||
'created_at' => [
|
||||
'formatter' => 'textNowrapFormatter',
|
||||
'align' => 'center',
|
||||
'visible' => false,
|
||||
],
|
||||
'updated_at' => [
|
||||
'formatter' => 'textNowrapFormatter',
|
||||
'align' => 'center',
|
||||
'visible' => false,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Montamos el componente y llamamos al parent::mount() para configurar la tabla.
|
||||
*/
|
||||
public function mount(): void
|
||||
{
|
||||
parent::mount();
|
||||
|
||||
// Definimos las rutas específicas de este componente
|
||||
$this->routes = [
|
||||
'admin.user.show' => route('admin.core.users.show', ['user' => ':id']),
|
||||
'admin.contact.show' => route('admin.contacts.contacts.show', ['contact' => ':id']),
|
||||
'admin.contact.edit' => route('admin.contacts.contacts.edit', ['contact' => ':id']),
|
||||
'admin.contact.delete' => route('admin.contacts.contacts.delete', ['contact' => ':id']),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retorna la vista a renderizar por este componente.
|
||||
*/
|
||||
protected function viewPath(): string
|
||||
{
|
||||
return 'vuexy-contacts::livewire.contacts.index';
|
||||
}
|
||||
}
|
233
Livewire/Contacts/ContactOffCanvasForm.php
Normal file
233
Livewire/Contacts/ContactOffCanvasForm.php
Normal file
@ -0,0 +1,233 @@
|
||||
<?php
|
||||
|
||||
namespace Koneko\VuexyContacts\Livewire\Contacts;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Koneko\VuexyAdmin\Livewire\Form\AbstractFormOffCanvasComponent;
|
||||
use Koneko\VuexyContacts\Services\ContactCatalogService;
|
||||
use Koneko\VuexyStoreManager\Services\StoreCatalogService;
|
||||
use Koneko\VuexyAdmin\Models\User;
|
||||
|
||||
/**
|
||||
* Class ContactOffCanvasForm
|
||||
*
|
||||
* Componente Livewire para gestionar almacenes.
|
||||
* Extiende la clase AbstractFormOffCanvasComponent e implementa validaciones dinámicas,
|
||||
* manejo de formularios, eventos y actualizaciones en tiempo real.
|
||||
*
|
||||
* @package Koneko\VuexyContacts\Livewire\Contacts
|
||||
*/
|
||||
class ContactOffCanvasForm extends AbstractFormOffCanvasComponent
|
||||
{
|
||||
/**
|
||||
* Propiedades del formulario relacionadas con el almacén.
|
||||
*/
|
||||
public $code,
|
||||
$parent_id,
|
||||
$name,
|
||||
$last_name,
|
||||
$email,
|
||||
$company,
|
||||
$rfc,
|
||||
$nombre_fiscal,
|
||||
$tipo_persona,
|
||||
$c_regimen_fiscal,
|
||||
$domicilio_fiscal,
|
||||
$is_partner,
|
||||
$is_employee,
|
||||
$is_prospect,
|
||||
$is_customer,
|
||||
$is_provider,
|
||||
$status;
|
||||
|
||||
/**
|
||||
* Listas de opciones para selects en el formulario.
|
||||
*/
|
||||
public $store_options = [],
|
||||
$work_center_options = [],
|
||||
$manager_options = [];
|
||||
|
||||
/**
|
||||
* Eventos de escucha de Livewire.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $listeners = [
|
||||
'editContacts' => 'loadFormModel',
|
||||
'confirmDeletionContacts' => 'loadFormModelForDeletion',
|
||||
];
|
||||
|
||||
/**
|
||||
* Definición de tipos de datos que se deben castear.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'status' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* Define el modelo Eloquent asociado con el formulario.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function model(): string
|
||||
{
|
||||
return User::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define los campos del formulario.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected function fields(): array
|
||||
{
|
||||
return (new User())->getFillable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Valores por defecto para el formulario.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function defaults(): array
|
||||
{
|
||||
return [
|
||||
//'status' => true,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Campo que se debe enfocar cuando se abra el formulario.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function focusOnOpen(): string
|
||||
{
|
||||
return 'name';
|
||||
}
|
||||
|
||||
/**
|
||||
* Define reglas de validación dinámicas basadas en el modo actual.
|
||||
*
|
||||
* @param string $mode El modo actual del formulario ('create', 'edit', 'delete').
|
||||
* @return array
|
||||
*/
|
||||
protected function dynamicRules(string $mode): array
|
||||
{
|
||||
switch ($mode) {
|
||||
case 'create':
|
||||
case 'edit':
|
||||
return [
|
||||
'store_id' => ['required', 'integer', 'exists:stores,id'],
|
||||
'work_center_id' => ['nullable', 'integer', 'exists:store_work_centers,id'],
|
||||
'code' => ['required', 'string', 'max:16', Rule::unique('contact', 'code')->ignore($this->id)],
|
||||
'name' => ['required', 'string', 'max:96'],
|
||||
'description' => ['nullable', 'string', 'max:1024'],
|
||||
'manager_id' => ['nullable', 'integer', 'exists:users,id'],
|
||||
'tel' => ['nullable', 'regex:/^[0-9+\-\s]+$/', 'max:20'],
|
||||
'tel2' => ['nullable', 'regex:/^[0-9+\-\s]+$/', 'max:20'],
|
||||
'priority' => ['nullable', 'numeric', 'between:0,99'],
|
||||
'status' => ['nullable', 'boolean'],
|
||||
];
|
||||
|
||||
case 'delete':
|
||||
return [
|
||||
'confirmDeletion' => 'accepted', // Asegura que el usuario confirme la eliminación
|
||||
];
|
||||
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
// ===================== VALIDACIONES =====================
|
||||
|
||||
/**
|
||||
* Get custom attributes for validator errors.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
protected function attributes(): array
|
||||
{
|
||||
return [
|
||||
'code' => 'código de almacén',
|
||||
'name' => 'nombre del almacén',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the error messages for the defined validation rules.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
protected function messages(): array
|
||||
{
|
||||
return [
|
||||
'store_id.required' => 'El almacén debe estar asociado a un negocio.',
|
||||
'code.required' => 'El código del almacén es obligatorio.',
|
||||
'code.unique' => 'Este código ya está en uso por otro almacén.',
|
||||
'name.required' => 'El nombre del almacén es obligatorio.',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Carga el formulario con datos del almacén y actualiza las opciones dinámicas.
|
||||
*
|
||||
* @param int $id
|
||||
*/
|
||||
public function loadFormModel($id): void
|
||||
{
|
||||
parent::loadFormModel($id);
|
||||
|
||||
$this->work_center_options = $this->store_id
|
||||
? DB::table('store_work_centers')
|
||||
->where('store_id', $this->store_id)
|
||||
->pluck('name', 'id')
|
||||
->toArray()
|
||||
: [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Carga el formulario para eliminar un almacén, actualizando las opciones necesarias.
|
||||
*
|
||||
* @param int $id
|
||||
*/
|
||||
public function loadFormModelForDeletion($id): void
|
||||
{
|
||||
parent::loadFormModelForDeletion($id);
|
||||
|
||||
$this->work_center_options = DB::table('store_work_centers')
|
||||
->where('store_id', $this->store_id)
|
||||
->pluck('name', 'id')
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Define las opciones de los selectores desplegables.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function options(): array
|
||||
{
|
||||
$storeCatalogService = app(StoreCatalogService::class);
|
||||
$contactCatalogService = app(ContactCatalogService::class);
|
||||
|
||||
return [
|
||||
'store_options' => $storeCatalogService->searchCatalog('stores', '', ['limit' => -1]),
|
||||
'manager_options' => $contactCatalogService->searchCatalog('users', '', ['limit' => -1]),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Ruta de la vista asociada con este formulario.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function viewPath(): string
|
||||
{
|
||||
return 'vuexy-contacts::livewire.contacts.offcanvas-form';
|
||||
}
|
||||
}
|
283
Livewire/Contacts/ContactShow.php
Normal file
283
Livewire/Contacts/ContactShow.php
Normal file
@ -0,0 +1,283 @@
|
||||
<?php
|
||||
|
||||
namespace Koneko\VuexyContacts\Livewire\Contacts;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\Catalog\DropdownList;
|
||||
use Koneko\SatCatalogs\Models\UsoCfdi;
|
||||
use Koneko\SatCatalogs\Models\RegimenFiscal;
|
||||
use Intervention\Image\ImageManager;
|
||||
use Livewire\WithFileUploads;
|
||||
use Livewire\Component;
|
||||
|
||||
class ContactShow extends Component
|
||||
{
|
||||
use WithFileUploads;
|
||||
|
||||
public $image;
|
||||
|
||||
public User $user;
|
||||
public $status_options, $pricelists_options;
|
||||
public $regimen_fiscal_options, $uso_cfdi_options;
|
||||
public $userId,
|
||||
$name,
|
||||
$cargo,
|
||||
$profile_photo,
|
||||
$profile_photo_path,
|
||||
$email,
|
||||
$password,
|
||||
$password_confirmation,
|
||||
$tipo_persona,
|
||||
$rfc,
|
||||
$nombre_fiscal,
|
||||
$c_regimen_fiscal,
|
||||
$domicilio_fiscal,
|
||||
$c_uso_cfdi,
|
||||
$pricelist_id,
|
||||
$enable_credit,
|
||||
$credit_days,
|
||||
$credit_limit,
|
||||
$is_prospect,
|
||||
$is_customer,
|
||||
$is_provider,
|
||||
$is_user,
|
||||
$status;
|
||||
public $deleteUserImage;
|
||||
public $cuentaUsuarioAlert,
|
||||
$accesosAlert,
|
||||
$facturacionElectronicaAlert;
|
||||
|
||||
// Reglas de validación para la cuenta de usuario
|
||||
protected $rulesUser = [
|
||||
'tipo_persona' => 'nullable|integer',
|
||||
'name' => 'required|string|min:3|max:255',
|
||||
'cargo' => 'nullable|string|min:3|max:255',
|
||||
'is_prospect' => 'nullable|boolean',
|
||||
'is_customer' => 'nullable|boolean',
|
||||
'is_provider' => 'nullable|boolean',
|
||||
'is_user' => 'nullable|boolean',
|
||||
'pricelist_id' => 'nullable|integer',
|
||||
'enable_credit' => 'nullable|boolean',
|
||||
'credit_days' => 'nullable|integer',
|
||||
'credit_limit' => 'nullable|numeric|min:0|max:9999999.99|regex:/^\d{1,7}(\.\d{1,2})?$/',
|
||||
'image' => 'nullable|mimes:jpg,png|image|max:20480', // 20MB Max
|
||||
];
|
||||
|
||||
// Reglas de validación para los campos fiscales
|
||||
protected $rulesFacturacion = [
|
||||
'rfc' => 'nullable|string|max:13',
|
||||
'domicilio_fiscal' => [
|
||||
'nullable',
|
||||
'regex:/^[0-9]{5}$/',
|
||||
'exists:sat_codigo_postal,c_codigo_postal'
|
||||
],
|
||||
'nombre_fiscal' => 'nullable|string|max:255',
|
||||
'c_regimen_fiscal' => 'nullable|integer',
|
||||
'c_uso_cfdi' => 'nullable|string',
|
||||
];
|
||||
|
||||
public function mount($userId)
|
||||
{
|
||||
$this->user = User::findOrFail($userId);
|
||||
|
||||
$this->reloadUserData();
|
||||
|
||||
$this->pricelists_options = DropdownList::selectList(DropdownList::POS_PRICELIST);
|
||||
|
||||
$this->status_options = [
|
||||
User::STATUS_ENABLED => User::$statusList[User::STATUS_ENABLED],
|
||||
User::STATUS_DISABLED => User::$statusList[User::STATUS_DISABLED],
|
||||
];
|
||||
|
||||
$this->regimen_fiscal_options = RegimenFiscal::selectList();
|
||||
$this->uso_cfdi_options = UsoCfdi::selectList();
|
||||
}
|
||||
|
||||
|
||||
public function reloadUserData()
|
||||
{
|
||||
$this->tipo_persona = $this->user->tipo_persona;
|
||||
$this->name = $this->user->name;
|
||||
$this->cargo = $this->user->cargo;
|
||||
$this->is_prospect = $this->user->is_prospect? true : false;
|
||||
$this->is_customer = $this->user->is_customer? true : false;
|
||||
$this->is_provider = $this->user->is_provider? true : false;
|
||||
$this->is_user = $this->user->is_user? true : false;
|
||||
$this->pricelist_id = $this->user->pricelist_id;
|
||||
$this->enable_credit = $this->user->enable_credit? true : false;
|
||||
$this->credit_days = $this->user->credit_days;
|
||||
$this->credit_limit = $this->user->credit_limit;
|
||||
$this->profile_photo = $this->user->profile_photo_url;
|
||||
$this->profile_photo_path = $this->user->profile_photo_path;
|
||||
$this->image = null;
|
||||
$this->deleteUserImage = false;
|
||||
|
||||
$this->status = $this->user->status;
|
||||
$this->email = $this->user->email;
|
||||
$this->password = null;
|
||||
$this->password_confirmation = null;
|
||||
|
||||
$this->rfc = $this->user->rfc;
|
||||
$this->domicilio_fiscal = $this->user->domicilio_fiscal;
|
||||
$this->nombre_fiscal = $this->user->nombre_fiscal;
|
||||
$this->c_regimen_fiscal = $this->user->c_regimen_fiscal;
|
||||
$this->c_uso_cfdi = $this->user->c_uso_cfdi;
|
||||
|
||||
$this->cuentaUsuarioAlert = null;
|
||||
$this->accesosAlert = null;
|
||||
$this->facturacionElectronicaAlert = null;
|
||||
}
|
||||
|
||||
|
||||
public function saveCuentaUsuario()
|
||||
{
|
||||
try {
|
||||
// Validar Información de usuario
|
||||
$validatedData = $this->validate($this->rulesUser);
|
||||
|
||||
$validatedData['name'] = trim($validatedData['name']);
|
||||
$validatedData['cargo'] = $validatedData['cargo']? trim($validatedData['cargo']): null;
|
||||
$validatedData['is_prospect'] = $validatedData['is_prospect'] ? 1 : 0;
|
||||
$validatedData['is_customer'] = $validatedData['is_customer'] ? 1 : 0;
|
||||
$validatedData['is_provider'] = $validatedData['is_provider'] ? 1 : 0;
|
||||
$validatedData['is_user'] = $validatedData['is_user'] ? 1 : 0;
|
||||
$validatedData['pricelist_id'] = $validatedData['pricelist_id'] ?: null;
|
||||
$validatedData['enable_credit'] = $validatedData['enable_credit'] ? 1 : 0;
|
||||
$validatedData['credit_days'] = $validatedData['credit_days'] ?: null;
|
||||
$validatedData['credit_limit'] = $validatedData['credit_limit'] ?: null;
|
||||
|
||||
if($this->tipo_persona == User::TIPO_RFC_PUBLICO){
|
||||
$validatedData['cargo'] = null;
|
||||
$validatedData['is_prospect'] = null;
|
||||
$validatedData['is_provider'] = null;
|
||||
$validatedData['is_user'] = null;
|
||||
$validatedData['enable_credit'] = null;
|
||||
$validatedData['credit_days'] = null;
|
||||
$validatedData['credit_limit'] = null;
|
||||
}
|
||||
|
||||
if(!$this->user->is_prospect && !$this->user->is_customer){
|
||||
$validatedData['pricelist_id'] = null;
|
||||
}
|
||||
|
||||
if(!$this->user->is_customer){
|
||||
$validatedData['enable_credit'] = null;
|
||||
$validatedData['credit_days'] = null;
|
||||
$validatedData['credit_limit'] = null;
|
||||
}
|
||||
|
||||
$this->user->update($validatedData);
|
||||
|
||||
|
||||
if($this->deleteUserImage && $this->user->profile_photo_path){
|
||||
$this->user->deleteProfilePhoto();
|
||||
|
||||
// Reiniciar variables después de la eliminación
|
||||
$this->deleteUserImage = false;
|
||||
$this->profile_photo_path = null;
|
||||
$this->profile_photo = $this->user->profile_photo_url;
|
||||
|
||||
}else if ($this->image) {
|
||||
$image = ImageManager::imagick()->read($this->image->getRealPath());
|
||||
$image = $image->scale(520, 520);
|
||||
|
||||
$imageName = $this->image->hashName(); // Genera un nombre único
|
||||
|
||||
$image->save(storage_path('app/public/profile-photos/' . $imageName));
|
||||
|
||||
$this->user->deleteProfilePhoto();
|
||||
|
||||
$this->profile_photo_path = $this->user->profile_photo_path = 'profile-photos/' . $imageName;
|
||||
$this->profile_photo = $this->user->profile_photo_url;
|
||||
$this->user->save();
|
||||
|
||||
unlink($this->image->getRealPath());
|
||||
|
||||
$this->reset('image');
|
||||
}
|
||||
|
||||
// Puedes también devolver un mensaje de éxito si lo deseas
|
||||
$this->setAlert('Se guardó los cambios exitosamente.', 'cuentaUsuarioAlert');
|
||||
|
||||
} catch (\Illuminate\Validation\ValidationException $e) {
|
||||
// Si hay errores de validación, los puedes capturar y manejar aquí
|
||||
$this->setAlert('Ocurrieron errores en la validación: ' . $e->validator->errors()->first(), 'cuentaUsuarioAlert', 'danger');
|
||||
}
|
||||
}
|
||||
|
||||
public function saveAccesos()
|
||||
{
|
||||
try {
|
||||
$validatedData = $this->validate([
|
||||
'status' => 'integer',
|
||||
'email' => ['required', 'email', 'unique:users,email,' . $this->user->id],
|
||||
'password' => ['nullable', 'string', 'min:6', 'max:32', 'confirmed'], // La regla 'confirmed' valida que ambas contraseñas coincidan
|
||||
], [
|
||||
'email.required' => 'El correo electrónico es obligatorio.',
|
||||
'email.email' => 'Debes ingresar un correo electrónico válido.',
|
||||
'email.unique' => 'Este correo ya está en uso.',
|
||||
'password.min' => 'La contraseña debe tener al menos 5 caracteres.',
|
||||
'password.max' => 'La contraseña no puede tener más de 32 caracteres.',
|
||||
'password.confirmed' => 'Las contraseñas no coinciden.',
|
||||
]);
|
||||
|
||||
// Si la validación es exitosa, continuar con el procesamiento
|
||||
$validatedData['email'] = trim($this->email);
|
||||
|
||||
if ($this->password)
|
||||
$validatedData['password'] = bcrypt($this->password);
|
||||
|
||||
else
|
||||
unset($validatedData['password']);
|
||||
|
||||
$this->user->update($validatedData);
|
||||
|
||||
$this->password = null;
|
||||
$this->password_confirmation = null;
|
||||
|
||||
// Puedes también devolver un mensaje de éxito si lo deseas
|
||||
$this->setAlert('Se guardó los cambios exitosamente.', 'accesosAlert');
|
||||
|
||||
} catch (\Illuminate\Validation\ValidationException $e) {
|
||||
// Si hay errores de validación, los puedes capturar y manejar aquí
|
||||
$this->setAlert('Ocurrieron errores en la validación: ' . $e->validator->errors()->first(), 'accesosAlert', 'danger');
|
||||
}
|
||||
}
|
||||
|
||||
public function saveFacturacionElectronica()
|
||||
{
|
||||
try {
|
||||
// Validar Información fiscal
|
||||
$validatedData = $this->validate($this->rulesFacturacion);
|
||||
|
||||
$validatedData['rfc'] = strtoupper(trim($validatedData['rfc'])) ?: null;
|
||||
$validatedData['domicilio_fiscal'] = $validatedData['domicilio_fiscal'] ?: null;
|
||||
$validatedData['nombre_fiscal'] = strtoupper(trim($validatedData['nombre_fiscal'])) ?: null;
|
||||
$validatedData['c_regimen_fiscal'] = $validatedData['c_regimen_fiscal'] ?: null;
|
||||
$validatedData['c_uso_cfdi'] = $validatedData['c_uso_cfdi'] ?: null;
|
||||
|
||||
$this->user->update($validatedData);
|
||||
|
||||
// Puedes también devolver un mensaje de éxito si lo deseas
|
||||
$this->setAlert('Se guardó los cambios exitosamente.', 'facturacionElectronicaAlert');
|
||||
|
||||
} catch (\Illuminate\Validation\ValidationException $e) {
|
||||
// Si hay errores de validación, los puedes capturar y manejar aquí
|
||||
$this->setAlert('Ocurrieron errores en la validación: ' . $e->validator->errors()->first(), 'facturacionElectronicaAlert', 'danger');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function setAlert($message, $alertName, $type = 'success')
|
||||
{
|
||||
$this->$alertName = [
|
||||
'message' => $message,
|
||||
'type' => $type
|
||||
];
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.admin.crm.contact-view');
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user