eddy 0.8.2 → 0.9.2

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.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -4
  3. data/CHANGELOG.md +46 -1
  4. data/Gemfile.lock +8 -8
  5. data/README.md +2 -5
  6. data/data/code-lists/333.tsv +8 -0
  7. data/data/segments/amt.segment.yml +7 -0
  8. data/data/segments/bia.segment.yml +10 -0
  9. data/data/segments/cur.segment.yml +8 -0
  10. data/data/segments/dtm.segment.yml +1 -0
  11. data/data/segments/fob.segment.yml +8 -0
  12. data/data/segments/itd.segment.yml +13 -0
  13. data/data/segments/mtx.segment.yml +7 -0
  14. data/data/segments/n9.segment.yml +7 -0
  15. data/data/segments/per.segment.yml +13 -0
  16. data/data/segments/po1.segment.yml +6 -0
  17. data/data/segments/po3.segment.yml +13 -0
  18. data/data/segments/qty.segment.yml +10 -0
  19. data/data/segments/ref.segment.yml +1 -0
  20. data/data/segments/sac.segment.yml +4 -0
  21. data/data/segments/sch.segment.yml +7 -0
  22. data/data/segments/sdq.segment.yml +8 -0
  23. data/data/segments/txi.segment.yml +9 -0
  24. data/data/transaction_sets/810.edi.yml +93 -0
  25. data/data/transaction_sets/846.edi.yml +57 -0
  26. data/data/transaction_sets/850.edi.yml +73 -0
  27. data/data/transaction_sets/855.edi.yml +74 -0
  28. data/data/transaction_sets/856.edi.yml +54 -0
  29. data/eddy.gemspec +1 -1
  30. data/exe/eddy +1 -0
  31. data/lib/definitions/elements/generated/100.currency_code.rb +200 -0
  32. data/lib/definitions/elements/generated/146.shipment_method_of_payment.rb +65 -0
  33. data/lib/definitions/elements/generated/1551.message_text.rb +29 -0
  34. data/lib/definitions/elements/generated/280.exchange_rate.rb +29 -0
  35. data/lib/definitions/elements/generated/309.location_qualifier.rb +209 -0
  36. data/lib/definitions/elements/generated/310.location_identifier.rb +29 -0
  37. data/lib/definitions/elements/generated/311.shipment_type_code.rb +42 -0
  38. data/lib/definitions/elements/generated/322.load_empty_status_code.rb +40 -0
  39. data/lib/definitions/elements/generated/325.tax_identification_number.rb +29 -0
  40. data/lib/definitions/elements/generated/333.terms_basis_date_code.rb +44 -0
  41. data/lib/definitions/elements/generated/336.terms_type_code.rb +102 -0
  42. data/lib/definitions/elements/generated/338.terms_discount_percent.rb +29 -0
  43. data/lib/definitions/elements/generated/351.terms_discount_days_due.rb +30 -0
  44. data/lib/definitions/elements/generated/363.note_reference_code.rb +278 -0
  45. data/lib/definitions/elements/generated/364.communication_number.rb +29 -0
  46. data/lib/definitions/elements/generated/365.communication_number_qualifier.rb +77 -0
  47. data/lib/definitions/elements/generated/366.contact_function_code.rb +267 -0
  48. data/lib/definitions/elements/generated/369.free_form_description.rb +29 -0
  49. data/lib/definitions/elements/generated/370.terms_discount_due_date.rb +29 -0
  50. data/lib/definitions/elements/generated/371.change_reason_code.rb +67 -0
  51. data/lib/definitions/elements/generated/378.allowance_charge_percent_qualifier.rb +48 -0
  52. data/lib/definitions/elements/generated/386.terms_net_days.rb +30 -0
  53. data/lib/definitions/elements/generated/446.terms_net_due_date.rb +29 -0
  54. data/lib/definitions/elements/generated/522.amount_qualifier_code.rb +1510 -0
  55. data/lib/definitions/elements/generated/673.quantity_qualifier.rb +869 -0
  56. data/lib/definitions/elements/generated/755.report_type_code.rb +559 -0
  57. data/lib/definitions/elements/generated/954.percent.rb +29 -0
  58. data/lib/definitions/elements/generated/963.tax_type_code.rb +111 -0
  59. data/lib/definitions/elements/manual/i/I10.interchange_control_standards_identifier.rb +2 -2
  60. data/lib/definitions/elements/manual/i/I11.interchange_control_version_number.rb +1 -0
  61. data/lib/definitions/segments/generated/amt.rb +56 -0
  62. data/lib/definitions/segments/generated/bia.rb +107 -0
  63. data/lib/definitions/segments/generated/cur.rb +73 -0
  64. data/lib/definitions/segments/generated/dtm.rb +17 -0
  65. data/lib/definitions/segments/generated/fob.rb +73 -0
  66. data/lib/definitions/segments/generated/hl.rb +90 -0
  67. data/lib/definitions/segments/generated/itd.rb +158 -0
  68. data/lib/definitions/segments/generated/mtx.rb +56 -0
  69. data/lib/definitions/segments/generated/n2.rb +56 -0
  70. data/lib/definitions/segments/generated/n9.rb +56 -0
  71. data/lib/definitions/segments/generated/per.rb +158 -0
  72. data/lib/definitions/segments/generated/po1.rb +102 -0
  73. data/lib/definitions/segments/generated/po3.rb +158 -0
  74. data/lib/definitions/segments/generated/qty.rb +73 -0
  75. data/lib/definitions/segments/generated/ref.rb +17 -0
  76. data/lib/definitions/segments/generated/sac.rb +68 -0
  77. data/lib/definitions/segments/generated/sch.rb +56 -0
  78. data/lib/definitions/segments/generated/sdq.rb +73 -0
  79. data/lib/definitions/segments/generated/txi.rb +90 -0
  80. data/lib/definitions/transaction_sets/manual/846/846.rb +122 -0
  81. data/lib/definitions/transaction_sets/manual/846/loops/lin.rb +155 -0
  82. data/lib/definitions/transaction_sets/manual/846/loops/n1.rb +107 -0
  83. data/lib/definitions/transaction_sets/manual/846/loops/qty.rb +75 -0
  84. data/lib/definitions/transaction_sets/manual/846/loops/sch.rb +59 -0
  85. data/lib/definitions/transaction_sets/manual/846/loops/sln.rb +59 -0
  86. data/lib/definitions/transaction_sets/manual/850/850.rb +108 -1
  87. data/lib/definitions/transaction_sets/manual/850/loops/ctp.rb +47 -0
  88. data/lib/definitions/transaction_sets/manual/850/loops/n1.rb +31 -10
  89. data/lib/definitions/transaction_sets/manual/850/loops/n9.rb +59 -0
  90. data/lib/definitions/transaction_sets/manual/850/loops/pid.rb +47 -0
  91. data/lib/definitions/transaction_sets/manual/850/loops/po1.rb +78 -10
  92. data/lib/definitions/transaction_sets/manual/850/loops/sac.rb +47 -0
  93. data/lib/eddy.rb +49 -3
  94. data/lib/eddy/build/transaction_set_builder.rb +1 -1
  95. data/lib/eddy/config.rb +0 -21
  96. data/lib/eddy/data.rb +0 -40
  97. data/lib/eddy/data/persistence/base.rb +5 -11
  98. data/lib/eddy/data/persistence/memory.rb +14 -22
  99. data/lib/eddy/errors.rb +13 -9
  100. data/lib/eddy/models/element/composite.rb +2 -0
  101. data/lib/eddy/models/element/id.rb +1 -1
  102. data/lib/eddy/models/element/r.rb +1 -0
  103. data/lib/eddy/models/functional_group.rb +3 -2
  104. data/lib/eddy/models/interchange.rb +6 -2
  105. data/lib/eddy/models/transaction_set.rb +1 -1
  106. data/lib/eddy/parse.rb +4 -56
  107. data/lib/eddy/parse/interchange.rb +58 -0
  108. data/lib/eddy/summary/loop.rb +1 -1
  109. data/lib/eddy/summary/segment.rb +2 -1
  110. data/lib/eddy/version.rb +1 -1
  111. metadata +78 -5
@@ -58,7 +58,7 @@ module Eddy
58
58
  def build_loops()
59
59
  FileUtils.mkdir_p(File.join(self.folder, "loops"))
60
60
  self.summary.unique_loops.each do |looop|
61
- File.open(File.join(self.folder, "loops", "#{looop.normalized_name}.rb"), "a") do |f|
61
+ File.open(File.join(self.folder, "loops", "#{looop.class_name}.rb"), "a") do |f|
62
62
  f.write(Eddy::Build::Loop.render(looop, self.normalized_name) + "\n")
63
63
  end
64
64
  end
@@ -41,25 +41,4 @@ module Eddy
41
41
  end
42
42
 
43
43
  end
44
-
45
- # Configuration for Eddy
46
- #
47
- # @return [Eddy::Config]
48
- def self.config()
49
- @config ||= Config.new
50
- end
51
-
52
- # Modify Eddy's current config
53
- #
54
- # @example
55
- # Eddy.configure do |config|
56
- # config.persistence_method = :file
57
- # end
58
- #
59
- # @yieldparam [Eddy::Config] config current Eddy config
60
- # @return [void]
61
- def self.configure()
62
- yield self.config
63
- end
64
-
65
44
  end
@@ -3,36 +3,8 @@ require "eddy/data/persistence/base"
3
3
  require "eddy/data/persistence/memory"
4
4
 
5
5
  module Eddy
6
-
7
- # Persistent data used by Eddy.
8
- #
9
- # @return [Eddy::Data::Persistence::Base]
10
- def self.data
11
- return @data if defined?(@data) && !@data.nil?
12
- case Eddy.config.persistence_method
13
- when :memory then @data = Eddy::Data::Persistence::Memory.new()
14
- when :file then raise NotImplementedError
15
- when :active_record
16
- if defined?(Rails) && defined?(Eddy::Rails)
17
- @data = Eddy::Data::Persistence::ActiveRecord.new()
18
- else
19
- raise Eddy::Errors::Error, "ActiveRecord persistence method can currently only be used with Ruby on Rails"
20
- end
21
- else raise Eddy::Errors::Error, "Unsupported persistence method: #{Eddy.config.persistence_method}"
22
- end
23
- return @data
24
- end
25
-
26
- # Set `@data` to `nil` so that a new persistence_method can be set up.
27
- #
28
- # @return [void]
29
- def self.clear_data()
30
- @data = nil
31
- end
32
-
33
6
  # Code for storing & generating data used by Eddy when generating EDI documents.
34
7
  module Data
35
-
36
8
  # Return a new, unique number.
37
9
  #
38
10
  # @return [Integer]
@@ -53,17 +25,5 @@ module Eddy
53
25
  Eddy.data.add_transaction_set_control_number(transaction_set_id, new_ctrl_num)
54
26
  return new_ctrl_num
55
27
  end
56
-
57
- # Return a new, unique number.
58
- #
59
- # @param functional_group [String]
60
- # @return [Integer]
61
- def self.new_functional_group_control_number(functional_group)
62
- existing = Eddy.data.functional_group_control_numbers(functional_group)
63
- new_ctrl_num = Eddy::Util.new_number(existing)
64
- Eddy.data.add_functional_group_control_number(functional_group, new_ctrl_num)
65
- return new_ctrl_num
66
- end
67
-
68
28
  end
69
29
  end
@@ -4,14 +4,15 @@ module Eddy
4
4
  # Base class for data persistence wrappers.
5
5
  class Base
6
6
 
7
- # @return [Array<Integer>]
8
- def interchange_control_numbers()
7
+ # Clear persisted data.
8
+ #
9
+ # @return [void]
10
+ def reset()
9
11
  raise NotImplementedError
10
12
  end
11
13
 
12
- # @param _functional_group [String]
13
14
  # @return [Array<Integer>]
14
- def functional_group_control_numbers(_functional_group)
15
+ def interchange_control_numbers()
15
16
  raise NotImplementedError
16
17
  end
17
18
 
@@ -27,13 +28,6 @@ module Eddy
27
28
  raise NotImplementedError
28
29
  end
29
30
 
30
- # @param _functional_group [String]
31
- # @param _new_ctrl_num [Integer]
32
- # @return [Array<Integer>]
33
- def add_functional_group_control_number(_functional_group, _new_ctrl_num)
34
- raise NotImplementedError
35
- end
36
-
37
31
  # @param _transaction_set_id [String]
38
32
  # @param _new_ctrl_num [Integer]
39
33
  # @return [Array<Integer>]
@@ -8,23 +8,23 @@ module Eddy
8
8
  def initialize()
9
9
  @data = {
10
10
  interchange_control_numbers: [],
11
- functional_group_control_numbers: {},
12
11
  transaction_set_control_numbers: {},
13
12
  }
14
13
  end
15
14
 
16
- # @return [Array<Integer>]
17
- def interchange_control_numbers()
18
- return @data[:interchange_control_numbers]
15
+ # Clear persisted data.
16
+ #
17
+ # @return [void]
18
+ def reset()
19
+ @data = {
20
+ interchange_control_numbers: [],
21
+ transaction_set_control_numbers: {},
22
+ }
19
23
  end
20
24
 
21
- # @param functional_group [String]
22
25
  # @return [Array<Integer>]
23
- def functional_group_control_numbers(functional_group)
24
- unless @data[:functional_group_control_numbers].key?(functional_group)
25
- @data[:functional_group_control_numbers][functional_group] = []
26
- end
27
- return @data[:functional_group_control_numbers][functional_group]
26
+ def interchange_control_numbers()
27
+ return @data[:interchange_control_numbers]
28
28
  end
29
29
 
30
30
  # @param transaction_set_id [String]
@@ -37,26 +37,18 @@ module Eddy
37
37
  end
38
38
 
39
39
  # @param new_ctrl_num [Integer]
40
- # @return [void]
40
+ # @return [Array<Integer>]
41
41
  def add_interchange_control_number(new_ctrl_num)
42
42
  self.interchange_control_numbers.append(new_ctrl_num)
43
- return nil
44
- end
45
-
46
- # @param functional_group [String]
47
- # @param new_ctrl_num [Integer]
48
- # @return [void]
49
- def add_functional_group_control_number(functional_group, new_ctrl_num)
50
- self.functional_group_control_numbers(functional_group).append(new_ctrl_num)
51
- return nil
43
+ return self.interchange_control_numbers()
52
44
  end
53
45
 
54
46
  # @param transaction_set_id [String]
55
47
  # @param new_ctrl_num [Integer]
56
- # @return [void]
48
+ # @return [Array<Integer>]
57
49
  def add_transaction_set_control_number(transaction_set_id, new_ctrl_num)
58
50
  self.transaction_set_control_numbers(transaction_set_id).append(new_ctrl_num)
59
- return nil
51
+ return self.transaction_set_control_numbers(transaction_set_id)
60
52
  end
61
53
 
62
54
  end
@@ -4,6 +4,18 @@ module Eddy
4
4
  # Exceptions raised by Eddy inherit from Error.
5
5
  class Error < StandardError; end
6
6
 
7
+ # Exception raised when an issue occurs while generating code.
8
+ class BuildError < Error; end
9
+
10
+ # Exception raised from a `render` method.
11
+ class RenderError < Error; end
12
+
13
+ # Exception raised when a definition file can't be found.
14
+ class MissingDefinitionError < Error; end
15
+
16
+ # Exception raised when a definition file can't be found.
17
+ class ParseError < Error; end
18
+
7
19
  # @!group Element Validation Errors
8
20
 
9
21
  # Exception raised by descendents of {Eddy::Models::Element::Base}.
@@ -99,15 +111,7 @@ module Eddy
99
111
  end
100
112
  end
101
113
 
102
- # @!endgroup Element Validation Errors
114
+ # @!endgroup
103
115
 
104
- # Exception raised when an issue occurs while generating code.
105
- class BuildError < Error; end
106
-
107
- # Exception raised from a `render` method.
108
- class RenderError < Error; end
109
-
110
- # Exception raised when a definition file can't be found.
111
- class MissingDefinitionError < Error; end
112
116
  end
113
117
  end
@@ -2,6 +2,8 @@ module Eddy
2
2
  module Models
3
3
  module Element
4
4
  # - [References to Component Data Elements - X12 RFI](http://www.x12.org/rfis/References%20to%20Component%20Data%20Elements.pdf)
5
+ # - [What’s the Repetition Separator Character in 5010 X12?](http://www.rdpcrystal.com/whats-the-repetition-separator-character-in-5010-x12/)
6
+ # - [Delimiters in data fields (RFI 1815)](http://rfi.x12.org/Request/Details/1815?stateViewModel=WPC.RFI.Models.ViewModels.RequestViewModel)
5
7
  class Composite; end
6
8
  end
7
9
  end
@@ -1,7 +1,7 @@
1
1
  module Eddy
2
2
  module Models
3
3
  module Element
4
- # Identifier (works with a code list specified by the dictionary).
4
+ # Identifier. Works with a code list specified by the dictionary.
5
5
  class ID < Base
6
6
 
7
7
  # @param min [Integer]
@@ -70,6 +70,7 @@ module Eddy
70
70
  when Integer
71
71
  return val.to_s.slice(0..max)
72
72
  when Float
73
+ # FIXME: This isn't correct.
73
74
  return val.to_s.slice(0..(max + 1))
74
75
  when Complex
75
76
  # TODO: Handle case
@@ -16,17 +16,18 @@ module Eddy
16
16
  attr_accessor :transaction_sets
17
17
 
18
18
  # @param store [Eddy::Data::Store]
19
+ # @param control_number [Integer]
19
20
  # @param transaction_sets [Eddy::Models::TransactionSet]
20
21
  # @return [void]
21
- def initialize(store, *transaction_sets)
22
+ def initialize(store, control_number, *transaction_sets)
22
23
  self.store = store
24
+ self.control_number = control_number
23
25
  transaction_sets.flatten!
24
26
  self.transaction_sets = transaction_sets || []
25
27
  if self.transaction_sets.length == 0
26
28
  raise ArgumentError, "At least one transaction set is required to create a functional group"
27
29
  end
28
30
  @id = self.transaction_sets.first.functional_group
29
- self.control_number = Eddy::Data.new_functional_group_control_number(@id)
30
31
  end
31
32
 
32
33
  # @return [Array<#render>]
@@ -34,7 +34,7 @@ module Eddy
34
34
  isa = Eddy::Segments::ISA.new(self.store, self.control_number)
35
35
  iea = Eddy::Segments::IEA.new(self.store, self.control_number, f_groups.length)
36
36
  yield(isa, iea) if block_given?
37
- return [isa, f_groups, iea].flatten.map(&:render).join(sep) + sep
37
+ return ([isa, f_groups, iea].flatten.map(&:render).join(sep) + sep).rstrip()
38
38
  end
39
39
 
40
40
  # @return [Array<Eddy::Models::FunctionalGroup>]
@@ -44,7 +44,11 @@ module Eddy
44
44
  sorted_sets[ts.functional_group] ||= []
45
45
  sorted_sets[ts.functional_group] << ts
46
46
  end
47
- return sorted_sets.map { |_, value| Eddy::Models::FunctionalGroup.new(self.store, *value) }
47
+ i = 0
48
+ return sorted_sets.map do |_, value|
49
+ i += 1
50
+ Eddy::Models::FunctionalGroup.new(self.store, i, *value)
51
+ end
48
52
  end
49
53
 
50
54
  private
@@ -82,7 +82,7 @@ module Eddy
82
82
  # @return [String]
83
83
  def render(s_sep = self.store.segment_separator)
84
84
  add_envelope()
85
- return self.all_components.map { |s| s.render(self.store.element_separator) }.compact.join(s_sep)
85
+ return self.all_components.map { |s| s.render(self.store.element_separator) }.compact.join(s_sep).rstrip()
86
86
  end
87
87
 
88
88
  # Return the count of Segments in the Transaction Set where `skip` is false,
@@ -1,58 +1,6 @@
1
- module Eddy
2
- module Parse
3
- # Wrapper around an interchange file or string.
4
- class Interchange
5
-
6
- # Raw content of the interchange.
7
- # @return [String]
8
- attr_accessor :document
9
- # Component Element Separator
10
- # @return [String] (">")
11
- attr_accessor :component_separator
12
- # @return [String] ("~")
13
- attr_accessor :segment_separator
14
- # Data Element Separator
15
- # @return [String] ("\*")
16
- attr_accessor :element_separator
17
-
18
- # @param doc [String] EDI document.
19
- # @param component_separator [String] (">")
20
- # @param segment_separator [String] ("~")
21
- # @param element_separator [String] ("\*")
22
- # @return [void]
23
- def initialize(doc, component_separator: ">", segment_separator: "~", element_separator: "*")
24
- self.document = doc
25
- self.component_separator = component_separator
26
- self.segment_separator = segment_separator
27
- self.element_separator = element_separator
28
- end
29
-
30
- # @param path [String]
31
- # @return [self]
32
- def self.from_file(path, **kwargs)
33
- return self.new(File.read(path), **kwargs)
34
- end
1
+ require "eddy/parse/interchange"
35
2
 
36
- # @return [Array<Hash>]
37
- def parse()
38
- doc = self.document.gsub(/\n/, "")
39
- segments = doc.split(self.segment_separator)
40
- segments.map { |seg| self.parse_segment(seg) }
41
- end
42
-
43
- # @param seg [String]
44
- # @return [Hash]
45
- def parse_segment(seg)
46
- name, *elements = seg.split(self.element_separator)
47
- res = { name: name, elements: {} }
48
- elements.each_with_index do |value, index|
49
- next if value == ""
50
- key = sprintf("%s%02d", name, index + 1)
51
- res[:elements][key] = value
52
- end
53
- return res
54
- end
55
-
56
- end
57
- end
3
+ module Eddy
4
+ # Code for reading EDI documents.
5
+ module Parse; end
58
6
  end
@@ -0,0 +1,58 @@
1
+ module Eddy
2
+ module Parse
3
+ # Wrapper around an interchange file or string.
4
+ class Interchange
5
+
6
+ # Raw content of the interchange.
7
+ # @return [String]
8
+ attr_accessor :document
9
+ # Component Element Separator
10
+ # @return [String] (">")
11
+ attr_accessor :component_separator
12
+ # @return [String] ("~")
13
+ attr_accessor :segment_separator
14
+ # Data Element Separator
15
+ # @return [String] ("\*")
16
+ attr_accessor :element_separator
17
+
18
+ # @param doc [String] EDI document.
19
+ # @param component_separator [String] (">")
20
+ # @param segment_separator [String] ("~")
21
+ # @param element_separator [String] ("\*")
22
+ # @return [void]
23
+ def initialize(doc, component_separator: ">", segment_separator: "~", element_separator: "*")
24
+ self.document = doc
25
+ self.component_separator = component_separator
26
+ self.segment_separator = segment_separator
27
+ self.element_separator = element_separator
28
+ end
29
+
30
+ # @param path [String]
31
+ # @return [self]
32
+ def self.from_file(path, **kwargs)
33
+ return self.new(File.read(path), **kwargs)
34
+ end
35
+
36
+ # @return [Array<Hash>]
37
+ def parse()
38
+ doc = self.document.gsub(/\n/, "")
39
+ segments = doc.split(self.segment_separator)
40
+ segments.map { |seg| self.parse_segment(seg) }
41
+ end
42
+
43
+ # @param seg [String]
44
+ # @return [Hash]
45
+ def parse_segment(seg)
46
+ name, *elements = seg.split(self.element_separator)
47
+ res = { name: name, elements: {} }
48
+ elements.each_with_index do |value, index|
49
+ next if value == ""
50
+ key = sprintf("%s%02d", name, index + 1)
51
+ res[:elements][key] = value
52
+ end
53
+ return res
54
+ end
55
+
56
+ end
57
+ end
58
+ end
@@ -108,7 +108,7 @@ module Eddy
108
108
  end
109
109
  end
110
110
 
111
- # Return `id` with the prefixes `"l_"` or `"hl_" removed.
111
+ # Return `id` with the prefixes `l_` or `"hl_"` removed.
112
112
  #
113
113
  # @return [String]
114
114
  def class_name()
@@ -113,7 +113,8 @@ module Eddy
113
113
 
114
114
  # Helper function to simplify conditional logic in {Eddy::Build}.
115
115
  #
116
- # @see {Eddy::Summary::Loop#treat_as_segment?}
116
+ # See `Eddy::Summary::Loop#treat_as_segment?`
117
+ #
117
118
  # @return [Boolean] (true) Always returns true.
118
119
  def build_as_segment?()
119
120
  return true