vesr 0.1.0 → 0.1.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.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.1.2
@@ -0,0 +1,62 @@
1
+ require 'action_controller/test_process.rb'
2
+
3
+ class EsrBookingsController < ApplicationController
4
+ # GET /esr_bookings
5
+ def index
6
+ @esr_files = EsrFile.paginate(:page => params['page'], :per_page => 20, :order => 'updated_at DESC')
7
+
8
+ respond_to do |format|
9
+ format.html {
10
+ render :action => 'list'
11
+ }
12
+ end
13
+ end
14
+
15
+ # GET /esr_bookings/new
16
+ def new
17
+ @esr_file = EsrFile.new
18
+
19
+ respond_to do |format|
20
+ format.html {
21
+ render :partial => 'form', :layout => 'application'
22
+ }
23
+ format.js { }
24
+ end
25
+ end
26
+
27
+ # POST /esr_bookings
28
+ def create
29
+ # if :filename param is set, file exists
30
+ if params[:filename]
31
+ vesr_path = params[:filename]
32
+
33
+ @esr_file = EsrFile.new(:uploaded_data => ActionController::TestUploadedFile.new(vesr_path))
34
+ else
35
+ @esr_file = EsrFile.new(params[:esr_file])
36
+ end
37
+
38
+ if @esr_file.save
39
+ # Delete file if saved as attachment
40
+ File.delete(vesr_path) if vesr_path
41
+ end
42
+
43
+ respond_to do |format|
44
+ format.html {
45
+ redirect_to :action => 'show', :id => @esr_file
46
+ }
47
+ format.js { }
48
+ end
49
+ end
50
+
51
+ # GET /esr_bookings/1
52
+ def show
53
+ @esr_file = EsrFile.find(params[:id])
54
+
55
+ respond_to do |format|
56
+ format.html {
57
+ render :action => 'show'
58
+ }
59
+ format.js { }
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,26 @@
1
+ class EsrFile < ActiveRecord::Base
2
+ has_attachment :storage => :file_system
3
+ has_many :esr_records, :dependent => :destroy
4
+
5
+ def to_s(format = :default)
6
+ case format
7
+ when :short
8
+ "#{updated_at.strftime('%d.%m.%Y')}: #{esr_records.count} Buchungen"
9
+ else
10
+ s = ''
11
+ esr_records.each {|record|
12
+ s += record.to_s + "\n"
13
+ }
14
+ s
15
+ end
16
+ end
17
+
18
+ after_save :create_records
19
+
20
+ private
21
+ def create_records
22
+ File.new(full_filename).each {|line|
23
+ self.esr_records << EsrRecord.new.parse(line) unless line[0..2] == '999'
24
+ }
25
+ end
26
+ end
@@ -0,0 +1,147 @@
1
+ class EsrRecord < ActiveRecord::Base
2
+ belongs_to :esr_file
3
+
4
+ belongs_to :booking, :dependent => :destroy
5
+ belongs_to :invoice
6
+
7
+ named_scope :valid, :conditions => "state = 'valid'"
8
+ named_scope :missing, :conditions => "state = 'missing'"
9
+ named_scope :bad, :conditions => "state = 'bad'"
10
+ named_scope :invalid, :conditions => "state != 'valid'"
11
+
12
+ private
13
+ def parse_date(value)
14
+ year = value[0..1].to_i + 2000
15
+ month = value[2..3].to_i
16
+ day = value[4..5].to_i
17
+
18
+ return Date.new(year, month, day)
19
+ end
20
+
21
+ def payment_date=(value)
22
+ write_attribute(:payment_date, parse_date(value))
23
+ end
24
+
25
+ def transaction_date=(value)
26
+ write_attribute(:transaction_date, parse_date(value))
27
+ end
28
+
29
+ def value_date=(value)
30
+ write_attribute(:value_date, parse_date(value))
31
+ end
32
+
33
+ def reference=(value)
34
+ write_attribute(:reference, value[0..-2])
35
+ end
36
+
37
+ public
38
+ def to_s
39
+ "CHF #{amount} for client #{client_id} on #{value_date}, reference #{reference}"
40
+ end
41
+
42
+ def client_id
43
+ reference[0..5]
44
+ end
45
+
46
+ def invoice_id
47
+ reference[19..-1].to_i
48
+ end
49
+
50
+ def patient_id
51
+ reference[6..18].to_i
52
+ end
53
+
54
+ def parse(line)
55
+ # self.recipe_type = line[0, 1]
56
+ self.bank_pc_id = line[3..11]
57
+ self.reference = line[12..38]
58
+ self.amount = BigDecimal.new(line[39..48]) / 100
59
+ self.payment_reference = line[49..58]
60
+ self.payment_date = line[59..64]
61
+ self.transaction_date = line[65..70]
62
+ self.value_date = line[71..76]
63
+ self.microfilm_nr = line[77..85]
64
+ self.reject_code = line[86, 1]
65
+ self.reserved = line[87,95]
66
+ self.payment_tax = line[96..99]
67
+
68
+ self
69
+ end
70
+
71
+ # Invoices
72
+ before_create :assign_invoice, :create_esr_booking
73
+
74
+ private
75
+ def evaluate_bad
76
+ if invoice.state == 'paid'
77
+ # already paid
78
+ if invoice.amount.currency_round == self.amount.currency_round
79
+ # paid twice
80
+ self.remarks += ", doppelt bezahlt"
81
+ else
82
+ self.remarks += ", bereits bezahlt"
83
+ end
84
+ elsif !(invoice.active)
85
+ # canceled invoice
86
+ self.remarks += ", wurde #{invoice.state_adverb}"
87
+ elsif invoice.amount.currency_round == self.amount.currency_round
88
+ # TODO much too open condition (issue #804)
89
+ # reminder fee not paid
90
+ self.remarks += ", Mahnspesen nicht bezahlt"
91
+ else
92
+ # bad amount
93
+ self.remarks += ", falscher Betrag"
94
+ end
95
+ end
96
+
97
+ def assign_invoice
98
+ if Invoice.exists?(invoice_id)
99
+ self.invoice_id = invoice_id
100
+ self.remarks += "Referenz #{reference}"
101
+ if invoice.due_amount.currency_round != self.amount.currency_round
102
+ evaluate_bad
103
+ self.state = "bad"
104
+ else
105
+ self.state = "valid"
106
+ end
107
+ elsif imported_invoice = Invoice.find(:first, :conditions => ["imported_esr_reference LIKE concat(?, '%')", reference])
108
+ self.invoice = imported_invoice
109
+ self.remarks += "Referenz #{reference}"
110
+ if invoice.due_amount.currency_round != self.amount.currency_round
111
+ self.remarks += ", falscher Betrag"
112
+ self.state = "bad"
113
+ else
114
+ self.state = "valid"
115
+ end
116
+ else
117
+ self.remarks += "Rechnung ##{invoice_id} nicht gefunden"
118
+ self.state = "missing"
119
+ end
120
+ end
121
+
122
+ def vesr_account
123
+ BankAccount.find_by_esr_id(client_id)
124
+ end
125
+
126
+ def create_esr_booking
127
+ if invoice
128
+ esr_booking = invoice.bookings.build
129
+ else
130
+ esr_booking = Booking.new
131
+ end
132
+
133
+ esr_booking.update_attributes(
134
+ :amount => amount,
135
+ :credit_account => vesr_account,
136
+ :debit_account => Invoice::DEBIT_ACCOUNT,
137
+ :value_date => value_date,
138
+ :title => "VESR Zahlung",
139
+ :comments => remarks)
140
+
141
+ esr_booking.save
142
+
143
+ self.booking = esr_booking
144
+
145
+ return esr_booking
146
+ end
147
+ end
@@ -0,0 +1,8 @@
1
+ <div class="contextual">
2
+ <%= link_to "VESR Liste", esr_bookings_path, :class => "icon icon-book" %>
3
+ </div>
4
+ <h2>VESR Datei einlesen</h2>
5
+ <% form_for :esr_file, :url => esr_bookings_path, :html => { :multipart => true } do |esr_file| %>
6
+ Datei: <%= esr_file.file_field :uploaded_data %>
7
+ <%= esr_file.submit 'Einlesen' %>
8
+ <% end %>
@@ -0,0 +1,6 @@
1
+ <tr id="esr_file_<%= item.id %>">
2
+ <td><%= link_to l(item.updated_at), esr_booking_path(item) %></td>
3
+ <td style="text-align: right"><%=h item.esr_records.valid.count %></td>
4
+ <td style="text-align: right"><%=h item.esr_records.invalid.count %></td>
5
+ <td style="text-align: right"><%=h sprintf("%0.2f", item.esr_records.sum(:amount) || 0.0) %></td>
6
+ </tr>
@@ -0,0 +1,3 @@
1
+ <tr>
2
+ <th colspan="5" style="text-align: right"><%= will_paginate @esr_files, :params => {:query => params[:query]} %></th>
3
+ </tr>
@@ -0,0 +1,7 @@
1
+ <tr>
2
+ <th>Verbucht am</th>
3
+ <th>Buchungen</th>
4
+ <th>Fehlerhafte Buchungen</th>
5
+ <th style="text-align: right">Total (inkl. fehlerh.)</th>
6
+ <th/>
7
+ </tr>
@@ -0,0 +1,21 @@
1
+ <table class="list" style="width: 100%">
2
+ <tr>
3
+ <th>Valuta Datum</th>
4
+ <th>Patient</th>
5
+ <th>Status</th>
6
+ <th style="text-align: right">Rechnungsbetrag</th>
7
+ <th style="text-align: right">Bezahlbetrag</th>
8
+ <th style="text-align: right">Saldo</th>
9
+ </tr>
10
+
11
+ <% for esr_record in list_records %>
12
+ <tr>
13
+ <td><%=h esr_record.value_date %></td>
14
+ <td><%= link_to esr_record.invoice.patient.to_s, esr_record.invoice if esr_record.invoice %></td>
15
+ <td><%= esr_record.invoice ? link_to(esr_record.remarks, esr_record.invoice) : esr_record.remarks %></td>
16
+ <td style="text-align: right"><%=h sprintf("%0.2f", esr_record.invoice.amount.currency_round) if esr_record.invoice %></td>
17
+ <td style="text-align: right"><%=h sprintf("%0.2f", esr_record.amount.currency_round) %></td>
18
+ <td style="text-align: right"><%=h sprintf("%0.2f", esr_record.invoice.due_amount.currency_round) if esr_record.invoice %></td>
19
+ </tr>
20
+ <% end %>
21
+ </table>
@@ -0,0 +1,5 @@
1
+ <%= navigation_section(:esr, {
2
+ :esr_bookings => :esr_bookings,
3
+ :new_esr => new_esr_booking_path
4
+ # "Fehlerhafte Buchungen" => bad_esr_bookings_path
5
+ }, '48x48/esr.png') %>
@@ -0,0 +1,10 @@
1
+ <% content_for :sidebar do %>
2
+ <div class="sub-tabs">
3
+ <h3>Ältere Buchungsläufe</h3>
4
+ <ul>
5
+ <% for esr_file in EsrFile.find :all, :limit => 10, :order => 'updated_at DESC' %>
6
+ <li><%= link_to esr_file.to_s(:short), esr_booking_path(esr_file) %></li>
7
+ <% end %>
8
+ </ul>
9
+ </div>
10
+ <% end %>
@@ -0,0 +1,14 @@
1
+ <div class="contextual">
2
+ <%= link_to "VESR Datei einlesen", new_esr_booking_path, :class => "icon icon-book" %>
3
+ </div>
4
+
5
+ <h2>VESR Buchungsläufe</h2>
6
+ <div id="vesr_list">
7
+ <table class="list">
8
+ <%= render :partial => 'esr_bookings/list_header' %>
9
+ <%= render :partial => 'esr_bookings/item', :collection => @esr_files %>
10
+ <%= render :partial => 'esr_bookings/list_footer' %>
11
+ </table>
12
+ </div>
13
+
14
+ <%= render :partial => 'sidebar' %>
@@ -0,0 +1,18 @@
1
+ <div class="contextual">
2
+ <%= link_to_function "Protokoll drucken", 'window.print()', :class => "icon icon-print" %>
3
+ <%= link_to "VESR Liste", esr_bookings_path, :class => "icon icon-book" %>
4
+ </div>
5
+ <h2>VESR Protokoll vom <%= l(@esr_file.updated_at.to_date) %></h2>
6
+ <%= render :partial => 'list_records', :object => @esr_file.esr_records.valid %>
7
+
8
+ <% unless @esr_file.esr_records.bad.empty? %>
9
+ <h3>Falscher Betrag</h3>
10
+ <%= render :partial => 'list_records', :object => @esr_file.esr_records.bad %>
11
+ <% end %>
12
+
13
+ <% unless @esr_file.esr_records.missing.empty? %>
14
+ <h3>Rechnung nicht gefunden</h3>
15
+ <%= render :partial => 'list_records', :object => @esr_file.esr_records.missing %>
16
+ <% end %>
17
+
18
+ <%= render :partial => 'sidebar' %>
@@ -27,7 +27,7 @@ module Prawn
27
27
  text vcard.street_address
28
28
  text vcard.postal_code + " " + vcard.locality
29
29
 
30
- move_down cm2pt(0.7)
30
+ move_down cm2pt(0.8)
31
31
  indent cm2pt(2.3) do
32
32
  font_size 9 do
33
33
  text esr_account.pc_id
@@ -37,13 +37,13 @@ module Prawn
37
37
 
38
38
  bounding_box [0, cm2pt(4.5)], :width => cm2pt(3.5) do
39
39
  font_size 9 do
40
- text sprintf('%.0f', amount.floor), :align => :right
40
+ text sprintf('%.0f', amount.floor), :align => :right, :character_spacing => 1
41
41
  end
42
42
  end
43
43
 
44
44
  bounding_box [cm2pt(4.7), cm2pt(4.5)], :width => cm2pt(1) do
45
45
  font_size 9 do
46
- text sprintf('%.0f', amount * 100 % 100)
46
+ text sprintf('%02.0f', amount * 100 % 100), :character_spacing => 1
47
47
  end
48
48
  end
49
49
 
@@ -73,7 +73,7 @@ module Prawn
73
73
  text vcard.street_address
74
74
  text vcard.postal_code + " " + vcard.locality
75
75
 
76
- move_down cm2pt(0.7)
76
+ move_down cm2pt(0.8)
77
77
  indent cm2pt(2.6) do
78
78
  font_size 9 do
79
79
  text esr_account.pc_id
@@ -83,18 +83,18 @@ module Prawn
83
83
 
84
84
  bounding_box [cm2pt(6), cm2pt(4.5)], :width => cm2pt(3.5) do
85
85
  font_size 9 do
86
- text sprintf('%.0f', amount.floor), :align => :right
86
+ text sprintf('%.0f', amount.floor), :align => :right, :character_spacing => 1
87
87
  end
88
88
  end
89
89
 
90
90
  bounding_box [cm2pt(10.8), cm2pt(4.5)], :width => cm2pt(1) do
91
91
  font_size 9 do
92
- text sprintf('%.0f', amount * 100 % 100)
92
+ text sprintf('%02.0f', amount * 100 % 100), :character_spacing => 1
93
93
  end
94
94
  end
95
95
 
96
96
  font_size 10 do
97
- draw_text esr9_reference(invoice, esr_account), :at => [cm2pt(12.3), cm2pt(5.9)]
97
+ draw_text esr9_reference(invoice, esr_account), :at => [cm2pt(12.3), cm2pt(5.9)], :character_spacing => 0.6
98
98
  end
99
99
 
100
100
  bounding_box [cm2pt(12.1), cm2pt(4.5)], :width => cm2pt(7.5) do
@@ -107,10 +107,10 @@ module Prawn
107
107
  end
108
108
 
109
109
  # ESR-Reference
110
- font_size 10
110
+ font_size 11
111
111
  font ::Rails.root.join('data/ocrb10.ttf') if FileTest.exists?(::Rails.root.join('data/ocrb10.ttf'))
112
112
 
113
- draw_text esr9(invoice, esr_account), :at => [cm2pt(5.2), 0]
113
+ draw_text esr9(invoice, esr_account), :at => [cm2pt(6.3), cm2pt(0.9)]
114
114
  end
115
115
 
116
116
  private
@@ -120,20 +120,21 @@ module Prawn
120
120
  end
121
121
 
122
122
  def esr9_reference(invoice, esr_account)
123
- esr9_format(esr9_add_validation_digit(esr_number(esr_account.esr_id, invoice.customer.id)))
123
+ esr9_format(esr9_add_validation_digit(esr_number(esr_account.esr_id, invoice.customer.id, invoice.id)))
124
124
  end
125
125
 
126
126
  def esr9_build(esr_amount, invoice, biller_id, esr_id)
127
127
  # 01 is type 'Einzahlung in CHF'
128
128
  amount_string = "01#{sprintf('%011.2f', esr_amount).delete('.')}"
129
- id_string = esr_number(esr_id, invoice.customer.id)
129
+ id_string = esr_number(esr_id, invoice.customer.id, invoice.id)
130
130
  biller_string = esr9_format_account_id(biller_id)
131
131
 
132
132
  "#{esr9_add_validation_digit(amount_string)}>#{esr9_add_validation_digit(id_string)}+ #{biller_string}>"
133
133
  end
134
134
 
135
- def esr_number(esr_id, patient_id)
136
- esr_id.to_s + sprintf('%013i', patient_id).delete(' ') + sprintf('%07i', id).delete(' ')
135
+ def esr_number(esr_id, customer_id, invoice_id)
136
+ customer_id_length = 19 - esr_id.to_s.length
137
+ esr_id.to_s + sprintf("%0#{customer_id_length}i", customer_id).delete(' ') + sprintf('%07i', invoice_id).delete(' ')
137
138
  end
138
139
 
139
140
  def esr9_add_validation_digit(value)
@@ -160,4 +161,4 @@ module Prawn
160
161
  sprintf('%02i%06i%1i', pre, main, post)
161
162
  end
162
163
  end
163
- end
164
+ end
data/vesr.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{vesr}
8
- s.version = "0.1.0"
8
+ s.version = "0.1.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = [%q{Roman Simecek}]
12
- s.date = %q{2011-10-07}
12
+ s.date = %q{2011-10-10}
13
13
  s.description = %q{VESR}
14
14
  s.email = %q{roman.simecek@cyt.ch}
15
15
  s.extra_rdoc_files = [
@@ -24,6 +24,18 @@ Gem::Specification.new do |s|
24
24
  "README.rdoc",
25
25
  "Rakefile",
26
26
  "VERSION",
27
+ "app/controllers/esr_bookings_controller.rb",
28
+ "app/models/esr_file.rb",
29
+ "app/models/esr_record.rb",
30
+ "app/views/esr_bookings/_form.html.erb",
31
+ "app/views/esr_bookings/_item.html.erb",
32
+ "app/views/esr_bookings/_list_footer.html.erb",
33
+ "app/views/esr_bookings/_list_header.html.erb",
34
+ "app/views/esr_bookings/_list_records.html.erb",
35
+ "app/views/esr_bookings/_navigation_section.html.erb",
36
+ "app/views/esr_bookings/_sidebar.html.erb",
37
+ "app/views/esr_bookings/list.html.erb",
38
+ "app/views/esr_bookings/show.html.erb",
27
39
  "lib/vesr.rb",
28
40
  "lib/vesr/prawn.rb",
29
41
  "lib/vesr/prawn/esr_recipe.rb",
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vesr
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 31
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 0
10
- version: 0.1.0
9
+ - 2
10
+ version: 0.1.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Roman Simecek
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-10-07 00:00:00 Z
18
+ date: 2011-10-10 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  requirement: &id001 !ruby/object:Gem::Requirement
@@ -122,6 +122,18 @@ files:
122
122
  - README.rdoc
123
123
  - Rakefile
124
124
  - VERSION
125
+ - app/controllers/esr_bookings_controller.rb
126
+ - app/models/esr_file.rb
127
+ - app/models/esr_record.rb
128
+ - app/views/esr_bookings/_form.html.erb
129
+ - app/views/esr_bookings/_item.html.erb
130
+ - app/views/esr_bookings/_list_footer.html.erb
131
+ - app/views/esr_bookings/_list_header.html.erb
132
+ - app/views/esr_bookings/_list_records.html.erb
133
+ - app/views/esr_bookings/_navigation_section.html.erb
134
+ - app/views/esr_bookings/_sidebar.html.erb
135
+ - app/views/esr_bookings/list.html.erb
136
+ - app/views/esr_bookings/show.html.erb
125
137
  - lib/vesr.rb
126
138
  - lib/vesr/prawn.rb
127
139
  - lib/vesr/prawn/esr_recipe.rb