adf_builder 1.2.2 → 1.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: f5c6497310cd559356bd6e358243d2dd2ed5d2a859330fe403ae959b32592b0b
4
- data.tar.gz: 77e66f74d658adc2022d401d85a037549f8f92c91d984c265db337a33c05353c
3
+ metadata.gz: c0e75f097adeb0e0f73541ee79c693ae5de334a55b9330eb49130037fd6fbbe5
4
+ data.tar.gz: 78c32bb06e602c81270ce30b97ed526fb9449d9bc5aa6b6ddf19ac22593c8596
5
5
  SHA512:
6
- metadata.gz: 8aba468994e77c3af346c7f6dccbdd4eed16fd858ccf6206226c90d97a5e1126d75bc5083440d40ce1ac3233d2b6f0395b899fcce70afc76ccba7691867e779f
7
- data.tar.gz: 215970d63f001f71e21c55651368c9ebab28dafd9e5f26d19519dbff6c897ed4859443623f01d3a99a5c014743d00f8e74b351eda0b371d28e578edc744d5582
6
+ metadata.gz: c00a8c760bac13e7347f7a365e9598f6c2993ccf72c3adeaf1ef498e3092b6eab70bcd65b8c31e5bc0594014c012339b2653d4017b09716e20fc5364f174d587
7
+ data.tar.gz: 1c2a4588b945d2cc5275e1a583dea5da1fffc6fa7c6d9004c3466bf984d905bbc9bdfe49496073191a025f5c99efbc0ba503042ce587e2cf97380290336869bb
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## [1.3.1] - 2026-01-19
2
+ - **Validation Refinement**: `Address` now strictly enforces 1 to 5 `street` lines.
3
+
4
+ ## [1.3.0] - 2026-01-19
5
+ - **Customer & Contact Validations**:
6
+ - `Contact`: Requires Name and at least one Phone or Email.
7
+ - `Address`: Validates Country against ISO 3166-1 alpha-2 codes.
8
+ - `Timeframe`: Validates ISO 8601 dates and requires earliest/latest date if present.
9
+ - `Phone/Email`: Enforces valid types and preference flags.
10
+
1
11
  ## [1.2.2] - 2026-01-19
2
12
  - **Strict Validations**: Added ISO 4217 currency validation for `Price`, `Amount`, and `Balance`.
3
13
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- adf_builder (1.2.1)
4
+ adf_builder (1.3.0)
5
5
  ox (~> 2.14)
6
6
 
7
7
  GEM
@@ -39,20 +39,41 @@ module AdfBuilder
39
39
  @tag_name = :timeframe
40
40
  end
41
41
 
42
+ def validate!
43
+ super
44
+ # If timeframe is present, earliestdate or latestdate is required
45
+ return if @children.any? { |c| %i[earliestdate latestdate].include?(c.tag_name) }
46
+
47
+ raise AdfBuilder::Error, "Timeframe must have at least one of earliestdate or latestdate"
48
+ end
49
+
42
50
  def description(value)
43
51
  remove_children(:description)
44
52
  add_child(GenericNode.new(:description, {}, value))
45
53
  end
46
54
 
47
55
  def earliestdate(value)
56
+ validate_iso8601(value)
48
57
  remove_children(:earliestdate)
49
58
  add_child(GenericNode.new(:earliestdate, {}, value))
50
59
  end
51
60
 
52
61
  def latestdate(value)
62
+ validate_iso8601(value)
53
63
  remove_children(:latestdate)
54
64
  add_child(GenericNode.new(:latestdate, {}, value))
55
65
  end
66
+
67
+ private
68
+
69
+ def validate_iso8601(value)
70
+ # Simple ISO 8601 check (YYYY-MM-DDT...)
71
+ # Using a basic regex for now or standard library
72
+ require "date"
73
+ Date.iso8601(value.to_s)
74
+ rescue ArgumentError
75
+ raise AdfBuilder::Error, "Invalid ISO 8601 date: #{value}"
76
+ end
56
77
  end
57
78
  end
58
79
  end
@@ -14,7 +14,14 @@ module AdfBuilder
14
14
  end
15
15
  end
16
16
 
17
+ # Common ISO 3166-1 alpha-2 codes
18
+ ISO_3166 = %w[US CA MX GB DE FR GR IT ES JP CN IN BR RU ZA AU NZ KR SE NO FI DK NL BE CH].freeze
19
+
17
20
  class Phone < Node
21
+ validates_inclusion_of :type, in: %i[phone fax cellphone pager]
22
+ validates_inclusion_of :time, in: %i[morning afternoon evening nopreference day]
23
+ validates_inclusion_of :preferredcontact, in: [0, 1, "0", "1"]
24
+
18
25
  def initialize(value, type: nil, time: nil, preferredcontact: nil)
19
26
  super()
20
27
  @tag_name = :phone
@@ -26,6 +33,8 @@ module AdfBuilder
26
33
  end
27
34
 
28
35
  class Email < Node
36
+ validates_inclusion_of :preferredcontact, in: [0, 1, "0", "1"]
37
+
29
38
  def initialize(value, preferredcontact: nil)
30
39
  super()
31
40
  @tag_name = :email
@@ -35,6 +44,9 @@ module AdfBuilder
35
44
  end
36
45
 
37
46
  class Name < Node
47
+ validates_inclusion_of :part, in: %i[first middle suffix last full]
48
+ validates_inclusion_of :type, in: %i[individual business]
49
+
38
50
  def initialize(value, part: nil, type: nil)
39
51
  super()
40
52
  @tag_name = :name
@@ -45,12 +57,24 @@ module AdfBuilder
45
57
  end
46
58
 
47
59
  class Address < Node
60
+ validates_inclusion_of :type, in: %i[work home delivery]
61
+ validates_inclusion_of :country, in: ISO_3166
62
+
48
63
  def initialize(type: nil)
49
64
  super()
50
65
  @tag_name = :address
51
66
  @attributes[:type] = type if type
52
67
  end
53
68
 
69
+ def validate!
70
+ super
71
+ streets = @children.select { |c| c.tag_name == :street }
72
+ raise AdfBuilder::Error, "Address must have at least one street line" if streets.empty?
73
+ return unless streets.size > 5
74
+
75
+ raise AdfBuilder::Error, "Address can have at most 5 street lines"
76
+ end
77
+
54
78
  def street(value, line: nil)
55
79
  node = GenericNode.new(:street, { line: line }.compact, value)
56
80
  add_child(node)
@@ -59,16 +83,33 @@ module AdfBuilder
59
83
  # Simple elements
60
84
  %i[apartment city regioncode postalcode country].each do |tag|
61
85
  define_method(tag) do |value|
86
+ if tag == :country && !ISO_3166.include?(value.to_s.upcase)
87
+ raise AdfBuilder::Error, "Invalid country code: #{value}"
88
+ end
89
+
62
90
  add_child(GenericNode.new(tag, {}, value))
63
91
  end
64
92
  end
65
93
  end
66
94
 
67
95
  class Contact < Node
68
- def initialize(primary_contact: false)
96
+ validates_inclusion_of :primarycontact, in: [0, 1, "0", "1"]
97
+
98
+ def initialize(primary_contact: nil)
69
99
  super()
70
100
  @tag_name = :contact
71
- # primary_contact might be useful for logic but not an attribute
101
+ @attributes[:primarycontact] = primary_contact if primary_contact
102
+ end
103
+
104
+ def validate!
105
+ super
106
+ # Custom Validation: Name is required
107
+ raise AdfBuilder::Error, "Contact must have a Name" unless @children.any? { |c| c.tag_name == :name }
108
+
109
+ # Custom Validation: At least one Phone OR Email
110
+ return if @children.any? { |c| %i[phone email].include?(c.tag_name) }
111
+
112
+ raise AdfBuilder::Error, "Contact must have at least one Phone or Email"
72
113
  end
73
114
 
74
115
  def name(value, part: nil, type: nil)
@@ -31,7 +31,11 @@ module AdfBuilder
31
31
  next if value.nil?
32
32
 
33
33
  allowed = validation[:in]
34
- unless allowed.include?(value)
34
+ # Normalize for comparison (allow string/symbol interchangeably)
35
+ value_s = value.to_s
36
+ allowed_s = allowed.map(&:to_s)
37
+
38
+ unless allowed_s.include?(value_s)
35
39
  raise AdfBuilder::Error,
36
40
  "Invalid value for #{validation[:attribute]}: #{value}. Allowed: #{allowed.join(", ")}"
37
41
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AdfBuilder
4
- VERSION = "1.2.2"
4
+ VERSION = "1.3.1"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: adf_builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - marcus.salinas