Sistema de ventas con Laravel, Bootstrap y MySQL – Open source

Hoy voy a presentar un sistema que acabo de hacer con Laravel. Se trata de un sistema de ventas, punto de venta, PDV o como le llames, que sirve para llevar el seguimiento de los productos que se venden, el registro de ventas, etcétera.

Es un sistema totalmente gratuito y además open source; lo que quiere decir que puedes usarlo sin costo, y modificarlo a tus necesidades o personalizarlo. Entre sus opciones encontramos:

  • Utiliza Laravel en su última versión (a la fecha de escribir esto)
  • Bootstrap es usado para los estilos
  • Iconos de FontAwesome
  • Sistema totalmente responsivo, es decir, funciona en móviles, tabletas y computadoras
  • Control de inventario con precio de venta, precio de compra, utilidad, existencia, etcétera
  • Opción para realizar venta, agregando productos
  • Comprobación de existencia de inventario al vender
  • Resta de existencia al vender
  • Impresión de tickets de venta en impresora térmica
  • Reporte de ventas
  • Inicio de sesión y registro de usuarios
  • Gestión de usuarios (novedad)
  • Registro de clientes (novedad)
  • Ticket que incluye el nombre del cliente (novedad)

Ahora veamos cómo está hecho, en dónde obtenerlo, etcétera.

Diseño del sistema de ventas

Laravel utiliza Blade para las plantillas, así que he utilizado su sistema de layouts y herencia. Defino la plantilla maestra que se basa en un starter template de Bootstrap 4:

De este modo, ahora solo tengo que sobrescribir el contenido. De la plantilla puedes ver que muestro un menú de navegación y que oculto algunos elementos en caso de que el usuario no esté logueado.

Rutas

Tenemos varias rutas configuradas para vender, ver ventas, imprimir tickets, ver productos, etcétera. Todas ellas están protegidas con el middleware auth, por lo que no se permite acceder a ellas si no se ha iniciado sesión.

El archivo de web.php se ve así:

En ella se registran los controladores que son resources, además de otras rutas como el login, el registro, agregar producto al carrito de compras, etcétera.

Login al sistema

He usado la autenticación por defecto de Laravel, así que para usar el sistema de ventas hay que iniciar sesión:

Iniciar sesión en sistema de ventas Laravel y Bootstrap

De igual modo se provee una pantalla para registrarse, que se puede deshabilitar al gusto.

Pantalla de bienvenida

Al iniciar sesión se dirige al índice o pantalla de bienvenida. En el mismo se muestran accesos directos a los apartados del sistema:

Bienvenida al sistema de ventas – Índice con opciones para vender, ver productos o ventas

El código del inicio es el siguiente:

Utilizo tarjetas de Bootstrap. Y a partir de eso se puede navegar a los siguientes apartados.

Los productos

Tenemos la gestión de productos con Laravel en donde se registra la existencia, el precio de compra, el precio de venta, el código de barras y la descripción del artículo. La definición del modelo y  sus fillables se ve así:

El formulario de registro de producto se ve así:

Es un simple formulario que llevará al siguiente controlador o controller de productos, que a su vez es un resource:

El formulario de editar es muy parecido al de insertar. Para mostrar los productos se utiliza una tabla responsiva de Bootstrap además de usar @foreach de Blade:

Con el siguiente resultado:

Listado de productos con existencia y utilidad

Recuerda que el código completo lo puedes ver en GitHub; al final dejaré el enlace. A partir de aquí no explicaré a fondo el código repetitivo, pues ya lo hice con los productos. Veamos las cosas que son más importantes.

Realizar ventas

Interfaz para vender

En la interfaz tenemos un campo que sirve para escanear el código de barras, ya sea que se use un lector o que se escriba el código y se presione la tecla Enter.

Cuando hay productos, se muestra la lista de los mismos así como algunos botones para cancelar la venta, terminar la venta o quitar un producto de la lista de venta.

Realizar venta – Agregar productos al carrito por código de barras

Además de eso, se muestra el total de la venta formateado como moneda.

Lista de productos que se venden

El carrito de compras o lista de productos para la venta se guarda en la sesión como un arreglo, de este modo no se pierde aunque el usuario refresque la página o navegue a otro lugar; permitiendo así un mejor control.

He implementado un simple carrito de compras con un arreglo, las funciones que lo manejan son:

Maneja varias opciones. Por ejemplo, cuando se agrega un producto se envía el código de barras y se busca un producto por ese código; después se hacen dos verificaciones:

  1. Que haya existencia del producto
  2. Que al agregar el producto a la lista de venta no se vaya a quedar sin existencia

Por poner un ejemplo, si se quiere vender más de lo que existe, se muestra una advertencia:

Comprobar existencia de productos antes de vender
Comprobar existencia de productos antes de vender

Además, si el producto ya existe, no se agrega, sino que se aumenta su cantidad.

Terminar venta

Al terminar la venta se involucran varias cosas. Comenzando con que tenemos un modelo distinto llamado ProductoVendido que se encarga de encapsular cómo se comporta un producto vendido.

Lo he separado de este modo porque el precio de venta no siempre será el mismo; es decir, hoy puedes vender un producto a 100 pesos que mañana costará 112 por ejemplo; entonces se debe guardar el precio de venta en el que se vendió.

Además de eso, el producto lleva una relación con la tabla Ventas, mismas que tienen una fecha de creación (los timestamps) y un id:

Aquí hay un punto interesante, pues tenemos una relación entre productos y ventas, usando las relaciones que Laravel provee. Finalmente, para terminar la venta se hace lo siguiente:

Y así es como se guardan los productos vendidos junto con la venta y la fecha de creación. Más tarde vamos a usar esto para ver el reporte de ventas, el detalle de una venta y para imprimir tickets.

Reporte de ventas

El reporte de ventas muestra el total de la venta, la fecha de venta y botones para ver los detalles, imprimir el ticket o eliminar la venta. La consulta para listar las ventas con el total es:

Es un poco compleja y me llevó algo de tiempo, sobre todo porque quise hacerla con el Query builder en lugar de hacer la consulta raw. Esas ventas son mostradas en una tabla, así:

Reporte de ventas con total y fecha

Cuando se muestra el detalle de la venta utilizamos el método show del controlador, que muestra una venta. Ahí, gracias a la relación que definimos anteriormente podemos obtener la tabla de productos y dibujar el detalle como el total:

Detalle de venta con opción para imprimir ticket

Por cierto, la vista se ve así:

Eso es lo que se encarga de dibujar la tabla, colocar los enlaces, etcétera.

Ticket de venta

Nota: si quieres saber cómo configurar tu impresora mira el post sobre cómo imprimir un ticket en PHP.

Veamos cómo es que se imprime el ticket en una impresora térmica. Lo que hay que hacer es instalar la librería de mike42; me basé en mi tutorial para imprimir en impresora térmica con Laravel.

La función del controlador es la siguiente:

Comenzamos obteniendo la venta por ID, misma variable que es pasada a través de la URL. El nombre de la impresora está en el archivo .env, así se puede configurar de manera sencilla.

Imprimimos el encabezado, la fecha de la venta y luego recorremos los productos de la venta (previamente registrados en la base de datos). Por cada uno dibujamos la cantidad, la descripción y el subtotal.

Al pie del ticket imprimimos el total y un mensaje de agradecimiento. Más tarde se redirecciona a la página de donde se venía y si todo está bien, el ticket se debería ver parecido al de la siguiente imagen:

Ticket de venta impreso desde PDV con Laravel

Obviamente el ticket cambiará dependiendo de la lista de productos, y es totalmente dinámico.

Sistema de ventas responsivo

Quiero mostrar que este sistema se adapta a cualquier tamaño de pantalla. Por ejemplo, en un teléfono móvil se ve así:

Sistema de ventas responsivo – Mostrado en iPhone

Por lo tanto puedes usarlo en una red de área local o subirlo a un hosting; puedes visitarlo desde cualquier lugar.

Descargar software y ver código fuente

El código fuente del programa está en mi repositorio de GitHub. Si quieres descargar el código haz click en Clone or download > Download ZIP dentro del repositorio. Para usarlo configura el archivo env, instala las dependencias con composer y realiza las migraciones pertinentes.

Instalación del sistema

He creado un vídeo en YouTube para mostrar cómo instalar este sistema, en caso de que se te complique.

Demostración

Puedes ver un vídeo de demostración del sistema:

Conclusión

Para una clase que estoy llevando actualmente en la universidad tenía que realizar un CRUD con Laravel, pero tenía ganas (desde hace mucho) de hacer un punto de venta con Laravel y agregarle algunas cosas como la impresión de tickets.

Si te gusta el framework, te invito a leer más sobre Laravel en mi blog. También te invito a ver mis otros proyectos, algunos de ellos open source.

Además, he realizado varios puntos de venta. Entre ellos:

Nota: he agregado más módulos a este sistema, entre ellos el módulo de clientes y el módulo de usuarios.

Encantado de ayudarte


Estoy disponible para trabajar en tu proyecto, modificar el programa del post o realizar tu tarea pendiente, no dudes en ponerte en contacto conmigo.

No te pierdas ninguno de mis posts

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.

28 comentarios en “Sistema de ventas con Laravel, Bootstrap y MySQL – Open source”

    1. Ahí mismo le está diciendo el error. “laravel/passport require php 7.2 ,Your version 8.0.2 does satisfy that requirem…” es decir, laravel/passport necesita la versión 7.2 y usted tiene la 8.0.2. Ahí recomiendo actualizar la dependencia a una versión que soporte PHP 8.0.2 y ya como última opción cambiar de PHP 8 a 7

  1. BUenas noches amigo, estuve revisando el codigo y al momento de eliminar una venta ya realizada el stock deberia de regresar al stock inicial, ejemplo si tengo un producto con 10 en stock al vender 5 el stock queda en 5 pero al eliminar la venta el stock deberia de regresar al 10 si es que no me equivoco

    1. Hola, buenas noches. Entiendo, gracias por revisar. Recuerde que el programa es open source, espero su pull request para mejorar la parte que me menciona.
      Saludos!

  2. Buenas tardes amigo como esta.?
    Querìa instalar dicho sistema para probarlo.
    pero me genera el siguiente error.
    In PackageManifest.php line 131:

    Undefined index: name

    Script @php artisan package:discover –ansi handling the post-autoload-dump event returned with error code 1

    alguna soluciòn

  3. Se que las ultimas versiones son para 64bit, pero necesito que funcione en 32bit por un tema de portabilidad. Ya he intentado actualizar PHP a 7.4 pero no logro hacerlo fucionar con 32bit esta disponible hasta la ver. 7.3.2 busque tutoriales pero lo logro hacerlo funcionar. Agradeceria que me des una ayuda con esto por que parece muy interesante el sistema. Muchas gracias.

  4. Hola amigo me salta un problema con “php artisan migrate” crea solo 2 tablas y luego da error de conexion a la base de datos. Como lo puedo resolver?
    C:\xampp\htdocs\sistema_ventas_laravel>php artisan migrate
    Migration table created successfully.
    Migrating: 2014_10_12_000000_create_users_table

    Illuminate\Database\QueryException

    SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too
    long; max key length is 767 bytes (SQL: alter table `users` add unique `users_em
    ail_unique`(`email`))

    at C:\xampp\htdocs\sistema_ventas_laravel\vendor\laravel\framework\src\Illumin
    ate\Database\Connection.php:669
    665| // If an exception occurs when attempting to run a query, we’ll
    format the error
    666| // message to include the bindings with SQL, which will make th
    is exception a
    667| // lot more helpful to the developer instead of just the databa
    se’s errors.
    668| catch (Exception $e) {
    > 669| throw new QueryException(
    670| $query, $this->prepareBindings($bindings), $e
    671| );
    672| }
    673|

    1 C:\xampp\htdocs\sistema_ventas_laravel\vendor\laravel\framework\src\Illumi
    nate\Database\Connection.php:463
    PDOException::(“SQLSTATE[42000]: Syntax error or access violation: 1071 Sp
    ecified key was too long; max key length is 767 bytes”)

    2 C:\xampp\htdocs\sistema_ventas_laravel\vendor\laravel\framework\src\Illumi
    nate\Database\Connection.php:463
    PDOStatement::execute()

  5. amigo soy yo de nuevo, intenté instalar el ‘composer require mike42/escpos-php’, pero me genera otro error:

    C:\xampp\htdocs\sistema_ventas_laravel-master>composer require mike42/escpos-php
    Using version ^3.0 for mike42/escpos-php
    ./composer.json has been updated
    Loading composer repositories with package information
    Updating dependencies (including require-dev)
    Your requirements could not be resolved to an installable set of packages.

    Problem 1
    – mike42/escpos-php v3.0 requires ext-intl * -> the requested PHP extension intl is missing from your system.
    – mike42/escpos-php v3.0 requires ext-intl * -> the requested PHP extension intl is missing from your system.
    – Installation request for mike42/escpos-php ^3.0 -> satisfiable by mike42/escpos-php[v3.0].

    To enable extensions, verify that they are enabled in your .ini files:
    – C:\xampp\php\php.ini
    You can also run `php –ini` inside terminal to see which files are used by PHP in CLI mode.

    Installation failed, reverting ./composer.json to its original content.

  6. amigo genial aplicación, quería descargarla y probarla. Pero me genera un error al momento del ‘composer update’ , el cual es el siguiente:

    C:\xampp\htdocs\sistema_ventas_laravel-master>composer update
    Loading composer repositories with package information
    Updating dependencies (including require-dev)
    Your requirements could not be resolved to an installable set of packages.

    Problem 1
    – Installation request for mike42/escpos-php ^3.0 -> satisfiable by mike42/escpos-php[v3.0].
    – mike42/escpos-php v3.0 requires ext-intl * -> the requested PHP extension intl is missing from your system.

    To enable extensions, verify that they are enabled in your .ini files:
    – C:\xampp\php\php.ini
    You can also run `php –ini` inside terminal to see which files are used by PHP in CLI mode.

    C:\xampp\htdocs\sistema_ventas_laravel-master>composer install
    Loading composer repositories with package information
    Installing dependencies (including require-dev) from lock file

Dejar un comentario