manejo de recibos + mejoras #8

Open
rodo wants to merge 2 commits from 2026-mejoras-mas-recibo into main
  1. 22
      afip_ingresar_datos_emision.lua
  2. 131
      afip_ingresar_datos_operacion.lua
  3. 4
      afip_ingresar_datos_receptor.lua
  4. 21
      afip_ingresar_generacion_comprobantes.lua
  5. 22
      afip_ingresar_punto_venta_y_comprobante.lua

22
afip_ingresar_datos_emision.lua

@ -1,4 +1,11 @@
--[[
Se ignresan los siguientes datos de la operacion en AFIP:
- Bienes o Servicios o "Bienes y Servicios"
- Fecha del comprobante
- Fecha de servicio desde y hasta (en caso de corresponder)
- Vencimiento de pago
- Referencia
{
"uid": "53935f27-5cf0-4281-9a29-a68f100ee981",
"execution_status": "Borrador",
@ -28,6 +35,10 @@ local function logErrorAndExit(message)
error(message)
end
local function is_recibo(tipo)
return tipo == "recibo"
end
local function is_servicios(tipo_concepto)
if tipo_concepto == "servicios" or tipo_concepto == "servicio" then
return true
@ -108,6 +119,12 @@ local function main()
logErrorAndExit("afip_ingresar_datos_emision: tipo_concepto value not recognized: " .. tostring(tipoConceptoTexto))
end
local tipoComprobanteRaw = payload["tipo_comprobante"]
if not tipoComprobanteRaw or tipoComprobanteRaw == "" then
logErrorAndExit("afip_ingresar_datos_emision: tipo_comprobante is missing in payload")
end
--------------------------------------------------------------------
-- 1) Fecha de comprobante y concepto (ids: fc, idconcepto)
--------------------------------------------------------------------
@ -119,10 +136,15 @@ local function main()
logErrorAndExit("afip_ingresar_datos_emision: setTextFieldById for fechaComprobante failed: " .. err)
end
-- TODO: Un recibo no tiene un select para tipo de concepto!! a mi me sale directamente como servicios
if is_recibo(tipoComprobanteRaw) then
log("afip_ingresar_datos_emision: tipo_comprobante is 'recibo', skipping setting concepto")
else
err = setTextFieldById(conceptoId, tostring(conceptoValue))
if err then
logErrorAndExit("afip_ingresar_datos_emision: setTextFieldById for concepto failed: " .. err)
end
end
--------------------------------------------------------------------
-- 2) Periodo de servicio y vencimiento de pago (solo servicios o

131
afip_ingresar_datos_operacion.lua

@ -1,4 +1,6 @@
--[[
Ingresa los datos de la operacion en la pagina de AFIP, es la parte de la tabla donde se agregan los items, monto unitario y descripcion.
Recibe un JSON con los datos de la operacion, por ejemplo:
{
"uid": "53935f27-5cf0-4281-9a29-a68f100ee981",
"execution_status": "Borrador",
@ -18,70 +20,123 @@
}
--]]
log("Inicio afip_ingresar_datos_operacion from LUA!!")
local err
local json = require("json")
-- Parse the JSON string
local obj, err = json.decode(json_payload)
if err then
message = "Error parsing JSON: " .. err
----------------------------------------------------------------------
-- Helpers
----------------------------------------------------------------------
local function logErrorAndExit(message)
log(message)
error(message)
end
local error_on_page
local function is_factura(tipo_comprobante)
return string.match(tipo_comprobante, "factura")
end
local function is_recibo(tipo_comprobante)
return string.match(tipo_comprobante, "recibo")
end
descripcion = obj["descripcion"]
monto_unitario = obj["monto_unitario"]
tipo_comprobante = obj["tipo_comprobante"]
local function input_recibo_data(descripcion, monto_unitario, tipo_comprobante)
--[[
<textarea class="soloTexto" name="detalleDescripcion" id="detalle_descripcion" maxlength="400" style="width:500px;" rows="6" onkeypress="return limitarLongitudTextArea(event,this,400);" onkeyup="recortar(this,400);" onblur="recortar(this,400);"></textarea>
--]]
log("afip_ingresar_datos_operacion.input_recibo_data Descripcion: " .. descripcion .. " Monto: " .. monto_unitario .. " Tipo: " .. tipo_comprobante)
descripcion_selector = "#detalle_descripcion"
err = setTextFieldByQuerySelector(descripcion_selector, descripcion)
if err then
message = "Error setting detalle_descripcion: " .. err
logErrorAndExit(message)
end
--[[
if string.match(tipo_comprobante, "factura") then
log("Setting tipo_comprobante to factura")
tipo_comprobante = "factura"
else
log("Setting tipo_comprobante to ")
tipo_comprobante = "recibo"
--[[
<input type="text" class="soloNumerosConDecimales" name="detallePrecio" maxlength="16" id="detalle_precio" onkeyup="calcularSubtotalDetalle();">
--]]
precio_selector = "#detalle_precio"
err = setTextFieldByQuerySelector(precio_selector, monto_unitario)
if err then
message = "Error setting detalle_precio: " .. err
logErrorAndExit(message)
end
end
--]]
-- TODO: handle factura AND recibo!
log("Descripcion: " .. descripcion .. " Monto: " .. monto_unitario .. " Tipo: " .. tipo_comprobante)
local function input_factura_data(descripcion, monto_unitario, tipo_comprobante)
log("afip_ingresar_datos_operacion.input_factura_data Descripcion: " .. descripcion .. " Monto: " .. monto_unitario .. " Tipo: " .. tipo_comprobante)
-- TODO: Properly handle recibo which has different fields!
-- Descripcion : <textarea class="soloTexto" name="detalleDescripcion" id="detalle_descripcion" maxlength="400" style="width:500px;" rows="6" onkeypress="return limitarLongitudTextArea(event,this,400);" onkeyup="recortar(this,400);" onblur="recortar(this,400);"></textarea>
-- Monto:
descripcion_selector = "#detalle_descripcion1"
precio_selector = "#detalle_precio1"
descripcion_selector = "#detalle_descripcion1"
precio_selector = "#detalle_precio1"
err = waitVisibleByQuerySelector(descripcion_selector)
if err then
err = waitVisibleByQuerySelector(descripcion_selector)
if err then
message = "Error waiting for detalle_descripcion1: " .. err
log(message)
error(message)
end
end
err = setTextFieldByQuerySelector(descripcion_selector, descripcion)
if err then
err = setTextFieldByQuerySelector(descripcion_selector, descripcion)
if err then
message = "Error setting detalle_descripcion1: " .. err
log(message)
error(message)
end
end
waitSecs(1)
waitSecs(1)
err = waitVisibleByQuerySelector(precio_selector)
if err then
err = waitVisibleByQuerySelector(precio_selector)
if err then
message = "Error waiting for detalle_precio1: " .. err
log(message)
error(message)
end
end
err = setTextFieldByQuerySelector(precio_selector, monto_unitario)
if err then
err = setTextFieldByQuerySelector(precio_selector, monto_unitario)
if err then
message = "Error setting detalle_precio1: " .. err
log(message)
error(message)
end
waitSecs(1)
end
waitSecs(1)
log("Finishing afip_ingresar_datos_operacion from LUA!!")
----------------------------------------------------------------------
-- Main logic
----------------------------------------------------------------------
local function main()
log("Inicio afip_ingresar_datos_operacion from LUA!!")
local err
local json = require("json")
-- Parse the JSON string
local obj, err = json.decode(json_payload)
if err then
message = "Error parsing JSON: " .. err
log(message)
error(message)
end
local error_on_page
descripcion = obj["descripcion"]
monto_unitario = obj["monto_unitario"]
tipo_comprobante = obj["tipo_comprobante"]
if is_factura(tipo_comprobante) then
input_factura_data(descripcion, monto_unitario, tipo_comprobante)
elseif is_recibo(tipo_comprobante) then
input_recibo_data(descripcion, monto_unitario, tipo_comprobante)
else
message = "Tipo de comprobante no soportado en afip_ingresar_datos_operacion: " .. tostring(tipo_comprobante)
logErrorAndExit(message)
end
log("Finishing afip_ingresar_datos_operacion")
end
local ok, err = pcall(main)
if not ok then
-- Let Go see this as a Lua error so it can fall back to legacy datosDeEmision
logErrorAndExit("afip_ingresar_datos_operacion failed: " .. tostring(err))
end

4
afip_ingresar_datos_receptor.lua

@ -1,4 +1,8 @@
--[[
Se ingresa la informacion del receptor:
- Tipo IVA del receptor (responsable inscripto, consumidor final, monotributo, etc)
- CUIT del receptor (si corresponde)
- Forma de pago (contado, tarjeta de credito, cuenta corriente, etc)
{
"uid": "53935f27-5cf0-4281-9a29-a68f100ee981",
"execution_status": "Borrador",

21
afip_ingresar_generacion_comprobantes.lua

@ -1,3 +1,24 @@
--[[
Desde el menu principal de AFIP se ingresa a la funcionalidad de Generacion de Comprobantes.
{
"uid": "53935f27-5cf0-4281-9a29-a68f100ee981",
"execution_status": "Borrador",
"tipo_comprobante": "factura c",
"fecha_comprobante": "13/11/2025",
"tipo_concepto": "servicios",
"servicio_fecha_desde": "01/10/2025",
"servicio_fecha_hasta": "01/10/2025",
"servicio_fecha_vencimiento_pago": "13/11/2025",
"referencia": "",
"tipo_iva_receptor": "consumidor final",
"cuit_receptor": "",
"forma_pago": "contado",
"monto_unitario": "10000",
"cantidad": "1",
"descripcion": "Clase de apoyo"
}
--]]
local json = require("json")
----------------------------------------------------------------------

22
afip_ingresar_punto_venta_y_comprobante.lua

@ -1,6 +1,9 @@
-- TODO GENERAL: El json del comprobante no contiene el punto de venta, esto es algo que es atributo del cliente!
-- TODO GENERAL: Completar la generacion de factura A y B (hoy solo esta C de monotributo)
--[[
Se ingresa:
- Punto de venta (dropdown con los elementos)
- El tipo de comprobante a generar (factura A, B, C, recibo, nota de debito, nota de credito, etc)
{
"uid": "53935f27-5cf0-4281-9a29-a68f100ee981",
"execution_status": "Borrador",
@ -117,7 +120,7 @@ local function mapTipoComprobante(tipo)
return "7" -- TODO: Check real value
end
return tipo or ""
return ""
end
----------------------------------------------------------------------
@ -192,6 +195,19 @@ local function main()
--------------------------------------------------------------------
local tipoComprobanteId = "universocomprobante"
--[[
<select name="universoComprobante" onchange="actualizarDescripcionTC(this.selectedIndex);" id="universocomprobante">
<option value="2">Factura C</option>
<option value="3">Nota de Débito C</option>
<option value="4">Nota de Crédito C</option>
<option value="5">Recibo C</option>
<option value="120">Factura de Crédito Electrónica MiPyMEs (FCE) C</option>
<option value="121">Nota de Débito Electrónica MiPyMEs (FCE) C</option>
<option value="122">Nota de Crédito Electrónica MiPyMEs (FCE) C</option>
</select>
]]--
-- ERROR: 2026/01/19 23:57:13 Error running script: <string>:45: afip_ingresar_punto_venta_y_comprobante failed: <string>:45: afip_ingresar_punto_venta_y_comprobante: setTextFieldById for tipo_comprobante failed: could not set value on node 65
-- TODO: The error above does not affect the flow, but happens because after the punto de venta is selected, the tipo de comprobante select is set with the first value which happens to be already "factura c (2)". So when we try to set it again to the same value, it fails. We should improve the function to not fail in this case. Needs some more binding functions on the Go Side.
err = setTextFieldById(tipoComprobanteId, tostring(tipoComprobanteValor))
if err then
logErrorAndExit(

Loading…
Cancel
Save