has_accounts 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -9,7 +9,7 @@ Install
9
9
 
10
10
  In Rails 3 simply add
11
11
 
12
- gem 'has_accounts'
12
+ gem 'has_accounts'
13
13
 
14
14
 
15
15
  Example
@@ -17,24 +17,24 @@ Example
17
17
 
18
18
  A few models are available:
19
19
 
20
- class Booking
21
- class Account
22
- class AccountType
20
+ class Booking
21
+ class Account
22
+ class AccountType
23
23
 
24
24
  There's also a ready to use module available to attach accountable
25
25
  functionality to existing models.
26
26
 
27
27
  To use it, simply add the following to your Model:
28
28
 
29
- include HasAccounts::Model
29
+ include HasAccounts::Model
30
30
 
31
31
 
32
32
  License
33
33
  =======
34
34
 
35
- Copyright (c) 2008 Agrabah <http://www.agrabah.ch>
36
- Copyright (c) 2008-2011 Simon Hürlimann <simon.huerlimann@cyt.ch>
37
- Copyright (c) 2010-2011 CyT <http://www.cyt.ch>
38
- Copyright (c) 2008-2010 ZytoLabor <http://www.zyto-labor.com>
35
+ * Copyright (c) 2008 Agrabah <http://www.agrabah.ch>
36
+ * Copyright (c) 2008-2011 Simon Hürlimann <simon.huerlimann@cyt.ch>
37
+ * Copyright (c) 2010-2011 CyT <http://www.cyt.ch>
38
+ * Copyright (c) 2008-2010 ZytoLabor <http://www.zyto-labor.com>
39
39
 
40
40
  Released under the MIT license.
@@ -83,8 +83,16 @@ class Account < ActiveRecord::Base
83
83
  }]
84
84
  end
85
85
  elsif
86
- # TODO support inclusive param
87
- condition = {:value_date => selector}
86
+ if selector.first == selector.last
87
+ condition = ["date(value_date) = :value_date", {
88
+ :value_date => selector.first
89
+ }]
90
+ else
91
+ condition = ["date(value_date) BETWEEN :first_value_date AND :latest_value_date", {
92
+ :first_value_date => selector.first,
93
+ :latest_value_date => selector.last
94
+ }]
95
+ end
88
96
  end
89
97
  else
90
98
  if selector.is_a? Booking
@@ -93,7 +101,7 @@ class Account < ActiveRecord::Base
93
101
  condition = ["(value_date < :value_date) OR (date(value_date) = :value_date AND id <#{equality} :id)", {:value_date => selector.value_date, :id => selector.id}]
94
102
  else
95
103
  equality = "=" if inclusive
96
- condition = ["value_date <#{equality} ?", selector]
104
+ condition = ["date(value_date) <#{equality} ?", selector]
97
105
  end
98
106
  end
99
107
 
@@ -0,0 +1,113 @@
1
+ class Account < ActiveRecord::Base
2
+ # Scopes
3
+ default_scope :order => 'code'
4
+
5
+ # Dummy scope to make scoped_by happy
6
+ scope :by_value_period, scoped
7
+
8
+ # Validation
9
+ validates_presence_of :code, :title
10
+
11
+ # String
12
+ def to_s(format = :default)
13
+ "%s (%s)" % [title, code]
14
+ end
15
+
16
+ # Account Type
17
+ # ============
18
+ belongs_to :account_type
19
+
20
+ def is_asset_account?
21
+ [1, 2, 5].include? account_type_id
22
+ end
23
+
24
+ def is_liability_account?
25
+ [3, 4, 6].include? account_type_id
26
+ end
27
+
28
+ scope :current_assets, where('account_type_id = 1') do
29
+ include AccountScopeExtension
30
+ end
31
+ scope :capital_assets, where('account_type_id = 2') do
32
+ include AccountScopeExtension
33
+ end
34
+ scope :outside_capital, where('account_type_id = 3') do
35
+ include AccountScopeExtension
36
+ end
37
+ scope :equity_capital, where('account_type_id = 4') do
38
+ include AccountScopeExtension
39
+ end
40
+ scope :expenses, where('account_type_id = 5') do
41
+ include AccountScopeExtension
42
+ end
43
+ scope :earnings, where('account_type_id = 6') do
44
+ include AccountScopeExtension
45
+ end
46
+
47
+ # Holder
48
+ # ======
49
+ belongs_to :holder, :polymorphic => true
50
+
51
+ # Bookings
52
+ # ========
53
+ has_many :credit_bookings, :class_name => "Booking", :foreign_key => "credit_account_id"
54
+ has_many :debit_bookings, :class_name => "Booking", :foreign_key => "debit_account_id"
55
+
56
+ def bookings
57
+ Booking.by_account(id)
58
+ end
59
+
60
+ # Helpers
61
+ # =======
62
+ def self.overview(value_range = Date.today, format = :default)
63
+ Account.all.map{|a| a.to_s(value_range, format)}
64
+ end
65
+
66
+ # Calculations
67
+ def turnover(selector = Date.today, inclusive = true)
68
+ if selector.is_a? Range or selector.is_a? Array
69
+ if selector.first.is_a? Booking
70
+ equality = "=" if inclusive
71
+ if selector.first.value_date == selector.last.value_date
72
+ condition = ["date(value_date) = :value_date AND id >#{equality} :first_id AND id <#{equality} :last_id", {
73
+ :value_date => selector.first.value_date,
74
+ :first_id => selector.first.id,
75
+ :last_id => selector.last.id
76
+ }]
77
+ else
78
+ condition = ["(value_date > :first_value_date AND value_date < :latest_value_date) OR (date(value_date) = :first_value_date AND id >#{equality} :first_id) OR (date(value_date) = :latest_value_date AND id <#{equality} :last_id)", {
79
+ :first_value_date => selector.first.value_date,
80
+ :latest_value_date => selector.last.value_date,
81
+ :first_id => selector.first.id,
82
+ :last_id => selector.last.id
83
+ }]
84
+ end
85
+ elsif
86
+ # TODO support inclusive param
87
+ condition = {:value_date => selector}
88
+ end
89
+ else
90
+ if selector.is_a? Booking
91
+ equality = "=" if inclusive
92
+ # date(value_date) is needed on sqlite!
93
+ condition = ["(value_date < :value_date) OR (date(value_date) = :value_date AND id <#{equality} :id)", {:value_date => selector.value_date, :id => selector.id}]
94
+ else
95
+ equality = "=" if inclusive
96
+ condition = ["value_date <#{equality} ?", selector]
97
+ end
98
+ end
99
+
100
+ credit_amount = credit_bookings.where(condition).sum(:amount)
101
+ debit_amount = debit_bookings.where(condition).sum(:amount)
102
+
103
+ [credit_amount || 0.0, debit_amount || 0.0]
104
+ end
105
+
106
+ def saldo(selector = Date.today, inclusive = true)
107
+ credit_amount, debit_amount = turnover(selector, inclusive)
108
+
109
+ amount = credit_amount - debit_amount
110
+
111
+ return is_asset_account? ? amount : -amount
112
+ end
113
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 2
8
- - 1
9
- version: 0.2.1
8
+ - 2
9
+ version: 0.2.2
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-11 00:00:00 +02:00
17
+ date: 2011-04-12 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies: []
20
20
 
@@ -28,15 +28,14 @@ extensions: []
28
28
  extra_rdoc_files: []
29
29
 
30
30
  files:
31
+ - app/models/account.rb~
31
32
  - app/models/account_scope_extension.rb
32
33
  - app/models/bank.rb
33
34
  - app/models/account.rb
34
35
  - app/models/booking.rb
35
36
  - app/models/account_type.rb
36
37
  - app/models/bank_account.rb
37
- - lib/has_accounts.rb~
38
38
  - lib/has_accounts.rb
39
- - lib/booking.rb~
40
39
  - lib/has_accounts/class_methods.rb
41
40
  - lib/has_accounts/railtie.rb~
42
41
  - lib/has_accounts/core_ext/rounding.rb~
data/lib/booking.rb~ DELETED
@@ -1,92 +0,0 @@
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
- belongs_to :debit_account, :foreign_key => 'debit_account_id', :class_name => "Account"
7
- belongs_to :credit_account, :foreign_key => 'credit_account_id', :class_name => "Account"
8
-
9
- # Scoping
10
- named_scope :by_value_date, lambda {|value_date| { :conditions => { :value_date => value_date } } }
11
- named_scope :by_value_period, lambda {|from, to| { :conditions => { :value_date => from..to } } }
12
-
13
- named_scope :by_account, lambda {|account_id|
14
- { :conditions => ["debit_account_id = :account_id OR credit_account_id = :account_id", {:account_id => account_id}] }
15
- } do
16
- # Returns array of all booking titles.
17
- def titles
18
- find(:all, :group => :title).map{|booking| booking.title}
19
- end
20
-
21
- # Statistics per booking title.
22
- #
23
- # The statistics are an array of hashes with keys title, count, sum, average.
24
- def statistics
25
- find(:all, :select => "title, count(*) AS count, sum(amount) AS sum, avg(amount) AS avg", :group => :title).map{|stat| stat.attributes}
26
- end
27
- end
28
-
29
- # Returns array of all years we have bookings for
30
- def self.fiscal_years
31
- with_exclusive_scope do
32
- find(:all, :select => "year(value_date) AS year", :group => "year(value_date)").map{|booking| booking.year}
33
- end
34
- end
35
-
36
- def self.scope_by_value_date(value_date)
37
- scoping = self.default_scoping - [@by_value_scope]
38
-
39
- @by_value_scope = {:find => {:conditions => {:value_date => value_date}}}
40
- scoping << @by_value_scope
41
-
42
- Thread.current["#{self}_scoped_methods"] = nil
43
- self.default_scoping = scoping
44
- end
45
-
46
- def self.filter(controller, &block)
47
- if controller.value_date_scope
48
- with_scope(:find => {:conditions => {:value_date => controller.value_date_scope}}, &block)
49
- else
50
- block.call
51
- end
52
- end
53
-
54
- # Standard methods
55
- def to_s(format = :default)
56
- case format
57
- when :short
58
- "#{value_date.strftime('%d.%m.%Y')}: #{credit_account.code} / #{debit_account.code} CHF #{amount_as_string} "
59
- else
60
- "#{value_date.strftime('%d.%m.%Y')}: #{credit_account.title} (#{credit_account.code}) an #{debit_account.title} (#{debit_account.code}) CHF #{amount_as_string}, #{title} " +
61
- (comments.blank? ? "" :"(#{comments})")
62
- end
63
- end
64
-
65
- # Helpers
66
- def accounted_amount(account)
67
- if credit_account == account
68
- return amount
69
- elsif debit_account == account
70
- return -(amount)
71
- else
72
- return 0.0
73
- end
74
- end
75
-
76
- def amount_as_string
77
- '%0.2f' % amount
78
- end
79
-
80
- def amount_as_string=(value)
81
- self.amount = value
82
- end
83
-
84
- # Reference
85
- belongs_to :reference, :polymorphic => true
86
- after_save :notify_references
87
-
88
- private
89
- def notify_references
90
- reference.booking_saved(self) if reference.respond_to?(:booking_saved)
91
- end
92
- end
data/lib/has_accounts.rb~ DELETED
@@ -1,3 +0,0 @@
1
- require 'has_accounts/model'
2
-
3
- require 'has_accounts/railtie' if defined?(::Rails::Railtie)