has_accounts 0.2.2 → 0.3.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.
@@ -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~