has_accounts 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -43,7 +43,7 @@ class Booking < ActiveRecord::Base
43
43
  rescue ArgumentError
44
44
  end
45
45
 
46
- where("title LIKE :text OR amount = :amount OR value_date = :value_date", :text => text, :amount => amount, :value_date => date)
46
+ where("title LIKE :text OR remarks = :text OR amount = :amount OR value_date = :value_date", :text => text, :amount => amount, :value_date => date)
47
47
  }
48
48
 
49
49
  # Returns array of all years we have bookings for
@@ -0,0 +1,166 @@
1
+ class Booking < ActiveRecord::Base
2
+ # Validation
3
+ validates_presence_of :debit_account, :credit_account, :title, :amount, :value_date
4
+ validates_time :value_date
5
+
6
+ # Associations
7
+ belongs_to :debit_account, :foreign_key => 'debit_account_id', :class_name => "Account"
8
+ belongs_to :credit_account, :foreign_key => 'credit_account_id', :class_name => "Account"
9
+
10
+ # Scoping
11
+ default_scope order('value_date, id')
12
+
13
+ scope :by_value_date, lambda {|value_date| where(:value_date => value_date) }
14
+ scope :by_value_period, lambda {|from, to| where(:value_date => (from..to)) }
15
+
16
+ scope :by_account, lambda {|account_id|
17
+ { :conditions => ["debit_account_id = :account_id OR credit_account_id = :account_id", {:account_id => account_id}] }
18
+ } do
19
+ # Returns array of all booking titles.
20
+ def titles
21
+ find(:all, :group => :title).map{|booking| booking.title}
22
+ end
23
+
24
+ # Statistics per booking title.
25
+ #
26
+ # The statistics are an array of hashes with keys title, count, sum, average.
27
+ def statistics
28
+ find(:all, :select => "title, count(*) AS count, sum(amount) AS sum, avg(amount) AS avg", :group => :title).map{|stat| stat.attributes}
29
+ end
30
+ end
31
+
32
+ scope :by_text, lambda {|value|
33
+ text = '%' + value + '%'
34
+
35
+ amount = value.delete("'").to_f
36
+ if amount == 0.0
37
+ amount = nil unless value.match(/^[0.]*$/)
38
+ end
39
+
40
+ date = nil
41
+ begin
42
+ date = Date.parse(value)
43
+ rescue ArgumentError
44
+ end
45
+
46
+ where("title LIKE :text OR amount = :amount OR value_date = :value_date", :text => text, :amount => amount, :value_date => date)
47
+ }
48
+
49
+ # Returns array of all years we have bookings for
50
+ def self.fiscal_years
51
+ with_exclusive_scope do
52
+ select("DISTINCT year(value_date) AS year").all.map{|booking| booking.year}
53
+ end
54
+ end
55
+
56
+ def self.scope_by_value_date(value_date)
57
+ scoping = self.default_scoping - [@by_value_scope]
58
+
59
+ @by_value_scope = {:find => {:conditions => {:value_date => value_date}}}
60
+ scoping << @by_value_scope
61
+
62
+ Thread.current["#{self}_scoped_methods"] = nil
63
+ self.default_scoping = scoping
64
+ end
65
+
66
+ def self.filter(controller, &block)
67
+ if controller.value_date_scope
68
+ with_scope(:find => {:conditions => {:value_date => controller.value_date_scope}}, &block)
69
+ else
70
+ block.call
71
+ end
72
+ end
73
+
74
+ # Standard methods
75
+ def to_s(format = :default)
76
+ case format
77
+ when :short
78
+ "%s: %s / %s CHF %s" % [
79
+ value_date ? value_date : '?',
80
+ credit_account ? credit_account.code : '?',
81
+ debit_account ? debit_account.code : '?',
82
+ amount ? "%0.2f" % amount : '?',
83
+ ]
84
+ else
85
+ "%s: %s an %s CHF %s, %s (%s)" % [
86
+ value_date ? value_date : '?',
87
+ credit_account ? "#{credit_account.title} (#{credit_account.code})" : '?',
88
+ debit_account ? "#{debit_account.title} (#{debit_account.code})" : '?',
89
+ amount ? "%0.2f" % amount : '?',
90
+ title.present? ? title : '?',
91
+ comments.present? ? comments : '?'
92
+ ]
93
+ end
94
+ end
95
+
96
+ # Helpers
97
+ def accounted_amount(account)
98
+ if credit_account == account
99
+ balance = -(amount)
100
+ elsif debit_account == account
101
+ balance = amount
102
+ else
103
+ return BigDecimal.new('0')
104
+ end
105
+
106
+ if account.is_asset_account?
107
+ return -(balance)
108
+ else
109
+ return balance
110
+ end
111
+ end
112
+
113
+ def amount_as_string
114
+ '%0.2f' % amount
115
+ end
116
+
117
+ def amount_as_string=(value)
118
+ self.amount = value
119
+ end
120
+
121
+ def rounded_amount
122
+ if amount.nil?
123
+ return 0
124
+ else
125
+ return (amount * 20).round / 20.0
126
+ end
127
+ end
128
+
129
+ # Templates
130
+ def booking_template_id
131
+ nil
132
+ end
133
+
134
+ def booking_template_id=(value)
135
+ end
136
+
137
+ # Reference
138
+ belongs_to :reference, :polymorphic => true
139
+ after_save :notify_references
140
+
141
+ # Safety net for form assignments
142
+ def reference_type=(value)
143
+ write_attribute(:reference_type, value) unless value.blank?
144
+ end
145
+
146
+ scope :by_reference, lambda {|value|
147
+ where(:reference_id => value.id, :reference_type => value.class.base_class)
148
+ } do
149
+ # TODO duplicated in Invoice
150
+ def direct_balance(direct_account)
151
+ balance = 0.0
152
+
153
+ for booking in all
154
+ balance += booking.accounted_amount(direct_account)
155
+ end
156
+
157
+ balance
158
+ end
159
+ end
160
+
161
+ private
162
+ def notify_references
163
+ return unless reference and reference.respond_to?(:booking_saved)
164
+ reference.booking_saved(self)
165
+ end
166
+ end
@@ -34,9 +34,16 @@ module HasAccounts
34
34
  self.class.direct_account
35
35
  end
36
36
 
37
- def build_booking
38
- booking_template = BookingTemplate.find_by_code(self.class.to_s.underscore + ':invoice')
37
+ # Build booking
38
+ def build_booking(params = {}, template_code = nil)
39
+ template_code ||= self.class.to_s.underscore + ':invoice'
40
+ booking_template = BookingTemplate.find_by_code(template_code)
39
41
 
42
+ # Prepare booking parameters
43
+ booking_params = {:value_date => value_date, :amount => amount}
44
+ booking_params.merge!(params)
45
+
46
+ # Build and assign booking
40
47
  booking = booking_template.build_booking(:value_date => value_date, :amount => amount)
41
48
  bookings << booking
42
49
 
@@ -0,0 +1,51 @@
1
+ module HasAccounts
2
+ module Model
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ class_inheritable_accessor :direct_account
7
+
8
+ has_many :bookings, :as => :reference, :dependent => :destroy do
9
+ # TODO: duplicated in Booking (without parameter)
10
+ def direct_balance(value_date = nil, direct_account = nil)
11
+ return BigDecimal.new('0') unless proxy_owner.direct_account
12
+
13
+ direct_account ||= proxy_owner.direct_account
14
+ balance = BigDecimal.new('0')
15
+
16
+ direct_bookings = scoped
17
+ direct_bookings = direct_bookings.where("value_date <= ?", value_date) if value_date
18
+
19
+ for booking in direct_bookings.all
20
+ balance += booking.accounted_amount(direct_account)
21
+ end
22
+
23
+ balance
24
+ end
25
+ end
26
+ end
27
+
28
+ module ClassMethods
29
+ end
30
+
31
+ module InstanceMethods
32
+ # Delegate to class
33
+ def direct_account
34
+ self.class.direct_account
35
+ end
36
+
37
+ def build_booking
38
+ booking_template = BookingTemplate.find_by_code(self.class.to_s.underscore + ':invoice')
39
+
40
+ booking = booking_template.build_booking(:value_date => value_date, :amount => amount)
41
+ bookings << booking
42
+
43
+ booking
44
+ end
45
+
46
+ def balance(value_date = nil)
47
+ bookings.direct_balance(value_date)
48
+ end
49
+ end
50
+ end
51
+ end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 2
8
- - 2
9
- version: 0.2.2
7
+ - 3
8
+ - 0
9
+ version: 0.3.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - "Simon H\xC3\xBCrlimann (CyT)"
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-04-12 00:00:00 +02:00
17
+ date: 2011-04-13 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies: []
20
20
 
@@ -35,7 +35,9 @@ files:
35
35
  - app/models/booking.rb
36
36
  - app/models/account_type.rb
37
37
  - app/models/bank_account.rb
38
+ - app/models/booking.rb~
38
39
  - lib/has_accounts.rb
40
+ - lib/has_accounts/model.rb~
39
41
  - lib/has_accounts/class_methods.rb
40
42
  - lib/has_accounts/railtie.rb~
41
43
  - lib/has_accounts/core_ext/rounding.rb~