facturx 0.1.0 → 0.2.0
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/CHANGELOG.md +10 -1
- data/NOTICE.md +2 -0
- data/README.md +27 -1
- data/lib/facturx/coerce.rb +74 -0
- data/lib/facturx/diagnostic.rb +20 -0
- data/lib/facturx/document.rb +45 -0
- data/lib/facturx/group.rb +5 -0
- data/lib/facturx/model/common.rb +8 -0
- data/lib/facturx/model/immutable.rb +75 -0
- data/lib/facturx/model/line.rb +14 -0
- data/lib/facturx/model/party.rb +10 -0
- data/lib/facturx/model/payment.rb +9 -0
- data/lib/facturx/model/reference.rb +7 -0
- data/lib/facturx/model/trade.rb +9 -0
- data/lib/facturx/model.rb +9 -0
- data/lib/facturx/pdf/extractor.rb +7 -4
- data/lib/facturx/reader/semantic_mapper/delivery_mapping.rb +43 -0
- data/lib/facturx/reader/semantic_mapper/document_mapping.rb +109 -0
- data/lib/facturx/reader/semantic_mapper/helpers.rb +114 -0
- data/lib/facturx/reader/semantic_mapper/line_mapping.rb +120 -0
- data/lib/facturx/reader/semantic_mapper/party_mapping.rb +90 -0
- data/lib/facturx/reader/semantic_mapper/payment_mapping.rb +71 -0
- data/lib/facturx/reader/semantic_mapper/trade_mapping.rb +83 -0
- data/lib/facturx/reader/semantic_mapper.rb +67 -0
- data/lib/facturx/reader/term_reader/coercion.rb +69 -0
- data/lib/facturx/reader/term_reader/unmapped.rb +37 -0
- data/lib/facturx/reader/term_reader.rb +124 -0
- data/lib/facturx/reader.rb +101 -0
- data/lib/facturx/reading.rb +23 -0
- data/lib/facturx/source_reader.rb +30 -0
- data/lib/facturx/term.rb +5 -0
- data/lib/facturx/terms/declaration.rb +20 -0
- data/lib/facturx/terms/declarations/adjustments.rb +230 -0
- data/lib/facturx/terms/declarations/delivery.rb +83 -0
- data/lib/facturx/terms/declarations/document.rb +223 -0
- data/lib/facturx/terms/declarations/groups.rb +356 -0
- data/lib/facturx/terms/declarations/lines.rb +166 -0
- data/lib/facturx/terms/declarations/parties.rb +609 -0
- data/lib/facturx/terms/declarations/payment.rb +106 -0
- data/lib/facturx/terms/declarations/products.rb +103 -0
- data/lib/facturx/terms/declarations/references.rb +72 -0
- data/lib/facturx/terms/declarations/taxes.rb +92 -0
- data/lib/facturx/terms/declarations/totals.rb +107 -0
- data/lib/facturx/terms/reference.rb +21 -0
- data/lib/facturx/terms.rb +109 -0
- data/lib/facturx/version.rb +1 -1
- data/lib/facturx.rb +14 -0
- metadata +45 -4
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../coerce'
|
|
4
|
+
require_relative '../diagnostic'
|
|
5
|
+
|
|
6
|
+
module Facturx
|
|
7
|
+
class Reader
|
|
8
|
+
class TermReader
|
|
9
|
+
attr_reader :diagnostics
|
|
10
|
+
|
|
11
|
+
def initialize(document:, profile:, registry:, coercer:, diagnostics:)
|
|
12
|
+
@document = document
|
|
13
|
+
@profile = profile
|
|
14
|
+
@registry = registry
|
|
15
|
+
@coercer = coercer
|
|
16
|
+
@diagnostics = diagnostics
|
|
17
|
+
@matched_nodes = {}.compare_by_identity
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def value(id, context: @document, base_xpath: nil, nodes: nil)
|
|
21
|
+
term = active_term(id)
|
|
22
|
+
return unless term
|
|
23
|
+
|
|
24
|
+
selected = nodes || context.xpath(relative_xpath(term.xpath, base_xpath), NAMESPACES)
|
|
25
|
+
selected.each { |node| mark(node) }
|
|
26
|
+
cardinality = term.cardinalities.fetch(@profile.id)
|
|
27
|
+
diagnose_cardinality(term, selected, cardinality)
|
|
28
|
+
materialize(term, selected, cardinality)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def group_nodes(id, context: @document, base_xpath: nil, &)
|
|
32
|
+
group = active_group(id)
|
|
33
|
+
return [].freeze unless group
|
|
34
|
+
|
|
35
|
+
nodes = context.xpath(relative_xpath(group.xpath, base_xpath), NAMESPACES).to_a
|
|
36
|
+
nodes.select!(&) if block_given?
|
|
37
|
+
cardinality = group.cardinalities.fetch(@profile.id)
|
|
38
|
+
diagnose_cardinality(group, nodes, cardinality)
|
|
39
|
+
nodes.each { |node| mark(node) }
|
|
40
|
+
nodes.freeze
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def raw_value(xpath, context:, mark_node: true)
|
|
44
|
+
node = context.at_xpath(xpath, NAMESPACES)
|
|
45
|
+
mark(node) if node && mark_node
|
|
46
|
+
node&.text
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def mark_value(id, context: @document, base_xpath: nil)
|
|
50
|
+
term = active_term(id)
|
|
51
|
+
return unless term
|
|
52
|
+
|
|
53
|
+
context.xpath(relative_xpath(term.xpath, base_xpath), NAMESPACES).each { |node| mark(node) }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def mark(node)
|
|
57
|
+
return unless node
|
|
58
|
+
|
|
59
|
+
@matched_nodes[node] = true
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def add(code, term_id, path, message, details = {})
|
|
63
|
+
@diagnostics << Diagnostic.new(
|
|
64
|
+
code:,
|
|
65
|
+
term_id:,
|
|
66
|
+
path:,
|
|
67
|
+
message:,
|
|
68
|
+
details:
|
|
69
|
+
)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
def active_term(id)
|
|
75
|
+
term = @registry.fetch(id)
|
|
76
|
+
term if term.cardinalities.key?(@profile.id)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def active_group(id)
|
|
80
|
+
group = @registry.group(id)
|
|
81
|
+
|
|
82
|
+
group if group.cardinalities.key?(@profile.id)
|
|
83
|
+
rescue KeyError
|
|
84
|
+
raise KeyError, "Unknown Factur-X group: #{id}"
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def diagnose_cardinality(definition, nodes, cardinality)
|
|
88
|
+
missing(definition) if nodes.empty? && required?(cardinality)
|
|
89
|
+
multiple(definition, nodes.size) if nodes.size > 1 && !repeated?(cardinality)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def materialize(term, nodes, cardinality)
|
|
93
|
+
values = nodes.map { |node| coerce(node, term) }
|
|
94
|
+
return values.freeze if repeated?(cardinality)
|
|
95
|
+
|
|
96
|
+
values.first
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def missing(definition)
|
|
100
|
+
add(:missing_required_term, definition.id, definition.xpath, 'Required value is missing')
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def multiple(definition, count)
|
|
104
|
+
add(:multiple_values, definition.id, definition.xpath, 'Multiple values found for a scalar field', count:)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def relative_xpath(xpath, base_xpath)
|
|
108
|
+
return xpath unless base_xpath
|
|
109
|
+
|
|
110
|
+
suffix = xpath.delete_prefix(base_xpath)
|
|
111
|
+
raise ArgumentError, "#{xpath} is outside #{base_xpath}" if suffix == xpath
|
|
112
|
+
|
|
113
|
+
suffix.empty? ? '.' : ".#{suffix}"
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def required?(cardinality) = cardinality.start_with?('1')
|
|
117
|
+
|
|
118
|
+
def repeated?(cardinality) = cardinality.end_with?('n')
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
require_relative 'term_reader/unmapped'
|
|
124
|
+
require_relative 'term_reader/coercion'
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'diagnostic'
|
|
4
|
+
require_relative 'document'
|
|
5
|
+
require_relative 'coerce'
|
|
6
|
+
require_relative 'error'
|
|
7
|
+
require_relative 'profiles'
|
|
8
|
+
require_relative 'reading'
|
|
9
|
+
require_relative 'source_reader'
|
|
10
|
+
require_relative 'terms'
|
|
11
|
+
require_relative 'xml/parser'
|
|
12
|
+
require_relative 'xml/profile_detector'
|
|
13
|
+
|
|
14
|
+
module Facturx
|
|
15
|
+
class Reader
|
|
16
|
+
CII_NAMESPACE = 'urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100'
|
|
17
|
+
NAMESPACES = {
|
|
18
|
+
'qdt' => 'urn:un:unece:uncefact:data:standard:QualifiedDataType:100',
|
|
19
|
+
'ram' => 'urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100',
|
|
20
|
+
'rsm' => CII_NAMESPACE,
|
|
21
|
+
'udt' => 'urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100'
|
|
22
|
+
}.freeze
|
|
23
|
+
UNKNOWN_PROFILE_POLICIES = %i[fallback raise].freeze
|
|
24
|
+
|
|
25
|
+
COLLABORATORS = %i[profile_resolver registry coercer profiles].freeze
|
|
26
|
+
|
|
27
|
+
def initialize(parser: Xml::Parser.new, extractor: Pdf::Extractor.new, **collaborators)
|
|
28
|
+
unknown = collaborators.keys - COLLABORATORS
|
|
29
|
+
raise ArgumentError, "Unknown collaborators: #{unknown.join(', ')}" unless unknown.empty?
|
|
30
|
+
|
|
31
|
+
@parser = parser
|
|
32
|
+
@source_reader = SourceReader.new(extractor:)
|
|
33
|
+
@profile_resolver = collaborators.fetch(:profile_resolver) { Xml::ProfileDetector.new }
|
|
34
|
+
@registry = collaborators.fetch(:registry, Terms)
|
|
35
|
+
@coercer = collaborators.fetch(:coercer, Coerce)
|
|
36
|
+
@profiles = collaborators.fetch(:profiles, Profiles)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def call(source, on_unknown_profile: :fallback)
|
|
40
|
+
validate_unknown_profile_policy!(on_unknown_profile)
|
|
41
|
+
input = @source_reader.call(source)
|
|
42
|
+
parsed = parse(input.xml)
|
|
43
|
+
diagnostics = []
|
|
44
|
+
profile = resolve_profile(parsed, on_unknown_profile, diagnostics)
|
|
45
|
+
document = map(parsed, profile, diagnostics)
|
|
46
|
+
|
|
47
|
+
Reading.new(document:, profile:, diagnostics:, source: input.xml, source_type: input.source_type)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def validate_unknown_profile_policy!(policy)
|
|
53
|
+
return if UNKNOWN_PROFILE_POLICIES.include?(policy)
|
|
54
|
+
|
|
55
|
+
raise ArgumentError, "on_unknown_profile must be one of #{UNKNOWN_PROFILE_POLICIES.inspect}"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def cross_industry_invoice(document)
|
|
59
|
+
root = document.root
|
|
60
|
+
return root if root&.name == 'CrossIndustryInvoice' && root.namespace&.href == CII_NAMESPACE
|
|
61
|
+
|
|
62
|
+
raise InvalidXmlError.new('XML is not a CrossIndustryInvoice', reason: :unsupported_document)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def parse(xml)
|
|
66
|
+
document = @parser.call(xml:)
|
|
67
|
+
cross_industry_invoice(document)
|
|
68
|
+
document
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def map(parsed, profile, diagnostics)
|
|
72
|
+
mapper = SemanticMapper.new(
|
|
73
|
+
document: parsed, profile:, registry: @registry, coercer: @coercer, diagnostics:
|
|
74
|
+
)
|
|
75
|
+
document = mapper.call
|
|
76
|
+
mapper.add_unmapped(parsed.root)
|
|
77
|
+
document
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def resolve_profile(document, policy, diagnostics)
|
|
81
|
+
@profile_resolver.call(document:)
|
|
82
|
+
rescue UnknownProfileError => e
|
|
83
|
+
raise if policy == :raise
|
|
84
|
+
|
|
85
|
+
diagnostics << profile_diagnostic(e)
|
|
86
|
+
@profiles.fetch(:extended)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def profile_diagnostic(error)
|
|
90
|
+
guideline_urn = error.details[:guideline_urn]
|
|
91
|
+
Diagnostic.new(
|
|
92
|
+
code: guideline_urn.nil? || guideline_urn.empty? ? :missing_profile : :unknown_profile,
|
|
93
|
+
term_id: 'BT-24', path: Xml::ProfileDetector::GUIDELINE_XPATH,
|
|
94
|
+
message: error.message, details: error.details
|
|
95
|
+
)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
require_relative 'reader/term_reader'
|
|
101
|
+
require_relative 'reader/semantic_mapper'
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'model/immutable'
|
|
4
|
+
|
|
5
|
+
module Facturx
|
|
6
|
+
READING_SOURCE_TYPES = %i[xml pdf].freeze
|
|
7
|
+
private_constant :READING_SOURCE_TYPES
|
|
8
|
+
|
|
9
|
+
Reading = Data.define(:document, :profile, :diagnostics, :source, :source_type) do
|
|
10
|
+
include Model::ValidatedWith
|
|
11
|
+
|
|
12
|
+
def initialize(document:, profile:, source:, diagnostics: [], source_type: :xml)
|
|
13
|
+
raise TypeError, 'source must be a byte String' unless source.is_a?(String)
|
|
14
|
+
raise TypeError, 'diagnostics must be an Array' unless diagnostics.is_a?(Array)
|
|
15
|
+
unless READING_SOURCE_TYPES.include?(source_type)
|
|
16
|
+
raise ArgumentError, "Unknown source type: #{source_type.inspect}"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
xml = source.dup.force_encoding(Encoding::BINARY).freeze
|
|
20
|
+
super(document:, profile:, diagnostics: Model.copy_and_freeze(diagnostics), source: xml, source_type:)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'error'
|
|
4
|
+
require_relative 'pdf/extractor'
|
|
5
|
+
|
|
6
|
+
module Facturx
|
|
7
|
+
class SourceReader
|
|
8
|
+
Result = Data.define(:xml, :source_type)
|
|
9
|
+
|
|
10
|
+
def initialize(extractor: Pdf::Extractor.new)
|
|
11
|
+
@extractor = extractor
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def call(source)
|
|
15
|
+
unless source.is_a?(String)
|
|
16
|
+
raise InvalidXmlError.new('Source must be provided as a byte String', input_class: source.class.name)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
return Result.new(xml: source, source_type: :xml) unless pdf?(source)
|
|
20
|
+
|
|
21
|
+
Result.new(xml: @extractor.call(source).xml, source_type: :pdf)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def pdf?(bytes)
|
|
27
|
+
bytes.byteslice(0, 1024).b.include?('%PDF-'.b)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
data/lib/facturx/term.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../term'
|
|
4
|
+
require_relative '../group'
|
|
5
|
+
|
|
6
|
+
module Facturx
|
|
7
|
+
module TermDeclarations
|
|
8
|
+
module Declaration
|
|
9
|
+
module_function
|
|
10
|
+
|
|
11
|
+
def term(*attributes, **cardinalities)
|
|
12
|
+
Term.new(*attributes, cardinalities.freeze).freeze
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def group(*attributes, **cardinalities)
|
|
16
|
+
Group.new(*attributes, cardinalities.freeze).freeze
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Facturx::TermDeclarations::ADJUSTMENTS = [
|
|
4
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
5
|
+
'BT-138', :allowance_charge, :percentage, 'BG-27',
|
|
6
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem' \
|
|
7
|
+
'/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:CalculationPercent',
|
|
8
|
+
:decimal, nil,
|
|
9
|
+
en16931: '0..1',
|
|
10
|
+
extended: '0..1'
|
|
11
|
+
),
|
|
12
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
13
|
+
'BT-137', :allowance_charge, :base_amount, 'BG-27',
|
|
14
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem' \
|
|
15
|
+
'/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:BasisAmount',
|
|
16
|
+
:decimal, 2,
|
|
17
|
+
en16931: '0..1',
|
|
18
|
+
extended: '0..1'
|
|
19
|
+
),
|
|
20
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
21
|
+
'BT-136', :allowance_charge, :amount, 'BG-27',
|
|
22
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem' \
|
|
23
|
+
'/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:ActualAmount',
|
|
24
|
+
:decimal, 2,
|
|
25
|
+
basic: '1..1',
|
|
26
|
+
en16931: '1..1',
|
|
27
|
+
extended: '1..1'
|
|
28
|
+
),
|
|
29
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
30
|
+
'BT-140', :allowance_charge, :reason_code, 'BG-27',
|
|
31
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem' \
|
|
32
|
+
'/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:ReasonCode',
|
|
33
|
+
:string, nil,
|
|
34
|
+
basic: '0..1',
|
|
35
|
+
en16931: '0..1',
|
|
36
|
+
extended: '0..1'
|
|
37
|
+
),
|
|
38
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
39
|
+
'BT-139', :allowance_charge, :reason, 'BG-27',
|
|
40
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem' \
|
|
41
|
+
'/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:Reason',
|
|
42
|
+
:string, nil,
|
|
43
|
+
basic: '0..1',
|
|
44
|
+
en16931: '0..1',
|
|
45
|
+
extended: '0..1'
|
|
46
|
+
),
|
|
47
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
48
|
+
'BT-143', :allowance_charge, :percentage, 'BG-28',
|
|
49
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem' \
|
|
50
|
+
'/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:CalculationPercent',
|
|
51
|
+
:decimal, nil,
|
|
52
|
+
en16931: '0..1',
|
|
53
|
+
extended: '0..1'
|
|
54
|
+
),
|
|
55
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
56
|
+
'BT-142', :allowance_charge, :base_amount, 'BG-28',
|
|
57
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem' \
|
|
58
|
+
'/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:BasisAmount',
|
|
59
|
+
:decimal, 2,
|
|
60
|
+
en16931: '0..1',
|
|
61
|
+
extended: '0..1'
|
|
62
|
+
),
|
|
63
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
64
|
+
'BT-141', :allowance_charge, :amount, 'BG-28',
|
|
65
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem' \
|
|
66
|
+
'/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:ActualAmount',
|
|
67
|
+
:decimal, 2,
|
|
68
|
+
basic: '1..1',
|
|
69
|
+
en16931: '1..1',
|
|
70
|
+
extended: '1..1'
|
|
71
|
+
),
|
|
72
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
73
|
+
'BT-145', :allowance_charge, :reason_code, 'BG-28',
|
|
74
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem' \
|
|
75
|
+
'/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:ReasonCode',
|
|
76
|
+
:string, nil,
|
|
77
|
+
basic: '0..1',
|
|
78
|
+
en16931: '0..1',
|
|
79
|
+
extended: '0..1'
|
|
80
|
+
),
|
|
81
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
82
|
+
'BT-144', :allowance_charge, :reason, 'BG-28',
|
|
83
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem' \
|
|
84
|
+
'/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:Reason',
|
|
85
|
+
:string, nil,
|
|
86
|
+
basic: '0..1',
|
|
87
|
+
en16931: '0..1',
|
|
88
|
+
extended: '0..1'
|
|
89
|
+
),
|
|
90
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
91
|
+
'BT-94', :allowance_charge, :percentage, 'BG-20',
|
|
92
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement' \
|
|
93
|
+
'/ram:SpecifiedTradeAllowanceCharge/ram:CalculationPercent',
|
|
94
|
+
:decimal, nil,
|
|
95
|
+
basic_wl: '0..1',
|
|
96
|
+
basic: '0..1',
|
|
97
|
+
en16931: '0..1',
|
|
98
|
+
extended: '0..1'
|
|
99
|
+
),
|
|
100
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
101
|
+
'BT-93', :allowance_charge, :base_amount, 'BG-20',
|
|
102
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement' \
|
|
103
|
+
'/ram:SpecifiedTradeAllowanceCharge/ram:BasisAmount',
|
|
104
|
+
:decimal, 2,
|
|
105
|
+
basic_wl: '0..1',
|
|
106
|
+
basic: '0..1',
|
|
107
|
+
en16931: '0..1',
|
|
108
|
+
extended: '0..1'
|
|
109
|
+
),
|
|
110
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
111
|
+
'BT-92', :allowance_charge, :amount, 'BG-20',
|
|
112
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement' \
|
|
113
|
+
'/ram:SpecifiedTradeAllowanceCharge/ram:ActualAmount',
|
|
114
|
+
:decimal, 2,
|
|
115
|
+
basic_wl: '1..1',
|
|
116
|
+
basic: '1..1',
|
|
117
|
+
en16931: '1..1',
|
|
118
|
+
extended: '1..1'
|
|
119
|
+
),
|
|
120
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
121
|
+
'BT-98', :allowance_charge, :reason_code, 'BG-20',
|
|
122
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement' \
|
|
123
|
+
'/ram:SpecifiedTradeAllowanceCharge/ram:ReasonCode',
|
|
124
|
+
:string, nil,
|
|
125
|
+
basic_wl: '0..1',
|
|
126
|
+
basic: '0..1',
|
|
127
|
+
en16931: '0..1',
|
|
128
|
+
extended: '0..1'
|
|
129
|
+
),
|
|
130
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
131
|
+
'BT-97', :allowance_charge, :reason, 'BG-20',
|
|
132
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement' \
|
|
133
|
+
'/ram:SpecifiedTradeAllowanceCharge/ram:Reason',
|
|
134
|
+
:string, nil,
|
|
135
|
+
basic_wl: '0..1',
|
|
136
|
+
basic: '0..1',
|
|
137
|
+
en16931: '0..1',
|
|
138
|
+
extended: '0..1'
|
|
139
|
+
),
|
|
140
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
141
|
+
'BT-95', :allowance_charge, :tax, 'BG-20',
|
|
142
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement' \
|
|
143
|
+
'/ram:SpecifiedTradeAllowanceCharge/ram:CategoryTradeTax/ram:CategoryCode',
|
|
144
|
+
:string, nil,
|
|
145
|
+
basic_wl: '1..1',
|
|
146
|
+
basic: '1..1',
|
|
147
|
+
en16931: '1..1',
|
|
148
|
+
extended: '1..1'
|
|
149
|
+
),
|
|
150
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
151
|
+
'BT-96', :allowance_charge, :tax, 'BG-20',
|
|
152
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement' \
|
|
153
|
+
'/ram:SpecifiedTradeAllowanceCharge/ram:CategoryTradeTax/ram:RateApplicablePercent',
|
|
154
|
+
:decimal, nil,
|
|
155
|
+
basic_wl: '0..1',
|
|
156
|
+
basic: '0..1',
|
|
157
|
+
en16931: '0..1',
|
|
158
|
+
extended: '0..1'
|
|
159
|
+
),
|
|
160
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
161
|
+
'BT-101', :allowance_charge, :percentage, 'BG-21',
|
|
162
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement' \
|
|
163
|
+
'/ram:SpecifiedTradeAllowanceCharge/ram:CalculationPercent',
|
|
164
|
+
:decimal, nil,
|
|
165
|
+
basic_wl: '0..1',
|
|
166
|
+
basic: '0..1',
|
|
167
|
+
en16931: '0..1',
|
|
168
|
+
extended: '0..1'
|
|
169
|
+
),
|
|
170
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
171
|
+
'BT-100', :allowance_charge, :base_amount, 'BG-21',
|
|
172
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement' \
|
|
173
|
+
'/ram:SpecifiedTradeAllowanceCharge/ram:BasisAmount',
|
|
174
|
+
:decimal, 2,
|
|
175
|
+
basic_wl: '0..1',
|
|
176
|
+
basic: '0..1',
|
|
177
|
+
en16931: '0..1',
|
|
178
|
+
extended: '0..1'
|
|
179
|
+
),
|
|
180
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
181
|
+
'BT-99', :allowance_charge, :amount, 'BG-21',
|
|
182
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement' \
|
|
183
|
+
'/ram:SpecifiedTradeAllowanceCharge/ram:ActualAmount',
|
|
184
|
+
:decimal, 2,
|
|
185
|
+
basic_wl: '1..1',
|
|
186
|
+
basic: '1..1',
|
|
187
|
+
en16931: '1..1',
|
|
188
|
+
extended: '1..1'
|
|
189
|
+
),
|
|
190
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
191
|
+
'BT-105', :allowance_charge, :reason_code, 'BG-21',
|
|
192
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement' \
|
|
193
|
+
'/ram:SpecifiedTradeAllowanceCharge/ram:ReasonCode',
|
|
194
|
+
:string, nil,
|
|
195
|
+
basic_wl: '0..1',
|
|
196
|
+
basic: '0..1',
|
|
197
|
+
en16931: '0..1',
|
|
198
|
+
extended: '0..1'
|
|
199
|
+
),
|
|
200
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
201
|
+
'BT-104', :allowance_charge, :reason, 'BG-21',
|
|
202
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement' \
|
|
203
|
+
'/ram:SpecifiedTradeAllowanceCharge/ram:Reason',
|
|
204
|
+
:string, nil,
|
|
205
|
+
basic_wl: '0..1',
|
|
206
|
+
basic: '0..1',
|
|
207
|
+
en16931: '0..1',
|
|
208
|
+
extended: '0..1'
|
|
209
|
+
),
|
|
210
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
211
|
+
'BT-102', :allowance_charge, :tax, 'BG-21',
|
|
212
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement' \
|
|
213
|
+
'/ram:SpecifiedTradeAllowanceCharge/ram:CategoryTradeTax/ram:CategoryCode',
|
|
214
|
+
:string, nil,
|
|
215
|
+
basic_wl: '1..1',
|
|
216
|
+
basic: '1..1',
|
|
217
|
+
en16931: '1..1',
|
|
218
|
+
extended: '1..1'
|
|
219
|
+
),
|
|
220
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
221
|
+
'BT-103', :allowance_charge, :tax, 'BG-21',
|
|
222
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement' \
|
|
223
|
+
'/ram:SpecifiedTradeAllowanceCharge/ram:CategoryTradeTax/ram:RateApplicablePercent',
|
|
224
|
+
:decimal, nil,
|
|
225
|
+
basic_wl: '0..1',
|
|
226
|
+
basic: '0..1',
|
|
227
|
+
en16931: '0..1',
|
|
228
|
+
extended: '0..1'
|
|
229
|
+
)
|
|
230
|
+
].freeze
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Facturx::TermDeclarations::DELIVERY = [
|
|
4
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
5
|
+
'BT-134', :period, :start_date, 'BG-26',
|
|
6
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem' \
|
|
7
|
+
'/ram:SpecifiedLineTradeSettlement/ram:BillingSpecifiedPeriod/ram:StartDateTime' \
|
|
8
|
+
'/udt:DateTimeString',
|
|
9
|
+
:date_102, nil,
|
|
10
|
+
basic: '0..1',
|
|
11
|
+
en16931: '0..1',
|
|
12
|
+
extended: '0..1'
|
|
13
|
+
),
|
|
14
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
15
|
+
'BT-135', :period, :end_date, 'BG-26',
|
|
16
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem' \
|
|
17
|
+
'/ram:SpecifiedLineTradeSettlement/ram:BillingSpecifiedPeriod/ram:EndDateTime/udt:DateTimeString',
|
|
18
|
+
:date_102, nil,
|
|
19
|
+
basic: '0..1',
|
|
20
|
+
en16931: '0..1',
|
|
21
|
+
extended: '0..1'
|
|
22
|
+
),
|
|
23
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
24
|
+
'BT-71', :delivery, :location_identifier, 'BG-13',
|
|
25
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery' \
|
|
26
|
+
'/ram:ShipToTradeParty/ram:ID',
|
|
27
|
+
:string, nil,
|
|
28
|
+
basic_wl: '0..1',
|
|
29
|
+
basic: '0..1',
|
|
30
|
+
en16931: '0..1',
|
|
31
|
+
extended: '0..1'
|
|
32
|
+
),
|
|
33
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
34
|
+
'BT-71-1', :delivery, :location_identifier, 'BG-13',
|
|
35
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery' \
|
|
36
|
+
'/ram:ShipToTradeParty/ram:GlobalID/@schemeID',
|
|
37
|
+
:string, nil,
|
|
38
|
+
basic_wl: '0..1',
|
|
39
|
+
basic: '0..1',
|
|
40
|
+
en16931: '0..1',
|
|
41
|
+
extended: '0..1'
|
|
42
|
+
),
|
|
43
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
44
|
+
'BT-70', :delivery, :party, 'BG-13',
|
|
45
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery' \
|
|
46
|
+
'/ram:ShipToTradeParty/ram:Name',
|
|
47
|
+
:string, nil,
|
|
48
|
+
basic_wl: '0..1',
|
|
49
|
+
basic: '0..1',
|
|
50
|
+
en16931: '0..1',
|
|
51
|
+
extended: '0..1'
|
|
52
|
+
),
|
|
53
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
54
|
+
'BT-72', :delivery, :date, 'BG-13-00',
|
|
55
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery' \
|
|
56
|
+
'/ram:ActualDeliverySupplyChainEvent/ram:OccurrenceDateTime/udt:DateTimeString',
|
|
57
|
+
:date_102, nil,
|
|
58
|
+
basic_wl: '0..1',
|
|
59
|
+
basic: '0..1',
|
|
60
|
+
en16931: '0..1',
|
|
61
|
+
extended: '0..1'
|
|
62
|
+
),
|
|
63
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
64
|
+
'BT-73', :period, :start_date, 'BG-14',
|
|
65
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement' \
|
|
66
|
+
'/ram:BillingSpecifiedPeriod/ram:StartDateTime/udt:DateTimeString',
|
|
67
|
+
:date_102, nil,
|
|
68
|
+
basic_wl: '0..1',
|
|
69
|
+
basic: '0..1',
|
|
70
|
+
en16931: '0..1',
|
|
71
|
+
extended: '0..1'
|
|
72
|
+
),
|
|
73
|
+
Facturx::TermDeclarations::Declaration.term(
|
|
74
|
+
'BT-74', :period, :end_date, 'BG-14',
|
|
75
|
+
'/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement' \
|
|
76
|
+
'/ram:BillingSpecifiedPeriod/ram:EndDateTime/udt:DateTimeString',
|
|
77
|
+
:date_102, nil,
|
|
78
|
+
basic_wl: '0..1',
|
|
79
|
+
basic: '0..1',
|
|
80
|
+
en16931: '0..1',
|
|
81
|
+
extended: '0..1'
|
|
82
|
+
)
|
|
83
|
+
].freeze
|