vesr 0.10.1 → 0.11.0

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.
Binary file
@@ -0,0 +1,15 @@
1
+ tr.esr_record.overpaid {
2
+ background-color: #FCF8E3;
3
+ }
4
+
5
+ tr.esr_record.underpaid {
6
+ background-color: #F2DEDE;
7
+ }
8
+
9
+ tr.esr_record.resolved {
10
+ background-color: #DFF0D8;
11
+ }
12
+
13
+ tr.esr_record.missing {
14
+ background-color: #D9EDF7;
15
+ }
@@ -1,2 +1,5 @@
1
1
  class EsrFilesController < AuthorizedController
2
+ before_filter :only => [:index, :show] do
3
+ EsrRecord.update_unsolved_states
4
+ end
2
5
  end
@@ -0,0 +1,50 @@
1
+ class EsrRecordsController < AuthorizedController
2
+ respond_to :html, :js
3
+
4
+ before_filter :only => [:index] do
5
+ EsrRecord.update_unsolved_states
6
+ end
7
+
8
+ # Scopes
9
+ def index
10
+ @esr_records = EsrRecord.unsolved.paginate :page => params[:page], :order => 'state, value_date'
11
+ end
12
+
13
+ # State events
14
+ def write_off
15
+ @esr_record = EsrRecord.find(params[:id])
16
+ @esr_record.invoice.write_off("Korrektur nach VESR Zahlung").save
17
+ @esr_record.write_off!
18
+
19
+ respond_to do |format|
20
+ format.js {}
21
+ format.html {redirect_to @esr_record.esr_file}
22
+ end
23
+ end
24
+
25
+ def book_extra_earning
26
+ @esr_record = EsrRecord.find(params[:id])
27
+ if invoice = @esr_record.invoice
28
+ @esr_record.invoice.book_extra_earning("Korrektur nach VESR Zahlung").save
29
+ else
30
+ @esr_record.create_extra_earning_booking
31
+ end
32
+
33
+ @esr_record.book_extra_earning!
34
+ respond_to do |format|
35
+ format.js {}
36
+ format.html {redirect_to @esr_record.esr_file}
37
+ end
38
+ end
39
+
40
+ def resolve
41
+ @esr_record = EsrRecord.find(params[:id])
42
+ @esr_record.resolve!
43
+
44
+ respond_to do |format|
45
+
46
+ format.js {}
47
+ format.html {redirect_to @esr_record.esr_file}
48
+ end
49
+ end
50
+ end
@@ -6,10 +6,14 @@ class EsrFile < ActiveRecord::Base
6
6
 
7
7
  def to_s(format = :default)
8
8
  case format
9
- when :long
10
- esr_records.map{|record| record.to_s}.join("\n")
11
- else
9
+ when :short
12
10
  "#{updated_at.strftime('%d.%m.%Y')}: #{esr_records.count} Buchungen"
11
+ else
12
+ s = ''
13
+ esr_records.each {|record|
14
+ s += record.to_s + "\n"
15
+ }
16
+ s
13
17
  end
14
18
  end
15
19
 
@@ -4,11 +4,35 @@ class EsrRecord < ActiveRecord::Base
4
4
  belongs_to :booking, :dependent => :destroy, :autosave => true
5
5
  belongs_to :invoice
6
6
 
7
- scope :valid, where(:state => 'valid')
8
- scope :missing, where(:state => 'missing')
9
- scope :bad, where(:state => 'bad')
10
- scope :invalid, where(:state => 'invalid')
11
-
7
+ # State Machine
8
+ include AASM
9
+ aasm_column :state
10
+ validates_presence_of :state
11
+
12
+ aasm_initial_state :ready
13
+ aasm_state :ready
14
+ aasm_state :paid
15
+ aasm_state :missing
16
+ aasm_state :overpaid
17
+ aasm_state :underpaid
18
+ aasm_state :resolved
19
+
20
+ aasm_event :write_off do
21
+ transitions :from => :underpaid, :to => :resolved
22
+ end
23
+
24
+ aasm_event :resolve do
25
+ transitions :from => :underpaid, :to => :resolved
26
+ end
27
+
28
+ aasm_event :book_extra_earning do
29
+ transitions :from => [:overpaid, :missing], :to => :resolved
30
+ end
31
+
32
+ scope :invalid, where(:state => ['overpaid', 'underpaid', 'resolved'])
33
+ scope :unsolved, where(:state => ['overpaid', 'underpaid', 'missing'])
34
+ scope :valid, where(:state => 'paid')
35
+
12
36
  private
13
37
  def parse_date(value)
14
38
  year = value[0..1].to_i + 2000
@@ -68,14 +92,12 @@ class EsrRecord < ActiveRecord::Base
68
92
  self
69
93
  end
70
94
 
71
- # Invoices
72
- before_create :assign_invoice, :build_esr_booking
73
-
74
- private
75
- def evaluate_bad
76
- if invoice.state == 'paid'
95
+ def update_remarks
96
+ if invoice.nil?
97
+ self.remarks += ", Rechnung ##{invoice_id} nicht gefunden"
98
+ elsif invoice.state == 'paid'
77
99
  # already paid
78
- if invoice.amount.currency_round == self.amount.currency_round
100
+ if invoice.amount == self.amount
79
101
  # paid twice
80
102
  self.remarks += ", doppelt bezahlt"
81
103
  else
@@ -83,8 +105,8 @@ class EsrRecord < ActiveRecord::Base
83
105
  end
84
106
  elsif !(invoice.active)
85
107
  # canceled invoice
86
- self.remarks += ", wurde #{invoice.state_adverb}"
87
- elsif invoice.amount.currency_round == self.amount.currency_round
108
+ self.remarks += ", wurde bereits #{invoice.state_adverb}"
109
+ elsif invoice.amount == self.amount
88
110
  # TODO much too open condition (issue #804)
89
111
  # reminder fee not paid
90
112
  self.remarks += ", Mahnspesen nicht bezahlt"
@@ -93,31 +115,44 @@ class EsrRecord < ActiveRecord::Base
93
115
  self.remarks += ", falscher Betrag"
94
116
  end
95
117
  end
118
+
119
+ def update_state
120
+ if self.invoice.nil?
121
+ self.state = 'missing'
122
+ return
123
+ end
124
+
125
+ balance = self.invoice.balance
126
+ if balance == 0
127
+ self.state = 'paid'
128
+ elsif balance > 0
129
+ self.state = 'underpaid'
130
+ elsif balance < 0
131
+ self.state = 'overpaid'
132
+ end
133
+ end
134
+
135
+ def self.update_unsolved_states
136
+ self.unsolved.find_each do |e|
137
+ e.update_state
138
+ e.save
139
+ end
140
+ end
141
+
142
+ # Invoices
143
+ before_create :assign_invoice, :create_esr_booking, :update_remarks, :update_state
96
144
 
145
+ private
97
146
  def assign_invoice
98
147
  # Prepare remarks to not be null
99
148
  self.remarks ||= ''
149
+
150
+ self.remarks += "Referenz #{reference}"
151
+
100
152
  if Invoice.exists?(invoice_id)
101
153
  self.invoice_id = invoice_id
102
- self.remarks += "Referenz #{reference}"
103
- if invoice.balance.currency_round != self.amount.currency_round
104
- evaluate_bad
105
- self.state = "bad"
106
- else
107
- self.state = "valid"
108
- end
109
154
  elsif Invoice.column_names.include?(:imported_esr_reference) && imported_invoice = Invoice.find(:first, :conditions => ["imported_esr_reference LIKE concat(?, '%')", reference])
110
155
  self.invoice = imported_invoice
111
- self.remarks += "Referenz #{reference}"
112
- if invoice.balance.currency_round != self.amount.currency_round
113
- self.remarks += ", falscher Betrag"
114
- self.state = "bad"
115
- else
116
- self.state = "valid"
117
- end
118
- else
119
- self.remarks += "Rechnung ##{invoice_id} nicht gefunden"
120
- self.state = "missing"
121
156
  end
122
157
  end
123
158
 
@@ -125,7 +160,7 @@ class EsrRecord < ActiveRecord::Base
125
160
  BankAccount.find_by_esr_id(client_id)
126
161
  end
127
162
 
128
- def build_esr_booking
163
+ def create_esr_booking
129
164
  if invoice
130
165
  esr_booking = invoice.bookings.build
131
166
  else
@@ -140,8 +175,20 @@ class EsrRecord < ActiveRecord::Base
140
175
  :title => "VESR Zahlung",
141
176
  :comments => remarks)
142
177
 
178
+ esr_booking.save
179
+
143
180
  self.booking = esr_booking
144
181
 
145
182
  return esr_booking
146
183
  end
184
+
185
+ public
186
+ def create_extra_earning_booking(comments = nil)
187
+ Booking.create(:title => "Ausserordentlicher Ertrag",
188
+ :comments => comments || "Zahlung kann keiner Rechnung zugewiesen werden",
189
+ :amount => self.amount,
190
+ :debit_account => Account.find_by_code(Invoice.settings['invoices.extra_earnings_account_code']),
191
+ :credit_account => Account.find_by_code(Invoice.settings['invoices.balance_account_code']),
192
+ :value_date => Date.today)
193
+ end
147
194
  end
@@ -1,5 +1,6 @@
1
1
  %tr[esr_file]
2
- %td= link_to esr_file.updated_at, esr_file
3
- %td.currency= esr_file.esr_records.valid.count
4
- %td.currency= esr_file.esr_records.invalid.count
5
- %td.currency= sprintf("%0.2f", esr_file.esr_records.sum(:amount) || 0.0)
2
+ %td= link_to l(esr_file.updated_at), esr_file, 'data-href-container' => 'tr'
3
+ %td.right= esr_file.esr_records.paid.count
4
+ %td.right= esr_file.esr_records.invalid.count
5
+ %td.right= esr_file.esr_records.missing.count
6
+ %td.right= currency_fmt(esr_file.esr_records.sum(:amount) || 0.0)
@@ -1,9 +1,10 @@
1
1
  %table.list#esr_file_list
2
2
  %tr
3
3
  %th= t_attr :updated_at, EsrFile
4
- %th.currency= t_attr :bookings, EsrFile
5
- %th.currency= t_attr :bad_bookings, EsrFile
6
- %th.currency= t_attr :total_amount, EsrFile
4
+ %th.right= t_attr :bookings, EsrFile
5
+ %th.right= t_attr :invalid_bookings, EsrFile
6
+ %th.right= t_attr :missing_bookings, EsrFile
7
+ %th.right= t_attr :total_amount, EsrFile
7
8
  %th.action-links
8
9
 
9
10
  = render @esr_files
@@ -1,5 +1,5 @@
1
1
  <%= navigation_section(:esr, {
2
- :esr_bookings => :esr_bookings,
3
- :new_esr => new_esr_booking_path
4
- # "Fehlerhafte Buchungen" => bad_esr_bookings_path
2
+ :esr_files => :esr_files,
3
+ :new_esr => new_esr_file_path,
4
+ :unresolved_records => esr_records_path
5
5
  }, '48x48/esr.png') %>
@@ -0,0 +1,5 @@
1
+ .contextual
2
+ = link_to t_title(:index), esr_files_path, :class => "icon icon-book"
3
+
4
+ %h2= t_title
5
+ = render 'form'
@@ -1,13 +1,20 @@
1
1
  .contextual
2
2
  = link_to_function "Protokoll drucken", 'window.print()', :class => "icon icon-print"
3
3
  = link_to "VESR Liste", esr_files_path, :class => "icon icon-book"
4
- %h2
5
- VESR Protokoll vom #{l(@esr_file.updated_at.to_date)}
6
- = render :partial => 'list_records', :object => @esr_file.esr_records.valid
7
- - unless @esr_file.esr_records.bad.empty?
4
+ = link_to t_action(:show_all), {:show_valid => true}, :class => 'icon icon-show_all' unless params['show_valid']
5
+
6
+ %h2 VESR Protokoll vom #{l(@esr_file.updated_at.to_date)}
7
+
8
+ - unless @esr_file.esr_records.invalid.empty?
8
9
  %h3 Falscher Betrag
9
- = render :partial => 'list_records', :object => @esr_file.esr_records.bad
10
+ = render 'esr_records/list', :esr_records => @esr_file.esr_records.invalid
11
+
10
12
  - unless @esr_file.esr_records.missing.empty?
11
13
  %h3 Rechnung nicht gefunden
12
- = render :partial => 'list_records', :object => @esr_file.esr_records.missing
14
+ = render 'esr_records/list', :esr_records => @esr_file.esr_records.missing
15
+
16
+ - if params['show_valid'].present?
17
+ %h3 Korrekte Zahlungen
18
+ = render 'esr_records/list', :esr_records => @esr_file.esr_records.valid
19
+
13
20
  = render :partial => 'sidebar'
@@ -0,0 +1,10 @@
1
+ %tr[esr_record]{:class => esr_record.state}
2
+ %td= esr_record.value_date
3
+ %td= link_to esr_record.invoice.customer.to_s, esr_record.invoice.customer if esr_record.invoice
4
+ %td= esr_record.invoice ? link_to(esr_record.remarks, esr_record.invoice) : esr_record.remarks
5
+ %td.currency= currency_fmt(esr_record.invoice.amount.currency_round) if esr_record.invoice
6
+ %td.currency= currency_fmt(esr_record.amount.currency_round)
7
+ %td.currency= currency_fmt(esr_record.invoice.balance.currency_round) if esr_record.invoice
8
+ %td.action-links
9
+ - esr_record.aasm_events_for_current_state.each do |event|
10
+ = link_to image_tag("16x16/#{event}.png"), polymorphic_url([event, esr_record]), :remote => true, :method => :post, :title => t_action(event)
@@ -0,0 +1,11 @@
1
+ %table.list{:style => "width: 100%"}
2
+ %tr
3
+ %th= t_attr :value_date, EsrRecord
4
+ %th= t_attr :customer, EsrRecord
5
+ %th= t_attr :state, EsrRecord
6
+ %th.currency= t_attr :amount, EsrRecord
7
+ %th.currency= t_attr :payment_amount, EsrRecord
8
+ %th.currency= t_attr :saldo, EsrRecord
9
+ %th.action-links
10
+
11
+ = render @esr_records || esr_records
@@ -0,0 +1 @@
1
+ jQuery('#esr_record_<%= @esr_record.id %>').replaceWith('<%= escape_javascript(render @esr_record) %>');
@@ -0,0 +1 @@
1
+ jQuery('#esr_record_<%= @esr_record.id %>').replaceWith('<%= escape_javascript(render @esr_record) %>');
@@ -0,0 +1 @@
1
+ jQuery('#esr_record_<%= @esr_record.id %>').replaceWith('<%= escape_javascript(render @esr_record) %>');
@@ -10,12 +10,14 @@ de:
10
10
  file: Dateiname
11
11
  updated_at: Verbucht am
12
12
  bookings: Buchungen
13
- bad_bookings: Fehlerhafte Buchungen
13
+ invalid_bookings: Fehlerhafte Buchungen
14
+ missing_bookings: Rechnung nicht gefunden
14
15
  total_amount: Total (inkl. fehlerhaft)
16
+ uploaded_data: Datei
15
17
  esr_record:
16
18
  bank_pc_id: Teilnehmer-Nr.
17
19
  reference: Referenz
18
- amount: Betrag
20
+ amount: Rechnungsbetrag
19
21
  transaction_date: Transaktionsdatum
20
22
  payment_amount: Zahlbetrag
21
23
  payment_date: Zahldatum
@@ -26,3 +28,19 @@ de:
26
28
  booking: Buchung
27
29
  state: Status
28
30
  remarks: Bemerkungen
31
+
32
+ # Titles
33
+ esr_files:
34
+ new:
35
+ title: VESR Datei einlesen
36
+ index:
37
+ index: VESR Liste
38
+
39
+ # CRUD
40
+ crud:
41
+ action:
42
+ show_all: Alle anzeigen
43
+ reactivate: Reaktivieren
44
+ write_off: Abschreiben
45
+ book_extra_earning: Ausserordentlicher Gewinn verbuchen
46
+ resolve: Als erledigt markieren
data/config/routes.rb CHANGED
@@ -1,3 +1,8 @@
1
1
  Rails.application.routes.draw do
2
2
  resources :esr_files
3
+ resources :esr_records do
4
+ member do
5
+ post :write_off, :book_extra_earning, :resolve
6
+ end
7
+ end
3
8
  end
data/lib/vesr/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Vesr
2
- VERSION = "0.10.1"
2
+ VERSION = "0.11.0"
3
3
  end
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: 53
4
+ hash: 51
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 10
9
- - 1
10
- version: 0.10.1
8
+ - 11
9
+ - 0
10
+ version: 0.11.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Roman Simecek
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2012-02-04 00:00:00 Z
19
+ date: 2012-03-02 00:00:00 Z
20
20
  dependencies: []
21
21
 
22
22
  description: VESR provides support for ESR number calculations and gives ready to use Rails components.
@@ -31,7 +31,14 @@ extra_rdoc_files:
31
31
  - README.rdoc
32
32
  - LICENSE.txt
33
33
  files:
34
+ - app/assets/images/16x16/book_extra_earning.png
35
+ - app/assets/images/16x16/reactivate.png
36
+ - app/assets/images/16x16/resolve.png
37
+ - app/assets/images/16x16/show_all.png
38
+ - app/assets/images/16x16/write_off.png
39
+ - app/assets/stylesheets/vesr.css
34
40
  - app/controllers/esr_files_controller.rb
41
+ - app/controllers/esr_records_controller.rb
35
42
  - app/models/esr_file.rb
36
43
  - app/models/esr_record.rb
37
44
  - app/uploaders/esr_file_uploader.rb
@@ -40,7 +47,13 @@ files:
40
47
  - app/views/esr_files/_list_records.html.haml
41
48
  - app/views/esr_files/_navigation_section.html.erb
42
49
  - app/views/esr_files/_sidebar.html.haml
50
+ - app/views/esr_files/new.html.haml
43
51
  - app/views/esr_files/show.html.haml
52
+ - app/views/esr_records/_esr_record.html.haml
53
+ - app/views/esr_records/_list.html.haml
54
+ - app/views/esr_records/book_extra_earning.js.erb
55
+ - app/views/esr_records/resolve.js.erb
56
+ - app/views/esr_records/write_off.js.erb
44
57
  - config/locales/de.yml
45
58
  - config/routes.rb
46
59
  - db/migrate/1_create_vesr_tables.rb
@@ -81,7 +94,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
81
94
  requirements: []
82
95
 
83
96
  rubyforge_project:
84
- rubygems_version: 1.8.15
97
+ rubygems_version: 1.8.10
85
98
  signing_key:
86
99
  specification_version: 3
87
100
  summary: VESR invoice support library.