Lenguaje PHP

Sistema factura con PHP y MySQL: Ejemplo Completo

Sistema facturas es un software web. Ahora, los sistemas de gestión de facturas o sistema factura con PHP, son muy asequibles, es decir fácil de usar y por su bajo costo de implementación ya que si deseo vender en todo el mundo se necesita de un sistema en línea.

La mayoría de las transacciones financieras se realizan a través de internet. Por lo tanto, todos los vendedores y compradores necesitan un sistema de facturación para gestionar los pagos a través de la red de internet.

Crear sistema factura con PHP y MySQL
Crear sistema factura con PHP y MySQL

Sistema factura con PHP y MySQL

Ahora, si estás buscando un sistema de facturación desarrollado con PHP y MySQL, entonces aquí puedes encontrar la solución a tu búsqueda. Por lo tanto, en este artículo mostraremos un ejemplo de cómo desarrollar un pequeño sistema de facturas.

¿El sistema facturación imprime las facturas creadas?

La respuesta es sí, va a emitir la factura en formato PDF para enviárselo al cliente mediante correo electrónico si se diera el caso.

La librería llamada «dompdf» convierte el HTML en formato PDF de manera dinámica y para lograr su objetivo de manera correcta necesita ciertos recursos.

Requerimientos de tu servidor

  • PHP 5.4+ (requerido o superior)
  • DOM extension (requerido, habilitado port defecto)
  • MBString extension. MBString es necesario para el soporte de Unicode.
  • php-font-lib
  • php-svg-lib

Recomendaciones necesarias

Para que la librería funcione en óptimas condiciones y rapidez, se recomienda lo siguiente.

Estructura de archivos y carpetas del sistema

El presente sistema consta de archivos y librerías externas que son vitales para el correcto funcionamiento del sistema. Sin embargo, aquí les dejare la estructura de archivos y carpetas del sistema.

Estructura de archivos sistema facturas
Estructura de archivos sistema facturas

Secuencia y pasos del sistema de facturación

A continuación, veremos una serie de pasos y funciones que debemos de conocer.

A) Paso 1: Crear la base de datos y las tablas MySQL

Primero crearemos la base de datos llamado «php_factura» y posteriormente usando la herramienta del phpMyAdmin ejecutar las consultas para la creación de las siguientes tablas.

1) Tabla (factura_usuarios).-  Esta tabla almacena los usuarios que acceden y/o administren el sistema.

2) Tabla (factura_orden).- Tabla que registra los pedidos, los montos a pagar e impuestos.

3) Tabla (factura_orden_producto).- Almacena los productos del sistema.

A continuación, les dejare las consultas SQL del sistema.

CREATE TABLE `factura_orden` (
  `order_id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `order_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `order_receiver_name` varchar(250) CHARACTER SET utf8 NOT NULL,
  `order_receiver_address` text CHARACTER SET utf8 NOT NULL,
  `order_total_before_tax` decimal(10,2) NOT NULL,
  `order_total_tax` decimal(10,2) NOT NULL,
  `order_tax_per` varchar(250) CHARACTER SET utf8 NOT NULL,
  `order_total_after_tax` double(10,2) NOT NULL,
  `order_amount_paid` decimal(10,2) NOT NULL,
  `order_total_amount_due` decimal(10,2) NOT NULL,
  `note` text CHARACTER SET utf8 NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

-- --------------------------------------------------------

CREATE TABLE `factura_orden_producto` (
  `order_item_id` int(11) NOT NULL,
  `order_id` int(11) NOT NULL,
  `item_code` varchar(250) NOT NULL,
  `item_name` varchar(250) NOT NULL,
  `order_item_quantity` decimal(10,2) NOT NULL,
  `order_item_price` decimal(10,2) NOT NULL,
  `order_item_final_amount` decimal(10,2) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- --------------------------------------------------------

CREATE TABLE `factura_usuarios` (
  `id` int(11) NOT NULL,
  `email` varchar(100) NOT NULL,
  `password` varchar(100) NOT NULL,
  `first_name` varchar(100) NOT NULL,
  `last_name` varchar(100) NOT NULL,
  `mobile` bigint(20) NOT NULL,
  `address` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO `factura_usuarios` (`id`, `email`, `password`, `first_name`, `last_name`, `mobile`, `address`) VALUES
(1, 'registro@www.baulphp.com', '12345', 'BaulPHP', '', 78979676, '');

ALTER TABLE `factura_orden`
  ADD PRIMARY KEY (`order_id`);

ALTER TABLE `factura_orden_producto`
  ADD PRIMARY KEY (`order_item_id`);

ALTER TABLE `factura_usuarios`
  ADD PRIMARY KEY (`id`);

ALTER TABLE `factura_orden`
  MODIFY `order_id` int(11) NOT NULL AUTO_INCREMENT;

ALTER TABLE `factura_orden_producto`
  MODIFY `order_item_id` int(11) NOT NULL AUTO_INCREMENT;

ALTER TABLE `factura_usuarios`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;

B) Paso 2: Crear el inicio de sesión de usuario

En este punto tenemos que crear un formulario dinámico con incrustaciones PHP para su respectiva validación y conexión con la base de datos.

Facturas usando PHP y MySQL
Facturas usando PHP y MySQL
<div class="row">	
  <div class="col-xs-6">
  
<div class="heading">
		<h2>Build Invoice System with PHP & MySQL</h2>
	</div>
<div class="login-form">
<form action="" method="post">
    <h2 class="text-center">Iniciar Sesión</h2>  
<div class="form-group">
<?php if ($loginError ) { ?>
<div class="alert alert-warning"><?php echo $loginError; ?></div>
<?php } ?>
</div>         
<div class="form-group">
    <input name="email" id="email" type="email" class="form-control" placeholder="Email address" autofocus required>
</div>
<div class="form-group">
    <input type="password" class="form-control" name="pwd" placeholder="Password" required>
</div> 
<div class="form-group">
    <button type="submit" name="login" class="btn btn-primary" style="width: 100%;"> Acceder </button>
</div>
<div class="clearfix">
<label class="pull-left checkbox-inline"><input type="checkbox"> Recordarme</label>
</div>        
</form>
</div>   

</div>
<div class="col-xs-6">-</div>	
</div>		
</div>

Usaremos el método loginUsers(). Para validar la información enviada por el formulario.

<?php
if (!empty($_POST['email']) && !empty($_POST['pwd'])) {
include 'Invoice.php';
$invoice = new Invoice();
$user = $invoice->loginUsers($_POST['email'], $_POST['pwd']);
if(!empty($user)) {
$_SESSION['user'] = $user[0]['first_name']."".$user[0]['last_name'];
$_SESSION['userid'] = $user[0]['id'];
$_SESSION['email'] = $user[0]['email'];
$_SESSION['address'] = $user[0]['address'];
$_SESSION['mobile'] = $user[0]['mobile'];
header("Location:invoice_list.php");
} else {
$loginError = "Email o Password Invalido!";
}
}
?>

C) Paso 3: Mostrar lista de facturas generadas

Aquí, solo mostraremos un panel con todas las facturas emitidas por el sistema y el fichero se llamara «invoice_list.php«. Por lo tanto, este fichero podremos:

  • Imprimir la factura.
  • Editar la factura.
  • Eliminar la factura.
Lista de Facturas PHP y MySQL
Lista de Facturas PHP y MySQL
<div class="container">		
<h2 class="title">Sistema de facturación PHP</h2>
<?php include('menu.php');?>			  
<table id="data-table" class="table table-condensed table-striped">
<thead>
  <tr>
    <th width="7%">Fac. No.</th>
    <th width="15%">Fecha Creación</th>
    <th width="35%">Cliente</th>
    <th width="15%">Fatura Total</th>
    <th width="3%"></th>
    <th width="3%"></th>
    <th width="3%"></th>
  </tr>
</thead>
<?php		
$invoiceList = $invoice->getInvoiceList();
foreach($invoiceList as $invoiceDetails){
    $invoiceDate = date("d/M/Y, H:i:s", strtotime($invoiceDetails["order_date"]));
    echo '
      <tr>
        <td>'.$invoiceDetails["order_id"].'</td>
        <td>'.$invoiceDate.'</td>
        <td>'.$invoiceDetails["order_receiver_name"].'</td>
        <td>'.$invoiceDetails["order_total_after_tax"].'</td>
        <td><a href="print_invoice.php?invoice_id='.$invoiceDetails["order_id"].'" title="Imprimir Factura"><div class="btn btn-primary"><span class="glyphicon glyphicon-print"></span></div></a></td>
        <td><a href="edit_invoice.php?update_id='.$invoiceDetails["order_id"].'"  title="Editar Factura"><div class="btn btn-primary"><span class="glyphicon glyphicon-edit"></span></div></a></td>
        <td><a href="#" id="'.$invoiceDetails["order_id"].'" class="deleteInvoice"  title="Borrar Factura"><div class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span></div></a></td>
      </tr>
    ';
}       
?>
</table>	
</div>	

D) Paso 4: Creación de la factura

Este punto veremos la creación de la factura para poder ser almacenada en la base de datos y posteriormente ser impresa en formato PDF. EL fichero encargado de tal tarea será «create_invoice.php«. Sin embargo, este fichero tendrá un rol importante ya que será el encargado de realizar las siguientes tareas:

  • Validar los campos obligatorios.
  • Calcular los montos de los productos.
  • Automatizar el monto de los impuestos.
  • Generar el total a pagar.
Sistema de facturacion PHP
Sistema de facturacion PHP
<div class="container content-invoice">
<form action="" id="invoice-form" method="post" class="invoice-form" role="form" novalidate> 
<div class="load-animate animated fadeInUp">
<div class="row">
<div class="col-xs-8 col-sm-8 col-md-8 col-lg-8">
    <h2 class="title">Sistema de Facturación PHP</h2>
    <?php include('menu.php');?>	
</div>		    		
</div>
<input id="currency" type="hidden" value="$">
<div class="row">
<div class="col-xs-12 col-sm-4 col-md-4 col-lg-4">
    <h3>De,</h3>
    <?php echo $_SESSION['user']; ?><br>	
    <?php echo $_SESSION['address']; ?><br>	
    <?php echo $_SESSION['mobile']; ?><br>
    <?php echo $_SESSION['email']; ?><br>	
</div>      		
<div class="col-xs-12 col-sm-4 col-md-4 col-lg-4 pull-right">
    <h3>Para,</h3>
    <div class="form-group">
        <input type="text" class="form-control" name="companyName" id="companyName" placeholder="Nombre de Empresa" autocomplete="off">
    </div>
    <div class="form-group">
        <textarea class="form-control" rows="3" name="address" id="address" placeholder="Su dirección"></textarea>
    </div>
    
</div>
</div>
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
    <table class="table table-bordered table-hover" id="invoiceItem">	
        <tr>
            <th width="2%"><input id="checkAll" class="formcontrol" type="checkbox"></th>
            <th width="15%">Prod. No</th>
            <th width="38%">Nombre Producto</th>
            <th width="15%">Cantidad</th>
            <th width="15%">Precio</th>								
            <th width="15%">Total</th>
        </tr>							
        <tr>
            <td><input class="itemRow" type="checkbox"></td>
            <td><input type="text" name="productCode[]" id="productCode_1" class="form-control" autocomplete="off"></td>
            <td><input type="text" name="productName[]" id="productName_1" class="form-control" autocomplete="off"></td>			
            <td><input type="number" name="quantity[]" id="quantity_1" class="form-control quantity" autocomplete="off"></td>
            <td><input type="number" name="price[]" id="price_1" class="form-control price" autocomplete="off"></td>
            <td><input type="number" name="total[]" id="total_1" class="form-control total" autocomplete="off"></td>
        </tr>						
    </table>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-sm-3 col-md-3 col-lg-3">
    <button class="btn btn-danger delete" id="removeRows" type="button">- Borrar</button>
    <button class="btn btn-success" id="addRows" type="button">+ Agregar Más</button>
</div>
</div>
<div class="row">	
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-8">
    <h3>Notas: </h3>
    <div class="form-group">
        <textarea class="form-control txt" rows="5" name="notes" id="notes" placeholder="Notas"></textarea>
    </div>
    <br>
    <div class="form-group">
        <input type="hidden" value="<?php echo $_SESSION['userid']; ?>" class="form-control" name="userId">
        <input data-loading-text="Guardando factura..." type="submit" name="invoice_btn" value="Guardar Factura" class="btn btn-success submit_btn invoice-save-btm">						
    </div>
    
</div>
<div class="col-xs-12 col-sm-4 col-md-4 col-lg-4">
    <span class="form-inline">
        <div class="form-group">
            <label>Subtotal: &nbsp;</label>
            <div class="input-group">
                <div class="input-group-addon currency">$</div>
                <input value="" type="number" class="form-control" name="subTotal" id="subTotal" placeholder="Subtotal">
            </div>
        </div>
        <div class="form-group">
            <label>Tasa Impuesto: &nbsp;</label>
            <div class="input-group">
                <input value="" type="number" class="form-control" name="taxRate" id="taxRate" placeholder="Tasa de Impuestos">
                <div class="input-group-addon">%</div>
            </div>
        </div>
        <div class="form-group">
            <label>Monto Inpuesto: &nbsp;</label>
            <div class="input-group">
                <div class="input-group-addon currency">$</div>
                <input value="" type="number" class="form-control" name="taxAmount" id="taxAmount" placeholder="Monto de Impuesto">
            </div>
        </div>							
        <div class="form-group">
            <label>Total: &nbsp;</label>
            <div class="input-group">
                <div class="input-group-addon currency">$</div>
                <input value="" type="number" class="form-control" name="totalAftertax" id="totalAftertax" placeholder="Total">
            </div>
        </div>
        <div class="form-group">
            <label>Cantidad pagada: &nbsp;</label>
            <div class="input-group">
                <div class="input-group-addon currency">$</div>
                <input value="" type="number" class="form-control" name="amountPaid" id="amountPaid" placeholder="Cantidad pagada">
            </div>
        </div>
        <div class="form-group">
            <label>Cantidad debida: &nbsp;</label>
            <div class="input-group">
                <div class="input-group-addon currency">$</div>
                <input value="" type="number" class="form-control" name="amountDue" id="amountDue" placeholder="Cantidad debida">
            </div>
        </div>
    </span>
</div>
</div>
<div class="clearfix"></div>		      	
</div>
</form>			
</div>
</div>	

Guardaremos los detalles de la factura utilizando el método de factura saveInvoice().

<?php
include 'Invoice.php';
$invoice = new Invoice();
$invoice->saveInvoice($_POST);
?>

E) Paso 5: Implementar actualización de facturas

El fichero encargado de tal proceso se llama «edit_invoice.php«. Por lo tanto, aquí implementaremos el evento para editar la factura. Nos apoyaremos en un formulario con los campos obligatorios para guardar la edición de facturas.

<table class="table table-bordered table-hover" id="invoiceItem">	
<tr>
    <th width="2%"><input id="checkAll" class="formcontrol" type="checkbox"></th>
<th width="15%">Prod. No</th>
<th width="38%">Nombre Producto</th>
<th width="15%">Cantidad</th>
<th width="15%">Precio</th>								
<th width="15%">Total</th>
</tr>
<?php 
$count = 0;
foreach($invoiceItems as $invoiceItem){
    $count++;
?>								
<tr>
    <td><input class="itemRow" type="checkbox"></td>
    <td><input type="text" value="<?php echo $invoiceItem["item_code"]; ?>" name="productCode[]" id="productCode_<?php echo $count; ?>" class="form-control" autocomplete="off"></td>
    <td><input type="text" value="<?php echo $invoiceItem["item_name"]; ?>" name="productName[]" id="productName_<?php echo $count; ?>" class="form-control" autocomplete="off"></td>			
    <td><input type="number" value="<?php echo $invoiceItem["order_item_quantity"]; ?>" name="quantity[]" id="quantity_<?php echo $count; ?>" class="form-control quantity" autocomplete="off"></td>
    <td><input type="number" value="<?php echo $invoiceItem["order_item_price"]; ?>" name="price[]" id="price_<?php echo $count; ?>" class="form-control price" autocomplete="off"></td>
    <td><input type="number" value="<?php echo $invoiceItem["order_item_final_amount"]; ?>" name="total[]" id="total_<?php echo $count; ?>" class="form-control total" autocomplete="off"></td>
    <input type="hidden" value="<?php echo $invoiceItem['order_item_id']; ?>" class="form-control" name="itemId[]">
</tr>	
<?php } ?>		
</table>

La factura se editará mediante el método de factura llamado  «updateInvoice()».

<?php
include 'Invoice.php';
$invoice = new Invoice();
$invoice->updateInvoice($_POST);
?>

F) Paso 6: Impresión de la Factura

Esta es la parte fundamental del sistema ya que imprimirá los productos y montos registrados en la factura. La funcionalidad de impresión será en formato PDF. Sin embargo, el fichero responsable será llamado «print_invoice.php» que permitirá al usuario imprimir o descargar la factura generada.

CONCLUSIÓN DEL SISTEMA

La implementación de este tipo de sistema es muy recomendables por varios factores que detallaremos a continuación:
Recordemos que existen tipos de software: Unos llamados software de escritorio y otro llamado software web. En este artículo rescataremos las ventajas del software web, veamos a continuación los siguientes puntos.

  • Su alcance es mundial.- Porque trabaja con un servidor web y puede generar facturas para cualquier parte del mundo.
  • El costo de implementación es muy bajo.- Básicamente para pequeñas empresas que recién están iniciando en ventas por internet.
  • Flexibilidad.- Porque puedes acceder desde cualquier parte del mundo al sistema desde un dispositivo que goce de línea de internet.

Esta son algunas ventajas y conclusiones acerca del uso del sistema de facturas. También, les dejare un fichero comprimido para que puedan descargar e implementar en sus sistemas web.

Descargar Código Fuente

 

Nestor Tapia

Bloggero, amante de la programación PHP, innovador y me fascina compartir información. Desde que conocí el entorno informatico y el internet me llamó la atención la programación, Por tal motivo he creado mi blog BAULPHP.COM para compartir mis experiencias con todos ustedes. ¡Gracias por leerme!.

27 comentarios

  1. buenas noches nestor, primero que todo muchas gracias por hacer tu trabajo publico solo para impartir tu conocimiento y ayudar a los demás.
    Hoy estuve tocando un poco el sistema y todo bien, solo que a la hora que voy a darle al botón de «imprimir» en alguna factura, me sale en siguiente error:
    2
    Fatal error: Uncaught Dompdf\Exception: file_get_contents(): Passing null to parameter #2 ($use_include_path) of type bool is deprecated 8192 in C:\xampp\htdocs\sistema_factura\dompdf\src\Helpers.php:507 Stack trace: #0 [internal function]: Dompdf\Helpers::record_warnings(8192, ‘file_get_conten…’, ‘C:\\xampp\\htdocs…’, 839) #1 C:\xampp\htdocs\sistema_factura\dompdf\src\Helpers.php(839): file_get_contents(‘C:\\xampp\\htdocs…’, NULL, NULL, 0) #2 C:\xampp\htdocs\sistema_factura\dompdf\src\Css\Stylesheet.php(367): Dompdf\Helpers::getFileContent(‘C:\\xampp\\htdocs…’, NULL) #3 C:\xampp\htdocs\sistema_factura\dompdf\src\Dompdf.php(572): Dompdf\Css\Stylesheet->load_css_file(‘C:\\xampp\\htdocs…’, 1) #4 C:\xampp\htdocs\sistema_factura\dompdf\src\Dompdf.php(724): Dompdf\Dompdf->processHtml() #5 C:\xampp\htdocs\sistema_factura\print_invoice.php(94): Dompdf\Dompdf->render() #6 {main} thrown in C:\xampp\htdocs\sistema_factura\dompdf\src\Helpers.php on line 507
    y estuve un rato intentando solucionarlo, y no he podido dar con la solución.
    Agradecería si me pudieras ayudar a resolver ese problema.

  2. Excelente aplicacion, lo estoy implementando para una orden de compra, he cambiado algunos campos en el detalle como el input de nombre de producto por un combobox pero este se carga de una tabla de productos de mysql.
    Lo que necesito es poder clonar otro combobox y que siempre cargue la informacion desde la base de datos, pero no logro como hacerlo en el codigo de javascript cuando le doy agregar mas en el boton solo me aparece el combobox vacio y ya no carga los datos que me envia la base de datos.

  3. Hola gracias por compartir el proyecto, pero me pasa lo mismo que a los demás, no se guardan las facturas y no se muestran en la lista de facturas.

  4. Ola Baul,
    Ola Todos, como podem ver irei escrever em portugues porque sou de Mocambique, um pais que se situa no Sul do Continente Africano e a minha lingua Nativa e Portugues..(risos)
    Estou me formando em Engenharia Informatica e gostaria de me especializar em Desenvolvimento Web (PhP) inclusive gostaria de me inspirar nos teus projectos/aulas para implementar um sistema web para o meu trabalho de conclusao do curso.! e ao mesmo tempo gostaria de saber como instalar um framwork para traduzir ou mostrar os conteudos em varios idiomas?
    Obrigado

  5. 🙁 Me he descargado el proyecto, lo he montado en local y no me lista las facturas porque no se almacenan en factura_orden.
    Las líneas al crear una factura nueva si se almacenan en factura_orden_producto pero no la factura. ¿Estoy haciendo algo mal?

    Gracias por tus aportaciones

  6. Saludos amigo. me gustaria saber si tienes algun sistema en php y mysql con el cual pueda gestionar los abonos o pagos se realizan a una facrura de un estudiante especifico.
    Si tienes al whatsapp para entrar en cotacto contigo . el pluing o programación es para el colegio.
    es para control los saldos pendientes por mensualidad que tienen los estudiantes

  7. Saludos amigo. me gustaria saber si tienes algun sistema en php y mysql con el cual pueda gestionar los abonos o pagos se realizan a una facrura de un estudiante especifico.
    Si tienes al whatsapp para entrar en cotacto contigo . el pluing o programación es para el colegio.
    es para control los saldos pendientes por mensualidad que tienen los estudiantes

  8. Warning: mysqli::__construct(): (HY000/1049): Unknown database ‘php_factura’ in C:\xampp\htdocs\hola\Invoice.php on line 13
    Error failed to connect to MySQL: Unknown database ‘php_factura’

    1. Hola Ignacio
      En el error que acabas de publicar se debe a que la aplicacion no puede conectar con la base de datos o la base de datos no existe.

      Lo que se tiene que hacer es crear la base de datos y vincularla en el script.

      Saludos

  9. HOLA BUENAS TARDES
    MUY BUEN CODIGO PERO TENGO UN PROBLEMA

    Fatal error: Cannot use string offset as an array in C:\AppServ\www\crear-sistema-de-facturas-con-php-y-mysql\index.php on line 11

    SI ME PUEDES AYUDAR A RESOLVER DE ANTEMANO LO AGRADEZCO

  10. Hola Nestor un saludo , gracias por compartir tus conocimientos Dios te va bendecir mucho. Soy principiante en esto de la programación pero me gusta mucho.. Intentare hacerlo y comprender cada paso. Excelente aporte Bendiciones a la distancia.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Botón volver arriba
Esta web utiliza cookies propias para su correcto funcionamiento. Contiene enlaces a sitios web de terceros con políticas de privacidad ajenas que podrás aceptar o no cuando accedas a ellos. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad