adf_builder 1.2.1 → 1.3.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 -0
- data/Gemfile.lock +1 -1
- data/lib/adf_builder/nodes/customer.rb +21 -0
- data/lib/adf_builder/nodes/shared.rb +37 -2
- data/lib/adf_builder/nodes/vehicle_nodes.rb +13 -0
- data/lib/adf_builder/validations.rb +5 -1
- data/lib/adf_builder/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d362b1ad0b8a252bd6e941a5c1c2572b098d1b0fb98da0eed415fa3074297fff
|
|
4
|
+
data.tar.gz: 8319bcc2fd7289ac3e0dfd46be7deb46166b1b2b1cbea247ad1b5eeac2f86b87
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f49bb434697231563e420d4da2123b38370b61ac8b83ae5e6e6d7ad3517c6308acdd7a4db70e7a3866f5c578c4f2bd012a7830d94a69dc0ca8aacd6c941f9dbc
|
|
7
|
+
data.tar.gz: 5441957e0585459da711b7943e8e5d0eca3b4d596c54159178a71656c6a532c185dcf5395765eae75dbe46c3a6df5d8c80eb02a8e9101f1cc25b09698c32549f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## [1.3.0] - 2026-01-19
|
|
2
|
+
- **Customer & Contact Validations**:
|
|
3
|
+
- `Contact`: Requires Name and at least one Phone or Email.
|
|
4
|
+
- `Address`: Validates Country against ISO 3166-1 alpha-2 codes.
|
|
5
|
+
- `Timeframe`: Validates ISO 8601 dates and requires earliest/latest date if present.
|
|
6
|
+
- `Phone/Email`: Enforces valid types and preference flags.
|
|
7
|
+
|
|
8
|
+
## [1.2.2] - 2026-01-19
|
|
9
|
+
- **Strict Validations**: Added ISO 4217 currency validation for `Price`, `Amount`, and `Balance`.
|
|
10
|
+
|
|
1
11
|
## [1.2.1] - 2026-01-19
|
|
2
12
|
- **Strict Validations**: Added `presence` validation for `Vehicle` (year, make, model required).
|
|
3
13
|
|
data/Gemfile.lock
CHANGED
|
@@ -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,6 +57,9 @@ 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
|
|
@@ -52,6 +67,9 @@ module AdfBuilder
|
|
|
52
67
|
end
|
|
53
68
|
|
|
54
69
|
def street(value, line: nil)
|
|
70
|
+
# Line validation 1-5
|
|
71
|
+
raise AdfBuilder::Error, "Street line must be 1-5" if line && !line.to_s.match?(/^[1-5]$/)
|
|
72
|
+
|
|
55
73
|
node = GenericNode.new(:street, { line: line }.compact, value)
|
|
56
74
|
add_child(node)
|
|
57
75
|
end
|
|
@@ -59,16 +77,33 @@ module AdfBuilder
|
|
|
59
77
|
# Simple elements
|
|
60
78
|
%i[apartment city regioncode postalcode country].each do |tag|
|
|
61
79
|
define_method(tag) do |value|
|
|
80
|
+
if tag == :country && !ISO_3166.include?(value.to_s.upcase)
|
|
81
|
+
raise AdfBuilder::Error, "Invalid country code: #{value}"
|
|
82
|
+
end
|
|
83
|
+
|
|
62
84
|
add_child(GenericNode.new(tag, {}, value))
|
|
63
85
|
end
|
|
64
86
|
end
|
|
65
87
|
end
|
|
66
88
|
|
|
67
89
|
class Contact < Node
|
|
68
|
-
|
|
90
|
+
validates_inclusion_of :primarycontact, in: [0, 1, "0", "1"]
|
|
91
|
+
|
|
92
|
+
def initialize(primary_contact: nil)
|
|
69
93
|
super()
|
|
70
94
|
@tag_name = :contact
|
|
71
|
-
|
|
95
|
+
@attributes[:primarycontact] = primary_contact if primary_contact
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def validate!
|
|
99
|
+
super
|
|
100
|
+
# Custom Validation: Name is required
|
|
101
|
+
raise AdfBuilder::Error, "Contact must have a Name" unless @children.any? { |c| c.tag_name == :name }
|
|
102
|
+
|
|
103
|
+
# Custom Validation: At least one Phone OR Email
|
|
104
|
+
return if @children.any? { |c| %i[phone email].include?(c.tag_name) }
|
|
105
|
+
|
|
106
|
+
raise AdfBuilder::Error, "Contact must have at least one Phone or Email"
|
|
72
107
|
end
|
|
73
108
|
|
|
74
109
|
def name(value, part: nil, type: nil)
|
|
@@ -67,10 +67,21 @@ module AdfBuilder
|
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
69
|
|
|
70
|
+
# Common ISO 4217 codes (Top valid ones per spec/common usage)
|
|
71
|
+
# Keeping it as a constant for reuse.
|
|
72
|
+
# This list can be expanded but covers major currencies.
|
|
73
|
+
ISO_4217 = %w[
|
|
74
|
+
USD EUR GBP JPY AUD CAD CHF CNY SEK NZD
|
|
75
|
+
MXN SGD HKD NOK KRW TRY RUB INR BRL ZAR
|
|
76
|
+
DKK PLN TWD THB IDR HUF CZK ILS CLP PHP
|
|
77
|
+
AED COP SAR MYR RON PEN VND NGN
|
|
78
|
+
].freeze
|
|
79
|
+
|
|
70
80
|
class Price < Node
|
|
71
81
|
validates_inclusion_of :type, in: %i[quote offer msrp invoice call appraisal asking]
|
|
72
82
|
validates_inclusion_of :delta, in: %i[absolute relative percentage]
|
|
73
83
|
validates_inclusion_of :relativeto, in: %i[msrp invoice]
|
|
84
|
+
validates_inclusion_of :currency, in: ISO_4217
|
|
74
85
|
|
|
75
86
|
def initialize(value, type: :quote, currency: nil, delta: nil, relativeto: nil, source: nil)
|
|
76
87
|
super()
|
|
@@ -87,6 +98,7 @@ module AdfBuilder
|
|
|
87
98
|
class Amount < Node
|
|
88
99
|
validates_inclusion_of :type, in: %i[downpayment monthly total]
|
|
89
100
|
validates_inclusion_of :limit, in: %i[maximum minimum exact]
|
|
101
|
+
validates_inclusion_of :currency, in: ISO_4217
|
|
90
102
|
|
|
91
103
|
def initialize(value, type: :total, limit: :maximum, currency: nil)
|
|
92
104
|
super()
|
|
@@ -100,6 +112,7 @@ module AdfBuilder
|
|
|
100
112
|
|
|
101
113
|
class Balance < Node
|
|
102
114
|
validates_inclusion_of :type, in: %i[finance residual]
|
|
115
|
+
validates_inclusion_of :currency, in: ISO_4217
|
|
103
116
|
|
|
104
117
|
def initialize(value, type: :finance, currency: nil)
|
|
105
118
|
super()
|
|
@@ -31,7 +31,11 @@ module AdfBuilder
|
|
|
31
31
|
next if value.nil?
|
|
32
32
|
|
|
33
33
|
allowed = validation[:in]
|
|
34
|
-
|
|
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
|
data/lib/adf_builder/version.rb
CHANGED