Para la tabla donde se guardara la información corremos el siguiente código SQL en PHPMYADMIN en nuestra base de datos, en publicaciones posteriores les dejare los archivos de migración para que no tengan la necesidad de correr archivos SQL y sirva para diferentes motores de base de datos
-- phpMyAdmin SQL Dump
-- version 5.0.4
-- https://www.phpmyadmin.net/
--
-- Servidor: 127.0.0.1
-- Tiempo de generación: 18-04-2023 a las 00:56:17
-- Versión del servidor: 10.4.17-MariaDB
-- Versión de PHP: 7.4.15
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Base de datos: `wheelsoft`
--
-- --------------------------------------------------------
--
-- Estructura de tabla para la tabla `mailsettings`
--
CREATE TABLE `mailsettings` (
`id` int(11) NOT NULL,
`email` varchar(512) DEFAULT NULL,
`host` varchar(128) DEFAULT NULL,
`smtpDebug` varchar(16) DEFAULT NULL,
`SMTPAuth` varchar(16) DEFAULT NULL,
`port` varchar(16) DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`deleted_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
`smptSecurity` varchar(64) DEFAULT NULL,
`pass` varchar(128) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--
-- Volcado de datos para la tabla `mailsettings`
--
INSERT INTO `mailsettings` (`id`, `email`, `host`, `smtpDebug`, `SMTPAuth`, `port`, `created_at`, `deleted_at`, `updated_at`, `smptSecurity`, `pass`) VALUES
(1, 'mail@domain.com', 'mail.host5.com', '1', '1', '587', NULL, NULL, NULL, 'tls', 'password');
--
-- Índices para tablas volcadas
--
--
-- Indices de la tabla `mailsettings`
--
ALTER TABLE `mailsettings`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT de las tablas volcadas
--
--
-- AUTO_INCREMENT de la tabla `mailsettings`
--
ALTER TABLE `mailsettings`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
Creamos el archivo app/controllers/SettingsMailController.php con el siguiente contenido
<?php
namespace julio101290\boilerplate\Controllers\Users;
namespace App\Controllers;
use CodeIgniter\API\ResponseTrait;
use CodeIgniter\Controller;
use App\Models\SettingsMailModel;
use App\Models\LogModel;
use julio101290\boilerplate\Controllers\BaseController;
use julio101290\boilerplate\Entities\Collection;
use julio101290\boilerplate\Models\GroupModel;
use CodeIgniter\Config\Services;
use App\Models\RegisterModel;
use App\Controllers\RegisterController;
use PHPMailer\PHPMailer;
/**
* Class UserController.
*/
class SettingsMailController extends BaseController
{
use ResponseTrait;
/** @var \agungsugiarto\boilerplate\Models\GroupModel */
protected $group;
protected $settingsMail;
protected $log;
protected $register;
protected $registerController;
protected $custumer;
/** @var \agungsugiarto\boilerplate\Models\UserModel */
protected $users;
public function __construct()
{
$this->group = new GroupModel();
$this->log = new LogModel();
$this->settingsMail = new SettingsMailModel();
$autorize = $this->authorize = Services::authorization();
helper('menu');
}
public function index()
{
$datos = $this->settingsMail->where("id", 1)->first();
$data["title"] = "Correo Electronicos";
$data["subtitle"] = "Configuraciones de Correo Electronico";
$data["data"] = $datos;
return view('mailSettings', $data);
}
/**
public function sendMailPDF($uuid)
{
//DATOS CORREO
$datos = $this->settingsMail->where("id", 1)->first();
//DATOS REGISTRO
$register = $this->register->select("*")->where("uuid", $uuid)->first();
$custumer = $this->custumer->select("*")->where("id", $register["custumer"])->first();
$mailsTarjets = "";
$correo = $datos["email"];
$SMTPDebug = $datos["smtpDebug"];
$host = $datos["host"];
if ($datos["SMTPAuth"] == 1) {
$SMTPAuth = true;
} else {
$SMTPAuth = false;
}
$puerto = $datos["port"];
$clave = $datos["pass"];
$SMTPSeguridad = $datos["smptSecurity"];
// Load Composer's autoloader
// Instantiation and passing `true` enables exceptions
$mail = new PHPMailer\PHPMailer();
try {
//Server settings
$mail->SMTPDebug = $SMTPDebug; // Enable verbose debug output
$mail->isSMTP(); // Send using SMTP
$mail->Host = $host; // Set the SMTP server to send through
$mail->SMTPAuth = $SMTPAuth; // Enable SMTP authentication
$mail->Username = $correo; // SMTP username
$mail->Password = $clave; // SMTP password
$mail->SMTPSecure = $SMTPSeguridad; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` also accepted
$mail->Port = $puerto;
$nombreEmpresa = "";
// TCP port to connect to
//Recipients
$mail->setFrom($correo, $nombreEmpresa);
if ($custumer["email1"] != "") {
try {
$mailAddress = $mail->addAddress($custumer["email1"], '');
if (!$mailAddress) {
echo "Error con el correo Electronico";
return;
}
} catch (Exception $ex) {
echo $ex->getMessage();
}
}
if ($custumer["email2"] != "") {
try {
$mailAddress = $mail->addAddress($custumer["email2"], '');
if (!$mailAddress) {
echo "Error con el correo Electronico";
return;
}
} catch (Exception $ex) {
echo $ex->getMessage();
}
}
if ($custumer["email3"] != "") {
try {
$mailAddress = $mail->addAddress($custumer["email3"], '');
if (!$mailAddress) {
echo "Error con el correo Electronico";
return;
}
if (!$mailAddress) {
echo "Error con el correo Electronico";
return;
}
} catch (Exception $ex) {
echo $ex->getMessage();
}
}
if ($custumer["email4"] != "") {
try {
$mailAddress = $mail->addAddress($custumer["email4"], '');
if (!$mailAddress) {
echo "Error con el correo Electronico";
return;
}
} catch (Exception $ex) {
echo $ex->getMessage();
}
}
if ($custumer["email5"] != "") {
try {
$mailAddress = $mail->addAddress($custumer["email5"], '');
if (!$mailAddress) {
echo "Error con el correo Electronico";
return;
}
} catch (Exception $ex) {
echo $ex->getMessage();
}
}
// Add a recipient
//$mail->addReplyTo('info@example.com', 'Information');
//mail->addCC('cc@example.com');
//$mail->addBCC('bcc@example.com');
// Attachments
$attachment = $this->registerController->report($uuid, 1);
$mail->AddStringAttachment($attachment, 'registro' . $register["codeCustumer"] . '.pdf', 'base64', 'application/pdf');
// Add attachments
//$mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name
// Content
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = "Envio de Registro";
$mail->Body = "Adjuntamos el registro de verificación de neumaticos";
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
try {
$send = $mail->send();
} catch (Exception $ex) {
echo $ex->getMessage();
return;
}
if ($send) {
echo 'Correo Enviado Correctamente';
} else {
echo 'Error al enviar el correo';
}
} catch (Exception $e) {
echo "Error al enviar el correo: {$e->ErrorInfo}";
}
}
*/
public function guardar()
{
helper('auth');
$userName = user()->username;
$idUser = user()->id;
//GUARDA CONFIGURACIONES
$this->settingsMail->update(1, $_POST);
// return redirect()->to("/admin/hospital");
return redirect()->back()->with('sweet-success', 'Actualizado Correctamente');
// return redirect()->back()->with('sweet-success','Guardado Correctamente');
}
}
Creamos el archivo app/views/mailSettings.php con el siguiente contenido
Ya tenemos nuestros menús creados ahora sigue meter los catálogos de configuración, el primero seria el catalogo de empresas en el cual se van a capturar los datos de la empresa como nombre, razón social, domicilio logo y datos de facturación del SAT, estos datos saldrán en las impresiones de cotizaciones, ventas y reportes.
Primero para hacer los datatables mas fácil instalamos el paquete de hermawan/codeigniter4-datatables esto solo lo haremos una vez y nos servira para los demás catálogos para instalarlo corremos el siguiente código en nuestro proyecto
composer require hermawan/codeigniter4-datatables
Luego en app/config/autoload.php en la variable $psr4 agregamos el namespace
public $psr4 = [
APP_NAMESPACE => APPPATH, // For custom app namespace
'Config' => APPPATH . 'Config',
'Hermawan\DataTables' => APPPATH .'ThirdParty/codeigniter4-datatables/src', // <-- namespace for this library
];
Ahora para obtener todos los catálogos del SAT instalamos el paquete de phpcfdi/sat-catalogos
composer require phpcfdi/sat-catalogos
El archivo de app/controller/BaseController.php quedaria de la siguiente forma para poder utilizar los catalogos del SAT en todo momento.
<?php
namespace App\Controllers;
use CodeIgniter\Controller;
use CodeIgniter\HTTP\CLIRequest;
use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Psr\Log\LoggerInterface;
use PhpCfdi\SatCatalogos\Factory;
/**
* Class BaseController
*
* BaseController provides a convenient place for loading components
* and performing functions that are needed by all your controllers.
* Extend this class in any new controllers:
* class Home extends BaseController
*
* For security be sure to declare any new methods as protected or private.
*/
abstract class BaseController extends Controller
{
/**
* Instance of the main Request object.
*
* @var CLIRequest|IncomingRequest
*/
protected $request;
/**
* An array of helpers to be loaded automatically upon
* class instantiation. These helpers will be available
* to all other controllers that extend BaseController.
*
* @var array
*/
protected $helpers = [];
public $catalogosSAT;
/**
* Constructor.
*/
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
{
// Do Not Edit This Line
parent::initController($request, $response, $logger);
// Preload any models, libraries, etc, here.
// E.g.: $this->session = \Config\Services::session();
$dsn = "sqlite:".ROOTPATH."writable\database\catalogossat.db";
$factory = new Factory();
$satCatalogos = $factory->catalogosFromDsn($dsn);
$this->catalogosSAT = $satCatalogos;
}
}
Si se dan cuenta nosotros tenemos un archivo en writable/database/catalogossat.db para generar el archivo de base de datos SQLITE con los datos que proporciona el SAT tenemos el siguiente script en PHP, cortesía de nuestro amigo Rene
En los archivos de lenguaje para ingles creamos el archivo app/Language/en/empresas.php con el siguiente contenido
<?php
$empresas["logDescription"] = "The companie was saved with the following data:";
$empresas["logUpdate"] = "The companie was updated with the following data:";
$empresas["logDeleted"] = "The companie was deleted with the following data:";
$empresas["msg_delete"] = "The companie was deleted correctly:";
$empresas["add"] = "Add companie";
$empresas["edit"] = "Edit companie";
$empresas["createEdit"] = "Create / Edith";
$empresas["title"] = "companie management";
$empresas["subtitle"] = "companie list";
$empresas["fields"]["nombre"] = "Name";
$empresas["fields"]["direccion"] = "direction";
$empresas["fields"]["rfc"] = "RFC";
$empresas["fields"]["logo"] = "logo";
$empresas["fields"]["certificado"] = "certificate";
$empresas["fields"]["archivoKey"] = "KeyFile";
$empresas["fields"]["contraCertificado"] = "Password Certificate";
$empresas["fields"]["regimenFiscal"] = "Tax Regime";
$empresas["fields"]["regimenFiscalOpcion"] = "Select tax regime";
$empresas["fields"]["razonSocial "] = "Business name";
$empresas["fields"]["codigoPostal "] = "Postal Code ";
$empresas["fields"]["CURP"] = "CURP";
$empresas["fields"]["Created_at"] = "Created At";
$empresas["fields"]["Update_At"] = "Update At";
$empresas["msg"]["msg_save"] = "The companie has been correctly saved.";
$empresas["msg"]["msg_insert"] = "The companie has been correctly added.";
$empresas["msg"]["msg_update"] = "The companie has been correctly modified.";
$empresas["msg"]["msg_delete"] = "The companie has been correctly deleted.";
$empresas["msg"]["msg_get"] = "The companie has been successfully get.";
$empresas["msg"]["msg_get_fail"] = "The vehicle not found or already deleted.";
$empresas["imagenesFormato"] = "The image must be in PNG format!";
$empresas["imagenesPeso"] = "The image must not be larger than 2MB!";
$empresas["imagenesPesoMaximo"] = "Maximum weight of the photo 1MB";
$empresas["certExtensionIncorrect"] = "Extensión certificate incorrect";
$empresas["keyFileExtensionIncorrect"] = "Extensión key file incorrect";
$empresas["pngFileExtensionIncorrect"] = "This image not is PNG";
return $empresas;
En los archivos de lenguaje para ingles creamos el archivo app/Language/es/empresas.php con el siguiente contenido
<?php
$empresas["logDescription"] = "El Empresa ha sido guardado con los siguientes datos:";
$empresas["logUpdate"] = "EL Empresa ha sido actualizado con los siguientes datos";
$empresas["logDeleted"] = "El Empresa ha sido eliminado con los siguientes datos:";
$empresas["add"] = "Agregar Empresa";
$empresas["edit"] = "Editar Empresa";
$empresas["createEdit"] = "Crear / Editar";
$empresas["title"] = "Administración de Empresas";
$empresas["subtitle"] = "Lista de Empresas";
$empresas["fields"]["nombre"] = "Nombre";
$empresas["fields"]["direccion"] = "Direccion";
$empresas["fields"]["rfc"] = "RFC";
$empresas["fields"]["logo"] = "Logo";
$empresas["fields"]["certificado"] = "Certificado";
$empresas["fields"]["archivoKey"] = "Archivo Key";
$empresas["fields"]["telefono"] = "Telefono";
$empresas["fields"]["contraCertificado"] = "Contra Certificado";
$empresas["fields"]["regimenFiscal"] = "Regimen Fiscal";
$empresas["fields"]["regimenFiscalOpcion"] = "Seleccionar regimen fiscal";
$empresas["fields"]["razonSocial"] = "Razon Social";
$empresas["fields"]["codigoPostal"] = "Código Postal";
$empresas["fields"]["CURP"] = "CURP";
$empresas["fields"]["correoElectronico"] = "Correo Electronico";
$empresas["fields"]["acciones"] = "Acciones";
$empresas["msg"]["msg_save"] = "La Empresa ha sido correctamente guardada.";
$empresas["msg"]["msg_insert"] = "La Empresa ha sido correctamente agregado.";
$empresas["msg"]["msg_update"] = "La Empresa ha sido correctamente actualizado.";
$empresas["msg"]["msg_delete"] = "La Empresa ha sido correctamente eliminado.";
$empresas["msg"]["msg_get"] = "La Empresa ha sido correctamente obtenido.";
$empresas["msg"]["msg_get_fail"] = "No se encontro Empresa o fue eliminado.";
// Validations
$empresas["imagenesFormato"] = "¡La imagen debe estar en formato PNG!";
$empresas["imagenesPeso"] = "¡La imagen no debe pesar más de 2MB!";
$empresas["imagenesPesoMaximo"] = "Peso máximo de la foto 1MB";
$empresas["certExtensionIncorrect"] = "Extensión del certificado incorrecto";
$empresas["keyFileExtensionIncorrect"] = "Extensión del archivo key incorrecto";
$empresas["pngFileExtensionIncorrect"] = "Solo se permiten imagenes con formato png";
return $empresas;
Creamos el siguiente directorio para las imagenes, public/images/logo
Creamos el archivo app/databe/migrations/2023-02-14001801_Empresas.php con el siguiente contenido, este nos servirá para crear la tabla
Ya tenemos la base del proyecto, ahora lo que sigue es darle forma creando los menús
Realmente aquí no hay nada complejo, el menú soporta 2 niveles, podemos escoger nuestro icono de font awesome le pones la ruta y que roles tendrán acceso a ese nivel, para acomodar el menú solo basta con arrastrar y soltar los items
Creamos nuestra base de datos en phpmyadmin con el nombre ci4jcpos
CREATE SCHEMA ci4jcpos DEFAULT CHARACTER SET utf8 COLLATE utf8_spanish2_ci
Ahora instalamos la plantilla boilerplate el cual nos instalara la plantilla adminlte3 con el administrador de usuario auth, lo instalamos corriendo el siguiente comando dentro del proyecto
Ahora siguiente las instrucciones del paquete https://packagist.org/packages/julio101290/boilerplate corremos el comando migrate para auth
php spark auth:publish
Publish Migration? [y, n]: y
created: Database/Migrations/2017-11-20-223112_create_auth_tables.php
Remember to run `spark migrate -all` to migrate the database.
Publish Models? [y, n]: n
Publish Entities? [y, n]: n
Publish Controller? [y, n]: n
Publish Views? [y, n]: n
Publish Filters? [y, n]: n
Publish Config file? [y, n]: y
created: Config/Auth.php
Publish Language file? [y, n]: n
En app/config/auth.php modifcamos la matriz/arreglo de $views y la dejamos asi
En app/controller/home.php lo dejamos así para que entre directamente al administrador
<?php
namespace App\Controllers;
class Home extends BaseController
{
public function index()
{
return redirect()->to("/admin");
}
}
En app/config/constants.php al final del archivo le agregamos la siguiente constante para que nos permita debugear, una vez que este en producción se tiene que quitar
define("ENVIRONMENT","development");
En app/config/app.php le quita a la variable $indexPage el valor dejandolo en blanco, la variable defaultLocale y supportedLocales la dejamos con el valor “es”
public string $indexPage = '';
public string $defaultLocale = 'es';
public array $supportedLocales = ['en'];
En el archivo app/config/boilerplate.php asignamos el nombre de la app y en $i18n que es para el lenguaje de los datatables lo dejamos como Spanish
Y listo ya tenemos nuestro login y adminlte3 listo para agregarle los módulos
JCPOS es un sistema de punto de venta (POS) de código abierto desarrollado en PHP. Recientemente, JCPOS se ha migrado a CodeIgniter 4, lo que ha mejorado significativamente su rendimiento y escalabilidad. En este artículo, exploraremos los detalles de la migración de JCPOS a CodeIgniter 4 y sus beneficios.
Antes de profundizar en la migración de JCPOS a CodeIgniter 4, es importante comprender qué es CodeIgniter y por qué es una opción popular para desarrolladores de PHP.
CodeIgniter es un framework PHP de código abierto que se utiliza para desarrollar aplicaciones web dinámicas y sitios web. Es popular debido a su facilidad de uso, velocidad y seguridad. Además, CodeIgniter tiene una gran comunidad de desarrolladores que proporciona soporte y actualizaciones regulares.
La migración de JCPOS a CodeIgniter 4 implica actualizar el código de JCPOS para que sea compatible con la última versión del framework. CodeIgniter 4 presenta varias mejoras y cambios significativos en comparación con su versión anterior, CodeIgniter 3. Algunas de estas mejoras incluyen:
Mayor rendimiento y velocidad gracias a la utilización de características avanzadas de PHP 7
Soporte mejorado para la creación de APIs RESTful
Mejoras en la seguridad y en la gestión de sesiones
Uso de clases y métodos modernos para mejorar la legibilidad y mantenibilidad del código
Flexibilidad y escalabilidad mejoradas gracias a su arquitectura modular
Para migrar JCPOS a CodeIgniter 4, los desarrolladores tuvieron que actualizar el código de JCPOS para utilizar las nuevas características y métodos de CodeIgniter 4. Esto incluyó cambios en la estructura del directorio, en la configuración del archivo y en el uso de nuevos métodos y características de CodeIgniter 4.
Una vez completada la migración, JCPOS obtuvo varios beneficios significativos. En primer lugar, el rendimiento y la velocidad de JCPOS se mejoraron considerablemente gracias a la utilización de características avanzadas de PHP 7 y a la optimización de la arquitectura de CodeIgniter 4. Esto significa que el sistema puede manejar más transacciones y usuarios simultáneamente, lo que es especialmente importante en entornos de punto de venta de alta demanda.
Además, la migración a CodeIgniter 4 proporcionó una mayor flexibilidad y escalabilidad a JCPOS. La arquitectura modular de CodeIgniter 4 permite que los desarrolladores de JCPOS agreguen fácilmente nuevas funcionalidades y características al sistema sin afectar negativamente al rendimiento o la estabilidad. Esto significa que JCPOS puede adaptarse y crecer para satisfacer las necesidades cambiantes de sus usuarios.
En conclusión, la migración de JCPOS a CodeIgniter 4 ha mejorado significativamente el rendimiento, la escalabilidad y la flexibilidad del sistema. Los desarrolladores de JCPOS han aprovechado las características avanzadas y la arquitectura modular de CodeIgniter 4 para optimizar el sistema y garantizar su compatibilidad con las últimas tecnologías y tendencias en el desarrollo web.
JCPOS: Una solución de punto de venta en constante evolución
En una reciente transmisión en vivo, el equipo de desarrollo detrás de JCPOS discutió los últimos cambios y mejoras en su solución de punto de venta. JCPOS es un sistema de punto de venta que ha estado en desarrollo desde el 2020, y ha evolucionado constantemente desde entonces para satisfacer las necesidades de sus usuarios.
Uno de los cambios más notables que el equipo ha realizado es el cambio de nombre de JC post a JCPOS. Esto se hizo para mantener la coherencia en el nombre a lo largo de los años, y evitar confusiones al cambiar el nombre cada año.
Otro de los cambios que se discutió en la transmisión fue la reciente publicación del repositorio de JCPOS en Github. Ahora está disponible para que cualquier persona interesada lo pueda descargar y explorar el código fuente. Además, se hizo hincapié en que los usuarios pueden contribuir al proyecto si encuentran algún problema o tienen alguna sugerencia.
El equipo también habló de algunos cambios específicos que han realizado en JCPOS, como la corrección de un problema en la bitácora que no estaba ordenando los botones de manera correcta. También se discutió la implementación de descuentos en las ventas, para asegurarse de que funcionen correctamente. Además, se está trabajando en la corrección de detalles menores, como la ordenación de la lista de ventas.
El equipo de JCPOS también habló sobre su intención de usar Composer para gestionar las dependencias del proyecto, lo que les permitirá mantenerse actualizados con las últimas versiones de las librerías que utilizan. También se mencionó la adición de impuestos a los productos, lo que permitirá la implementación de facturación electrónica en el futuro.
Finalmente, el equipo mencionó a sus patrocinadores y clientes, agradeciendo su apoyo y mencionando que los nombres de los patrocinadores se agregarán al repositorio en el futuro. También se proporcionó información sobre cómo patrocinar el proyecto.
En resumen, JCPOS es un proyecto de punto de venta en constante evolución. El equipo detrás de JCPOS está trabajando constantemente para mejorar la solución, escuchar las necesidades de los usuarios y mantenerse actualizado con las últimas tecnologías y herramientas de desarrollo. Si estás interesado en probar JCPOS o contribuir al proyecto, ¡asegúrate de visitar su repositorio en Github!
Nuevo cambio en el cual se podrán mover cn el mouse los modales
Modal Draggable se refiere a la capacidad de arrastrar y mover un cuadro de diálogo modal (o ventana emergente) en una interfaz de usuario. Una ventana modal es un tipo de ventana emergente que requiere que el usuario realice una acción antes de poder interactuar con el resto de la aplicación o sitio web. A menudo se utilizan para solicitar información importante o para mostrar mensajes críticos al usuario.
La función Modal Draggable permite que el usuario arrastre la ventana modal a cualquier lugar en la pantalla para evitar que obstruya información importante o para hacer más fácil su uso en pantallas pequeñas. Esta función se implementa en algunos frameworks y librerías de JavaScript para la creación de interfaces de usuario, como Bootstrap, Materialize y jQuery UI.
Para activarlo en modales ya hechos solo basta con poner el siguiente código, ejemplo
Al momento de hacer la factura en su versión 4.0 hay clientes que en su razón social tienen la tilde invertida ` en la constancia de situación fiscal y aunque se copie tal cual no funciona y al timbrar la factura sale error de que no coincide el RFC con el nombre del receptor
La solucion que funciono para nosotros fue cambiar la tilde invertida por comilla simple ‘
Usamos cookies en nuestro sitio web para brindarle la experiencia más relevante recordando sus preferencias y visitas repetidas. Al hacer clic en "Aceptar", acepta el uso de TODAS las cookies.
This website uses cookies to improve your experience while you navigate through the website. Out of these cookies, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may have an effect on your browsing experience.
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.
Any cookies that may not be particularly necessary for the website to function and is used specifically to collect user personal data via analytics, ads, other embedded contents are termed as non-necessary cookies. It is mandatory to procure user consent prior to running these cookies on your website.