factur-x-builder 0.1.2 → 0.1.4
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 +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +9 -0
- data/Gemfile.lock +4 -1
- data/README.md +35 -0
- data/lib/factur_x/codes.rb +5 -0
- data/lib/factur_x/party.rb +6 -0
- data/lib/factur_x/validation/rules.rb +15 -0
- data/lib/factur_x/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: da7a9bafbb80d9e9ac88ee325e49b76c1855e91774f3a1bf1c4dacdcf679cdc9
|
|
4
|
+
data.tar.gz: 729c3209aa5378bbde0b2400c797db122d887a34cb370d588c22e61df9a94d0b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bd23212eaeb87434500c7f45b41708b1bb9f72bea9f8c178a35953194d0503a41d939e0f36db9b24ae0ba1ace8bdb79035905e70516d0886f54c3af52da26b3a
|
|
7
|
+
data.tar.gz: 362f6dfba5482d591a1131e866e29ffbf1300873fe2aa73841f65ce3e36b829a8b417c3376cf4fbfc5a2fca6e0038159103b372d9e4a3e10d8907fb1dea55a4c
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## [Unreleased]
|
|
2
|
+
|
|
3
|
+
### Added
|
|
4
|
+
|
|
5
|
+
- A credit note is now checked against BR-FR-CO-05: it must reference the invoice it corrects with
|
|
6
|
+
both the number (BT-25) and the issue date (BT-26). A reference missing its date failed the
|
|
7
|
+
French schematron exactly like an absent one, and neither was caught before generating.
|
|
8
|
+
`Codes::CREDIT_NOTE_TYPES` names the document types the rule applies to.
|
|
9
|
+
|
|
1
10
|
## [0.1.2] - 2026-08-15
|
|
2
11
|
|
|
3
12
|
### Added
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
factur-x-builder (0.1.
|
|
4
|
+
factur-x-builder (0.1.4)
|
|
5
5
|
nokogiri (~> 1.15, < 1.16)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
@@ -12,6 +12,8 @@ GEM
|
|
|
12
12
|
language_server-protocol (3.17.0.6)
|
|
13
13
|
lint_roller (1.1.0)
|
|
14
14
|
minitest (5.26.1)
|
|
15
|
+
nokogiri (1.15.7-arm64-darwin)
|
|
16
|
+
racc (~> 1.4)
|
|
15
17
|
nokogiri (1.15.7-x86_64-darwin)
|
|
16
18
|
racc (~> 1.4)
|
|
17
19
|
parallel (1.28.0)
|
|
@@ -43,6 +45,7 @@ GEM
|
|
|
43
45
|
unicode-emoji (4.2.0)
|
|
44
46
|
|
|
45
47
|
PLATFORMS
|
|
48
|
+
arm64-darwin-25
|
|
46
49
|
x86_64-darwin-21
|
|
47
50
|
|
|
48
51
|
DEPENDENCIES
|
data/README.md
CHANGED
|
@@ -133,6 +133,41 @@ anything is generated.
|
|
|
133
133
|
A credit note carries **positive** amounts; the type code conveys the direction. Negative unit
|
|
134
134
|
prices are rejected (`BR-27`, `BR-28`).
|
|
135
135
|
|
|
136
|
+
Cancelling invoice A with credit note B changes four things and nothing else — B's own number
|
|
137
|
+
(BT-1) and issue date (BT-2), the type code `381` (BT-3), and a reference to A carrying **both** its
|
|
138
|
+
number and its issue date (BG-3). That reference is required by the French profile (`BR-FR-CO-05`)
|
|
139
|
+
though not by EN 16931 alone, and a reference without a date fails just like a missing one. Parties,
|
|
140
|
+
lines, prices, VAT breakdown and totals are copied over untouched.
|
|
141
|
+
|
|
142
|
+
```ruby
|
|
143
|
+
FacturX::Invoice.new(
|
|
144
|
+
number: "AV-2026-0012",
|
|
145
|
+
issued_on: Date.today,
|
|
146
|
+
type_code: FacturX::Codes::CREDIT_NOTE,
|
|
147
|
+
preceding_invoices: [
|
|
148
|
+
FacturX::ReferencedInvoice.new(number: "5-2026-0004", issued_on: Date.new(2026, 8, 4))
|
|
149
|
+
],
|
|
150
|
+
# … everything else identical to the invoice being cancelled
|
|
151
|
+
)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Routing address
|
|
155
|
+
|
|
156
|
+
`routing_id` is the electronic address the platform delivers to (BT-34 for the seller, BT-49 for the
|
|
157
|
+
buyer). It defaults to the SIRET, and its scheme identifier — mandatory under BR-62 and BR-63 — is
|
|
158
|
+
filled in as `0225`.
|
|
159
|
+
|
|
160
|
+
That code designates the addressing of the French reform itself, not a particular identifier, so it
|
|
161
|
+
stays `0225` whatever the directory registered: SIREN, SIRET, `SIREN_SIRET`, or
|
|
162
|
+
`SIREN_SIRET_CODE_ROUTAGE` for an address finer than the establishment. The value is opaque to the
|
|
163
|
+
gem — forwarded verbatim, never parsed — and every shape is covered by the conformance suite.
|
|
164
|
+
|
|
165
|
+
```ruby
|
|
166
|
+
FacturX::Party.new(name: "…", siret: "39876543800005",
|
|
167
|
+
routing_id: "398765438_39876543800005_COMPTA")
|
|
168
|
+
# => <ram:URIID schemeID="0225">398765438_39876543800005_COMPTA</ram:URIID>
|
|
169
|
+
```
|
|
170
|
+
|
|
136
171
|
### Payment instructions are optional
|
|
137
172
|
|
|
138
173
|
`payment_means` maps to BG-16 *Payment instructions*, which both schematrons accept as absent. It
|
data/lib/factur_x/codes.rb
CHANGED
|
@@ -10,6 +10,11 @@ module FacturX
|
|
|
10
10
|
|
|
11
11
|
DOCUMENT_TYPES = [COMMERCIAL_INVOICE, CREDIT_NOTE, SELF_BILLED_INVOICE].freeze
|
|
12
12
|
|
|
13
|
+
# The document types BR-FR-CO-05 treats as credit notes. Only 381 is
|
|
14
|
+
# emitted by this gem; the others are listed so the rule keeps matching
|
|
15
|
+
# if DOCUMENT_TYPES ever widens.
|
|
16
|
+
CREDIT_NOTE_TYPES = %w[261 381 396 502 503].freeze
|
|
17
|
+
|
|
13
18
|
# Invoicing modes accepted by the French e-invoicing reform (BR-FR-08).
|
|
14
19
|
BUSINESS_PROCESSES = %w[B1 S1 M1 B2 S2 M2 S3 B4 S4 M4 S5 S6 B7 S7 B8 S8 M8 B9 S9 M9].freeze
|
|
15
20
|
|
data/lib/factur_x/party.rb
CHANGED
|
@@ -10,6 +10,12 @@ module FacturX
|
|
|
10
10
|
# `routing_id` the electronic address (scheme 0225) used to route the
|
|
11
11
|
# invoice through the PPF, defaulting to the SIRET.
|
|
12
12
|
#
|
|
13
|
+
# Scheme 0225 designates the addressing of the French reform itself, not a
|
|
14
|
+
# particular identifier, so it holds whatever shape the directory registered:
|
|
15
|
+
# SIREN, SIRET, SIREN_SIRET, or SIREN_SIRET_CODE_ROUTAGE for an address finer
|
|
16
|
+
# than the establishment. The value is opaque here - it is forwarded verbatim,
|
|
17
|
+
# never parsed - so a new directory shape needs no change to this gem.
|
|
18
|
+
#
|
|
13
19
|
# `legal_information` is BT-33, the seller's additional legal information:
|
|
14
20
|
# legal form, share capital, RCS registration, and any other statement the
|
|
15
21
|
# printed invoice must carry. A party holds a single postal address, so this
|
|
@@ -91,6 +91,21 @@ module FacturX
|
|
|
91
91
|
"notes (BT-22 with subject code #{code}, BR-FR-05) - " \
|
|
92
92
|
"Note.french_legal_mentions provides the three of them")
|
|
93
93
|
end
|
|
94
|
+
|
|
95
|
+
check_corrected_invoice
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# BR-FR-CO-05: a credit note must say which invoice it corrects. EN 16931
|
|
99
|
+
# alone is happy without it, the French profile is not. The number and the
|
|
100
|
+
# issue date are both required - a reference carrying only the number
|
|
101
|
+
# fails the rule just as an absent one does.
|
|
102
|
+
def check_corrected_invoice
|
|
103
|
+
return unless Codes::CREDIT_NOTE_TYPES.include?(invoice.type_code)
|
|
104
|
+
return if invoice.preceding_invoices.any? { |ref| !blank?(ref.number) && !ref.issued_on.nil? }
|
|
105
|
+
|
|
106
|
+
add("a credit note must reference the invoice it corrects, with both its number and " \
|
|
107
|
+
"its issue date (BT-25 and BT-26, BR-FR-CO-05) - pass preceding_invoices: " \
|
|
108
|
+
"[ReferencedInvoice.new(number:, issued_on:)]")
|
|
94
109
|
end
|
|
95
110
|
|
|
96
111
|
def check_document
|
data/lib/factur_x/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: factur-x-builder
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Hotentic
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08
|
|
11
|
+
date: 2026-09-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: nokogiri
|