has_accounts 0.2.1 → 0.2.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/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)