Numero de factura. En la factura de Ecuador, una factura tiene 3 numeros unidos por "-". Su formato es: ###-###-######### A continuación se explica cada numero.
serie1. El primer numero se llama "punto de establecimiento". Este es un numero asignado por el SRI para cada local del cliente. En el sistema RunFood se llamada "serie1". En la base de datos a veces se le llama "estab". Consta de 3 digitos (con los zeros rellenando hacia la izquierda). Es decir, 1 se representa como "001".
serie2. El segundo digito en una factura se llama "punto de emision". Esta es la caja desde donde la factura fué emitida dentro de un local. En nuestro sistema se llama "serie2". En la baes de datos puede llamarse a veces "ptoEmi". Consta de 3 digitos (con los zeros rellenando hacia la izquierda). Es decir, 10 se representa como "010".
secuencial. Es el numero que avanza con cada documento nuevo. En una nota de entrega avanza 1, 2, 3, etc. A veces se representa como un numero de 9 digitos con ceros rellenando hacia la izquierda. Es decir 10 se representa como "000000010".
Rango. Un rango es una grupo de numeros que tiene un inicio y un final.
Historia: Antes de la factura electrónica se emitian facturas manuales. Tenias que ir a una imprenta autorizada por el SRI e imprimir una serie de papeles, cada uno con su numero de factura unico. Por ejemplo podías pedir facturas impresoras #1 a la #100, o de la #50 a la #250. Luego tu llenabas el contenido de la factura a mano (productos, datos del cliente, metodos de pago) a medida que vendías. O podías usar un sistema que imprima sobre el papel. A este grupo de numeros de factura se le llamaba "rango". Ahora con la factura electronica ya no necesitas pedir "rangos". La factura electrónica es un numero que va del 1 al 999999999. Por lo tanto el nombre "rango" ahora significa simplemente "secuencia" para un punto de emision y un punto de establecimiento.
Cada punto de establecimiento y punto de emision tiene su propia secuencia. No se cruzan.
Es decir, 001-001 tiene un rango del numero 1 al numero 999999999. En otras palabras 001-001-1, 001-001-2, 001-001-3, etc.
Y también:
001-002 tambien tiene un rango del numero 1 al numero 999999999. En otras palabras 001-002-1, 001-002-2, 001-002-3, etc.
El negocio maneja multiples cajas. Es decir, tienes más de 1 persona facturando en el mismo turno.
La experiencia me ha enseñado que, en algún momento, estas N personas facturarán algo el mismo segundo. Si sólo manejas una única secuencia para todas estas personas, el sistema se puede confundir y asignar el mismo número de factura a todos.
Hemos hecho varias mejoras internas en el sistema para evitar esta situación. Sin embargo, una mejor solución es simplemente asignar una secuencia de facturas para cada usuario. De esta forma sólo una persona tiene una secuencia, y así nunca va a darse el caso de posible colisión de secuencia entre usuarios.
A continuación se detalla cómo se configura y se usa dicha función.
Advertencia. Esta configuración no tiene "Interfaz de usuario". Lo que quiere decir que su configuración es 100% interna: Directamente en base de datos, mediante archivos de configuración o variables de entorno.
Primero el sistema asigna a una factura el valor "serie1" y "serie2" (es decir, el punto de establecimiento y punto de emisión). Las reglas que sigue el sistema son:
Si la configuración en base de datos SecuenciaDocumentosPorUsuario = true y "secuencia_facturas_x_estab_y_emision": true (app.json) → busca en las tablas RANGO_ELECTRONICO y RANGO_ELECTRONICO_USUARIO y filtra por usuario y bodega. Si hay registros, asigna el valor "serie1" y "serie2" a la factura.
Si no se ha asignado un valor "serie1" y "serie2" antes de este punto → se asignan los valores serie1_default y serie2_default (app.json).
Una vez que la factura ya cuenta con el valor "serie1" y "serie2" entonces se busca la secuencia correspondiente siguiendo este camino:
Si el metodo de pago es de tipo "tarjeta de credito o debito" y "cambiar_secuencia_factura_con_TCTD": true → busca en la tabla runfood.estab_x_formapago la secuencia correspondiente.
Si documento es FACTURA y "secuencia_facturas_x_estab_y_emision": true y la factura esElectronica → tabla RANGO_ELECTRONICO filtrando por los valores "serie1", "serie2" de la factura + "bodega_default" (app.json). Si no existe un registro, pasa a la siguiente regla.
Si "documentos_x_bodega": true y "force_defaults": true → tabla "DOCUMENTO_BODEGA" filtrando por el valor "bodega_default". Si no existe un registro, lanza error.
Si "documentos_x_bodega": false o no existe en el archivo app.json → tabla "DOCUMENTO".
app.json habilita:"secuencia_facturas_x_estab_y_emision" : true
"serie1_default": "numero va aqui",
"serie2_default": "numero va aqui",
"force_defaults": true
OPCIONAL: Si vas a utilizar Facturación electrónica habilita también:
"facturaElectronica_default": true
DECLARE @ID_BODEGA as int = ### (tu ID de bodega)
BEGIN TRANSACTION
DELETE FROM CONFIGURACION_RUNFOOD where idBodega = @ID_BODEGA AND descripcion = 'SecuenciaDocumentosPorUsuario'
DELETE FROM runfood.CONFIGURACION_BODEGA where idBodega = @ID_BODEGA AND descripcion = 'SecuenciaDocumentosPorUsuario'
INSERT INTO runfood.CONFIGURACION_BODEGA (idBodega, descripcion, valor) values (@ID_BODEGA, 'SecuenciaDocumentosPorUsuario', 'true')
COMMIT TRANSACTION
DECLARE @serie1 as char(3) = '###'
DECLARE @serie2 as char(3) = '###'
DECLARE @idBodega as int = ###
DECLARE @numero_secuencial as int = ###
DECLARE @codigo_factura_sri as int = 4 -- "4" = factura / "7" = nota de credito
BEGIN TRANSACTION
IF EXISTS (SELECT * from rango_electronico where estab = @serie1 and ptoEmi = @serie2 and idBodega = @idBodega)
BEGIN
SELECT 'ya existe un registro en base de datos para estab = ''' + @serie1 + ''' ptoEmi = ''' + @serie2 + ''', idBodega = ' + cast(@idBodega as varchar(18)) + ' con la secuencia = ' + cast(@numero_secuencial as varchar(18)) as error
rollback TRANSACTION
END
ELSE
BEGIN
INSERT INTO RANGO_ELECTRONICO (estab, ptoEmi, numero, iddocumentoSRI, idBodega)
OUTPUT inserted.id, inserted.estab, inserted.ptoEmi, inserted.numero, inserted.idDocumentoSRI, inserted.idBodega
VALUES (@serie1, @serie2, @numero_secuencial, @codigo_factura_sri, @idBodega)
COMMIT TRANSACTION
END
Nota. Si el registro se ha creado, te va a devolver el registro con su ID, caso contrario, te va a devolver un mensaje de error. Vas a necesitar esos IDs para el siguiente paso.
OPCIONAL. En este punto también puedes asignar la secuencia correspondiente a los valores predeterminados (es decir "serie1_default" y "serie2_default" en app.json). Aunque no es recomendable. Sólo hazlo si tienes N servicios conectados a 1 unica bodega (Aunque la experiencia me ha enseñado que N servicios - 1 bodega no funciona bien porque no se sincronizan las mesas entre bodegas, ni productos. El sistema está pensado para trabajar 1 servicio - 1 bodega. Se deja mas que nada para que tengas una mejor comprensión del tema "secuencias por serie1 y serie2".)
DECLARE @idRangoElectronico AS INT = ###
DECLARE @idUsuario AS INT = ###
BEGIN TRANSACTION
IF EXISTS (
SELECT 1
FROM RANGO_ELECTRONICO_USUARIO reu
JOIN RANGO_ELECTRONICO re_exist ON re_exist.id = reu.idRangoElectronico -- rango que ya tiene
JOIN RANGO_ELECTRONICO re_new ON re_new.id = @idRangoElectronico -- rango que se quiere asignar
WHERE reu.idUsuario = @idUsuario
AND re_exist.idDocumentoSRI = re_new.idDocumentoSRI
AND re_exist.idBodega = re_new.idBodega
)
BEGIN
SELECT 'El usuario ' + CAST(@idUsuario AS VARCHAR(18))
+ ' ya tiene un rango asignado para el mismo documento ('
+ CAST((SELECT idDocumentoSRI FROM RANGO_ELECTRONICO WHERE id = @idRangoElectronico) AS VARCHAR(18))
+ ') y la misma bodega ('
+ CAST((SELECT idBodega FROM RANGO_ELECTRONICO WHERE id = @idRangoElectronico) AS VARCHAR(18))
+ '). Solo se permite 1 usuario - 1 documento - 1 bodega.' AS error;
ROLLBACK TRANSACTION
END
ELSE
BEGIN
INSERT INTO RANGO_ELECTRONICO_USUARIO (idUsuario, idRangoElectronico)
OUTPUT inserted.idUsuario, inserted.idRangoElectronico
VALUES (@idUsuario, @idRangoElectronico);
COMMIT TRANSACTION;
END
Nota. Si el registro se ha creado, te va a devolver los valores guardados. Caso contrario te va a lanzar un error.
Ahora el sistema está listo para trabajar. Como lo he explicado antes, si un usuario no cuenta con una secuencia asignada, usará la secuencia predeterminada.
Estás listo para hacer una factura real:
Entra con el usuario con secuencia personalizada.
Realiza una factura.
Revisa en la factura impresa (o la vista previa) los valores "serie1", "serie2" y "numero". Verifica que los parametros coinciden con que configuraste.
Listo!
Y también verifica la secuencia predeterminada:
Encontra con un usuario sin secuencia personalizada.
Realiza una factura.
Revisa en la factura impresa (o la vista previa) los valores "serie1", "serie2" y "numero". Verifica que los parametros coinciden con la configuración predeterminada.
Listo!
Configura cada sistema de acuerdo a su necesidad. Si hay más de 1 persona facturando en un mismo turno, habilita esta función.
Hay restaurantes donde cada mesero factura. Hay hoteles donde cada estación trabaja con su factura propia (por ejemplo cuando tienen Barra, Area de masajes, restaurante, etc).
Haz un buen analisis y configura según la necesidad del cliente.