has_accounts 0.8.3 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -33,7 +33,13 @@ class Booking < ActiveRecord::Base
33
33
  default_scope order('value_date, id')
34
34
 
35
35
  scope :by_value_date, lambda {|value_date| where("date(value_date) = ?", value_date) }
36
- scope :by_value_period, lambda {|from, to| where("date(value_date) BETWEEN :from AND :to", :from => from, :to => to) }
36
+ scope :by_value_period, lambda {|from, to|
37
+ if from.present?
38
+ where("date(value_date) BETWEEN :from AND :to", :from => from, :to => to)
39
+ else
40
+ where("date(value_date) <= :to", :to => to)
41
+ end
42
+ }
37
43
 
38
44
  scope :by_account, lambda {|account_id|
39
45
  { :conditions => ["debit_account_id = :account_id OR credit_account_id = :account_id", {:account_id => account_id}] }
@@ -0,0 +1,3 @@
1
+ module HasAccounts
2
+ VERSION = "0.9.0"
3
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: has_accounts
3
3
  version: !ruby/object:Gem::Version
4
- hash: 57
5
- prerelease:
4
+ hash: 59
5
+ prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 8
9
- - 3
10
- version: 0.8.3
8
+ - 9
9
+ - 0
10
+ version: 0.9.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - "Simon H\xC3\xBCrlimann (CyT)"
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-07-06 00:00:00 +02:00
18
+ date: 2011-07-27 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
@@ -26,31 +26,26 @@ executables: []
26
26
 
27
27
  extensions: []
28
28
 
29
- extra_rdoc_files: []
30
-
29
+ extra_rdoc_files:
30
+ - README.md
31
31
  files:
32
+ - app/models/account.rb
32
33
  - app/models/account_scope_extension.rb
33
- - app/models/booking.rb~
34
+ - app/models/account_type.rb
34
35
  - app/models/bank.rb
35
- - app/models/account.rb
36
36
  - app/models/bank_account.rb
37
- - app/models/account_type.rb
38
37
  - app/models/booking.rb
39
- - app/models/account.rb~
40
- - lib/has_accounts/railtie.rb
38
+ - lib/generators/has_accounts/migration_generator.rb
39
+ - lib/generators/has_accounts/templates/migration.rb
40
+ - lib/has_accounts.rb
41
41
  - lib/has_accounts/class_methods.rb
42
42
  - lib/has_accounts/core_ext/rounding.rb
43
43
  - lib/has_accounts/model.rb
44
- - lib/has_accounts.rb
45
- - lib/generators/has_accounts/migration_generator.rb
46
- - lib/generators/has_accounts/templates/migration.rb~
47
- - lib/generators/has_accounts/templates/migration.rb
48
- - lib/generators/migration_generator.rb~
49
- - MIT-LICENSE
50
- - Rakefile
44
+ - lib/has_accounts/railtie.rb
45
+ - lib/has_accounts/version.rb
51
46
  - README.md
52
47
  has_rdoc: true
53
- homepage:
48
+ homepage: https://github.com/huerlisi/has_accounts
54
49
  licenses: []
55
50
 
56
51
  post_install_message:
@@ -79,7 +74,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
79
74
  requirements: []
80
75
 
81
76
  rubyforge_project:
82
- rubygems_version: 1.5.2
77
+ rubygems_version: 1.3.7
83
78
  signing_key:
84
79
  specification_version: 3
85
80
  summary: HasAccounts provides models for financial accounting.
data/MIT-LICENSE DELETED
@@ -1,20 +0,0 @@
1
- Copyright (c) 2008 [name of plugin creator]
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile DELETED
@@ -1,26 +0,0 @@
1
- # encoding: UTF-8
2
- require 'rubygems'
3
- begin
4
- require 'bundler/setup'
5
- rescue LoadError
6
- puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
- end
8
-
9
- require 'rake'
10
- require 'rdoc/task'
11
-
12
- require 'rspec/core'
13
- require 'rspec/core/rake_task'
14
-
15
- RSpec::Core::RakeTask.new(:spec)
16
-
17
- task :default => :spec
18
-
19
- desc 'Generate documentation for the has_accounts plugin.'
20
- Rake::RDocTask.new(:rdoc) do |rdoc|
21
- rdoc.rdoc_dir = 'rdoc'
22
- rdoc.title = 'Accounting'
23
- rdoc.options << '--line-numbers' << '--inline-source'
24
- rdoc.rdoc_files.include('README')
25
- rdoc.rdoc_files.include('lib/**/*.rb')
26
- end
@@ -1,107 +0,0 @@
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
- validates_presence_of :account_type
20
-
21
- def is_asset_account?
22
- Account.by_type(['current_assets', 'capital_assets', 'costs']).exists?(self)
23
- end
24
-
25
- def is_liability_account?
26
- !is_asset_account?
27
- end
28
-
29
- scope :by_type, lambda {|value| includes(:account_type).where('account_types.name' => value)} do
30
- include AccountScopeExtension
31
- end
32
-
33
- # Holder
34
- # ======
35
- belongs_to :holder, :polymorphic => true
36
-
37
- # Bookings
38
- # ========
39
- has_many :credit_bookings, :class_name => "Booking", :foreign_key => "credit_account_id"
40
- has_many :debit_bookings, :class_name => "Booking", :foreign_key => "debit_account_id"
41
-
42
- def bookings
43
- Booking.by_account(id)
44
- end
45
-
46
- # Helpers
47
- # =======
48
- def self.overview(value_range = Date.today, format = :default)
49
- Account.all.map{|a| a.to_s(value_range, format)}
50
- end
51
-
52
- # Calculations
53
- def turnover(selector = Date.today, inclusive = true)
54
- if selector.is_a? Range or selector.is_a? Array
55
- if selector.first.is_a? Booking
56
- equality = "=" if inclusive
57
- if selector.first.value_date == selector.last.value_date
58
- condition = ["date(value_date) = :value_date AND id >#{equality} :first_id AND id <#{equality} :last_id", {
59
- :value_date => selector.first.value_date,
60
- :first_id => selector.first.id,
61
- :last_id => selector.last.id
62
- }]
63
- else
64
- 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)", {
65
- :first_value_date => selector.first.value_date,
66
- :latest_value_date => selector.last.value_date,
67
- :first_id => selector.first.id,
68
- :last_id => selector.last.id
69
- }]
70
- end
71
- elsif
72
- if selector.first == selector.last
73
- condition = ["date(value_date) = :value_date", {
74
- :value_date => selector.first
75
- }]
76
- else
77
- condition = ["date(value_date) BETWEEN :first_value_date AND :latest_value_date", {
78
- :first_value_date => selector.first,
79
- :latest_value_date => selector.last
80
- }]
81
- end
82
- end
83
- else
84
- if selector.is_a? Booking
85
- equality = "=" if inclusive
86
- # date(value_date) is needed on sqlite!
87
- condition = ["(value_date < :value_date) OR (date(value_date) = :value_date AND id <#{equality} :id)", {:value_date => selector.value_date, :id => selector.id}]
88
- else
89
- equality = "=" if inclusive
90
- condition = ["date(value_date) <#{equality} ?", selector]
91
- end
92
- end
93
-
94
- credit_amount = credit_bookings.where(condition).sum(:amount)
95
- debit_amount = debit_bookings.where(condition).sum(:amount)
96
-
97
- [credit_amount || 0.0, debit_amount || 0.0]
98
- end
99
-
100
- def saldo(selector = Date.today, inclusive = true)
101
- credit_amount, debit_amount = turnover(selector, inclusive)
102
-
103
- amount = credit_amount - debit_amount
104
-
105
- return is_asset_account? ? amount : -amount
106
- end
107
- end
@@ -1,186 +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
- # Account
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
- def direct_account
11
- return nil unless reference
12
-
13
- return reference.direct_account if reference.respond_to? :direct_account
14
- end
15
-
16
- def contra_account(account = nil)
17
- # Derive from direct_account if available
18
- account ||= direct_account
19
-
20
- return unless account
21
-
22
- if debit_account == account
23
- return credit_account
24
- elsif credit_account == account
25
- return debit_account
26
- else
27
- return nil
28
- end
29
- end
30
-
31
- # Scoping
32
- default_scope order('value_date, id')
33
-
34
- scope :by_value_date, lambda {|value_date| where("date(value_date) = ?", value_date) }
35
- scope :by_value_period, lambda {|from, to| where("date(value_date) BETWEEN :from AND :to", :from => from, :to => to) }
36
-
37
- scope :by_account, lambda {|account_id|
38
- { :conditions => ["debit_account_id = :account_id OR credit_account_id = :account_id", {:account_id => account_id}] }
39
- } do
40
- # Returns array of all booking titles.
41
- def titles
42
- find(:all, :group => :title).map{|booking| booking.title}
43
- end
44
-
45
- # Statistics per booking title.
46
- #
47
- # The statistics are an array of hashes with keys title, count, sum, average.
48
- def statistics
49
- find(:all, :select => "title, count(*) AS count, sum(amount) AS sum, avg(amount) AS avg", :group => :title).map{|stat| stat.attributes}
50
- end
51
- end
52
-
53
- scope :by_text, lambda {|value|
54
- text = '%' + value + '%'
55
-
56
- amount = value.delete("'").to_f
57
- if amount == 0.0
58
- amount = nil unless value.match(/^[0.]*$/)
59
- end
60
-
61
- date = nil
62
- begin
63
- date = Date.parse(value)
64
- rescue ArgumentError
65
- end
66
-
67
- where("title LIKE :text OR comments LIKE :text OR amount = :amount OR value_date = :value_date", :text => text, :amount => amount, :value_date => date)
68
- }
69
-
70
- # Returns array of all years we have bookings for
71
- def self.fiscal_years
72
- with_exclusive_scope do
73
- select("DISTINCT year(value_date) AS year").all.map{|booking| booking.year}
74
- end
75
- end
76
-
77
- # Standard methods
78
- def to_s(format = :default)
79
- case format
80
- when :short
81
- "%s: %s / %s CHF %s" % [
82
- value_date ? value_date : '?',
83
- credit_account ? credit_account.code : '?',
84
- debit_account ? debit_account.code : '?',
85
- amount ? "%0.2f" % amount : '?',
86
- ]
87
- else
88
- "%s: %s an %s CHF %s, %s (%s)" % [
89
- value_date ? value_date : '?',
90
- credit_account ? "#{credit_account.title} (#{credit_account.code})" : '?',
91
- debit_account ? "#{debit_account.title} (#{debit_account.code})" : '?',
92
- amount ? "%0.2f" % amount : '?',
93
- title.present? ? title : '?',
94
- comments.present? ? comments : '?'
95
- ]
96
- end
97
- end
98
-
99
- # Helpers
100
- def accounted_amount(account)
101
- if credit_account == account
102
- balance = -(amount)
103
- elsif debit_account == account
104
- balance = amount
105
- else
106
- return BigDecimal.new('0')
107
- end
108
-
109
- if account.is_asset_account?
110
- return -(balance)
111
- else
112
- return balance
113
- end
114
- end
115
-
116
- def amount_as_string
117
- '%0.2f' % amount
118
- end
119
-
120
- def amount_as_string=(value)
121
- self.amount = value
122
- end
123
-
124
- def rounded_amount
125
- if amount.nil?
126
- return 0
127
- else
128
- return (amount * 20).round / 20.0
129
- end
130
- end
131
-
132
- # Templates
133
- def booking_template_id
134
- nil
135
- end
136
-
137
- def booking_template_id=(value)
138
- end
139
-
140
- # Helpers
141
- def split(amount, params = {})
142
- # Clone
143
- new_booking = self.clone
144
-
145
- # Set amount
146
- new_booking[:amount] = amount
147
- self.amount -= amount
148
-
149
- # Update attributes
150
- params.each{|key, value|
151
- new_booking[key] = value
152
- }
153
-
154
- [self, new_booking]
155
- end
156
-
157
- # Reference
158
- belongs_to :reference, :polymorphic => true
159
- after_save :notify_references
160
-
161
- # Safety net for form assignments
162
- def reference_type=(value)
163
- write_attribute(:reference_type, value) unless value.blank?
164
- end
165
-
166
- scope :by_reference, lambda {|value|
167
- where(:reference_id => value.id, :reference_type => value.class.base_class)
168
- } do
169
- # TODO duplicated in Invoice
170
- def direct_balance(direct_account)
171
- balance = 0.0
172
-
173
- for booking in all
174
- balance += booking.accounted_amount(direct_account)
175
- end
176
-
177
- balance
178
- end
179
- end
180
-
181
- private
182
- def notify_references
183
- return unless reference and reference.respond_to?(:booking_saved)
184
- reference.booking_saved(self)
185
- end
186
- end
@@ -1,59 +0,0 @@
1
- class SetupHasAccountsEngine < ActiveRecord::Migration
2
- def self.up
3
- create_table "account_types", :force => true do |t|
4
- t.string "name", :limit => 100
5
- t.string "title", :limit => 100
6
- t.datetime "created_at"
7
- t.datetime "updated_at"
8
- end
9
-
10
- create_table "accounts", :force => true do |t|
11
- t.string "title", :limit => 100
12
- t.integer "parent_id"
13
- t.integer "account_type_id"
14
- t.integer "number"
15
- t.string "code"
16
- t.integer "type"
17
- t.integer "holder_id"
18
- t.string "holder_type"
19
- t.integer "bank_id"
20
- t.integer "esr_id"
21
- t.integer "pc_id"
22
- t.datetime "created_at"
23
- t.datetime "updated_at"
24
- end
25
-
26
- add_index "accounts", ["bank_id"], :name => "index_accounts_on_bank_id"
27
- add_index "accounts", ["code"], :name => "index_accounts_on_code"
28
- add_index "accounts", ["holder_id", "holder_type"], :name => "index_accounts_on_holder_id_and_holder_type"
29
- add_index "accounts", ["type"], :name => "index_accounts_on_type"
30
-
31
- create_table "banks", :force => true do |t|
32
- t.integer "vcard_id"
33
- t.datetime "created_at"
34
- t.datetime "updated_at"
35
- end
36
-
37
- create_table "bookings", :force => true do |t|
38
- t.string "title", :limit => 100
39
- t.decimal "amount"
40
- t.integer "credit_account_id"
41
- t.integer "debit_account_id"
42
- t.date "value_date"
43
- t.text "comments", :limit => 1000, :default => ""
44
- t.string "scan"
45
- t.string "debit_currency", :default => "CHF"
46
- t.string "credit_currency", :default => "CHF"
47
- t.float "exchange_rate", :default => 1.0
48
- t.datetime "created_at"
49
- t.datetime "updated_at"
50
- t.integer "reference_id"
51
- t.string "reference_type"
52
- end
53
- end
54
-
55
- def self.down
56
- drop_table :account_types, :accounts, :banks, :bookings
57
- end
58
- end
59
-
@@ -1,27 +0,0 @@
1
- require 'rails/generators/base'
2
- require 'rails/generators/migration'
3
-
4
- module HasVcards
5
- class MigrationGenerator < Rails::Generators::Base
6
- include Rails::Generators::Migration
7
-
8
- def self.source_root
9
- @source_root ||= File.join(File.dirname(__FILE__), 'templates')
10
- end
11
-
12
- # Implement the required interface for Rails::Generators::Migration.
13
- # taken from http://github.com/rails/rails/blob/master/activerecord/lib/generators/active_record.rb
14
- def self.next_migration_number(dirname)
15
- if ActiveRecord::Base.timestamped_migrations
16
- Time.now.utc.strftime("%Y%m%d%H%M%S")
17
- else
18
- "%.3d" % (current_migration_number(dirname) + 1)
19
- end
20
- end
21
-
22
- def create_migration_file
23
- migration_template 'migration.rb', 'db/migrate/create_has_vcards.rb'
24
- end
25
-
26
- end
27
- end