nacha 0.1.10 → 0.1.14

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 (83) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +63 -0
  3. data/.gitignore +2 -0
  4. data/.rubocop.yml +4 -2
  5. data/.ruby-version +1 -1
  6. data/CHANGELOG.md +42 -0
  7. data/README.md +10 -2
  8. data/exe/nacha +46 -29
  9. data/lib/nacha/aba_number.rb +33 -24
  10. data/lib/nacha/ach_date.rb +15 -8
  11. data/lib/nacha/field.rb +62 -77
  12. data/lib/nacha/formatter/base.rb +52 -0
  13. data/lib/nacha/formatter/html_formatter.rb +119 -0
  14. data/lib/nacha/formatter/json_formatter.rb +49 -0
  15. data/lib/nacha/formatter/markdown_formatter.rb +57 -0
  16. data/lib/nacha/formatter.rb +24 -0
  17. data/lib/nacha/has_errors.rb +12 -8
  18. data/lib/nacha/numeric.rb +13 -10
  19. data/lib/nacha/parser.rb +32 -31
  20. data/lib/nacha/parser_context.rb +4 -9
  21. data/lib/nacha/record/ack_entry_detail.rb +15 -8
  22. data/lib/nacha/record/addenda_record_type.rb +8 -1
  23. data/lib/nacha/record/adv_batch_control.rb +12 -7
  24. data/lib/nacha/record/adv_entry_detail.rb +3 -2
  25. data/lib/nacha/record/adv_file_control.rb +9 -5
  26. data/lib/nacha/record/adv_file_header.rb +11 -6
  27. data/lib/nacha/record/arc_entry_detail.rb +2 -2
  28. data/lib/nacha/record/base.rb +124 -106
  29. data/lib/nacha/record/batch_control.rb +13 -7
  30. data/lib/nacha/record/batch_header.rb +20 -11
  31. data/lib/nacha/record/batch_header_record_type.rb +5 -4
  32. data/lib/nacha/record/boc_entry_detail.rb +3 -2
  33. data/lib/nacha/record/ccd_addenda.rb +2 -2
  34. data/lib/nacha/record/ccd_entry_detail.rb +3 -2
  35. data/lib/nacha/record/cie_addenda.rb +2 -2
  36. data/lib/nacha/record/cie_entry_detail.rb +5 -3
  37. data/lib/nacha/record/ctx_addenda.rb +2 -2
  38. data/lib/nacha/record/ctx_corporate_entry_detail.rb +2 -2
  39. data/lib/nacha/record/detail_record_type.rb +4 -1
  40. data/lib/nacha/record/dne_addenda.rb +2 -2
  41. data/lib/nacha/record/dne_entry_detail.rb +6 -4
  42. data/lib/nacha/record/enr_addenda.rb +3 -2
  43. data/lib/nacha/record/enr_entry_detail.rb +4 -3
  44. data/lib/nacha/record/fifth_iat_addenda.rb +8 -4
  45. data/lib/nacha/record/file_control.rb +9 -5
  46. data/lib/nacha/record/file_control_record_type.rb +1 -1
  47. data/lib/nacha/record/file_header.rb +12 -8
  48. data/lib/nacha/record/file_header_record_type.rb +1 -1
  49. data/lib/nacha/record/filler.rb +3 -3
  50. data/lib/nacha/record/filler_record_type.rb +3 -1
  51. data/lib/nacha/record/first_iat_addenda.rb +4 -3
  52. data/lib/nacha/record/fourth_iat_addenda.rb +7 -4
  53. data/lib/nacha/record/iat_batch_header.rb +5 -3
  54. data/lib/nacha/record/iat_entry_detail.rb +9 -6
  55. data/lib/nacha/record/iat_foreign_coorespondent_bank_information_addenda.rb +10 -6
  56. data/lib/nacha/record/iat_remittance_information_addenda.rb +3 -2
  57. data/lib/nacha/record/mte_addenda.rb +4 -3
  58. data/lib/nacha/record/mte_entry_detail.rb +5 -3
  59. data/lib/nacha/record/pop_entry_detail.rb +3 -2
  60. data/lib/nacha/record/pos_addenda.rb +6 -3
  61. data/lib/nacha/record/pos_entry_detail.rb +5 -3
  62. data/lib/nacha/record/ppd_addenda.rb +3 -2
  63. data/lib/nacha/record/ppd_entry_detail.rb +5 -3
  64. data/lib/nacha/record/rck_entry_detail.rb +3 -2
  65. data/lib/nacha/record/second_iat_addenda.rb +3 -2
  66. data/lib/nacha/record/seventh_iat_addenda.rb +3 -2
  67. data/lib/nacha/record/shr_addenda.rb +5 -3
  68. data/lib/nacha/record/shr_entry_detail.rb +3 -2
  69. data/lib/nacha/record/sixth_iat_addenda.rb +5 -3
  70. data/lib/nacha/record/tel_entry_detail.rb +5 -3
  71. data/lib/nacha/record/third_iat_addenda.rb +3 -2
  72. data/lib/nacha/record/trc_entry_detail.rb +3 -2
  73. data/lib/nacha/record/trx_addenda.rb +3 -2
  74. data/lib/nacha/record/trx_entry_detail.rb +5 -3
  75. data/lib/nacha/record/validations/field_validations.rb +26 -14
  76. data/lib/nacha/record/validations/record_validations.rb +2 -1
  77. data/lib/nacha/record/web_addenda.rb +3 -2
  78. data/lib/nacha/record/web_entry_detail.rb +5 -3
  79. data/lib/nacha/record/xck_entry_detail.rb +3 -2
  80. data/lib/nacha/version.rb +4 -1
  81. data/lib/nacha.rb +21 -14
  82. data/nacha.gemspec +14 -16
  83. metadata +42 -8
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'nacha/formatter/base'
4
+
5
+ module Nacha
6
+ module Formatter
7
+ class HtmlFormatter < Base
8
+ def format
9
+ [
10
+ html_preamble,
11
+ file_statistics_html,
12
+ records_html,
13
+ html_postamble
14
+ ].join("\n")
15
+ end
16
+
17
+ private
18
+
19
+ def html_preamble
20
+ preamble_content = options.fetch(:preamble, default_preamble)
21
+ if File.exist?(preamble_content)
22
+ File.read(preamble_content)
23
+ else
24
+ preamble_content
25
+ end
26
+ end
27
+
28
+ def html_postamble
29
+ postamble_content = options.fetch(:postamble, default_postamble)
30
+ if File.exist?(postamble_content)
31
+ File.read(postamble_content)
32
+ else
33
+ postamble_content
34
+ end
35
+ end
36
+
37
+ def file_statistics_html
38
+ stats = file_statistics
39
+ <<~HTML
40
+ <div class="file-statistics">
41
+ <h2>File Information</h2>
42
+ <ul>
43
+ <li><strong>File Name:</strong> #{stats[:file_name]}</li>
44
+ <li><strong>File Size:</strong> #{stats[:file_size]} bytes</li>
45
+ <li><strong>Number of Lines:</strong> #{stats[:number_of_lines]}</li>
46
+ <li><strong>Created At:</strong> #{stats[:created_at]}</li>
47
+ <li><strong>Modified At:</strong> #{stats[:modified_at]}</li>
48
+ <li><strong>Checksum (SHA256):</strong> #{stats[:checksum]}</li>
49
+ <li><strong>Number of Filler Lines:</strong> #{stats[:number_of_filler_lines]}</li>
50
+ </ul>
51
+ </div>
52
+ HTML
53
+ end
54
+
55
+ def records_html
56
+ records.map { |record| record_to_html(record) }.join("\n")
57
+ end
58
+
59
+ def record_to_html(record)
60
+ record_error_class = record.errors.any? ? 'error' : ''
61
+ field_html = record.fields.values.map { |field| field_to_html(field) }.join
62
+
63
+ "<div class=\"nacha-record tooltip #{record.record_type} #{record_error_class}\">" \
64
+ "<span class=\"nacha-record-number\" data-name=\"record-number\">#{Kernel.format('%05d',
65
+ record.line_number)}&nbsp;|&nbsp</span>" \
66
+ "#{field_html}" \
67
+ "<span class=\"record-type\" data-name=\"record-type\">#{record.human_name}</span>" \
68
+ "</div>"
69
+ end
70
+
71
+ def field_to_html(field)
72
+ tooltip_text = "<span class=\"tooltiptext\">#{field.human_name} #{field.errors.join(' ')}</span>"
73
+ field_classes = %w[nacha-field tooltip]
74
+ field_classes << 'mandatory' if field.mandatory?
75
+ field_classes << 'required' if field.required?
76
+ field_classes << 'optional' if field.optional?
77
+ field_classes << 'error' if field.errors.any?
78
+
79
+ ach_string = field.to_ach.gsub(' ', '&nbsp;')
80
+ "<span data-field-name=\"#{field.name}\" contentEditable=true " \
81
+ "class=\"#{field_classes.join(' ')}\" data-name=\"#{field.name}\">" \
82
+ "#{ach_string}#{tooltip_text}</span>"
83
+ end
84
+
85
+ def default_preamble
86
+ stylesheet = options.fetch(:stylesheet, default_stylesheet)
87
+ javascript = options.fetch(:javascript, '')
88
+ <<~HTML
89
+ <!DOCTYPE html>
90
+ <html>
91
+ <head>
92
+ <title>NACHA File</title>
93
+ <style>#{stylesheet}</style>
94
+ <script>#{javascript}</script>
95
+ </head>
96
+ <body>
97
+ HTML
98
+ end
99
+
100
+ def default_postamble
101
+ <<~HTML
102
+ </body>
103
+ </html>
104
+ HTML
105
+ end
106
+
107
+ def default_stylesheet
108
+ <<~CSS
109
+ body { font-family: monospace; }
110
+ .tooltip { position: relative; display: inline-block; border-bottom: 1px dotted black; }
111
+ .tooltip .tooltiptext { visibility: hidden; width: 120px; background-color: black; color: #fff; text-align: center; border-radius: 6px; padding: 5px 0; position: absolute; z-index: 1; }
112
+ .tooltip:hover .tooltiptext { visibility: visible; }
113
+ .nacha-record { white-space: nowrap; }
114
+ .error { background-color: #ffdddd; }
115
+ CSS
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'nacha/formatter/base'
4
+ require 'json'
5
+
6
+ module Nacha
7
+ module Formatter
8
+ class JsonFormatter < Base
9
+ def format
10
+ output = {
11
+ file: file_statistics,
12
+ records: records.map { |record| record_to_h(record) }
13
+ }
14
+
15
+ JSON.pretty_generate(output)
16
+ end
17
+
18
+ private
19
+
20
+ def record_to_h(record)
21
+ {
22
+ nacha_record_type: record.record_type,
23
+ metadata: {
24
+ klass: record.class.name,
25
+ errors: record.errors,
26
+ line_number: record.line_number,
27
+ original_input_line: record.original_input_line
28
+ }
29
+ }.merge(
30
+ record.fields.keys.to_h do |key|
31
+ [key, field_to_json_output(record.fields[key])]
32
+ end
33
+ )
34
+ end
35
+
36
+ def field_to_json_output(field)
37
+ if field.json_output
38
+ # rubocop:disable GitlabSecurity/PublicSend
39
+ field.json_output.reduce(field.raw) do |memo, operation|
40
+ memo&.public_send(*operation)
41
+ end
42
+ # rubocop:enable GitlabSecurity/PublicSend
43
+ else
44
+ field.to_s
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'nacha/formatter/base'
4
+
5
+ module Nacha
6
+ module Formatter
7
+ class MarkdownFormatter < Base
8
+ def format
9
+ [
10
+ file_statistics_markdown,
11
+ records_markdown
12
+ ].join("\n")
13
+ end
14
+
15
+ private
16
+
17
+ def file_statistics_markdown
18
+ stats = file_statistics
19
+ <<~MARKDOWN
20
+ # File Information
21
+
22
+ - **File Name:** #{stats[:file_name]}
23
+ - **File Size:** #{stats[:file_size]} bytes
24
+ - **Number of Lines:** #{stats[:number_of_lines]}
25
+ - **Created At:** #{stats[:created_at]}
26
+ - **Modified At:** #{stats[:modified_at]}
27
+ - **Checksum (SHA256):** #{stats[:checksum]}
28
+ - **Number of Filler Lines:** #{stats[:number_of_filler_lines]}
29
+ MARKDOWN
30
+ end
31
+
32
+ def records_markdown
33
+ records.map { |record| record_to_markdown(record) }.join("\n")
34
+ end
35
+
36
+ def record_to_markdown(record)
37
+ if options[:flavor] == :github
38
+ github_flavored_markdown(record)
39
+ else
40
+ common_mark_markdown(record)
41
+ end
42
+ end
43
+
44
+ def common_mark_markdown(record)
45
+ "## #{record.human_name}\n\n" +
46
+ record.fields.map { |name, field| "* **#{name}:** #{field}" }.join("\n")
47
+ end
48
+
49
+ def github_flavored_markdown(record)
50
+ "### #{record.human_name}\n\n" \
51
+ "| Field | Value |\n" \
52
+ "|-------|-------|\n" +
53
+ record.fields.map { |name, field| "| #{name} | #{field} |" }.join("\n")
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'nacha/formatter/json_formatter'
4
+ require 'nacha/formatter/html_formatter'
5
+ require 'nacha/formatter/markdown_formatter'
6
+
7
+ module Nacha
8
+ module Formatter
9
+ class FormatterFactory
10
+ def self.get(format, records, options = {})
11
+ case format
12
+ when :json
13
+ JsonFormatter.new(records, options)
14
+ when :html
15
+ HtmlFormatter.new(records, options)
16
+ when :markdown
17
+ MarkdownFormatter.new(records, options)
18
+ else
19
+ raise ArgumentError, "Unknown format: #{format}"
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,12 +1,16 @@
1
- module HasErrors
2
- attr_reader :errors
1
+ # frozen_string_literal: true
3
2
 
4
- def add_error(message)
5
- @errors ||= []
6
- @errors << message
7
- end
3
+ module Nacha
4
+ module HasErrors
5
+ attr_reader :errors
6
+
7
+ def add_error(message)
8
+ @errors ||= []
9
+ @errors << message
10
+ end
8
11
 
9
- def has_errors?
10
- !@errors.nil? && !@errors.empty?
12
+ def has_errors?
13
+ !@errors.nil? && !@errors.empty?
14
+ end
11
15
  end
12
16
  end
data/lib/nacha/numeric.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  class Nacha::Numeric
3
- def initialize val = nil
4
+ def initialize(val = nil)
4
5
  self.value = val
5
6
  end
6
7
 
@@ -17,14 +18,14 @@ class Nacha::Numeric
17
18
  def value=(val)
18
19
  if val.is_a?(String)
19
20
  @value = val.dup
20
- if(val.strip.length > 0)
21
+ if !val.strip.empty?
21
22
  @op_value = BigDecimal(val.strip)
22
23
  @value = val.dup
23
24
  else
24
- @op_value = BigDecimal(0)
25
+ @op_value = BigDecimal('0')
25
26
  end
26
27
  elsif val.nil?
27
- @value = BigDecimal(0)
28
+ @value = BigDecimal('0')
28
29
  @op_value = @value
29
30
  else
30
31
  @value = BigDecimal(val)
@@ -36,8 +37,8 @@ class Nacha::Numeric
36
37
  @value ? @value.to_i.to_s : nil
37
38
  end
38
39
 
39
- def respond_to_missing?(method_name, include_private = false)
40
- @op_value.respond_to? method_name
40
+ def respond_to_missing?(method_name, _include_private = false)
41
+ @op_value.respond_to?(method_name)
41
42
  end
42
43
 
43
44
  # @op_value is the value for operations. @value may still be a string
@@ -45,20 +46,22 @@ class Nacha::Numeric
45
46
  # should be checked to see if the operation is valid for it, not
46
47
  # necessarily the potentially string @value
47
48
  def method_missing(method_name, *args, &block)
48
- if @op_value.respond_to? method_name
49
+ if @op_value.respond_to?(method_name)
49
50
  old_op_value = @op_value.dup
50
- if /!\z/.match?(method_name.to_s)
51
- # rubocop:disable GitlabSecurity/PublicSend
51
+ # rubocop:disable GitlabSecurity/PublicSend
52
+ if method_name.to_s.end_with?('!')
52
53
  @op_value.send(method_name, *args, &block)
53
54
  return_value = @op_value
54
55
  else
55
56
  return_value = @op_value.send(method_name, *args, &block)
56
- # rubocop:enable GitlabSecurity/PublicSend
57
57
  end
58
+ # rubocop:enable GitlabSecurity/PublicSend
59
+
58
60
  if old_op_value != return_value
59
61
  @value = return_value
60
62
  @op_value = return_value
61
63
  end
64
+
62
65
  @value
63
66
  else
64
67
  super
data/lib/nacha/parser.rb CHANGED
@@ -5,9 +5,11 @@ require 'nacha/parser_context'
5
5
 
6
6
  # Nacha Parser - deal with figuring out what record type a line is
7
7
  class Nacha::Parser
8
- DEFAULT_RECORD_TYPES = ['Nacha::Record::AdvFileHeader',
9
- 'Nacha::Record::FileHeader',
10
- 'Nacha::Record::Filler'].freeze
8
+ DEFAULT_RECORD_TYPES = [
9
+ 'Nacha::Record::FileHeader',
10
+ 'Nacha::Record::AdvFileHeader',
11
+ 'Nacha::Record::Filler'
12
+ ].freeze
11
13
 
12
14
  attr_reader :context
13
15
 
@@ -16,31 +18,25 @@ class Nacha::Parser
16
18
  end
17
19
 
18
20
  def parse_file(file)
19
- @context.parser_started_at = Time.now
21
+ @context.parser_started_at = Time.now.utc
20
22
  @context.file_name = file
21
23
  parse_string(file.read)
22
24
  end
23
25
 
24
26
  def detect_possible_record_types(line)
25
- Nacha.ach_record_types.map do |record_type|
26
- record_type if record_type.matcher =~ line
27
- end.compact
28
- end
29
-
30
- def parse_line(line)
31
- record_types = detect_possible_record_types(line)
32
-
33
- records = record_types.map do |record_type|
34
-
27
+ Nacha.ach_record_types.filter_map do |record_type|
28
+ record_type if record_type.matcher.match?(line)
35
29
  end
36
30
  end
37
31
 
38
32
  def parse_string(str)
39
33
  line_num = -1
40
34
  records = []
41
- @context.parser_started_at ||= Time.now
42
- str.scan(/(.{94}|(\A[^\n]+))/).each do |line|
43
- line = line.first.strip
35
+ @context.parser_started_at ||= Time.now.utc
36
+ str.scan(/(.{0,94})[\r\n]*/).each do |line|
37
+ line = line.compact.first.strip
38
+ next if line.empty? || line.start_with?('#') # Skip empty lines and comments
39
+
44
40
  line_num += 1
45
41
  @context.line_number = line_num
46
42
  @context.line_length = line.length
@@ -54,15 +50,24 @@ class Nacha::Parser
54
50
  parent = previous
55
51
 
56
52
  record_types = valid_record_types(parent)
53
+
57
54
  while record_types
58
55
  record = parse_first_by_types(line, record_types)
59
56
  break if record || !parent
60
- record.validate if record
57
+
58
+ record_types = valid_record_types(parent.parent)
61
59
  parent = parent.parent
62
- record_types = valid_record_types(parent)
63
60
  end
64
- record.line_number = line_num if record
65
- add_child(parent, record)
61
+ # Check all record types if no record was found
62
+ # TODO: remove this fallback logic
63
+ record ||= parse_first_by_types(line, Nacha.ach_record_types)
64
+
65
+ if record
66
+ record.line_number = line_num
67
+ record.validate
68
+ add_child(parent, record)
69
+ end
70
+
66
71
  record
67
72
  end
68
73
 
@@ -80,20 +85,16 @@ class Nacha::Parser
80
85
  end
81
86
 
82
87
  def parse_first_by_types(line, record_types)
83
- record_types.detect do |rt|
88
+ record_types.lazy.filter_map do |rt|
84
89
  record_type = rt.is_a?(Class) ? rt : Object.const_get(rt)
85
- record = nil
86
- record = record_type.parse(line) if record_type.matcher =~ line
87
- return record if record
88
- end
90
+ record_type.parse(line) if record_type.matcher.match?(line)
91
+ end.first
89
92
  end
90
93
 
91
94
  def parse_all_by_types(line, record_types)
92
- record_types.map do |rt|
95
+ record_types.filter_map do |rt|
93
96
  record_type = rt.is_a?(Class) ? rt : Object.const_get(rt)
94
- record = nil
95
- record = record_type.parse(line) if record_type.matcher =~ line
96
- record
97
- end.compact
97
+ record_type.parse(line) if record_type.matcher.match?(line)
98
+ end
98
99
  end
99
100
  end
@@ -2,13 +2,9 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  class Nacha::ParserContext
5
- attr_accessor :file_name
6
- attr_accessor :line_number
7
- attr_accessor :line_length
8
- attr_accessor :line_errors
9
- attr_accessor :parser_started_at
10
- attr_accessor :parser_ended_at # nil 'till the end of parsing
11
- attr_accessor :previous_record
5
+ attr_accessor :file_name, :line_number, :line_length, :line_errors,
6
+ :parser_started_at, :previous_record,
7
+ :parser_ended_at # nil 'till the end of parsing
12
8
  attr_reader :validated
13
9
 
14
10
  def initialize(opts = {})
@@ -16,7 +12,7 @@ class Nacha::ParserContext
16
12
  @line_number = opts[:line_number] || 0
17
13
  @line_length = opts[:line_length] || 0
18
14
  @current_line_errors = []
19
- @parser_started_at = Time.now
15
+ @parser_started_at = Time.now.utc
20
16
  @parser_ended_at = nil
21
17
  @previous_record = nil
22
18
  @validated = false
@@ -29,5 +25,4 @@ class Nacha::ParserContext
29
25
  def valid?
30
26
  @valid ||= errors.empty?
31
27
  end
32
-
33
28
  end
@@ -1,22 +1,29 @@
1
1
  # coding: utf-8
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'nacha/record/base.rb'
5
- require 'nacha/record/detail_record_type.rb'
4
+ require 'nacha/record/base'
5
+ require 'nacha/record/detail_record_type'
6
6
 
7
7
  module Nacha
8
8
  module Record
9
9
  class AckEntryDetail < Nacha::Record::Base
10
10
  include DetailRecordType
11
+
11
12
  nacha_field :record_type_code, inclusion: 'M', contents: 'C6', position: 1..1
12
13
  nacha_field :transaction_code, inclusion: 'M', contents: 'Numeric', position: 2..3
13
- nacha_field :receiving_dfi_identification, inclusion: 'M', contents: 'TTTTAAAAC', position: 4..12
14
- nacha_field :dfi_account_number, inclusion: 'R', contents: 'Alphameric', position: 13..29
14
+ nacha_field :receiving_dfi_identification,
15
+ inclusion: 'M', contents: 'TTTTAAAAC', position: 4..12
16
+ nacha_field :dfi_account_number,
17
+ inclusion: 'R', contents: 'Alphameric', position: 13..29
15
18
  nacha_field :amount, inclusion: 'M', contents: '$$$$$$$$¢¢', position: 30..39
16
- nacha_field :originl_entry_trace_number, inclusion: 'M', contents: 'Numeric', position: 40..54
17
- nacha_field :receiving_company_name, inclusion: 'R', contents: 'Alphameric', position: 55..76
18
- nacha_field :discretionary_data, inclusion: 'O', contents: 'Alphameric', position: 77..78
19
- nacha_field :addenda_record_indicator, inclusion: 'M', contents: 'Numeric', position: 79..79
19
+ nacha_field :originl_entry_trace_number,
20
+ inclusion: 'M', contents: 'Numeric', position: 40..54
21
+ nacha_field :receiving_company_name,
22
+ inclusion: 'R', contents: 'Alphameric', position: 55..76
23
+ nacha_field :discretionary_data,
24
+ inclusion: 'O', contents: 'Alphameric', position: 77..78
25
+ nacha_field :addenda_record_indicator,
26
+ inclusion: 'M', contents: 'Numeric', position: 79..79
20
27
  nacha_field :trace_number, inclusion: 'M', contents: 'Numeric', position: 80..94
21
28
  end
22
29
  end
@@ -9,7 +9,14 @@ module Nacha
9
9
 
10
10
  module ClassMethods
11
11
  def child_record_types
12
- []
12
+ [
13
+ "Nacha::Record::SecondIatAddenda",
14
+ "Nacha::Record::ThirdIatAddenda",
15
+ "Nacha::Record::FourthIatAddenda",
16
+ "Nacha::Record::FifthIatAddenda",
17
+ "Nacha::Record::SixthIatAddenda",
18
+ "Nacha::Record::SeventhIatAddenda"
19
+ ]
13
20
  end
14
21
 
15
22
  def self.next_record_types
@@ -1,22 +1,27 @@
1
1
  # coding: utf-8
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'nacha/record/base.rb'
5
- require 'nacha/record/batch_control_record_type.rb'
4
+ require 'nacha/record/base'
5
+ require 'nacha/record/batch_control_record_type'
6
6
 
7
7
  module Nacha
8
8
  module Record
9
-
10
9
  # The AdvBatchControl record is used to control the batch of adv entry detail records.
11
10
  class AdvBatchControl < Nacha::Record::Base
11
+ include BatchControlRecordType
12
+
12
13
  nacha_field :record_type_code, inclusion: 'M', contents: 'C8', position: 1..1
13
14
  nacha_field :service_class_code, inclusion: 'M', contents: 'Numeric', position: 2..4
14
15
  nacha_field :entry_addenda_count, inclusion: 'M', contents: 'Numeric', position: 5..10
15
16
  nacha_field :entry_hash, inclusion: 'M', contents: 'Numeric', position: 11..20
16
- nacha_field :total_debit_entry_dollar_amount, inclusion: 'M', contents: '$$$$$$$$$$$$$$$$$$¢¢', position: 21..40
17
- nacha_field :total_credit_entry_dollar_amount, inclusion: 'M', contents: '$$$$$$$$$$$$$$$$$$¢¢', position: 41..60
18
- nacha_field :ach_operator_data, inclusion: 'O', contents: 'Alphameric', position: 61..79
19
- nacha_field :originating_dfi_identification, inclusion: 'M', contents: 'TTTAAAA', position: 80..87
17
+ nacha_field :total_debit_entry_dollar_amount,
18
+ inclusion: 'M', contents: '$$$$$$$$$$$$$$$$$$¢¢', position: 21..40
19
+ nacha_field :total_credit_entry_dollar_amount,
20
+ inclusion: 'M', contents: '$$$$$$$$$$$$$$$$$$¢¢', position: 41..60
21
+ nacha_field :ach_operator_data,
22
+ inclusion: 'O', contents: 'Alphameric', position: 61..79
23
+ nacha_field :originating_dfi_identification,
24
+ inclusion: 'M', contents: 'TTTAAAA', position: 80..87
20
25
  nacha_field :batch_number, inclusion: 'M', contents: 'Numeric', position: 88..94
21
26
  end
22
27
  end
@@ -1,13 +1,14 @@
1
1
  # coding: utf-8
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'nacha/record/base.rb'
5
- require 'nacha/record/detail_record_type.rb'
4
+ require 'nacha/record/base'
5
+ require 'nacha/record/detail_record_type'
6
6
 
7
7
  module Nacha
8
8
  module Record
9
9
  class AdvEntryDetail < Nacha::Record::Base
10
10
  include DetailRecordType
11
+
11
12
  nacha_field :record_type_code, inclusion: 'M', contents: 'C6', position: 1..1
12
13
  nacha_field :transaction_code, inclusion: 'M', contents: 'Numeric', position: 2..3
13
14
  nacha_field :receiving_dfi_identification, inclusion: 'M', contents: 'TTTTAAAAC', position: 4..12
@@ -1,20 +1,24 @@
1
1
  # coding: utf-8
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'nacha/record/base.rb'
5
- require 'nacha/record/file_control_record_type.rb'
4
+ require 'nacha/record/base'
5
+ require 'nacha/record/file_control_record_type'
6
6
 
7
7
  module Nacha
8
8
  module Record
9
9
  class AdvFileControl < Nacha::Record::Base
10
10
  include FileControlRecordType
11
+
11
12
  nacha_field :record_type_code, inclusion: 'M', contents: 'C9', position: 1..1
12
13
  nacha_field :batch_count, inclusion: 'M', contents: 'Numeric', position: 2..7
13
14
  nacha_field :block_count, inclusion: 'M', contents: 'Numeric', position: 8..13
14
- nacha_field :entry_addenda_count, inclusion: 'M', contents: 'Numeric', position: 14..21
15
+ nacha_field :entry_addenda_count,
16
+ inclusion: 'M', contents: 'Numeric', position: 14..21
15
17
  nacha_field :entry_hash, inclusion: 'M', contents: 'Numeric', position: 22..31
16
- nacha_field :total_debit_entry_dollar_amount_in_file, inclusion: 'M', contents: '$$$$$$$$$$¢¢', position: 32..51
17
- nacha_field :total_credit_entry_dollar_amount_in_file, inclusion: 'M', contents: '$$$$$$$$$$¢¢', position: 52..71
18
+ nacha_field :total_debit_entry_dollar_amount_in_file,
19
+ inclusion: 'M', contents: '$$$$$$$$$$¢¢', position: 32..51
20
+ nacha_field :total_credit_entry_dollar_amount_in_file,
21
+ inclusion: 'M', contents: '$$$$$$$$$$¢¢', position: 52..71
18
22
  nacha_field :reserved, inclusion: 'M', contents: 'C', position: 72..94
19
23
  end
20
24
  end
@@ -1,25 +1,30 @@
1
1
  # coding: utf-8
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'nacha/record/base.rb'
5
- require 'nacha/record/file_header_record_type.rb'
4
+ require 'nacha/record/base'
5
+ require 'nacha/record/file_header_record_type'
6
6
 
7
7
  module Nacha
8
8
  module Record
9
9
  class AdvFileHeader < Nacha::Record::Base
10
10
  include FileHeaderRecordType
11
+
11
12
  nacha_field :record_type_code, inclusion: 'M', contents: 'C1', position: 1..1
12
13
  nacha_field :priority_code, inclusion: 'R', contents: 'Numeric', position: 2..3
13
- nacha_field :immediate_destination, inclusion: 'M', contents: 'bTTTTAAAAC', position: 4..13
14
- nacha_field :immediate_origin, inclusion: 'M', contents: 'bTTTTAAAAC', position: 14..23
14
+ nacha_field :immediate_destination, inclusion: 'M',
15
+ contents: 'bTTTTAAAAC', position: 4..13
16
+ nacha_field :immediate_origin, inclusion: 'M',
17
+ contents: 'bTTTTAAAAC', position: 14..23
15
18
  nacha_field :file_creation_date, inclusion: 'M', contents: 'YYMMDD', position: 24..29
16
19
  nacha_field :file_creation_time, inclusion: 'M', contents: 'HHMM', position: 30..33
17
20
  nacha_field :file_id_modifier, inclusion: 'M', contents: 'A-Z0-9', position: 34..34
18
21
  nacha_field :record_size, inclusion: 'M', contents: 'C094', position: 35..37
19
22
  nacha_field :blocking_factor, inclusion: 'M', contents: 'C10', position: 38..39
20
23
  nacha_field :format_code, inclusion: 'M', contents: 'C1', position: 40..40
21
- nacha_field :immediate_destination_name, inclusion: 'M', contents: 'Alphameric', position: 41..63
22
- nacha_field :immediate_origin_name, inclusion: 'M', contents: 'Alphameric', position: 64..86
24
+ nacha_field :immediate_destination_name, inclusion: 'M',
25
+ contents: 'Alphameric', position: 41..63
26
+ nacha_field :immediate_origin_name, inclusion: 'M',
27
+ contents: 'Alphameric', position: 64..86
23
28
  nacha_field :reference_code, inclusion: 'M', contents: 'CADV FILE', position: 87..94
24
29
  end
25
30
  end
@@ -1,8 +1,8 @@
1
1
  # coding: utf-8
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'nacha/record/base.rb'
5
- require 'nacha/record/detail_record_type.rb'
4
+ require 'nacha/record/base'
5
+ require 'nacha/record/detail_record_type'
6
6
 
7
7
  module Nacha
8
8
  module Record