From 7274540084314286276cdbf1d53a93f4fbb91c22 Mon Sep 17 00:00:00 2001 From: rodley82 Date: Sun, 23 Nov 2025 23:15:31 -0300 Subject: [PATCH 1/6] version funcionando --- afip_ingresar_datos_receptor.lua | 250 +++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 afip_ingresar_datos_receptor.lua diff --git a/afip_ingresar_datos_receptor.lua b/afip_ingresar_datos_receptor.lua new file mode 100644 index 0000000..986b614 --- /dev/null +++ b/afip_ingresar_datos_receptor.lua @@ -0,0 +1,250 @@ +--[[ +{ + "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") + +---------------------------------------------------------------------- +-- Helpers +---------------------------------------------------------------------- +local function logErrorAndExit(message) + log(message) + error(message) +end + +-- Based on the values from the json returns the expected option value to select on the the UI +--[[ +// +// +// +// +// +// +// +// +// +// +// +// +]]-- +local function mapTipoIvaReceptor(tipo) + if is_consumidor_final(tipo) then + return "5" + end + if is_responsable_inscripto(tipo) then + return "1" + end + if is_responsable_monotributo(tipo) then + return "6" + end + return "" +end + +local function is_consumidor_final(tipo) + return tipo == "consumidor final" or tipo == "final" +end + +local function is_responsable_inscripto(tipo) + return tipo == "responsable inscripto" or tipo == "responsable" +end + +local function is_responsable_monotributo(tipo) + return tipo == "responsable monotributo" or tipo == "monotributo" or tipo == "monotributista" +end + +local function mapFormaPago(forma) + --[[ + // + // + // + // + // + // + // + // + + FormaPagoInvalido = 0 + FormaPagoContado = 1 + FormaPagoTarjetaDebito = 2 + FormaPagoTarjetaCredito = 3 + FormaPagoCuentaCorriente = 4 + FormaPagoCheque = 5 + FormaPagoTicket = 6 + FormaPagoOtra = 7 + + case "contado", "efectivo": + return FormaPagoContado, nil + case "debito", "tarjeta de debito": + return FormaPagoTarjetaDebito, nil + case "credito", "tarjeta de credito": + return FormaPagoTarjetaCredito, nil + case "cuenta corriente", "cta corriente": + return FormaPagoCuentaCorriente, nil + case "cheque": + return FormaPagoCheque, nil + case "ticket": + return FormaPagoTicket, nil + case "otra", "otro": + return FormaPagoOtra, nil + ]]-- + + if forma == "contado" or forma == "efectivo" then + return "1" + end + if forma == "debito" or forma == "tarjeta de debito" then + return "2" + end + if forma == "credito" or forma == "tarjeta de credito" then + return "3" + end + if forma == "cuenta corriente" or forma == "cta corriente" then + return "4" + end + if forma == "cheque" then + return "5" + end + if forma == "ticket" then + return "6" + end + if forma == "otra" or forma == "otro" then + return "7" + end + return "" +end + +---------------------------------------------------------------------- +-- Main logic +---------------------------------------------------------------------- + +local function main() + log("afip_ingresar_datos_receptor: starting") + + local payload, err = json.decode(json_payload) + log("afip_ingresar_datos_receptor: decoded payload: " .. json.encode(payload)) + if err then + logErrorAndExit("afip_ingresar_datos_receptor: error decoding payload: " .. err) + end + + -------------------------------------------------------------------- + -- Extract fields from payload + -------------------------------------------------------------------- + local tipoIvaReceptor = payload["tipo_iva_receptor"] or "" + local cuitReceptor = payload["cuit_receptor"] or "" + local formaPago = payload["forma_pago"] or "" + + if tipoIvaReceptor == "" then + logErrorAndExit("afip_ingresar_datos_receptor: tipo_iva_receptor is empty") + end + if formaPago == "" then + logErrorAndExit("afip_ingresar_datos_receptor: forma_pago is empty") + end + + local ivaValue = mapTipoIvaReceptor(tipoIvaReceptor) + local formaValue = mapFormaPago(formaPago) + + -------------------------------------------------------------------- + -- 1) Select IVA del receptor (select#idivareceptor) + -------------------------------------------------------------------- + local ivaId = "idivareceptor" + err = setTextFieldById(ivaId, tostring(ivaValue)) + + if err then + logErrorAndExit("afip_ingresar_datos_receptor: set IVA failed: " .. err) + end + + log("afip_ingresar_datos_receptor: IVA receptor set to " .. tostring(ivaValue)) + + -------------------------------------------------------------------- + -- 2) Ingresar CUIT receptor si corresponde + -- (Go logic: only for some IVA types and when CUIT is non-empty) + -- Here we only check that CUIT is non-empty; if you want to restrict + -- by tipoIva, put that logic in requiresCuit(type). + -------------------------------------------------------------------- + + local function requiresCuit(tipo) + -- Should we check that CUIT is non-empty? + return is_responsable_inscripto(tipo) or is_responsable_monotributo(tipo) + end + + if requiresCuit(tipoIvaReceptor) then + local cuitSelectorId = "nrodocreceptor" + + err = waitVisibleById(cuitSelectorId) + if err then + logErrorAndExit("afip_ingresar_datos_receptor: waitVisible CUIT failed: " .. err) + end + + --ok, setErr = pcall(function() + -- -- Clear first, then set and send Tab (same idea as Go code: SetValue + Tab) + -- clearTextFieldByQuerySelector(cuitSelector) + -- setTextFieldByQuerySelector(cuitSelector, tostring(cuitReceptor)) + -- sendReturnKeyByQuerySelector(cuitSelector) -- or Tab if you add a binding; Enter usually also triggers validation + --end) + --if not ok then + -- error("afip_ingresar_datos_receptor: set CUIT failed: " .. tostring(setErr)) + --end + err = setTextFieldById(cuitSelectorId, tostring(cuitReceptor)) + if err then + logErrorAndExit("afip_ingresar_datos_receptor: setTextFieldById failed: " .. err) + end + + err = sendTabKeyById(cuitSelectorId) + if err then + logErrorAndExit("afip_ingresar_datos_receptor: sendTabKeyById failed: " .. err) + end + + log("afip_ingresar_datos_receptor: CUIT receptor set to " .. tostring(cuitReceptor)) + else + log("afip_ingresar_datos_receptor: CUIT not required for tipo_iva_receptor=" .. tostring(tipoIvaReceptor)) + end + + -------------------------------------------------------------------- + -- 3) Seleccionar forma de pago (input[id=formadepagoX]) + -------------------------------------------------------------------- + if formaValue ~= nil and formaValue ~= "" then + log("afip_ingresar_datos_receptor: seleccionando forma de pago " .. tostring(formaValue)) + local formaSelector = "#formadepago" .. tostring(formaValue) + + err = waitVisibleByQuerySelector(formaSelector) + + if err then + logErrorAndExit("afip_ingresar_datos_receptor: waitVisible formaPago failed: " .. tostring(waitErr)) + end + + err = clickElementByQuerySelector(formaSelector) + if err then + logErrorAndExit("afip_ingresar_datos_receptor: click formaPago failed: " .. tostring(setErr)) + end + + log("afip_ingresar_datos_receptor: forma_pago selected: " .. tostring(formaValue)) + else + log("afip_ingresar_datos_receptor: forma_pago is empty, skipping selection") + end + + -------------------------------------------------------------------- + -- Done + -------------------------------------------------------------------- + log("afip_ingresar_datos_receptor: completed successfully") +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 datosReceptor + logErrorAndExit("afip_ingresar_datos_receptor failed: " .. tostring(err)) +end From 03b0b2c4c37ac4bab3a4cb85a9b397494517a573 Mon Sep 17 00:00:00 2001 From: rodley82 Date: Mon, 24 Nov 2025 00:12:59 -0300 Subject: [PATCH 2/6] working --- afip_ingresar_datos_emision.lua | 183 ++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 afip_ingresar_datos_emision.lua diff --git a/afip_ingresar_datos_emision.lua b/afip_ingresar_datos_emision.lua new file mode 100644 index 0000000..54c70e1 --- /dev/null +++ b/afip_ingresar_datos_emision.lua @@ -0,0 +1,183 @@ +--[[ +{ + "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") + +---------------------------------------------------------------------- +-- Helpers +---------------------------------------------------------------------- +local function logErrorAndExit(message) + log(message) + error(message) +end + +local function is_servicios(tipo_concepto) + if tipo_concepto == "servicios" or tipo_concepto == "servicio" then + return true + end + return false +end + +local function is_productos_y_servicios(tipo_concepto) + if tipo_concepto == "productos y servicios" or tipo_concepto == "productos servicios" then + return true + end + return false +end + +local function is_productos(tipo_concepto) + if tipo_concepto == "productos" or tipo_concepto == "producto" then + return true + end + return false +end + +-- Map "tipo_concepto" (as text) to the numeric value expected by AFIP in +-- the "idconcepto" select. +-- Mirrors TipoConceptoFromString in Go (internal/robot/tipos.go). +local function mapTipoConcepto(tipo) + if is_productos(tipo) then + return "1" -- TipoConceptoProductos + end + if is_servicios(tipo) then + return "2" -- TipoConceptoServicios + end + if is_productos_y_servicios(tipo) then + return "3" -- TipoConceptoProductosYServicios + end + + return "" +end + +local function conceptoRequierePeriodoServicio(tipo) + if is_servicios(tipo) or is_productos_y_servicios(tipo) then + return true + end + + return false +end + +---------------------------------------------------------------------- +-- Main logic +---------------------------------------------------------------------- + +local function main() + log("afip_ingresar_datos_emision: starting") + + local payload, err = json.decode(json_payload) + log("afip_ingresar_datos_emision: decoded payload: " .. json.encode(payload)) + if err then + logErrorAndExit("afip_ingresar_datos_emision: error decoding payload: " .. err) + end + + -------------------------------------------------------------------- + -- Extract fields from payload + -------------------------------------------------------------------- + local fechaComprobante = payload["fecha_comprobante"] or "" + local tipoConceptoTexto = payload["tipo_concepto"] or "" + local servicioFechaDesde = payload["servicio_fecha_desde"] or "" + local servicioFechaHasta = payload["servicio_fecha_hasta"] or "" + local servicioFechaVencimiento= payload["servicio_fecha_vencimiento_pago"] or "" + local referencia = payload["referencia"] or "" + + if fechaComprobante == "" then + logErrorAndExit("afip_ingresar_datos_emision: fecha_comprobante is empty") + end + if tipoConceptoTexto == "" then + logErrorAndExit("afip_ingresar_datos_emision: tipo_concepto is empty") + end + + local conceptoValue = mapTipoConcepto(tipoConceptoTexto) + if conceptoValue == "" then + logErrorAndExit("afip_ingresar_datos_emision: tipo_concepto value not recognized: " .. tostring(tipoConceptoTexto)) + end + + -------------------------------------------------------------------- + -- 1) Fecha de comprobante y concepto (ids: fc, idconcepto) + -------------------------------------------------------------------- + local fechaComprobanteId = "fc" + local conceptoId = "idconcepto" + + err = setTextFieldById(fechaComprobanteId, tostring(fechaComprobante)) + if err then + logErrorAndExit("afip_ingresar_datos_emision: setTextFieldById for fechaComprobante failed: " .. err) + end + + err = setTextFieldById(conceptoId, tostring(conceptoValue)) + if err then + logErrorAndExit("afip_ingresar_datos_emision: setTextFieldById for concepto failed: " .. err) + end + + -------------------------------------------------------------------- + -- 2) Periodo de servicio y vencimiento de pago (solo servicios o + -- productos y servicios) + -------------------------------------------------------------------- + if conceptoRequierePeriodoServicio(tipoConceptoTexto) then + log("afip_ingresar_datos_emision: setting service period and due date") + + if servicioFechaDesde == "" or servicioFechaHasta == "" or servicioFechaVencimiento == "" then + logErrorAndExit("afip_ingresar_datos_emision: service period dates are required when tipo_concepto is 'servicios' or 'productos y servicios'") + end + + local fechaDesdeId = "fsd" + local fechaHastaId = "fsh" + local fechaVencimientoPagoId = "vencimientopago" + + err = setTextFieldById(fechaDesdeId, tostring(servicioFechaDesde)) + if err then + logErrorAndExit("afip_ingresar_datos_emision: setTextFieldById for fechaDesde failed: " .. err) + end + + err = setTextFieldById(fechaHastaId, tostring(servicioFechaHasta)) + if err then + logErrorAndExit("afip_ingresar_datos_emision: setTextFieldById for fechaHasta failed: " .. err) + end + + err = setTextFieldById(fechaVencimientoPagoId, tostring(servicioFechaVencimiento)) + if err then + logErrorAndExit("afip_ingresar_datos_emision: setTextFieldById for fechaVencimientoPago failed: " .. err) + end + else + log("afip_ingresar_datos_emision: tipo_concepto does not require service period: " .. tostring(tipoConceptoTexto)) + end + + -------------------------------------------------------------------- + -- 3) Referencia (id: refComEmisor) + -------------------------------------------------------------------- + local referenciaId = "refComEmisor" + + -- Even if referencia is empty, setting the field should be harmless and + -- mirrors the Go behavior that always calls SetValue. + err = setTextFieldById(referenciaId, tostring(referencia)) + if err then + logErrorAndExit("afip_ingresar_datos_emision: setTextFieldById for referencia failed: " .. err) + end + + -------------------------------------------------------------------- + -- Done + -------------------------------------------------------------------- + log("afip_ingresar_datos_emision: completed successfully") +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_emision failed: " .. tostring(err)) +end From 821a9ab8a2ed604488aeac3beaa1397f5cc406f2 Mon Sep 17 00:00:00 2001 From: rodley82 Date: Tue, 25 Nov 2025 12:04:27 -0300 Subject: [PATCH 3/6] tested these two --- afip_ingresar_datos_receptor.lua | 54 ++++-- afip_ingresar_punto_venta_y_comprobante.lua | 202 ++++++++++++++++++++ 2 files changed, 243 insertions(+), 13 deletions(-) create mode 100644 afip_ingresar_punto_venta_y_comprobante.lua diff --git a/afip_ingresar_datos_receptor.lua b/afip_ingresar_datos_receptor.lua index 986b614..7270de6 100644 --- a/afip_ingresar_datos_receptor.lua +++ b/afip_ingresar_datos_receptor.lua @@ -28,6 +28,18 @@ local function logErrorAndExit(message) error(message) end +local function is_consumidor_final(tipo) + return tipo == "consumidor final" or tipo == "final" +end + +local function is_responsable_inscripto(tipo) + return tipo == "responsable inscripto" or tipo == "responsable" +end + +local function is_responsable_monotributo(tipo) + return tipo == "responsable monotributo" or tipo == "monotributo" or tipo == "monotributista" +end + -- Based on the values from the json returns the expected option value to select on the the UI --[[ // @@ -56,16 +68,32 @@ local function mapTipoIvaReceptor(tipo) return "" end -local function is_consumidor_final(tipo) - return tipo == "consumidor final" or tipo == "final" +local function is_forma_pago_contado(forma) + return forma == "contado" or forma == "efectivo" end -local function is_responsable_inscripto(tipo) - return tipo == "responsable inscripto" or tipo == "responsable" +local function is_forma_pago_debito(forma) + return forma == "debito" or forma == "tarjeta de debito" end -local function is_responsable_monotributo(tipo) - return tipo == "responsable monotributo" or tipo == "monotributo" or tipo == "monotributista" +local function is_forma_pago_credito(forma) + return forma == "credito" or forma == "tarjeta de credito" +end + +local function is_forma_pago_cuenta_corriente(forma) + return forma == "cuenta corriente" or forma == "cta corriente" +end + +local function is_forma_pago_cheque(forma) + return forma == "cheque" +end + +local function is_forma_pago_ticket(forma) + return forma == "ticket" +end + +local function is_forma_pago_otra(forma) + return forma == "otra" or forma == "otro" end local function mapFormaPago(forma) @@ -104,25 +132,25 @@ local function mapFormaPago(forma) return FormaPagoOtra, nil ]]-- - if forma == "contado" or forma == "efectivo" then + if is_forma_pago_contado(forma) then return "1" end - if forma == "debito" or forma == "tarjeta de debito" then + if is_forma_pago_debito(forma) then return "2" end - if forma == "credito" or forma == "tarjeta de credito" then + if is_forma_pago_credito(forma) then return "3" end - if forma == "cuenta corriente" or forma == "cta corriente" then + if is_forma_pago_cuenta_corriente(forma) then return "4" end - if forma == "cheque" then + if is_forma_pago_cheque(forma) then return "5" end - if forma == "ticket" then + if is_forma_pago_ticket(forma) then return "6" end - if forma == "otra" or forma == "otro" then + if is_forma_pago_otra(forma) then return "7" end return "" diff --git a/afip_ingresar_punto_venta_y_comprobante.lua b/afip_ingresar_punto_venta_y_comprobante.lua new file mode 100644 index 0000000..c668f54 --- /dev/null +++ b/afip_ingresar_punto_venta_y_comprobante.lua @@ -0,0 +1,202 @@ +-- TODO GENERAL: El json del comprobante no contiene el punto de venta, esto es algo que es atributo del cliente! + +--[[ +{ + "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", + "request": { + "request_uid": "f976aa76-8d49-4564-8e44-2100819bae77", + "execution_status": "Fallido", + "user_uid": "bc31ddeb-b8c7-48e1-b569-20bbd8e7ec12", + "options": { + "automatic_confirmation_flag": false + }, + "csv_data": "factura c,16/11/2025,servicios,01/10/2025,01/10/2025,16/11/2025,,monotributo,27287630412,contado,10000,1,Clase de apoyo\\n", + "credentials": { + "cuit": "20292929092", + "password": "password", + "orden_punto_venta": 1, + "nombre_empresa": "NOMBRE DE EMPRESA" + } + } +} +--]] + +local json = require("json") + +---------------------------------------------------------------------- +-- Helpers +---------------------------------------------------------------------- +local function logErrorAndExit(message) + log(message) + error(message) +end + +-- Normalizar el input que viene del JSON por si acaso lowercase +local function normalize(s) + if not s then return "" end + s = string.lower(s) + -- s = s:gsub("^%s+", ""):gsub("%s+$", "") + return s +end + +-- TODO: Factura A o B +local function is_factura_a(tipo) + return tipo == "factura a" or tipo == "a" +end + +local function is_factura_b(tipo) + return tipo == "factura b" or tipo == "b" +end + +local function is_factura_c(tipo) + return tipo == "factura c" or tipo == "c" +end + +local function is_nota_debito(tipo) + return tipo == "nota de debito" or tipo == "debito" +end + +local function is_nota_credito(tipo) + return tipo == "nota de credito" or tipo == "credito" +end + +local function is_recibo(tipo) + return tipo == "recibo" +end + +--[[ +Valores que corresponden al value del select + TipoComprobanteInvalido = 0 + TipoComprobanteFacturaC = 2 + TipoComprobanteNotaDebito = 3 + TipoComprobanteNotaCredito = 4 + TipoComprobanteRecibo = 5 +]]-- +local function mapTipoComprobante(tipo) + local t = normalize(tipo) + + if is_factura_c(t) then + return "2" + elseif is_nota_debito(t) then + return "3" + elseif is_nota_credito(t) then + return "4" + elseif is_recibo(t) then + return "5" + elseif is_factura_a(t) then + return "6" -- TODO: Check real value + elseif is_factura_b(t) then + return "7" -- TODO: Check real value + end + + return tipo or "" +end + +---------------------------------------------------------------------- +-- Main logic +---------------------------------------------------------------------- +local function main() + log("afip_ingresar_punto_venta_y_comprobante: starting") + + -------------------------------------------------------------------- + -- Decode payload + -------------------------------------------------------------------- + local payload, err = json.decode(json_payload) + log("afip_ingresar_punto_venta_y_comprobante: decoded payload: " .. json.encode(payload)) + if err then + logErrorAndExit("afip_ingresar_punto_venta_y_comprobante: error decoding payload: " .. err) + end + + -------------------------------------------------------------------- + -- Extract fields from payload + -------------------------------------------------------------------- + -- Punto de venta: should correspond to comprobante.PuntoDeVenta + -- as used in Go (selectDropdownItemByPosition second argument). + local puntoDeVenta = nil + if payload["request"] and payload["request"]["credentials"] and payload["request"]["credentials"]["orden_punto_venta"] then + puntoDeVenta = payload["request"]["credentials"]["orden_punto_venta"] + else + logErrorAndExit("afip_ingresar_punto_venta_y_comprobante: punto_de_venta is missing in payload") + end + + -- Tipo de comprobante: we can receive textual or numeric. + local tipoComprobanteRaw = payload["tipo_comprobante"] + + if not tipoComprobanteRaw or tipoComprobanteRaw == "" then + logErrorAndExit("afip_ingresar_punto_venta_y_comprobante: tipo_comprobante is missing in payload") + end + + -- Ensure punto de venta is numeric + local puntoDeVentaNum = tonumber(puntoDeVenta) + if not puntoDeVentaNum then + logErrorAndExit( + "afip_ingresar_punto_venta_y_comprobante: punto_de_venta must be numeric, got: " .. tostring(puntoDeVenta) + ) + end + + local tipoComprobanteValor = mapTipoComprobante(tipoComprobanteRaw) + if tipoComprobanteValor == "" then + logErrorAndExit( + "afip_ingresar_punto_venta_y_comprobante: tipo_comprobante could not be mapped: " .. + tostring(tipoComprobanteRaw) + ) + end + + log("afip_ingresar_punto_venta_y_comprobante: punto_de_venta=", tostring(puntoDeVentaNum), + " tipo_comprobante_valor=", tostring(tipoComprobanteValor)) + + -------------------------------------------------------------------- + -- 1) Seleccionar punto de venta (select#puntodeventa) + -------------------------------------------------------------------- + local puntoVentaId = "puntodeventa" + + -- Uses the binding selectDropdownItemByPosition(id, position) + err = selectDropdownItemByPosition(puntoVentaId, puntoDeVentaNum) + if err then + logErrorAndExit( + "afip_ingresar_punto_venta_y_comprobante: selectDropdownItemByPosition failed for punto_de_venta: " .. + tostring(err) + ) + end + log("afip_ingresar_punto_venta_y_comprobante: punto_de_venta selected OK") + + -------------------------------------------------------------------- + -- 2) Seleccionar tipo de comprobante (select#universocomprobante) + -------------------------------------------------------------------- + local tipoComprobanteId = "universocomprobante" + + err = setTextFieldById(tipoComprobanteId, tostring(tipoComprobanteValor)) + if err then + logErrorAndExit( + "afip_ingresar_punto_venta_y_comprobante: setTextFieldById for tipo_comprobante failed: " .. + tostring(err) + ) + end + + log("afip_ingresar_punto_venta_y_comprobante: tipo_comprobante selected OK") + + -------------------------------------------------------------------- + -- Done + -------------------------------------------------------------------- + log("afip_ingresar_punto_venta_y_comprobante: completed successfully") +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 + logErrorAndExit("afip_ingresar_punto_venta_y_comprobante failed: " .. tostring(err)) +end From 16f62f953383235510463d8c4529c194677c6c79 Mon Sep 17 00:00:00 2001 From: rodley82 Date: Tue, 25 Nov 2025 12:21:24 -0300 Subject: [PATCH 4/6] Agregado comentario importante sobre seleccion de tipo de comprobante --- afip_ingresar_punto_venta_y_comprobante.lua | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/afip_ingresar_punto_venta_y_comprobante.lua b/afip_ingresar_punto_venta_y_comprobante.lua index c668f54..1edba79 100644 --- a/afip_ingresar_punto_venta_y_comprobante.lua +++ b/afip_ingresar_punto_venta_y_comprobante.lua @@ -53,6 +53,20 @@ local function normalize(s) return s end +--[[ +TODO: Analizar la posta, los tipos de comprobantes dependen del punto de venta, en el caso de un monotributo salen estos +asi que ver como hacer con el caso de un consumidor final y otros. Quizas buscar por el texto y en funcion de eso elegir el valor? (como se hace con el punto de venta?) + + +]]-- -- TODO: Factura A o B local function is_factura_a(tipo) return tipo == "factura a" or tipo == "a" From 2a73c8a311840b0f2d69f3f85716261bbd2b0b20 Mon Sep 17 00:00:00 2001 From: rodley82 Date: Tue, 25 Nov 2025 12:38:19 -0300 Subject: [PATCH 5/6] generacion comprobantes --- afip_ingresar_generacion_comprobantes.lua | 57 +++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 afip_ingresar_generacion_comprobantes.lua diff --git a/afip_ingresar_generacion_comprobantes.lua b/afip_ingresar_generacion_comprobantes.lua new file mode 100644 index 0000000..c6bfa81 --- /dev/null +++ b/afip_ingresar_generacion_comprobantes.lua @@ -0,0 +1,57 @@ +local json = require("json") + +---------------------------------------------------------------------- +-- Helpers +---------------------------------------------------------------------- +local function logErrorAndExit(message) + log(message) + error(message) +end + +---------------------------------------------------------------------- +-- Main logic +---------------------------------------------------------------------- +local function main() + log("afip_ingresar_generacion_comprobantes: starting") + + -------------------------------------------------------------------- + -- Decode payload (currently unused but kept for future extensibility) + -------------------------------------------------------------------- + local payload, err = json.decode(json_payload or "{}") + if err then + logErrorAndExit("afip_ingresar_generacion_comprobantes: error decoding payload: " .. err) + end + + -------------------------------------------------------------------- + -- Click on the Generar Comprobantes button + -- This mirrors the Go logic that waits for and clicks the element + -- with id="btn_gen_cmp" using chromedp. + -------------------------------------------------------------------- + local btnId = "btn_gen_cmp" + + -- Ensure the element is visible first + err = waitVisibleById(btnId) + if err then + logErrorAndExit( + "afip_ingresar_generacion_comprobantes: waitVisibleById failed for btnId= " .. + tostring(btnId) .. ": " .. tostring(err) + ) + end + + -- Click using id + err = clickElementById(btnId) + if err then + logErrorAndExit( + "afip_ingresar_generacion_comprobantes: clickElementById failed for btnId= " .. + tostring(btnId) .. ": " .. tostring(err) + ) + end + + log("afip_ingresar_generacion_comprobantes: completed successfully") +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 + logErrorAndExit("afip_ingresar_generacion_comprobantes failed: " .. tostring(err)) +end From 3c98cbf71cf86889a05e7bfd9f193c5968d6835b Mon Sep 17 00:00:00 2001 From: rodley82 Date: Sat, 6 Dec 2025 20:28:23 -0300 Subject: [PATCH 6/6] loading_bb_now_part_of_each_repo --- afip_confirmar_automaticamente.lua | 3 -- afip_ingresar_datos_operacion.lua | 2 -- afip_ingresar_datos_receptor.lua | 1 - afip_ingresar_punto_venta_y_comprobante.lua | 1 - afip_inicio_loading.lua | 32 +++++++++++++++++++++ afip_login.lua | 5 +--- botbunny_inicio.lua | 21 -------------- 7 files changed, 33 insertions(+), 32 deletions(-) create mode 100644 afip_inicio_loading.lua delete mode 100644 botbunny_inicio.lua diff --git a/afip_confirmar_automaticamente.lua b/afip_confirmar_automaticamente.lua index e6c5535..0a69dcf 100644 --- a/afip_confirmar_automaticamente.lua +++ b/afip_confirmar_automaticamente.lua @@ -1,9 +1,6 @@ log("Inicio confirmation from LUA!!") local err -print("BEFORE JSON LOADING payload: " .. json_payload) local json = require("json") -print("AFTER JSON LOADING") --- Parse the JSON string local obj, err = json.decode(json_payload) local error_on_page diff --git a/afip_ingresar_datos_operacion.lua b/afip_ingresar_datos_operacion.lua index 746cb2f..f065f19 100644 --- a/afip_ingresar_datos_operacion.lua +++ b/afip_ingresar_datos_operacion.lua @@ -21,9 +21,7 @@ log("Inicio afip_ingresar_datos_operacion from LUA!!") local err -print("BEFORE JSON LOADING payload: " .. json_payload) local json = require("json") -print("AFTER JSON LOADING") -- Parse the JSON string local obj, err = json.decode(json_payload) if err then diff --git a/afip_ingresar_datos_receptor.lua b/afip_ingresar_datos_receptor.lua index 7270de6..8900c28 100644 --- a/afip_ingresar_datos_receptor.lua +++ b/afip_ingresar_datos_receptor.lua @@ -164,7 +164,6 @@ local function main() log("afip_ingresar_datos_receptor: starting") local payload, err = json.decode(json_payload) - log("afip_ingresar_datos_receptor: decoded payload: " .. json.encode(payload)) if err then logErrorAndExit("afip_ingresar_datos_receptor: error decoding payload: " .. err) end diff --git a/afip_ingresar_punto_venta_y_comprobante.lua b/afip_ingresar_punto_venta_y_comprobante.lua index 1edba79..10dbbd3 100644 --- a/afip_ingresar_punto_venta_y_comprobante.lua +++ b/afip_ingresar_punto_venta_y_comprobante.lua @@ -130,7 +130,6 @@ local function main() -- Decode payload -------------------------------------------------------------------- local payload, err = json.decode(json_payload) - log("afip_ingresar_punto_venta_y_comprobante: decoded payload: " .. json.encode(payload)) if err then logErrorAndExit("afip_ingresar_punto_venta_y_comprobante: error decoding payload: " .. err) end diff --git a/afip_inicio_loading.lua b/afip_inicio_loading.lua new file mode 100644 index 0000000..f20d1df --- /dev/null +++ b/afip_inicio_loading.lua @@ -0,0 +1,32 @@ +log("inicia afip_inicio_loading") +local err +local json = require("json") +local obj, err = json.decode(json_payload) + +if err then + log("Decoding JSON error" .. err) + error("Decoding JSON error" .. err) +end + +local function post_to_n8n(endpoint, json) + local http = require("http") + local client = http.client() + local request = http.request("POST", endpoint, json) + request:header_set("Content-Type", "application/json") + local result, err = client:do_request(request) + if err then + log_print("post_to_n8n error: " .. err) + error(err) + end +end + +post_to_n8n("https://automation.rodley.ar/webhook/98b3a336-bb11-4b36-b206-c48690b54e0f", json_payload) + + +log("Por abrir pagina de loading") +err = navigate("https://www.bot-bunny.com/loading") +if err then + log("navigate error" .. err) + error("navigate error" .. err) +end +waitSecs(5) diff --git a/afip_login.lua b/afip_login.lua index c6f5e23..4927873 100644 --- a/afip_login.lua +++ b/afip_login.lua @@ -1,6 +1,5 @@ local err local json = require("json") --- Parse the JSON string local obj, err = json.decode(json_payload) log("Cuit:" .. obj["cuit"]) @@ -119,8 +118,6 @@ if string.match(current_url, "^https://auth%.afip%.gob%.ar/contribuyente_/login% error(message) end -log("Login successful!") - current_url, err = getCurrentUrl() if err then message = "Error getting current URL: " .. err @@ -134,4 +131,4 @@ if string.match(current_url, "^https://auth%.afip%.gob%.ar/contribuyente_/login% error(message) end -print("Login successful desde LUA!!") +log("Login successful!") diff --git a/botbunny_inicio.lua b/botbunny_inicio.lua deleted file mode 100644 index 7b348ab..0000000 --- a/botbunny_inicio.lua +++ /dev/null @@ -1,21 +0,0 @@ -log("inicia botbunny_inicio") -local err -print("BEFORE JSON LOADING payload: " .. json_payload) -local json = require("json") -print("AFTER JSON LOADING") --- Parse the JSON string -local obj, err = json.decode(json_payload) - -if err then - log("Decoding error" .. err) - error("Decoding error" .. err) -end - -log("Por abrir pagina de loading") -err = navigate("https://www.bot-bunny.com/loading") -if err then - log("navigate error" .. err) - error("navigate error" .. err) -end -log("durmiendo por 5 segundos") -waitSecs(5)