Skip to main content

Overview

The invoice creation system provides a comprehensive workflow for generating invoices with client selection, product line items, payment terms, and automatic calculations. The system supports multiple payment methods and real-time totals calculation.

Invoice Database Structure

Invoices are stored across two related tables:

Main Invoice Table

simple_invoice.sql
CREATE TABLE IF NOT EXISTS `facturas` (
  `id_factura` int(11) NOT NULL AUTO_INCREMENT,
  `numero_factura` int(11) NOT NULL,
  `fecha_factura` datetime NOT NULL,
  `id_cliente` int(11) NOT NULL,
  `id_vendedor` int(11) NOT NULL,
  `condiciones` varchar(30) NOT NULL,
  `total_venta` varchar(20) NOT NULL,
  `estado_factura` tinyint(1) NOT NULL,
  PRIMARY KEY (`id_factura`),
  UNIQUE KEY `numero_cotizacion` (`numero_factura`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Invoice Detail Table

simple_invoice.sql
CREATE TABLE IF NOT EXISTS `detalle_factura` (
  `id_detalle` int(11) NOT NULL AUTO_INCREMENT,
  `numero_factura` int(11) NOT NULL,
  `id_producto` int(11) NOT NULL,
  `cantidad` int(11) NOT NULL,
  `precio_venta` double NOT NULL,
  PRIMARY KEY (`id_detalle`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

New Invoice Interface

The new invoice page (nueva_factura.php) provides the complete invoice creation interface:
nueva_factura.php
<div class="panel panel-info">
    <div class="panel-heading">
        <h4><i class='glyphicon glyphicon-edit'></i> Nueva Factura</h4>
    </div>
    <div class="panel-body">
        <form class="form-horizontal" role="form" id="datos_factura">
            <!-- Invoice form fields -->
        </form>
    </div>
</div>

Client Selection with Autocomplete

Clients are selected using jQuery UI autocomplete functionality:
nueva_factura.php
<div class="form-group row">
    <label for="nombre_cliente" class="col-md-1 control-label">Cliente</label>
    <div class="col-md-3">
        <input type="text" class="form-control input-sm" id="nombre_cliente" 
               placeholder="Selecciona un cliente" required>
        <input id="id_cliente" type='hidden'>
    </div>
    <label for="tel1" class="col-md-1 control-label">Teléfono</label>
    <div class="col-md-2">
        <input type="text" class="form-control input-sm" id="tel1" 
               placeholder="Teléfono" readonly>
    </div>
    <label for="mail" class="col-md-1 control-label">Email</label>
    <div class="col-md-3">
        <input type="text" class="form-control input-sm" id="mail" 
               placeholder="Email" readonly>
    </div>
</div>

Autocomplete Implementation

nueva_factura.php
$("#nombre_cliente").autocomplete({
    source: "./ajax/autocomplete/clientes.php",
    minLength: 2,
    select: function(event, ui) {
        event.preventDefault();
        $('#id_cliente').val(ui.item.id_cliente);
        $('#nombre_cliente').val(ui.item.nombre_cliente);
        $('#tel1').val(ui.item.telefono_cliente);
        $('#mail').val(ui.item.email_cliente);
    }
});
Autocomplete activates after typing 2 characters and automatically populates the client’s phone and email fields.

Keyboard Event Handling

The system clears hidden fields when the client name is modified:
nueva_factura.php
$("#nombre_cliente").on("keydown", function(event) {
    if (event.keyCode == $.ui.keyCode.LEFT || 
        event.keyCode == $.ui.keyCode.RIGHT || 
        event.keyCode == $.ui.keyCode.UP || 
        event.keyCode == $.ui.keyCode.DOWN || 
        event.keyCode == $.ui.keyCode.DELETE || 
        event.keyCode == $.ui.keyCode.BACKSPACE) {
        $("#id_cliente").val("");
        $("#tel1").val("");
        $("#mail").val("");
    }
    
    if (event.keyCode == $.ui.keyCode.DELETE) {
        $("#nombre_cliente").val("");
        $("#id_cliente").val("");
        $("#tel1").val("");
        $("#mail").val("");
    }
});

Vendor and Date Selection

The invoice includes vendor and date information:
nueva_factura.php
<div class="form-group row">
    <label for="empresa" class="col-md-1 control-label">Vendedor</label>
    <div class="col-md-3">
        <select class="form-control input-sm" id="id_vendedor">
            <?php
            $sql_vendedor = mysqli_query($con, "SELECT * FROM users ORDER BY lastname");
            while ($rw = mysqli_fetch_array($sql_vendedor)) {
                $id_vendedor = $rw["user_id"];
                $nombre_vendedor = $rw["firstname"] . " " . $rw["lastname"];
                $selected = ($id_vendedor == $_SESSION['user_id']) ? "selected" : "";
                ?>
                <option value="<?php echo $id_vendedor?>" <?php echo $selected;?>>
                    <?php echo $nombre_vendedor?>
                </option>
            <?php } ?>
        </select>
    </div>
    <label for="tel2" class="col-md-1 control-label">Fecha</label>
    <div class="col-md-2">
        <input type="text" class="form-control input-sm" id="fecha" 
               value="<?php echo date('d/m/Y');?>" readonly>
    </div>
</div>
The vendor defaults to the currently logged-in user, and the date is automatically set to today.

Payment Conditions

Simple Invoice supports four payment methods:
nueva_factura.php
<label for="email" class="col-md-1 control-label">Pago</label>
<div class="col-md-3">
    <select class='form-control input-sm' id="condiciones">
        <option value="1">Efectivo</option>
        <option value="2">Cheque</option>
        <option value="3">Transferencia bancaria</option>
        <option value="4">Crédito</option>
    </select>
</div>
The payment conditions are stored as integers and displayed appropriately in PDFs:
pdf/documentos/res/factura_html.php
<?php 
if ($condiciones == 1) { echo "Efectivo"; }
elseif ($condiciones == 2) { echo "Cheque"; }
elseif ($condiciones == 3) { echo "Transferencia bancaria"; }
elseif ($condiciones == 4) { echo "Crédito"; }
?>

Action Buttons

The invoice form provides several action buttons:
nueva_factura.php
<div class="col-md-12">
    <div class="pull-right">
        <button type="button" class="btn btn-default" data-toggle="modal" data-target="#nuevoProducto">
            <span class="glyphicon glyphicon-plus"></span> Nuevo producto
        </button>
        <button type="button" class="btn btn-default" data-toggle="modal" data-target="#nuevoCliente">
            <span class="glyphicon glyphicon-user"></span> Nuevo cliente
        </button>
        <button type="button" class="btn btn-default" data-toggle="modal" data-target="#myModal">
            <span class="glyphicon glyphicon-search"></span> Agregar productos
        </button>
        <button type="submit" class="btn btn-default">
            <span class="glyphicon glyphicon-print"></span> Imprimir
        </button>
    </div>
</div>

Product Line Items

Products are added to the invoice and stored temporarily in the tmp table:
ajax/agregar_facturacion.php
$session_id = session_id();

if (!empty($id) and !empty($cantidad) and !empty($precio_venta)) {
    $insert_tmp = mysqli_query($con, 
        "INSERT INTO tmp (id_producto, cantidad_tmp, precio_tmp, session_id) 
         VALUES ('$id', '$cantidad', '$precio_venta', '$session_id')");
}

Removing Line Items

ajax/agregar_facturacion.php
if (isset($_GET['id'])) {
    $id_tmp = intval($_GET['id']);
    $delete = mysqli_query($con, "DELETE FROM tmp WHERE id_tmp='" . $id_tmp . "'");
}

Calculation Logic

The system automatically calculates subtotal, tax, and total:

Line Item Totals

ajax/agregar_facturacion.php
$sumador_total = 0;
$sql = mysqli_query($con, 
    "SELECT * FROM products, tmp 
     WHERE products.id_producto = tmp.id_producto 
     AND tmp.session_id = '" . $session_id . "'");

while ($row = mysqli_fetch_array($sql)) {
    $cantidad = $row['cantidad_tmp'];
    $precio_venta = $row['precio_tmp'];
    
    // Format and clean price
    $precio_venta_f = number_format($precio_venta, 2);
    $precio_venta_r = str_replace(",", "", $precio_venta_f);
    
    // Calculate line total
    $precio_total = $precio_venta_r * $cantidad;
    $precio_total_f = number_format($precio_total, 2);
    $precio_total_r = str_replace(",", "", $precio_total_f);
    
    // Add to running total
    $sumador_total += $precio_total_r;
}

Tax and Final Total

ajax/agregar_facturacion.php
// Get tax rate from company profile
$impuesto = get_row('perfil', 'impuesto', 'id_perfil', 1);

// Calculate subtotal
$subtotal = number_format($sumador_total, 2, '.', '');

// Calculate tax
$total_iva = ($subtotal * $impuesto) / 100;
$total_iva = number_format($total_iva, 2, '.', '');

// Calculate final total
$total_factura = $subtotal + $total_iva;

Display Totals

ajax/agregar_facturacion.php
echo '<tr>';
echo '<td class="text-right" colspan=4>SUBTOTAL ' . $simbolo_moneda . '</td>';
echo '<td class="text-right">' . number_format($subtotal, 2) . '</td>';
echo '<td></td>';
echo '</tr>';

echo '<tr>';
echo '<td class="text-right" colspan=4>IVA (' . $impuesto . ')% ' . $simbolo_moneda . '</td>';
echo '<td class="text-right">' . number_format($total_iva, 2) . '</td>';
echo '<td></td>';
echo '</tr>';

echo '<tr>';
echo '<td class="text-right" colspan=4>TOTAL ' . $simbolo_moneda . '</td>';
echo '<td class="text-right">' . number_format($total_factura, 2) . '</td>';
echo '<td></td>';
echo '</tr>';
Tax rates are configured in the company profile settings and apply automatically to all invoices.

Editing Invoices

Existing invoices can be edited via editar_factura.php:
editar_factura.php
if (isset($_GET['id_factura'])) {
    $id_factura = intval($_GET['id_factura']);
    $campos = "clientes.id_cliente, clientes.nombre_cliente, clientes.telefono_cliente, 
               clientes.email_cliente, facturas.id_vendedor, facturas.fecha_factura, 
               facturas.condiciones, facturas.estado_factura, facturas.numero_factura";
    
    $sql_factura = mysqli_query($con, 
        "SELECT $campos FROM facturas, clientes 
         WHERE facturas.id_cliente = clientes.id_cliente 
         AND id_factura = '" . $id_factura . "'");
    
    $count = mysqli_num_rows($sql_factura);
    
    if ($count == 1) {
        $rw_factura = mysqli_fetch_array($sql_factura);
        $id_cliente = $rw_factura['id_cliente'];
        $nombre_cliente = $rw_factura['nombre_cliente'];
        $telefono_cliente = $rw_factura['telefono_cliente'];
        $email_cliente = $rw_factura['email_cliente'];
        $id_vendedor_db = $rw_factura['id_vendedor'];
        $fecha_factura = date("d/m/Y", strtotime($rw_factura['fecha_factura']));
        $condiciones = $rw_factura['condiciones'];
        $estado_factura = $rw_factura['estado_factura'];
        $numero_factura = $rw_factura['numero_factura'];
        
        $_SESSION['id_factura'] = $id_factura;
        $_SESSION['numero_factura'] = $numero_factura;
    }
}

Invoice Status

Invoices can be marked as paid or pending:
editar_factura.php
<select class='form-control input-sm' id="estado_factura" name="estado_factura">
    <option value="1" <?php if ($estado_factura == 1) { echo "selected"; } ?>>Pagado</option>
    <option value="2" <?php if ($estado_factura == 2) { echo "selected"; } ?>>Pendiente</option>
</select>

Invoice Workflow

1

Start New Invoice

Navigate to “Nueva Factura” from the main menu
2

Select Client

Type client name (minimum 2 characters) and select from autocomplete suggestions
3

Configure Invoice

Select vendor, verify date, and choose payment method
4

Add Products

Click “Agregar productos” to search and add line items to the invoice
5

Review Totals

Verify subtotal, tax, and total calculations
6

Generate Invoice

Click “Imprimir” to generate the PDF and save the invoice to the database

Key Features

Client Autocomplete

Fast client selection with real-time search

Multiple Payment Methods

Efectivo, Cheque, Transferencia, Crédito

Automatic Calculations

Real-time subtotal, tax, and total calculation

Session-based Items

Products stored in session until invoice is finalized

Invoice Editing

Modify existing invoices and update status

Vendor Selection

Assign invoices to specific sales representatives
  • nueva_factura.php - New invoice creation interface
  • editar_factura.php - Edit existing invoice
  • ajax/agregar_facturacion.php - Add products to invoice
  • ajax/autocomplete/clientes.php - Client autocomplete search
  • modal/buscar_productos.php - Product search modal
  • js/nueva_factura.js - New invoice client-side logic
  • js/editar_factura.js - Edit invoice client-side logic
  • js/VentanaCentrada.js - Popup window helper
Products added to an invoice are stored in the tmp table with your session ID. Clearing your browser session before finalizing the invoice will lose these items.