sunnyside 0.0.5 → 0.0.7

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.
@@ -1,123 +1,149 @@
1
1
  module Sunnyside
2
2
 
3
- def payment_type
3
+ def self.cash_receipt
4
4
  puts "1.) EDI PAYMENT"
5
5
  puts "2.) MANUAL PAYMENT"
6
- return gets.chomp.upcase == '1' ? EdiPayment.new : ManualPayment.new
6
+ cash_receipt =
7
+ case gets.chomp
8
+ when '1'
9
+ CashReceipt.new(:electronic)
10
+ when '2'
11
+ CashReceipt.new(:manual)
12
+ end
13
+ cash_receipt.collate
7
14
  end
8
15
 
9
- def check_date_abbre
10
- puts 'Enter in check number, post date and then followed by the provider abbreviation (separated by a space - ex: 235345 10/12/2013 WEL): '
11
- ans = gets.chomp.split
12
- if ans.size == 3
13
- return ans
14
- else
15
- raise 'You need to enter in the specified fields.'
16
+ class CashReceipt
17
+ attr_reader :post_date, :type_of_entry
18
+
19
+ def initialize(type_of_entry)
20
+ print "Enter in post date (YYYY-MM-DD): "
21
+ @post_date = Date.parse(gets.chomp)
22
+ @type_of_entry = type_of_entry
16
23
  end
17
- end
18
24
 
19
- def invoice_numbers
20
- puts 'Enter in invoices, each separated by a space. If an invoice contains any denials, flag it by typing in a "-d" right after the last number. '
21
- return gets.chomp.split
22
- end
25
+ def collate
26
+ case type_of_entry
27
+ when :electronic
28
+ Sunnyside.check_prompt { |payment_id| EdiPayment.new(payment_id, post_date).collate }
29
+ when :manual
30
+ manual_invoices
31
+ else
32
+ exit
33
+ end
34
+ end
23
35
 
24
- class CashReceipt
25
- include Sunnyside
26
- attr_reader :type
27
- def initialize
28
- @type = self.payment_type
36
+ def invoice_selection
37
+ puts "Enter in the invoices, each separated by a space. If any invoice has a denial, 'flag' it by typing '-d' after the invoice number.\n"
38
+ invoices = gets.chomp.split
39
+ print "You have typed out #{invoices.length} number of invoices. Do you wish to add more to the same check? (Y or N): "
40
+ if gets.chomp.upcase == 'Y'
41
+ more_invoices = gets.chomp.split
42
+ return (more_invoices + invoices)
43
+ else
44
+ return invoices
45
+ end
29
46
  end
30
47
 
31
- def process
32
- type.collate
48
+ def manual_invoices
49
+ print "# of checks to enter for the post date of #{post_date}? "
50
+ num = gets.chomp.to_i
51
+ num.times do
52
+ prov = provider
53
+ print "Enter in the check number: "
54
+ check = gets.chomp
55
+ invoices = invoice_selection
56
+ manual = ManualPayment.new(invoices, post_date, prov, check)
57
+ manual.seed_claims_and_services
58
+ manual.create_csv
59
+ end
60
+ end
61
+
62
+ def provider
63
+ Provider.all.each { |prov| puts "#{prov.id}: #{prov.name}"}
64
+ print "Type in the Provider ID: "
65
+ return Provider[gets.chomp] || ''
33
66
  end
34
67
  end
35
68
 
69
+
70
+
36
71
  class EdiPayment
37
72
  include Sunnyside
38
- attr_reader :check_number, :post_date, :prov
39
-
40
- def initialize
41
- @check_number, @post_date, @prov = self.check_date_abbre
42
- end
73
+ attr_reader :payment, :post_date
43
74
 
44
- def invoices
45
- Claim.where(check_number: check_number).map { |clm| clm.invoice_id }.uniq
75
+ def initialize(payment, post_date)
76
+ @payment, @post_date = payment, post_date
46
77
  end
47
78
 
48
79
  def populated_data
49
- invoices.map { |inv| Invoice[inv] }
80
+ Claim.where(payment_id: payment.id).all.select { |clm| clm.paid > 0.0 }
50
81
  end
51
82
 
52
83
  def total
53
- populated_data.map { |inv| inv.amount }.inject { |x, y| x + y }.round(2)
54
- end
55
-
56
- def payment_id
57
- Payment.where(check_number: check_number).get(:id)
84
+ populated_data.map { |clm| clm.paid }.inject { |x, y| x + y }.round(2)
58
85
  end
59
86
 
60
87
  def collate
61
88
  puts "Total Amount Paid for this check is: #{total}\nProcessing..."
62
- populated_data.each { |inv| self.receivable_csv(inv, payment_id, check_number, post_date) if inv.amount > 0.0 }
63
- puts "Check added to #{LOCAL_FILES}/EDI-citywide-import.csv"
64
- puts "Please note that there are #{denied_services} service days with possible denials"
89
+ populated_data.each do |clm|
90
+ if not_paid_fully?(clm)
91
+ self.receivable_csv(clm, payment, post_date)
92
+ else
93
+ print "#{clm.invoice_id} was not added to the spreadsheet because the invoice was already fully paid for.\n"
94
+ print "Please consider this $#{clm.paid} as an interest payment.\n"
95
+ end
96
+ end
97
+ puts "----------------------------------------------------------------------------------------------------------"
98
+ puts "------------------------------Check added to #{DRIVE}/EDI-citywide-import.csv-----------------------------"
99
+ puts "-------------Please note that there are #{denied_services} service days with possible denials-------------"
100
+ puts "----------------------------------------------------------------------------------------------------------"
101
+ end
102
+
103
+ def not_fully_paid?(clm)
104
+ Claim.where(invoice_id: clm.invoice_id).sum(:paid).round(2) < clm.paid
65
105
  end
66
106
 
67
107
  def denied_services
68
- Service.where(check_number: check_number).exclude(denial_reason: [nil, '']).count
108
+ Service.where(payment_id: payment.id).exclude(denial_reason: nil).count
69
109
  end
70
110
  end
71
111
 
72
- class ManualPayment < CashReceipt
73
- attr_reader :check, :manual_invs, :post_date, :prov
74
-
75
- def initialize
76
- @check, @post_date, @prov = self.check_date_abbre
77
- @manual_invs = self.invoice_numbers
78
- end
112
+ class ManualPayment
113
+ include Sunnyside
114
+ attr_reader :denied_invoices, :paid_invoices, :post_date, :provider, :check, :payment_id
79
115
 
80
- def provider
81
- Provider.where(abbreviation: prov).first
116
+ def initialize(invoices, post_date, prov, check)
117
+ @denied_invoices = invoices.select { |inv| inv.include?('-d') }.map { |inv| Invoice[inv.gsub(/-d/, '')] }
118
+ @paid_invoices = invoices.reject { |inv| inv.include?('-d') }.map { |inv| Invoice[inv] }
119
+ @post_date = post_date
120
+ @provider = prov
121
+ @check = check
122
+ @payment_id = Payment.insert(check_number: check, post_date: post_date, provider_id: prov.id)
82
123
  end
83
124
 
84
- def payment_id
85
- if check_exists?
86
- Payment.where(check_number: check, post_date: post_date, provider_id: provider.id).get(:id)
87
- else
88
- Payment.insert(check_number: check, post_date: post_date, provider_id: provider.id)
125
+ def seed_claims_and_services
126
+ (denied_invoices + paid_invoices).each do |invoice|
127
+ claim_id = create_claim(invoice)
128
+ create_services(invoice, claim_id)
89
129
  end
130
+ edit_services if denied_invoices.length > 0
90
131
  end
91
132
 
92
- def check_exists?
93
- Payment.where(check_number: check, post_date: post_date, provider_id: provider.id).count > 0
133
+ def create_csv
134
+ claims.each { |clm| self.receivable_csv(clm, Payment[payment_id], post_date) if clm.paid > 0.0 }
94
135
  end
95
136
 
96
- def date
97
- Date.strptime(post_date, '%m/%d/%Y')
98
- end
99
-
100
- def collate
101
- manual_invs.each { |inv|
102
- invoice = Invoice[inv.gsub(/-d/, '')]
103
- claim_id = create_claim(invoice)
104
- create_services(invoice, claim_id)
105
- edit_services(claim_id) if denial_present?(inv)
106
- self.receivable_csv(invoice, payment_id, check, post_date)
107
- }
108
- end
109
-
110
- def invoice_data(inv)
111
- invoice = inv.gsub(/-d/, '').to_i
112
- yield Invoice[invoice]
137
+ def claims
138
+ (denied_invoices + paid_invoices).map { |inv| Claim.where(invoice_id: inv.invoice_number, payment_id: payment_id).first }
113
139
  end
114
140
 
115
141
  def create_claim(invoice)
116
142
  Claim.insert(
117
- :invoice_id => invoice.id,
143
+ :invoice_id => invoice.invoice_number,
118
144
  :client_id => invoice.client_id,
119
145
  :billed => invoice.amount,
120
- :paid => 0.0,
146
+ :paid => invoice.amount,
121
147
  :payment_id => payment_id,
122
148
  :provider_id => invoice.provider_id
123
149
  )
@@ -143,51 +169,53 @@ module Sunnyside
143
169
  Visit.where(invoice_id: invoice.invoice_number).all
144
170
  end
145
171
 
146
- def services(inv)
147
- Service.where(payment_id: payment_id, invoice_id: inv)
148
- end
149
-
150
- def edit_services(inv)
151
- service = EditServices.new(inv, payment_id)
152
- loop do
153
- service.show_all
154
- service.adjust
155
- end
156
- end
172
+ def edit_services
173
+ denied_invoices.each { |inv|
174
+ services = Service.where(invoice_id: inv.invoice_number, payment_id: payment_id)
175
+ edit_service = EditService.new(services)
176
+ edit_service.show_all
157
177
 
158
- def denial_present?(invoice)
159
- invoice.include?('-d')
178
+ edit_service.adjust
179
+
180
+ adjust_claim(inv)
181
+ }
160
182
  end
161
183
 
162
184
  def visits(invoice)
163
185
  Visit.where(invoice_id: invoice.invoice_number).all
164
186
  end
165
187
 
166
- class EditServices < ManualPayment::CashReceipt
167
- attr_reader :claim
188
+ def adjust_claim(inv)
189
+ service_sum = Service.where(payment_id: payment_id, invoice_id: inv.invoice_number).sum(:paid).round(2)
190
+ Claim.where(invoice_id: inv.invoice_number, payment_id: payment_id).update(:paid => service_sum)
191
+ end
192
+ end
168
193
 
169
- def initialize(claim_id)
170
- @claim = Claim[claim_id]
171
- @services = Service.where(claim_id: claim_id).all
172
- end
194
+ class EditService
195
+ attr_reader :services
173
196
 
174
- def show_all
175
- services.each { |svc| puts "ID: #{svc.id} #{svc.dos} #{svc.amount}" }
176
- end
197
+ def initialize(services)
198
+ @services = services.all
199
+ end
200
+
201
+ def show_all
202
+ services.each { |svc| puts "ID: #{svc.id} #{svc.dos} #{svc.service_code} #{svc.paid}" }
203
+ end
177
204
 
178
- def adjust
179
- print "Type in the Service ID # to change the amount: "
180
- id = gets.chomp
205
+ def adjust
206
+ print "Type in the Service(s) ID # to change the amount: "
207
+ ids = gets.chomp.split
208
+ ids.each do |id|
181
209
  print "You selected #{id} - Type in the adjusted amount: "
182
210
  amt = gets.chomp
183
211
  print "And now type in the denial reason: "
184
212
  reason = gets.chomp
185
213
  adjust_service(id, amt, reason)
186
214
  end
215
+ end
187
216
 
188
- def adjust_service
189
- Service[id].update(paid: amt, denial_reason: reason)
190
- end
217
+ def adjust_service(id, amt, reason)
218
+ Service[id].update(paid: amt, denial_reason: reason)
191
219
  end
192
220
  end
193
221
  end
data/lib/sunnyside/ftp.rb CHANGED
@@ -2,32 +2,47 @@ require "net/ftp"
2
2
  require 'rubygems'
3
3
 
4
4
  module Sunnyside
5
- PROVIDERS = [
6
- { :username => '****', :password => '****', :name => 'GUILDNET'},
7
- { :username => '****', :password => '****', :name => 'ELDERSERVE'},
8
- { :username => '****', :password => '****', :name => 'CPHL'}
9
- ]
10
- def self.access_ftp(process)
11
- PROVIDERS.each { |provider|
12
- access = SunnyFTP.new(provider)
13
- access.log_on
14
- puts "Logged into #{provider[:name]}..."
15
- if process == :download
16
- access.download_files
17
- elsif process == :upload
18
- access.upload_files
19
- end
20
- }
5
+ def self.access_ftp
6
+ puts "1.) GUILDNET"
7
+ puts "2.) ELDERSERVE"
8
+ puts "3.) CPHL"
9
+ print "Select option: "
10
+ case gets.chomp
11
+ when '1'
12
+ print 'Username for Guildnet? '
13
+ username = gets.chomp
14
+ print 'Password for Guildnet? '
15
+ pass = gets.chomp
16
+ access = SunnyFTP.new(username, pass, 'GUILDNET')
17
+ when '2'
18
+ print 'Username for ELDERSERVE? '
19
+ username = gets.chomp
20
+ print 'Password for ELDERSERVE? '
21
+ pass = gets.chomp
22
+ access = SunnyFTP.new(username, pass, 'ELDERSERVE')
23
+ when '3'
24
+ print 'Username for CPHL? '
25
+ username = gets.chomp
26
+ print 'Password for CPHL? '
27
+ pass = gets.chomp
28
+ access = SunnyFTP.new(username, pass, 'CPHL')
29
+ else
30
+ exit
31
+ end
32
+ access.log_on
33
+ puts "Logged into #{access.name}..."
34
+ access.download_files
35
+ access.upload_files
21
36
  end
22
37
 
23
38
  class SunnyFTP
24
39
  attr_reader :ftp, :username, :password, :name, :directory
25
40
 
26
- def initialize(provider = {})
41
+ def initialize(username, password, name)
27
42
  @ftp = Net::FTP.new('depot.per-se.com')
28
- @username = provider[:username]
29
- @password = provider[:password]
30
- @name = provider[:name]
43
+ @username = username
44
+ @password = password
45
+ @name = name
31
46
  end
32
47
 
33
48
  def log_on
@@ -44,7 +59,7 @@ module Sunnyside
44
59
 
45
60
  def download_folder
46
61
  ftp.chdir('../outgoing')
47
- if !empty?('.')
62
+ if ftp.nlst.size == 0
48
63
  puts "No files found. Exiting..."
49
64
  ftp.close
50
65
  return []
@@ -54,7 +69,7 @@ module Sunnyside
54
69
  end
55
70
 
56
71
  def up_files
57
- Dir["edi/outgoing/*.txt"]
72
+ Dir["#{DRIVE}/sunnyside-files/ftp/837/#{name}/*.txt"]
58
73
  end
59
74
 
60
75
  def upload_files
@@ -64,14 +79,14 @@ module Sunnyside
64
79
  ftp.putbinaryfile(file)
65
80
  puts "Upload complete."
66
81
  puts "deleting #{file} in local folder."
67
- FileUtils.mv(file, "edi/outgoing/uploaded/#{File.basename(file)}")
82
+ FileUtils.mv(file, "#{DRIVE}/sunnyside-files/ftp/837/#{name}/#{File.basename(file)}")
68
83
  end
69
84
  }
70
85
  ftp.close
71
86
  end
72
87
 
73
88
  def provider_folder
74
- Dir["edi/incoming/#{name}"].map { |file| File.basename(file) }
89
+ Dir["#{DRIVE}/sunnyside-files/ftp/835/#{name}"].map { |file| File.basename(file) }
75
90
  end
76
91
 
77
92
  def new_file?(file)
@@ -82,12 +97,7 @@ module Sunnyside
82
97
  download_folder.each do |file|
83
98
  if !provider_folder.include?(file)
84
99
  puts "Downloading #{file}..."
85
- case file
86
- when file.include?('TA1') then ftp.getbinaryfile(file, "edi/incoming/#{name}/TA1/#{file}")
87
- when file.include?('997') then ftp.getbinaryfile(file, "edi/incoming/#{name}/997/#{file}")
88
- else
89
- ftp.getbinaryfile(file, "edi/incoming/#{name}/#{file}")
90
- end
100
+ ftp.getbinaryfile(file, "#{DRIVE}/sunnyside-files/ftp/835/#{name}/#{file}") if File.basename(file).include?('835')
91
101
  puts "#{file} placed."
92
102
  end
93
103
  end
@@ -4,11 +4,13 @@ module Sunnyside
4
4
  # report page by page, it would be best to compress the text from every page into a single string and then parse from there.
5
5
 
6
6
  def self.parse_pdf
7
- Dir["#{LOCAL_FILES}/837/*.PDF"].select { |file| Filelib.where(filename: file).count == 0 }.each do |file|
7
+ files = Dir["#{DRIVE}/sunnyside-files/837/*.PDF"].select { |file| Filelib.where(filename: file).count == 0 }
8
+ files.each do |file|
8
9
  puts "processing #{file}..."
9
10
  data = PDF::Reader.new(file).pages.map { |page| page.raw_content.gsub(/^\(\s|\)'$/, '') }.join
10
- data.split(/^\((?=REG\s+LOC)/).each { |entry| ParseInvoice.new(entry).process }
11
+ data.split(/(?=REG\s+LOC)/).each { |entry| ParseInvoice.new(entry).process }
11
12
  Filelib.insert(filename: file, purpose: '837')
13
+ FileUtils.mv(file, "#{DRIVE}/sunnyside-files/837/archive/#{File.basename(file)}")
12
14
  end
13
15
  end
14
16
 
@@ -16,8 +18,12 @@ module Sunnyside
16
18
  attr_reader :client_line, :visits
17
19
 
18
20
  def initialize(entry)
19
- @client_line = entry.split(/\n/).select { |line| line =~ /\s+001\s+/ }
20
- @visits = entry.split(/\n/).select { |line| line =~ /^\d{6}/ }
21
+ @client_line = entry.split(/\n/).select { |line| line =~ /\s+001\s+/ }.join
22
+ @visits = entry.split(/\n/).select { |line| line =~ /^\d{6}/ }
23
+ end
24
+
25
+ def client_data
26
+ client_line.slice(9..28) + client_line.slice(54..120)
21
27
  end
22
28
 
23
29
  def invoice_lines
@@ -34,10 +40,7 @@ module Sunnyside
34
40
  }
35
41
  end
36
42
 
37
-
38
- def client_data
39
- client_line.map { |line| ( line.slice(9..28) + line.slice(66..120) ).split }[0]
40
- end
43
+ # removes the client name from the line
41
44
 
42
45
  def process
43
46
  invoice_lines.each { |inv| inv.to_db }
@@ -57,12 +60,12 @@ module Sunnyside
57
60
  @modifier = invoice_line[:modifier]
58
61
  @dos = invoice_line[:dos]
59
62
  @units = invoice_line[:units]
60
- @amount = invoice_line[:amount]
63
+ @amount = invoice_line[:amount].gsub(/,/, '')
61
64
  end
62
65
 
63
66
  def to_db
64
67
  Visit.insert(
65
- :client_id => client.client_number,
68
+ :client_id => client_id,
66
69
  :modifier => modifier,
67
70
  :invoice_id => invoice,
68
71
  :amount => amount,
@@ -70,39 +73,30 @@ module Sunnyside
70
73
  :dos => Date.strptime(dos, '%m/%d/%y'),
71
74
  :units => units
72
75
  )
73
- update_invoice
76
+ update_client_demographics
74
77
  end
75
78
 
76
- def update_invoice
77
- Invoice[invoice].update(:auth => auth, :recipient_id => client.recipient_id)
79
+ def client_id
80
+ Invoice[invoice].client_id
78
81
  end
79
82
 
80
- def auth
81
- client.authorization
83
+ def update_client_demographics
84
+ Invoice[invoice].update(:auth => client.authorization, :recipient_id => client.recipient_id, service_number: client.service_id)
85
+ Client[client_id].update(:recipient_id => client.recipient_id)
82
86
  end
83
87
  end
84
88
 
85
89
  class ClientData < ParseInvoice
86
- attr_reader :client_id, :service_id, :recipient_id, :authorization
90
+ attr_reader :client_id, :service_id, :recipient_id, :authorization, :dob
87
91
 
88
92
  def initialize(client)
89
- @client_id, @service_id, @recipient_id, @authorization = client.map { |line| line.strip }
90
- end
91
-
92
- def client_number
93
- if client_missing?
94
- puts 'how the hell is it happening? ' + client_id
95
- else
96
- client_id
97
- end
93
+ @client_id, @service_id, @dob, @recipient_id, @authorization = client.split.map { |line| line.strip }
98
94
  end
99
95
 
100
- def auth
101
- authorization
102
- end
96
+ # Not parsing correctly.
103
97
 
104
- def client_missing?
105
- Client[client_id].nil?
98
+ def date_of_birth
99
+ Date.strptime(dob, '%m/%d/%Y')
106
100
  end
107
101
  end
108
102
  end