rsr_group 0.1.6 → 1.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: da0117d9236b24b6cc871f4076d6ef25ec407150
4
- data.tar.gz: 67a6400b5a745cd85996619c79df541d80fcc5d8
3
+ metadata.gz: 7c9bf20350d6ad63a809ab9b1ec14ed29dec0acb
4
+ data.tar.gz: 0cdadb5c40579b6abe6d28fa55e68dd486f9e27d
5
5
  SHA512:
6
- metadata.gz: 25e0da72c0ffd17fec273a2a7dce18853e04787d4906a22abde1b97addf7b999e56a29f8e2ce76ce3cd0c06282b8b66274ae235ff42e1365bda8fc2dd6724006
7
- data.tar.gz: 747385a866206a1aa8e7ca927b6c4d14e5529fee074d186d3ea840310be804e2567d5f876ab7b2215f58512be107f7d14371ca4d3807b79c9974e6bc5d68fab2
6
+ metadata.gz: d608e462128d6ab5e7dcef36f317c5b028e21ce9d47329c5b5b4eacff091a363028fa66b2b1afc505fb7faa7fabc83689848c6de0120d0061aaaa242d92e5d87
7
+ data.tar.gz: 1ecd0f05f172f4a071df7e5c74c16e4367ad2cc9e269f67011cdf3bbb853e7f5d7a2f369d68b87370665d470f4c7f5b1f9d0b2f3f2db07a686e024e620c0807c
data/.gitignore CHANGED
@@ -7,3 +7,5 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ samples/*
11
+ script/*
data/config.rb.example ADDED
@@ -0,0 +1,5 @@
1
+ RsrGroup.configure do |config|
2
+ config.ftp_host = "ftp.example.com"
3
+ config.submission_dir = File.join("htdocs", "eo", "incoming")
4
+ config.vendor_email = "admin@example.com"
5
+ end
data/lib/rsr_group.rb CHANGED
@@ -7,9 +7,37 @@ require 'net/ftp'
7
7
  require 'rsr_group/base'
8
8
  require 'rsr_group/department'
9
9
  require 'rsr_group/inventory'
10
+ require 'rsr_group/order'
11
+ require 'rsr_group/order_detail'
12
+ require 'rsr_group/order_ffl'
13
+ require 'rsr_group/order_recipient'
10
14
  require 'rsr_group/user'
11
15
 
12
16
  module RsrGroup
13
17
  class NotAuthenticated < StandardError; end
14
18
  class UnknownDepartment < StandardError; end
19
+
20
+ class << self
21
+ attr_accessor :config
22
+ end
23
+
24
+ def self.config
25
+ @config ||= Configuration.new
26
+ end
27
+
28
+ def self.configure
29
+ yield(config)
30
+ end
31
+
32
+ class Configuration
33
+ attr_accessor :ftp_host
34
+ attr_accessor :submission_dir
35
+ attr_accessor :vendor_email
36
+
37
+ def initialize
38
+ @ftp_host ||= "ftp.rsrgroup.com"
39
+ @submission_dir ||= File.join("eo", "incoming")
40
+ @vendor_email ||= nil
41
+ end
42
+ end
15
43
  end
@@ -1,13 +1,22 @@
1
1
  module RsrGroup
2
2
  class Base
3
3
 
4
- FTP_HOST = 'ftp.rsrgroup.com'
4
+ SHIPPING_CARRIERS = %w(UPS USPS)
5
+
6
+ SHIPPING_METHODS = {
7
+ "Grnd" => "Ground",
8
+ "1Day" => "Next Day Air",
9
+ "2Day" => "2nd Day Air",
10
+ "3Day" => "3 Day Select",
11
+ "NDam" => "Next Day Early AM",
12
+ "NDAS" => "Next Day Air Saver",
13
+ "PRIO" => "Priority"
14
+ }
5
15
 
6
16
  protected
7
17
 
8
- # Wrapper to `self.requires!` that can be used as an instance method.
9
- def requires!(*args)
10
- self.class.requires!(*args)
18
+ def self.ftp_host
19
+ RsrGroup.config.ftp_host
11
20
  end
12
21
 
13
22
  def self.requires!(hash, *params)
@@ -23,16 +32,22 @@ module RsrGroup
23
32
  end
24
33
  end
25
34
 
35
+ def ftp_host
36
+ self.class.ftp_host
37
+ end
38
+
39
+ # Wrapper to `self.requires!` that can be used as an instance method.
40
+ def requires!(*args)
41
+ self.class.requires!(*args)
42
+ end
43
+
26
44
  def connect(options = {})
27
45
  requires!(options, :username, :password)
28
46
 
29
- Net::FTP.open(FTP_HOST, options[:username], options[:password]) do |ftp|
47
+ Net::FTP.open(ftp_host, options[:username], options[:password]) do |ftp|
30
48
  ftp.passive = true
31
49
  yield ftp
32
50
  end
33
- # TODO: Disable this rescue for now, so we can figure out what's happening when used in an actual app.
34
- # rescue Net::FTPPermError
35
- # raise RsrGroup::NotAuthenticated
36
51
  end
37
52
 
38
53
  end
@@ -0,0 +1,84 @@
1
+ module RsrGroup
2
+ class Order < Base
3
+
4
+ attr_reader :credentials
5
+ attr_reader :identifier
6
+ attr_reader :timestamp
7
+ attr_reader :sequence_number
8
+ attr_accessor :recipients
9
+
10
+ LINE_TYPES = {
11
+ "00" => "file_header",
12
+ "10" => "order_header",
13
+ "11" => "ffl_dealer",
14
+ "20" => "order_detail",
15
+ "90" => "order_trailer",
16
+ "99" => "file_trailer"
17
+ }
18
+
19
+ def initialize(options = {})
20
+ requires!(options, :sequence_number, :username, :password, :identifier)
21
+
22
+ @credentials = options.select { |k, v| [:username, :password].include?(k) }
23
+ @identifier = options[:identifier]
24
+ @sequence_number = "%04d" % options[:sequence_number] # Leading zeros are required
25
+ @timestamp = Time.now.strftime("%Y%m%e")
26
+ @recipients = options[:recipients] || []
27
+ end
28
+
29
+ def header
30
+ ["FILEHEADER", LINE_TYPES.key("file_header"), customer_number, @timestamp, @sequence_number].join(";")
31
+ end
32
+
33
+ def footer
34
+ ["FILETRAILER", LINE_TYPES.key("file_trailer"), ("%05d" % recipients.length)].join(";")
35
+ end
36
+
37
+ def filename
38
+ name = ["EORD", customer_number, timestamp, sequence_number].join("-")
39
+ [name, ".txt"].join
40
+ end
41
+
42
+ def recipients
43
+ @recipients ||= []
44
+ end
45
+
46
+ def to_txt
47
+ txt = header + "\n"
48
+ recipients.each do |recipient|
49
+ txt += (recipient.to_single_line + "\n")
50
+ if recipient.ffl
51
+ txt += (recipient.ffl.to_single_line + "\n")
52
+ end
53
+ recipient.items.each do |item|
54
+ txt += (item.to_single_line + "\n")
55
+ end
56
+ txt += recipient.trailer + "\n"
57
+ end
58
+ txt += footer
59
+ end
60
+
61
+ def submit!
62
+ connect(@credentials) do |ftp|
63
+ ftp.chdir(RsrGroup.config.submission_dir)
64
+ io = StringIO.new(to_txt)
65
+ begin
66
+ ftp.storlines("STOR " + filename, io)
67
+ ensure
68
+ io.close
69
+ end
70
+ end
71
+ end
72
+
73
+ private
74
+
75
+ def customer_number
76
+ credentials[:username]
77
+ end
78
+
79
+ def items
80
+ recipients.map(&:items).flatten.compact
81
+ end
82
+
83
+ end
84
+ end
@@ -0,0 +1,29 @@
1
+ module RsrGroup
2
+ class OrderDetail < Base
3
+
4
+ attr_reader :order_identifier
5
+ attr_reader :quantity
6
+
7
+ def initialize(options = {})
8
+ requires!(options, :order_identifier, :rsr_stock_number, :quantity, :shipping_carrier, :shipping_method)
9
+
10
+ @order_identifier = options[:order_identifier]
11
+ @rsr_stock_number = options[:rsr_stock_number]
12
+ @quantity = (options[:quantity].is_a?(Integer) ? ("%05d" % options[:quantity]) : options[:quantity])
13
+ @shipping_carrier = options[:shipping_carrier]
14
+ @shipping_method = options[:shipping_method]
15
+ end
16
+
17
+ def to_single_line
18
+ [
19
+ order_identifier,
20
+ Order::LINE_TYPES.key("order_detail"),
21
+ @rsr_stock_number,
22
+ @quantity,
23
+ @shipping_carrier,
24
+ @shipping_method
25
+ ].join(";")
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,24 @@
1
+ module RsrGroup
2
+ class OrderFFL < Base
3
+
4
+ attr_reader :order_identifier
5
+
6
+ def initialize(options = {})
7
+ requires!(options, :order_identifier, :licence_number, :name, :zip)
8
+
9
+ @options = options
10
+ @order_identifier = options[:order_identifier]
11
+ end
12
+
13
+ def to_single_line
14
+ [
15
+ order_identifier,
16
+ Order::LINE_TYPES.key("ffl_dealer"),
17
+ @options[:licence_number],
18
+ @options[:name],
19
+ @options[:zip],
20
+ ].join(";")
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,55 @@
1
+ module RsrGroup
2
+ class OrderRecipient < Base
3
+
4
+ attr_reader :order_identifier
5
+ attr_accessor :ffl
6
+ attr_accessor :items
7
+
8
+ def initialize(options = {})
9
+ requires!(options, :order_identifier, :shipping_name, :address_one, :city, :state, :zip)
10
+
11
+ @ffl = options[:ffl]
12
+ @items = options[:items] || []
13
+ @options = options
14
+ @order_identifier = options[:order_identifier]
15
+ end
16
+
17
+ def items
18
+ @items ||= []
19
+ end
20
+
21
+ def to_single_line
22
+ [
23
+ order_identifier,
24
+ Order::LINE_TYPES.key("order_header"),
25
+ @options[:shipping_name],
26
+ @options[:attn],
27
+ @options[:address_one],
28
+ @options[:address_two],
29
+ @options[:city],
30
+ @options[:state],
31
+ @options[:zip],
32
+ @options[:phone],
33
+ (@options[:email].nil? ? "N" : "Y"),
34
+ @options[:email],
35
+ RsrGroup.config.vendor_email,
36
+ nil
37
+ ].join(";")
38
+ end
39
+
40
+ def trailer
41
+ [
42
+ order_identifier,
43
+ Order::LINE_TYPES.key("order_trailer"),
44
+ ("%07d" % quantity_sum)
45
+ ].join(";")
46
+ end
47
+
48
+ private
49
+
50
+ def quantity_sum
51
+ items.map(&:quantity).map(&:to_i).inject(:+)
52
+ end
53
+
54
+ end
55
+ end
@@ -1,3 +1,3 @@
1
1
  module RsrGroup
2
- VERSION = "0.1.6"
2
+ VERSION = "1.0.0.pre"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rsr_group
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 1.0.0.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dale Campbell
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-11-15 00:00:00.000000000 Z
11
+ date: 2016-11-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -84,10 +84,15 @@ files:
84
84
  - Rakefile
85
85
  - bin/console
86
86
  - bin/setup
87
+ - config.rb.example
87
88
  - lib/rsr_group.rb
88
89
  - lib/rsr_group/base.rb
89
90
  - lib/rsr_group/department.rb
90
91
  - lib/rsr_group/inventory.rb
92
+ - lib/rsr_group/order.rb
93
+ - lib/rsr_group/order_detail.rb
94
+ - lib/rsr_group/order_ffl.rb
95
+ - lib/rsr_group/order_recipient.rb
91
96
  - lib/rsr_group/user.rb
92
97
  - lib/rsr_group/version.rb
93
98
  - rsr_group.gemspec
@@ -106,9 +111,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
106
111
  version: '2.0'
107
112
  required_rubygems_version: !ruby/object:Gem::Requirement
108
113
  requirements:
109
- - - ">="
114
+ - - ">"
110
115
  - !ruby/object:Gem::Version
111
- version: '0'
116
+ version: 1.3.1
112
117
  requirements: []
113
118
  rubyforge_project:
114
119
  rubygems_version: 2.6.7