snoopy_afip 4.3.0 → 4.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ddb431b984f379cd6f6030e90734cf449d025e804cacdc039a746bd5f2ab44b4
4
- data.tar.gz: cc2af52ee88ac9e1abcb9f6d7f478f6dbaad8abe99e5b51c7585f0e5ec7c856e
3
+ metadata.gz: 35130f258e01ade599f3cc2926ba8db91fb5f3b89692a55376e087575f399a1b
4
+ data.tar.gz: d708113acb8d0a3a7e3c01cb34482f8082ac790e69716217597d6645042414e3
5
5
  SHA512:
6
- metadata.gz: 260af80a82dbde4632293ee5458acdfff10fd98f33412e21c18d24b07fbe88e29eafda3d98d84fadda48e51cf793f45e59ac2ecc0c156a68d0c552b8bace6852
7
- data.tar.gz: 4d6f545f2004b35986f41d2e7f67ba931dbc4a056f948a5b670ab66a7cd7201aba9c6cd461efe511d3a13800f79cb61c6fa9baecc93048c244ff34013367ba53
6
+ metadata.gz: 559248bc96a670668347e0707567d5b24f54732a9a08ef40dddc40d68cd53764fd19914efea411d8902ed277655e5cca27e7279b099d1a933a4a31ff4827c577
7
+ data.tar.gz: 3e56da1b87f9e1a019de90c662c9dadf9ede67197faab7c6c2370f660a342864f600588a2ab5751c4a578efb441a282a67767f8fa6f187be8cea24932bc8c05d
@@ -0,0 +1,31 @@
1
+ name: Ruby
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+
8
+ pull_request:
9
+
10
+ jobs:
11
+ test:
12
+ runs-on: ubuntu-latest
13
+ name: Ruby ${{ matrix.ruby }}
14
+ strategy:
15
+ matrix:
16
+ ruby:
17
+ # La gema en master corre sobre el stack savon 2.12 (httpi 2.x), que
18
+ # requiere Ruby 2.7. Al mergear el upgrade a savon 2.17 (#19), subir a 3.x.
19
+ - '2.7'
20
+
21
+ steps:
22
+ - uses: actions/checkout@v5
23
+ with:
24
+ persist-credentials: false
25
+ - name: Set up Ruby
26
+ uses: ruby/setup-ruby@v1
27
+ with:
28
+ ruby-version: ${{ matrix.ruby }}
29
+ bundler-cache: true
30
+ - name: Run specs
31
+ run: bundle exec rspec
@@ -0,0 +1,33 @@
1
+ name: Publish to RubyGems
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ jobs:
9
+ build:
10
+ name: Build + Publish
11
+ runs-on: ubuntu-latest
12
+ permissions:
13
+ contents: read
14
+ packages: write
15
+
16
+ steps:
17
+ - uses: actions/checkout@v5
18
+
19
+ - name: Set up Ruby
20
+ uses: ruby/setup-ruby@v1
21
+ with:
22
+ ruby-version: '3.2'
23
+
24
+ - name: Publish to RubyGems
25
+ run: |
26
+ mkdir -p $HOME/.gem
27
+ touch $HOME/.gem/credentials
28
+ chmod 0600 $HOME/.gem/credentials
29
+ printf -- "---\n:rubygems_api_key: ${RUBYGEMS_API_KEY}\n" > $HOME/.gem/credentials
30
+ gem build *.gemspec
31
+ gem push *.gem
32
+ env:
33
+ RUBYGEMS_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}
data/AGENTS.md ADDED
@@ -0,0 +1,100 @@
1
+ # AGENTS.md — snoopy_afip
2
+
3
+ Fuente de verdad para reglas, convenciones, estructura, documentación, entorno y arquitectura de esta gema. Leer antes de hacer cambios.
4
+
5
+ ## 1. Identidad
6
+
7
+ `snoopy_afip` es una gema Ruby que adapta la **Facturación Electrónica de AFIP (Argentina)**. Expone el módulo `Snoopy`.
8
+
9
+ Resuelve dos servicios SOAP de AFIP (vía `savon`):
10
+
11
+ - **WSAA** (autenticación): obtiene `token`, `sign` y `expiration_time` a partir de una clave privada y un certificado. Implementado en `Snoopy::AuthenticationAdapter`.
12
+ - **WSFE** (autorización de comprobantes electrónicos): autoriza facturas/notas de crédito contra el web service. Implementado en `Snoopy::AuthorizeAdapter`, operando sobre objetos `Snoopy::Bill`.
13
+
14
+ Verificado en: `snoopy_afip.gemspec` (`summary = "Adaptador AFIP wsfe."`, `description = "Adaptador para Web Service de Facturación Electrónica Argentina (AFIP)"`), `README.md` y `lib/`.
15
+
16
+ ## 2. Convenciones del framework
17
+
18
+ El repo consume skills del framework de agentes, declaradas en `skills.yml`. Las skills se sincronizan en `.agents/skills/` y traen conocimiento específico de cada herramienta o dependencia.
19
+
20
+ - Antes de responder o actuar sobre un tema cubierto por una skill, leer la skill correspondiente en `.agents/skills/`.
21
+ - Skills declaradas hoy (`skills.yml`): `multi-vendor-feedback`, `yard`, `quality-code`, `gem-release`, `arch-structure`, `arch-compose`, `arch-enrich`, `skill-feedback`, `agent-issue`, `bug-report`, `dev-flow`, `documentation-writer`, `matrix-element`.
22
+ - MCPs declarados: `github`, `clickup`.
23
+
24
+ ## 3. Entorno
25
+
26
+ - Lenguaje: **Ruby**. No hay `.ruby-version` en el repo (no fijar una versión que no esté declarada).
27
+ - Dependencias resueltas en `Gemfile.lock`. Dependencia de runtime principal: `savon ~> 2.12.1` (cliente SOAP), declarada en el `.gemspec`.
28
+ - Gestión de versiones de Ruby con **chruby** (no rvm, no rbenv).
29
+ - **Bundler** para dependencias (`BUNDLED WITH 2.1.4` en `Gemfile.lock`). Instalar con `bundle install`.
30
+
31
+ ## 4. RuboCop
32
+
33
+ Esta gema **no** tiene `.rubocop.yml` configurado actualmente. La skill `quality-code` está declarada en `skills.yml` para calidad de código. Aplicar las reglas de calidad solo si se incorpora una configuración de RuboCop al repo; en ese caso, correr `bundle exec rubocop -a` antes de commitear.
34
+
35
+ ## 5. YARD
36
+
37
+ Documentación incremental con la skill `yard`. Medir cobertura de doc con:
38
+
39
+ ```bash
40
+ bundle exec yard stats --list-undoc
41
+ ```
42
+
43
+ Documentar el código nuevo o modificado.
44
+
45
+ ## 6. Testing
46
+
47
+ Framework: **RSpec** (verificado en `spec/spec_helper.rb` con `require 'rspec'` y specs `describe`/`it` en `spec/snoopy_afip/`). Correr la suite con:
48
+
49
+ ```bash
50
+ bundle exec rspec
51
+ ```
52
+
53
+ El código nuevo debe venir con tests. La suite (`spec/snoopy_afip/{bill,authorize_adapter,authentication_adapter,exceptions}_spec.rb`) son unit puros, sin fixtures ni llamadas reales a AFIP; usar placeholders, nunca CUIT/credenciales reales.
54
+
55
+ **Runtime: la suite corre bajo Ruby 2.7.x** (runtime del consumidor). En Ruby 3.x la gema **no carga** — el stack de savon 2.12 (httpi 2.x) depende de `kconv` y `Rack::Utils::HeaderHash`, removidos en Ruby 3.x / rack 3. Correr en 3.x requiere el upgrade de savon a 2.15+ (ver `docs/test/testing.md`). El `Gemfile.lock` está resuelto para 2.7.
56
+
57
+ ## 7. Releases
58
+
59
+ La versión vive en `lib/snoopy_afip/version.rb` (`Snoopy::VERSION`).
60
+
61
+ **Release automatizado por GitHub Actions** (`.github/workflows/release.yml`): publicar = bump de `version.rb` + commit + `git tag vX.Y.Z` + push del tag → el workflow corre `gem build` + `gem push` a RubyGems. Requiere el secret `RUBYGEMS_API_KEY` en el repo. No hace falta `gem push` manual.
62
+
63
+ **CI** (`.github/workflows/main.yml`): corre `bundle exec rspec` en cada push a master y PR. Hoy en **Ruby 2.7** (stack savon 2.12); subir a 3.x al mergear el upgrade de savon (#19).
64
+
65
+ ## 8. Arquitectura
66
+
67
+ Derivada de `lib/` (módulo `Snoopy`, autoloads en `lib/snoopy_afip.rb`):
68
+
69
+ - **`Snoopy`** (`lib/snoopy_afip.rb`): módulo de configuración global vía `attr_accessor` (`cuit`, `sale_point`, `service_url`, `auth_url`, `pkey`, `cert`, `default_document_type`, `default_concept`, `default_currency`, `own_iva_cond`, `open_timeout`, `read_timeout`, `verbose`). `open_timeout`/`read_timeout` por defecto en 30. Expone helpers `auth_hash` y `bill_types`.
70
+ - **`Snoopy::Client`** (`client.rb`): envoltorio fino sobre `Savon.client`; `#call` aplica `Timeout` y traduce fallos a `Snoopy::Exception::ServerTimeout` / `Snoopy::Exception::ClientError`.
71
+ - **`Snoopy::AuthenticationAdapter`** (`authentication_adapter.rb`): flujo WSAA — genera TRA/CMS y obtiene `token`/`sign`/`expiration_time`. También métodos de generación de clave privada y de solicitud de certificado (`generate_pkey`, `generate_certificate_request_with_ruby`, `..._with_bash`).
72
+ - **`Snoopy::AuthorizeAdapter`** (`authorize_adapter.rb`): flujo WSFE — toma un `Bill` más credenciales (`token`/`sign`/`cuit`/`pkey`/`cert`), arma el request, llama al web service y parsea la respuesta en capas independientes (resultado/CAE, `afip_errors`, `afip_events`, `afip_observations`); expone `set_bill_number!` y `authorize!`.
73
+ - **`Snoopy::Bill`** (`bill.rb`): modela el comprobante; valida con `valid?`/`errors` y consulta estado de aprobación con `approved?`, `partial_approved?`, `rejected?`.
74
+ - **`Snoopy::Constants`** (`constants.rb`) y **`Snoopy::Exception`** (`exceptions.rb`): tablas de dominio (tipos de documento, alícuotas, condiciones de IVA) y jerarquía de excepciones.
75
+ - **`lib/snoopy_afip/core_ext/`**: extensiones a `String`, `Hash` y `Float`.
76
+
77
+ El acoplamiento de las capas de parseo es deliberado (ver README §"No Explota"): un cambio de formato de AFIP en una capa no debe tumbar el parseo de las demás.
78
+
79
+ ## Mapa de conocimiento (cómo leer la doc de este repo)
80
+
81
+ - **Tu conocimiento = la UNIÓN de este repo + sus asociados.** No termina en el `docs/<capa>/` local: incluye la doc de los servicios/gemas de `skills.yml`. Un flujo o pregunta que cruza repos no vive como doc estática en ninguno — se compone on-demand recorriendo el grafo: seguí las anclas (`docs/consumed/`, `**Canónico:**`) hasta los repos asociados y unificá.
82
+ - **Entrá por** [`skill/SKILL.md`](skill/SKILL.md) — índice de agente; resume el contrato y linkea el detalle.
83
+ - **Detalle por capa** (`docs/<capa>/`), cobertura declarada:
84
+
85
+ | capa | estado |
86
+ |---|---|
87
+ | `docs/interface/` (RFC-004) | presente |
88
+ | `docs/topology/` (RFC-006) | presente |
89
+ | `docs/consumed/` (RFC-018) | presente — AFIP WSAA + WSFE |
90
+ | `docs/errors/` (RFC-020) | presente |
91
+ | `docs/config/` (RFC-012) | presente |
92
+ | `docs/test/` (RFC-013) | presente |
93
+ | `docs/glossary/` (RFC-009) | presente |
94
+ | `docs/behavior/` (RFC-007) | presente |
95
+ | `docs/api/` (RFC-003) | **n/a** — gema SOAP, sin superficie HTTP/CLI/eventos propia |
96
+ | `docs/data/` (RFC-002) | **n/a** — sin base de datos |
97
+ | `docs/events/` (RFC-005) · multi-tenancy (RFC-023) | **n/a** — sin pub/sub ni tenant |
98
+
99
+ - **Qué consumimos:** [`docs/consumed/afip.md`](docs/consumed/afip.md) (RFC-018) — servicios SOAP externos de AFIP.
100
+ - **Navegar una ancla cross-repo:** tomá la key de servicio en `skills.yml` (`services.<dep>.repo`) → ese repo es un checkout hermano local o alcanzable por GitHub MCP. La doc de los asociados ES parte de tu conocimiento accesible. (Hoy las dependencias de esta gema son externas a AFIP, no del fleet.)
data/CHANGELOG.md ADDED
@@ -0,0 +1,44 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
+ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [4.3.1] - 2026-06-29
8
+ ### Fixed
9
+ - `AuthorizeAdapter`: los rescues de parseo registraban con `errors << …` sobre un Hash (NoMethodError) y la consulta referenciaba una constante mal namespaceada (NameError), enmascarando el error real de AFIP. Ahora registran el mensaje sin explotar — sostiene el diseño "No Explota" (#10).
10
+ - `Snoopy::Exception::ServerTimeout` quedaba fuera de la jerarquía de la gema, así que `rescue` de la base no lo atrapaba (#11).
11
+
12
+ ### Added
13
+ - `Snoopy::Exception::Error`: módulo paraguas para `rescue` de todos los errores de la gema (incluido el timeout) sin romper `rescue Timeout::Error` (#11).
14
+
15
+ ### Removed
16
+ - `Snoopy.auth_hash`: código muerto que siempre levantaba NameError (constantes `Snoopy::TOKEN`/`Snoopy::SIGN` inexistentes) (#12).
17
+
18
+ ### Changed
19
+ - Higiene del `.gemspec` (`required_ruby_version >= 2.5`, fecha automática).
20
+ - Suite RSpec reescrita contra la API actual y `Gemfile.lock` regenerado (#13).
21
+ - Documentación de arquitectura (`docs/<capa>/`, README, `skill/SKILL.md`) regenerada.
22
+ - CI y publicación a RubyGems automatizados por GitHub Actions (tag `v*`).
23
+
24
+ ## [3.0.2] - July 14, 2017
25
+ ### Added
26
+ - `Cms Builder exception`.
27
+
28
+ ## [3.0.0] - June 29, 2017
29
+ ### Added
30
+ - `Authentication Class` destinada a la comunicación con el **WSAA**.
31
+ - `Authorize Class` destinada a la comunicación con el **WSFE**.
32
+ - `Client Class` destinada para crear el cliente de `Savon`.
33
+ - Mejor manejo de Exceptions.
34
+ - Validaciones en el modelo `Bill`.
35
+
36
+ ### Changed
37
+ - Se pasó toda la logica de comunicación con el **WSFE** del modelo `Bill` al modelo `Authorize`.
38
+ - No se crea mas el rchivo para la clave privada, devuelve en RAW.
39
+ - No se crea mas un archivo para almacenar el _token_, _sign_, se devuelve en RAW.
40
+ - Evitar raisear si se logró autorizar una factura con el **WSFE**. Manejo en el errors del `Bill` o el `Authorize`.
41
+
42
+ ### Removed
43
+ - Eliminiado modulo `AuthData`.
44
+ - Eliminado el uso de `Bash` para autenticar en el **WSAA**.
data/CLAUDE.md ADDED
@@ -0,0 +1,15 @@
1
+ # Claude Code Notes
2
+
3
+ ## Fuente de verdad del repositorio
4
+
5
+ Las reglas, convenciones, estructura y contexto del proyecto viven en `AGENTS.md`.
6
+
7
+ - Leer `AGENTS.md` antes de hacer cambios.
8
+ - Tratar `AGENTS.md` como fuente de verdad para identidad, estructura, documentación, convenciones del framework, entorno, y arquitectura.
9
+
10
+ ## Propósito de este archivo
11
+
12
+ `CLAUDE.md` queda reservado para instrucciones o notas específicas de Claude Code.
13
+
14
+ - No duplicar aquí reglas generales del repositorio.
15
+ - Si una regla aplica a cualquier agente, moverla a `AGENTS.md`.
data/Gemfile CHANGED
@@ -1,6 +1,10 @@
1
1
  source "http://rubygems.org"
2
2
 
3
3
  gemspec
4
+
5
+ # httpi 2.x (vía savon 2.12) usa Rack::Utils::HeaderHash, removido en rack 3.
6
+ # Pin de entorno de test; el consumidor Rails trae su propio rack 2.x.
7
+ gem "rack", "~> 2.2"
4
8
  # group :development do
5
9
  # platforms :ruby_18 do
6
10
  # gem "ruby-debug"
data/Gemfile.lock CHANGED
@@ -1,31 +1,72 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- snoopy_afip (4.0.1)
5
- akami (~> 1.3.1)
6
- nokogiri (~> 1.10.9)
7
- nori (~> 2.6.0)
8
- savon (~> 2.12.0)
9
- wasabi (~> 3.5.0)
4
+ snoopy_afip (4.3.1)
5
+ savon (~> 2.12.1)
10
6
 
11
7
  GEM
12
8
  remote: http://rubygems.org/
13
9
  specs:
14
- akami (1.3.1)
10
+ activesupport (7.1.6)
11
+ base64
12
+ benchmark (>= 0.3)
13
+ bigdecimal
14
+ concurrent-ruby (~> 1.0, >= 1.0.2)
15
+ connection_pool (>= 2.2.5)
16
+ drb
17
+ i18n (>= 1.6, < 2)
18
+ logger (>= 1.4.2)
19
+ minitest (>= 5.1)
20
+ mutex_m
21
+ securerandom (>= 0.3)
22
+ tzinfo (~> 2.0)
23
+ addressable (2.9.0)
24
+ public_suffix (>= 2.0.2, < 8.0)
25
+ akami (1.3.2)
15
26
  gyoku (>= 0.4.0)
16
27
  nokogiri
17
- builder (3.2.4)
18
- gyoku (1.3.1)
28
+ base64 (0.3.0)
29
+ benchmark (0.5.0)
30
+ bigdecimal (4.1.2)
31
+ builder (3.3.0)
32
+ concurrent-ruby (1.3.7)
33
+ connection_pool (2.5.5)
34
+ diff-lcs (1.6.2)
35
+ drb (2.2.3)
36
+ gyoku (1.4.0)
19
37
  builder (>= 2.1.2)
20
- httpi (2.4.4)
38
+ rexml (~> 3.0)
39
+ httpi (2.5.0)
21
40
  rack
22
41
  socksify
23
- mini_portile2 (2.4.0)
24
- nokogiri (1.10.9)
25
- mini_portile2 (~> 2.4.0)
42
+ i18n (1.14.8)
43
+ concurrent-ruby (~> 1.0)
44
+ logger (1.7.0)
45
+ minitest (5.26.1)
46
+ mutex_m (0.3.0)
47
+ nokogiri (1.15.7-arm64-darwin)
48
+ racc (~> 1.4)
49
+ nokogiri (1.15.7-x86_64-linux)
50
+ racc (~> 1.4)
26
51
  nori (2.6.0)
27
- rack (2.2.2)
28
- savon (2.12.0)
52
+ public_suffix (5.1.1)
53
+ racc (1.8.1)
54
+ rack (2.2.23)
55
+ rexml (3.4.4)
56
+ rspec (3.13.2)
57
+ rspec-core (~> 3.13.0)
58
+ rspec-expectations (~> 3.13.0)
59
+ rspec-mocks (~> 3.13.0)
60
+ rspec-core (3.13.6)
61
+ rspec-support (~> 3.13.0)
62
+ rspec-expectations (3.13.5)
63
+ diff-lcs (>= 1.2.0, < 2.0)
64
+ rspec-support (~> 3.13.0)
65
+ rspec-mocks (3.13.8)
66
+ diff-lcs (>= 1.2.0, < 2.0)
67
+ rspec-support (~> 3.13.0)
68
+ rspec-support (3.13.7)
69
+ savon (2.12.1)
29
70
  akami (~> 1.2)
30
71
  builder (>= 2.1.2)
31
72
  gyoku (~> 1.2)
@@ -33,16 +74,24 @@ GEM
33
74
  nokogiri (>= 1.8.1)
34
75
  nori (~> 2.4)
35
76
  wasabi (~> 3.4)
36
- socksify (1.7.1)
37
- wasabi (3.5.0)
77
+ securerandom (0.3.2)
78
+ socksify (1.8.1)
79
+ tzinfo (2.0.6)
80
+ concurrent-ruby (~> 1.0)
81
+ wasabi (3.7.0)
82
+ addressable
38
83
  httpi (~> 2.0)
39
84
  nokogiri (>= 1.4.2)
40
85
 
41
86
  PLATFORMS
42
- ruby
87
+ arm64-darwin-24
88
+ x86_64-linux
43
89
 
44
90
  DEPENDENCIES
91
+ activesupport
92
+ rack (~> 2.2)
93
+ rspec (~> 3.13)
45
94
  snoopy_afip!
46
95
 
47
96
  BUNDLED WITH
48
- 2.1.4
97
+ 2.4.22