ach_client 0.5.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.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +18 -0
  3. data/.gitignore +9 -0
  4. data/.rubocop.yml +1156 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +10 -0
  7. data/Gemfile +4 -0
  8. data/README.md +388 -0
  9. data/Rakefile +10 -0
  10. data/ach_client.gemspec +58 -0
  11. data/bin/console +93 -0
  12. data/bin/setup +8 -0
  13. data/config/return_codes.yml +761 -0
  14. data/lib/ach_client/abstract/abstract_method_error.rb +3 -0
  15. data/lib/ach_client/helpers/dollars_to_cents.rb +15 -0
  16. data/lib/ach_client/logging/log_provider_job.rb +36 -0
  17. data/lib/ach_client/logging/log_providers/log_provider.rb +22 -0
  18. data/lib/ach_client/logging/log_providers/null_log_provider.rb +14 -0
  19. data/lib/ach_client/logging/log_providers/stdout_log_provider.rb +14 -0
  20. data/lib/ach_client/logging/logging.rb +76 -0
  21. data/lib/ach_client/logging/savon_observer.rb +26 -0
  22. data/lib/ach_client/objects/account_types.rb +32 -0
  23. data/lib/ach_client/objects/responses/ach_response.rb +15 -0
  24. data/lib/ach_client/objects/responses/corrected_ach_response.rb +18 -0
  25. data/lib/ach_client/objects/responses/processing_ach_response.rb +6 -0
  26. data/lib/ach_client/objects/responses/returned_ach_response.rb +16 -0
  27. data/lib/ach_client/objects/responses/settled_ach_response.rb +5 -0
  28. data/lib/ach_client/objects/return_code.rb +20 -0
  29. data/lib/ach_client/objects/return_codes.rb +33 -0
  30. data/lib/ach_client/objects/transaction_types.rb +16 -0
  31. data/lib/ach_client/providers/abstract/ach_batch.rb +23 -0
  32. data/lib/ach_client/providers/abstract/ach_status_checker.rb +21 -0
  33. data/lib/ach_client/providers/abstract/ach_transaction.rb +70 -0
  34. data/lib/ach_client/providers/abstract/company_info.rb +28 -0
  35. data/lib/ach_client/providers/abstract/response_record_processor.rb +15 -0
  36. data/lib/ach_client/providers/abstract/transformer.rb +38 -0
  37. data/lib/ach_client/providers/sftp/account_type_transformer.rb +20 -0
  38. data/lib/ach_client/providers/sftp/ach_batch.rb +97 -0
  39. data/lib/ach_client/providers/sftp/ach_status_checker.rb +146 -0
  40. data/lib/ach_client/providers/sftp/ach_transaction.rb +62 -0
  41. data/lib/ach_client/providers/sftp/nacha_provider.rb +30 -0
  42. data/lib/ach_client/providers/sftp/sftp_provider.rb +124 -0
  43. data/lib/ach_client/providers/sftp/transaction_type_transformer.rb +19 -0
  44. data/lib/ach_client/providers/soap/ach_works/account_type_transformer.rb +17 -0
  45. data/lib/ach_client/providers/soap/ach_works/ach_batch.rb +89 -0
  46. data/lib/ach_client/providers/soap/ach_works/ach_status_checker.rb +86 -0
  47. data/lib/ach_client/providers/soap/ach_works/ach_transaction.rb +80 -0
  48. data/lib/ach_client/providers/soap/ach_works/ach_works.rb +57 -0
  49. data/lib/ach_client/providers/soap/ach_works/company_info.rb +87 -0
  50. data/lib/ach_client/providers/soap/ach_works/correction_details_processor.rb +92 -0
  51. data/lib/ach_client/providers/soap/ach_works/date_formatter.rb +33 -0
  52. data/lib/ach_client/providers/soap/ach_works/response_record_processor.rb +91 -0
  53. data/lib/ach_client/providers/soap/ach_works/transaction_type_transformer.rb +18 -0
  54. data/lib/ach_client/providers/soap/i_check_gateway/account_type_transformer.rb +20 -0
  55. data/lib/ach_client/providers/soap/i_check_gateway/ach_batch.rb +12 -0
  56. data/lib/ach_client/providers/soap/i_check_gateway/ach_status_checker.rb +35 -0
  57. data/lib/ach_client/providers/soap/i_check_gateway/ach_transaction.rb +53 -0
  58. data/lib/ach_client/providers/soap/i_check_gateway/company_info.rb +51 -0
  59. data/lib/ach_client/providers/soap/i_check_gateway/i_check_gateway.rb +39 -0
  60. data/lib/ach_client/providers/soap/i_check_gateway/response_record_processor.rb +59 -0
  61. data/lib/ach_client/providers/soap/i_check_gateway/transaction_type_transformer.rb +8 -0
  62. data/lib/ach_client/providers/soap/soap_provider.rb +47 -0
  63. data/lib/ach_client/version.rb +4 -0
  64. data/lib/ach_client.rb +38 -0
  65. metadata +346 -0
@@ -0,0 +1,3 @@
1
+ # To be raised when someone tries to call an abstract method
2
+ class AbstractMethodError < RuntimeError
3
+ end
@@ -0,0 +1,15 @@
1
+ module AchClient
2
+ # Utility classes shared by all providers
3
+ class Helpers
4
+
5
+ # Turns dollars into cents
6
+ class DollarsToCents
7
+
8
+ # @param dollars [Float | BigDecimal | Fixnum | Integer]
9
+ # @return [Fixnum] cents
10
+ def self.dollars_to_cents(dollars)
11
+ (dollars.to_f.round(2) * 100).to_i
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,36 @@
1
+ module AchClient
2
+ class Logging
3
+ # Worker to asynchronously invoke the log provider
4
+ class LogProviderJob
5
+ include SuckerPunch::Job
6
+
7
+ ## Prettifies the xml and sends it asynchronously to the log provider
8
+ # @param xml [String] xml body to log
9
+ # @param name [String] title for the log
10
+ def perform(body:, name:)
11
+ # Savon logger does a nice job of XML pretty print
12
+ # Takes: message, list of filters, pretty print boolean
13
+ AchClient::Logging.log_provider.send_logs(
14
+ body: maybe_encrypt_message(
15
+ message: Savon::LogMessage.new(
16
+ body,
17
+ AchClient::Logging.log_filters,
18
+ true
19
+ ).to_s
20
+ ),
21
+ name: name
22
+ )
23
+ end
24
+
25
+ private
26
+ def maybe_encrypt_message(message:)
27
+ # Only encrypt if the client provided a password and a salt
28
+ if AchClient::Logging.should_use_encryption?
29
+ AchClient::Logging.codec.encrypt_and_sign(message)
30
+ else
31
+ message
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,22 @@
1
+ module AchClient
2
+ class Logging
3
+ # Base class for log providers
4
+ # Extending classes must implement send_logs
5
+ # The consumer may implement their own log provider and assign it to
6
+ # AchClient:
7
+ # ```ruby
8
+ # class MyCustomLogger < AchClient::Logging::LogProvider
9
+ # def self.send_logs(body:, name:)
10
+ # # Do whatever you want, like send the log data to S3, or whatever
11
+ # # logging service you choose
12
+ # end
13
+ # end
14
+ # AchClient::Logging.log_provider = MyCustomLogger
15
+ # ```
16
+ class LogProvider
17
+ def self.send_logs(body:, name:)
18
+ raise AbstractMethodError, "#{body}#{name}"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ module AchClient
2
+ class Logging
3
+
4
+ # A log provider that does nothing.
5
+ class NullLogProvider < LogProvider
6
+
7
+ # Does absolutely nothing with the log info
8
+ def self.send_logs(*)
9
+ # Do nothing
10
+ nil
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module AchClient
2
+ class Logging
3
+ # Logs to stdout (using puts)
4
+ class StdoutLogProvider < LogProvider
5
+ # Prints the name and then the body
6
+ # @param body [String] the log body
7
+ # @param name [String] the log name
8
+ def self.send_logs(body:, name:)
9
+ puts name
10
+ puts body
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,76 @@
1
+ require_relative './savon_observer.rb'
2
+ require_relative './log_providers/log_provider.rb'
3
+
4
+ module AchClient
5
+ # Base class for all things logging
6
+ class Logging
7
+
8
+ # Register our observer with Savon
9
+ Savon.observers << AchClient::Logging::SavonObserver.new
10
+
11
+ # @return [Class] type of the log provider
12
+ class_attribute :_log_provider_type
13
+
14
+ # @return [String] password to use for encrypting logs
15
+ class_attribute :encryption_password
16
+
17
+ # @return [String] salt to use for encrypting logs
18
+ class_attribute :encryption_salt
19
+
20
+ # Defaults to AchClient::Logging::NullLogProvider
21
+ # @return [Class] The Log provider to use.
22
+ def self.log_provider
23
+ self._log_provider_type || AchClient::Logging::NullLogProvider
24
+ end
25
+
26
+ # Set the log provider
27
+ # Must extend AchClient::Logging::LogProvider
28
+ # @param [Class] the new log provider
29
+ def self.log_provider=(log_provider)
30
+ if log_provider.is_a?(Class) &&
31
+ log_provider < AchClient::Logging::LogProvider
32
+ self._log_provider_type = log_provider
33
+ else
34
+ raise 'Must be subclass of AchClient::Logging::LogProvider'
35
+ end
36
+ end
37
+
38
+ # @return [Array<String>] List of XML nodes to scrub
39
+ class_attribute :_log_filters
40
+
41
+ # @return [Array<String>] List of XML nodes to scrub
42
+ def self.log_filters
43
+ self._log_filters || []
44
+ end
45
+
46
+ # Updates the log filters
47
+ # @param filters [Array<String>] List of XML nodes to scrub from the logs
48
+ def self.log_filters=(filters)
49
+ self._log_filters = filters
50
+ end
51
+
52
+ # Creates a codec (does encryption and decryption) using the provided
53
+ # password and salt
54
+ # @return [ActiveSupport::MessageEncryptor] the encryptor
55
+ def self.codec
56
+ ActiveSupport::MessageEncryptor.new(
57
+ ActiveSupport::KeyGenerator.new(
58
+ AchClient::Logging.encryption_password
59
+ ).generate_key(AchClient::Logging.encryption_salt)
60
+ )
61
+ end
62
+
63
+ # Returns whether the client has enabled encryption - if both a username and
64
+ # salt have been provided
65
+ # @return [Boolean] is encryption enabled?
66
+ def self.should_use_encryption?
67
+ encryption_password && encryption_salt
68
+ end
69
+
70
+ # Decrypt encrypted log file
71
+ # @param gibberish [String] the log body to decrypt
72
+ def self.decrypt_log(gibberish)
73
+ codec.decrypt_and_verify(gibberish)
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,26 @@
1
+ module AchClient
2
+ class Logging
3
+ # Hooks into every savon request.
4
+ # #notify is called before the request is made
5
+ class SavonObserver
6
+
7
+ ##
8
+ # Hooks into every SOAP request and sends the XML body to be logged.
9
+ # @param operation_name [Symbol] name of SOAP operation being exectuted
10
+ # @param builder [Savon::Builder] Savon wrapper for the request
11
+ # @param globals [Savon::GlobalOptions] Savon's global options
12
+ # @param locals [Savon::LocalOptions] Savon's global options
13
+ # @return [NilClass] returns nothing so the request is not mutated
14
+ def notify(operation_name, builder, _globals, _locals)
15
+ # Send the xml body to the logger job
16
+ AchClient::Logging::LogProviderJob.perform_async(
17
+ body: builder.to_s,
18
+ name: "request-#{operation_name}-#{DateTime.now}.xml"
19
+ )
20
+
21
+ # Must return nil so the request is unaltered
22
+ nil
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,32 @@
1
+ module AchClient
2
+ ## Representations of merchant account types (checking or savings)
3
+ module AccountTypes
4
+ ## Base class for all account types
5
+ class AccountType
6
+ end
7
+
8
+ ## Represents a checking account
9
+ class Checking < AchClient::AccountTypes::AccountType
10
+ end
11
+
12
+ ## Represents a savings account
13
+ class Savings < AchClient::AccountTypes::AccountType
14
+ end
15
+
16
+ ## Represents a business checking account
17
+ class BusinessChecking < AchClient::AccountTypes::Checking
18
+ end
19
+
20
+ ## Represents a business savings account
21
+ class BusinessSavings < AchClient::AccountTypes::Savings
22
+ end
23
+
24
+ ## Represents a personal checking account
25
+ class PersonalChecking < AchClient::AccountTypes::Checking
26
+ end
27
+
28
+ ## Represents a personal savings account
29
+ class PersonalSavings < AchClient::AccountTypes::Savings
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,15 @@
1
+ module AchClient
2
+ # Abstract Response wrapper for the various ACH response statuses
3
+ class AchResponse
4
+
5
+
6
+ attr_reader :amount, # Amount of the processed ACH
7
+ :date # Date the Ach was in this status
8
+
9
+ def initialize(amount:, date:)
10
+ raise AbstractMethodError if self.class == AchClient::AchResponse
11
+ @amount = amount
12
+ @date = date
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ require_relative './returned_ach_response.rb'
2
+
3
+ module AchClient
4
+ # Representation of an Ach return that contains a correction
5
+ class CorrectedAchResponse < ReturnedAchResponse
6
+ attr_reader :corrections
7
+
8
+ ##
9
+ # @param date [DateTime] date of correction return
10
+ # @param return_code [AchClient::ReturnCode] Ach Return code for the
11
+ # correction (ie AchClient::ReturnCodes.find_by(code: 'C01'))
12
+ # @param corrections [Hash] A hash of corrected attributes and their values
13
+ def initialize(amount:, date:, return_code:, corrections:)
14
+ @corrections = corrections
15
+ super(amount: amount, date: date, return_code: return_code)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,6 @@
1
+ module AchClient
2
+ # The transaction is processing.
3
+ # Not much else to see here.
4
+ class ProcessingAchResponse < AchResponse
5
+ end
6
+ end
@@ -0,0 +1,16 @@
1
+ module AchClient
2
+ # Representation of an Ach return that failed
3
+ class ReturnedAchResponse < AchResponse
4
+
5
+ attr_reader :return_code
6
+
7
+ ##
8
+ # @param date [DateTime] date of correction return
9
+ # @param return_code [AchClient::ReturnCode] Ach Return code for the
10
+ # correction (ie AchClient::ReturnCodes.find_by(code: 'C01'))
11
+ def initialize(amount:, date:, return_code:)
12
+ @return_code = return_code
13
+ super(amount: amount, date: date)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,5 @@
1
+ module AchClient
2
+ # The transaction is settled. Huzzah!
3
+ class SettledAchResponse < AchResponse
4
+ end
5
+ end
@@ -0,0 +1,20 @@
1
+ module AchClient
2
+ # Represents an Ach Return code. Consult NACHA documentation for a full list
3
+ # See config/return_codes.yml for our list.
4
+ class ReturnCode
5
+
6
+ attr_accessor :code,
7
+ :description,
8
+ :reason
9
+
10
+ # Constructs a Ach return code
11
+ # @param code [String] the 3 char code identifier (ie 'R01')
12
+ # @param description [String] full explanation of the return
13
+ # @param reason [String] shorter explanation of the return
14
+ def initialize(code:, description:, reason: nil)
15
+ @code = code
16
+ @description = description
17
+ @reason = reason
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,33 @@
1
+ module AchClient
2
+ # Finding and listing all Ach return codes
3
+ class ReturnCodes
4
+
5
+ # The path to the file where the return codes are enumerated
6
+ RETURN_CODES_YAML = '../../../config/return_codes.yml'
7
+
8
+ class_attribute :_return_codes
9
+
10
+ # @return [Array<AchClient::ReturnCode>] A list of all return codes.
11
+ def self.all
12
+ self._return_codes ||= YAML.load_file(
13
+ File.expand_path(File.join(File.dirname(__FILE__), RETURN_CODES_YAML))
14
+ ).map do |code|
15
+ ReturnCode.new(
16
+ code: code['code'],
17
+ description: code['description'],
18
+ reason: code['reason']
19
+ )
20
+ end
21
+ end
22
+
23
+ # Finds the first ReturnCode with the given code, or raises an exception.
24
+ # @param [String] 3 char code identifier for a return code
25
+ # @param [AchClient::ReturnCode] The ReturnCode object with that code
26
+ def self.find_by(code:)
27
+ self.all.find do |return_code|
28
+ return_code.code == code
29
+ # For some reason || is bad syntax in this context
30
+ end or raise "Could not find return code #{code}"
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,16 @@
1
+ module AchClient
2
+ ## Representations of Ach transaction types (debit or credit)
3
+ module TransactionTypes
4
+ ## Base class for all transaction types
5
+ class TransactionType
6
+ end
7
+
8
+ ## Representation of a credit transaction type
9
+ class Credit < AchClient::TransactionTypes::TransactionType
10
+ end
11
+
12
+ ## Representation of a debit transaction type
13
+ class Debit < AchClient::TransactionTypes::TransactionType
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,23 @@
1
+ module AchClient
2
+ # Abstract Ach provider, which all other provider's inherit from
3
+ class Abstract
4
+
5
+ # Base class for sending batched ACH transactions to various providers
6
+ class AchBatch
7
+
8
+ ##
9
+ # @param ach_transactions [Array] List of AchTransaction objects to batch
10
+ def initialize(ach_transactions: [])
11
+ @ach_transactions = ach_transactions
12
+ end
13
+
14
+ ##
15
+ # Sends the batch to the provider, and returns a tracking identifier
16
+ # @return [Array<String>] Identifiers to use to poll for result of batch
17
+ # processing later on.
18
+ def send_batch
19
+ raise AbstractMethodError
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ module AchClient
2
+ class Abstract
3
+
4
+ # Interface for polling provider for ACH status responses
5
+ class AchStatusChecker
6
+ # Wrapper for a provider's "most recent bucket"
7
+ # @return [Hash{String => AchClient::AchResponse}] Hash with provider's
8
+ # external ACH id as the key, AchResponse objects as values
9
+ def self.most_recent
10
+ raise AbstractMethodError
11
+ end
12
+
13
+ # Wrapper for a providers range response endpoint
14
+ # @return [Hash{String => AchClient::AchResponse}] Hash with provider's
15
+ # external ACH id as the key, AchResponse objects as values
16
+ def self.in_range(*)
17
+ raise AbstractMethodError
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,70 @@
1
+ module AchClient
2
+ class Abstract
3
+
4
+ # Generic representation of a single Ach transaction
5
+ class AchTransaction
6
+
7
+ ##
8
+ # @return [Array] A list of arguments to use in the initializer, and as
9
+ # instance attributes
10
+ def self.arguments
11
+ [
12
+ :account_number,
13
+ :account_type,
14
+ :amount,
15
+ :effective_entry_date,
16
+ :external_ach_id,
17
+ :memo,
18
+ :merchant_name,
19
+ :originator_name,
20
+ :routing_number,
21
+ :sec_code,
22
+ :transaction_type
23
+ ]
24
+ end
25
+
26
+ attr_reader(*arguments)
27
+
28
+ ##
29
+ # @param account_number [String] Merchant's account number
30
+ # @param account_type [AchClient::AccountTypes::AccountType] Merchant's account type
31
+ # (debit or credit), must be an instance of AchClient::AccountTypes::AccountType
32
+ # @param amount [BigDecimal] Amount of the ACH transaction
33
+ # @param effective_entry_date [Date] The date the transaction should be enacted
34
+ # @param external_ach_id [String] Tracking string you would like the
35
+ # provider to use with your transaction
36
+ # @param memo [String] Ach memo thing
37
+ # @param merchant_name [String] Name associated with merchantaccount we
38
+ # are ACHing with
39
+ # @param originator_name [String] String identifying you, will appear on
40
+ # merchants bank statement
41
+ # @param routing_number [String] Routing number of the merchant's account
42
+ # @param sec_code [String] CCD, PPD, WEB, etc.
43
+ # See: https://en.wikipedia.org/wiki/Automated_Clearing_House#SEC_codes
44
+ # @param transaction_type [AchClient::TransactionTypes::TransactionType] debit or
45
+ def initialize(*arguments)
46
+ args = arguments.extract_options!
47
+ self.class.arguments.each do |param|
48
+ self.instance_variable_set(
49
+ "@#{param}".to_sym,
50
+ args[param]
51
+ )
52
+ end
53
+ end
54
+
55
+ # @return [Boolean] true if transaction is a debit
56
+ def debit?
57
+ transaction_type == AchClient::TransactionTypes::Debit
58
+ end
59
+
60
+ # @return [Boolean] true if transaction is a credit
61
+ def credit?
62
+ transaction_type == AchClient::TransactionTypes::Credit
63
+ end
64
+
65
+ def send
66
+ raise AbstractMethodError
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,28 @@
1
+ module AchClient
2
+ class Abstract
3
+ # Interface for storing company credentials used with a provider
4
+ class CompanyInfo
5
+
6
+ ##
7
+ # @return [CompanyInfo] instance built from configuration values
8
+ def self.build
9
+ raise AbstractMethodError
10
+ end
11
+
12
+ ##
13
+ # Build a hash to send to provider
14
+ # @return [Hash] hash to send to provider
15
+ def to_hash
16
+ raise AbstractMethodError
17
+ end
18
+
19
+ private_class_method def self.build_from_config(args)
20
+ self.new(
21
+ args.map do |arg|
22
+ {arg => self.to_s.deconstantize.constantize.send(arg)}
23
+ end.reduce(&:merge)
24
+ )
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,15 @@
1
+ module AchClient
2
+ class Abstract
3
+ ## Interface for turning a Provider's response representation of an ACH
4
+ # status into an instance of AchClient::Response
5
+ class ResponseRecordProcessor
6
+ ## Interface for turning a Provider's response representation of an ACH
7
+ # status into an instance of AchClient::Response
8
+ # @param record [Object] the record from the provider
9
+ # @return [AchClient::AchResponse] our representation of the response
10
+ def self.process_response_record(_record)
11
+ raise AbstractMethodError
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,38 @@
1
+ module AchClient
2
+ ##
3
+ # Transforms between client class and the strings that the provider expects
4
+ # For example, the TransactionType classes are serialized as 'C' or 'D' for
5
+ # AchWorks
6
+ class Transformer
7
+
8
+ ##
9
+ # Convert provider's string representation to AchClient class
10
+ # representation
11
+ # @param string [String] string to turn into class
12
+ # @return [Class] for example AchClient::AccountTypes::Checking or
13
+ # AchClient::AccountTypes::Savings
14
+ def self.deserialize_provider_value(string)
15
+ self.transformer[string] or raise(
16
+ "Unknown #{self} string #{string}"
17
+ )
18
+ end
19
+
20
+ ##
21
+ # Convert client class to string representation used by provider
22
+ # @param type [Class] the type to convert to a string
23
+ # @return [String] string serialization of the input class
24
+ def self.serialize_to_provider_value(type)
25
+ self.transformer.find do |_, v|
26
+ type <= v
27
+ end.try(:first) or raise(
28
+ "type must be one of #{self.transformer.values.join(', ')}"
29
+ )
30
+ end
31
+
32
+ # Mapping of classes to strings, to be overridden
33
+ # @return [Hash {String => Class}] the mapping
34
+ def self.transformer
35
+ raise AbstractMethodError
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,20 @@
1
+ module AchClient
2
+ class Sftp
3
+ ##
4
+ # Transforms AccountTypes between AchClient class and the string
5
+ # that NACHA expects
6
+ class AccountTypeTransformer < AchClient::Transformer
7
+
8
+ # '2' means Checking, '3' means Savings
9
+ # The account type string is the first character in the transaction_code
10
+ # field.
11
+ # @return [Hash {String => Class}] the mapping
12
+ def self.transformer
13
+ {
14
+ '3' => AchClient::AccountTypes::Savings,
15
+ '2' => AchClient::AccountTypes::Checking
16
+ }
17
+ end
18
+ end
19
+ end
20
+ end