keepr 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.travis.yml +9 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +62 -0
- data/Rakefile +6 -0
- data/ci/Gemfile-rails-4-1 +11 -0
- data/ci/Gemfile-rails-4-2 +11 -0
- data/keepr.gemspec +31 -0
- data/lib/generators/keepr/migration/migration_generator.rb +23 -0
- data/lib/generators/keepr/migration/templates/migration.rb +72 -0
- data/lib/keepr.rb +15 -0
- data/lib/keepr/account.rb +120 -0
- data/lib/keepr/active_record_extension.rb +27 -0
- data/lib/keepr/cost_center.rb +8 -0
- data/lib/keepr/group.rb +33 -0
- data/lib/keepr/groups_creator.rb +51 -0
- data/lib/keepr/groups_creator/asset.txt +36 -0
- data/lib/keepr/groups_creator/liability.txt +28 -0
- data/lib/keepr/groups_creator/profit_and_loss.txt +31 -0
- data/lib/keepr/journal.rb +48 -0
- data/lib/keepr/posting.rb +74 -0
- data/lib/keepr/tax.rb +13 -0
- data/lib/keepr/version.rb +3 -0
- data/spec/account_spec.rb +210 -0
- data/spec/active_record_extension_spec.rb +60 -0
- data/spec/cost_center_spec.rb +16 -0
- data/spec/database.yml +3 -0
- data/spec/factories/account.rb +7 -0
- data/spec/factories/cost_center.rb +6 -0
- data/spec/factories/group.rb +6 -0
- data/spec/factories/tax.rb +8 -0
- data/spec/group_spec.rb +89 -0
- data/spec/groups_creator_spec.rb +45 -0
- data/spec/journal_spec.rb +111 -0
- data/spec/posting_spec.rb +124 -0
- data/spec/spec_helper.rb +58 -0
- data/spec/support/document.rb +3 -0
- data/spec/support/ledger.rb +3 -0
- data/spec/support/spec_migration.rb +16 -0
- data/spec/tax_spec.rb +35 -0
- metadata +213 -0
@@ -0,0 +1,8 @@
|
|
1
|
+
class Keepr::CostCenter < ActiveRecord::Base
|
2
|
+
self.table_name = 'keepr_cost_centers'
|
3
|
+
|
4
|
+
validates_presence_of :number, :name
|
5
|
+
validates_uniqueness_of :number
|
6
|
+
|
7
|
+
has_many :keepr_postings, :class_name => 'Keepr::Posting', :foreign_key => 'keepr_cost_center_id', :dependent => :restrict_with_error
|
8
|
+
end
|
data/lib/keepr/group.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
class Keepr::Group < ActiveRecord::Base
|
2
|
+
self.table_name = 'keepr_groups'
|
3
|
+
|
4
|
+
has_ancestry :orphan_strategy => :restrict
|
5
|
+
|
6
|
+
enum :target => [ :asset, :liability, :profit_and_loss ]
|
7
|
+
|
8
|
+
validates_presence_of :name
|
9
|
+
|
10
|
+
has_many :keepr_accounts, :class_name => 'Keepr::Account', :foreign_key => 'keepr_group_id', :dependent => :restrict_with_error
|
11
|
+
|
12
|
+
before_validation :get_from_parent
|
13
|
+
|
14
|
+
def self.result
|
15
|
+
where(:is_result => true).first
|
16
|
+
end
|
17
|
+
|
18
|
+
def keepr_postings
|
19
|
+
if is_result
|
20
|
+
Keepr::Posting.joins(:keepr_account).where(:keepr_accounts => { :kind => [ Keepr::Account.kinds[:revenue],
|
21
|
+
Keepr::Account.kinds[:expense] ] })
|
22
|
+
else
|
23
|
+
Keepr::Posting.joins(:keepr_account => :keepr_group).merge(self.subtree)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
def get_from_parent
|
29
|
+
if self.parent
|
30
|
+
self.target = self.parent.target
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class Keepr::GroupsCreator
|
3
|
+
def initialize(target)
|
4
|
+
@target = target
|
5
|
+
end
|
6
|
+
|
7
|
+
def run
|
8
|
+
case @target
|
9
|
+
when :balance then
|
10
|
+
load 'asset.txt', :target => :asset
|
11
|
+
load 'liability.txt', :target => :liability
|
12
|
+
when :profit_and_loss
|
13
|
+
load 'profit_and_loss.txt', :target => :profit_and_loss
|
14
|
+
else
|
15
|
+
raise ArgumentError
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
def load(filename, options)
|
21
|
+
full_filename = File.join(File.dirname(__FILE__), "groups_creator/#{filename}".downcase)
|
22
|
+
lines = File.readlines(full_filename)
|
23
|
+
last_depth = 0
|
24
|
+
parents = []
|
25
|
+
|
26
|
+
lines.each do |line|
|
27
|
+
# Count leading spaces to calc hierarchy depth
|
28
|
+
depth = line[/\A */].size / 2
|
29
|
+
|
30
|
+
# Remove leading spaces and separate number and name
|
31
|
+
number, name = line.lstrip.match(/^(.*?)\s(.+)$/).to_a[1..-1]
|
32
|
+
|
33
|
+
attributes = options.merge(:name => name, :number => number)
|
34
|
+
if @target == :balance && name == 'Jahresüberschuss/Jahresfehlbetrag'
|
35
|
+
attributes[:is_result] = true
|
36
|
+
end
|
37
|
+
|
38
|
+
if depth == 0
|
39
|
+
parents = []
|
40
|
+
group = Keepr::Group.create!(attributes)
|
41
|
+
else
|
42
|
+
parents.pop if depth <= last_depth
|
43
|
+
parents.pop if depth < last_depth
|
44
|
+
group = parents.last.children.create!(attributes)
|
45
|
+
end
|
46
|
+
parents.push(group)
|
47
|
+
|
48
|
+
last_depth = depth
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
A. Anlagevermögen
|
2
|
+
I. Immaterielle Vermögensgegenstände
|
3
|
+
1. Selbst geschaffene gewerbliche Schutzrechte und ähnliche Rechte und Werte
|
4
|
+
2. entgeltlich erworbene Konzessionen, gewerbliche Schutzrechte und ähnliche Rechte und Werte sowie Lizenzen an solchen Rechten und Werten
|
5
|
+
3. Geschäfts- oder Firmenwert
|
6
|
+
4. geleistete Anzahlungen
|
7
|
+
II. Sachanlagen
|
8
|
+
1. Grundstücke, grundstücksgleiche Rechte und Bauten einschließlich der Bauten auf fremden Grundstücken
|
9
|
+
2. technische Anlagen und Maschinen
|
10
|
+
3. andere Anlagen, Betriebs- und Geschäftsausstattung
|
11
|
+
4. geleistete Anzahlungen und Anlagen im Bau
|
12
|
+
III. Finanzanlagen
|
13
|
+
1. Anteile an verbundenen Unternehmen
|
14
|
+
2. Ausleihungen an verbundene Unternehmen
|
15
|
+
3. Beteiligungen
|
16
|
+
4. Ausleihungen an Unternehmen, mit denen ein Beteiligungsverhältnis besteht
|
17
|
+
5. Wertpapiere des Anlagevermögens
|
18
|
+
6. sonstige Ausleihungen
|
19
|
+
B. Umlaufvermögen
|
20
|
+
I. Vorräte
|
21
|
+
1. Roh-, Hilfs- und Betriebsstoffe
|
22
|
+
2. unfertige Erzeugnisse, unfertige Leistungen
|
23
|
+
3. fertige Erzeugnisse und Waren
|
24
|
+
4. geleistete Anzahlungen
|
25
|
+
II. Forderungen und sonstige Vermögensgegenstände
|
26
|
+
1. Forderungen aus Lieferungen und Leistungen
|
27
|
+
2. Forderungen gegen verbundene Unternehmen
|
28
|
+
3. Forderungen gegen Unternehmen, mit denen ein Beteiligungsverhältnis besteht
|
29
|
+
4. sonstige Vermögensgegenstände
|
30
|
+
III. Wertpapiere
|
31
|
+
1. Anteile an verbundenen Unternehmen
|
32
|
+
2. sonstige Wertpapiere
|
33
|
+
IV. Kassenbestand, Bundesbankguthaben, Guthaben bei Kreditinstituten und Schecks
|
34
|
+
C. Rechnungsabgrenzungsposten
|
35
|
+
D. Aktive latente Steuern
|
36
|
+
E. Aktiver Unterschiedsbetrag aus der Vermögensverrechnung
|
@@ -0,0 +1,28 @@
|
|
1
|
+
A. Eigenkapital
|
2
|
+
I. Gezeichnetes Kapital
|
3
|
+
II. Kapitalrücklage
|
4
|
+
III. Gewinnrücklagen
|
5
|
+
1. gesetzliche Rücklage
|
6
|
+
2. Rücklage für Anteile an einem herrschenden oder mehrheitlich beteiligten Unternehmen
|
7
|
+
3. satzungsmäßige Rücklagen
|
8
|
+
4. andere Gewinnrücklagen
|
9
|
+
IV. Gewinnvortrag/Verlustvortrag
|
10
|
+
V. Jahresüberschuss/Jahresfehlbetrag
|
11
|
+
B. Rückstellungen
|
12
|
+
1. Rückstellungen für Pensionen und ähnliche Verpflichtungen
|
13
|
+
2. Steuerrückstellungen
|
14
|
+
3. sonstige Rückstellungen
|
15
|
+
C. Verbindlichkeiten
|
16
|
+
1. Anleihen
|
17
|
+
davon konvertibel
|
18
|
+
2. Verbindlichkeiten gegenüber Kreditinstituten
|
19
|
+
3. erhaltene Anzahlungen auf Bestellungen
|
20
|
+
4. Verbindlichkeiten aus Lieferungen und Leistungen
|
21
|
+
5. Verbindlichkeiten aus der Annahme gezogener Wechsel und der Ausstellung eigener Wechsel
|
22
|
+
6. Verbindlichkeiten gegenüber verbundenen Unternehmen
|
23
|
+
7. Verbindlichkeiten gegenüber Unternehmen, mit denen ein Beteiligungsverhältnis besteht
|
24
|
+
8. sonstige Verbindlichkeiten
|
25
|
+
a) davon aus Steuern
|
26
|
+
b) davon im Rahmen der sozialen Sicherheit
|
27
|
+
D. Rechnungsabgrenzungsposten
|
28
|
+
E. Passive latente Steuern
|
@@ -0,0 +1,31 @@
|
|
1
|
+
01. Umsatzerlöse
|
2
|
+
02. Erhöhung oder Verminderung des Bestands an fertigen und unfertigen Erzeugnissen
|
3
|
+
03. andere aktivierte Eigenleistungen
|
4
|
+
04. sonstige betriebliche Erträge
|
5
|
+
05. Materialaufwand
|
6
|
+
a) Aufwendungen für Roh-, Hilfs- und Betriebsstoffe und für bezogene Waren
|
7
|
+
b) Aufwendungen für bezogene Leistungen
|
8
|
+
06. Personalaufwand
|
9
|
+
a) Löhne und Gehälter
|
10
|
+
b) soziale Abgaben und Aufwendungen für Altersversorgung und für Unterstützung
|
11
|
+
davon für Altersversorgung
|
12
|
+
07. Abschreibungen
|
13
|
+
a) auf immaterielle Vermögensgegenstände des Anlagevermögens und Sachanlagen
|
14
|
+
b) auf Vermögensgegenstände des Umlaufvermögens, soweit diese die in der Kapitalgesellschaft üblichen Abschreibungen überschreiten
|
15
|
+
08. sonstige betriebliche Aufwendungen
|
16
|
+
09. Erträge aus Beteiligungen
|
17
|
+
a) davon aus verbundenen Unternehmen
|
18
|
+
10. Erträge aus anderen Wertpapieren und Ausleihungen des Finanzanlagevermögens
|
19
|
+
a) davon aus verbundenen Unternehmen
|
20
|
+
11. sonstige Zinsen und ähnliche Erträge
|
21
|
+
a) davon aus verbundenen Unternehmen
|
22
|
+
12. Abschreibungen auf Finanzanlagen und auf Wertpapiere des Umlaufvermögens
|
23
|
+
13. Zinsen und ähnliche Aufwendungen
|
24
|
+
davon an verbundene Unternehmen
|
25
|
+
14. Ergebnis der gewöhnlichen Geschäftstätigkeit
|
26
|
+
15. außerordentliche Erträge
|
27
|
+
16. außerordentliche Aufwendungen
|
28
|
+
17. außerordentliches Ergebnis
|
29
|
+
18. Steuern vom Einkommen und vom Ertrag
|
30
|
+
19. sonstige Steuern
|
31
|
+
20. Jahresüberschuss/Jahresfehlbetrag
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class Keepr::Journal < ActiveRecord::Base
|
2
|
+
self.table_name = 'keepr_journals'
|
3
|
+
|
4
|
+
validates_presence_of :date
|
5
|
+
validates_uniqueness_of :number, :allow_blank => true
|
6
|
+
|
7
|
+
has_many :keepr_postings, -> { order(:amount => :desc) },
|
8
|
+
:class_name => 'Keepr::Posting', :foreign_key => 'keepr_journal_id', :dependent => :destroy
|
9
|
+
|
10
|
+
belongs_to :accountable, :polymorphic => true
|
11
|
+
|
12
|
+
accepts_nested_attributes_for :keepr_postings, :allow_destroy => true, :reject_if => :all_blank
|
13
|
+
|
14
|
+
default_scope { order({:date => :desc}, {:id => :desc}) }
|
15
|
+
|
16
|
+
validate :validate_postings
|
17
|
+
|
18
|
+
def credit_postings
|
19
|
+
existing_postings.select(&:credit?)
|
20
|
+
end
|
21
|
+
|
22
|
+
def debit_postings
|
23
|
+
existing_postings.select(&:debit?)
|
24
|
+
end
|
25
|
+
|
26
|
+
def amount
|
27
|
+
debit_postings.sum(&:amount)
|
28
|
+
end
|
29
|
+
|
30
|
+
after_initialize :set_defaults
|
31
|
+
|
32
|
+
private
|
33
|
+
def existing_postings
|
34
|
+
keepr_postings.to_a.delete_if(&:marked_for_destruction?)
|
35
|
+
end
|
36
|
+
|
37
|
+
def set_defaults
|
38
|
+
self.date ||= Date.today
|
39
|
+
end
|
40
|
+
|
41
|
+
def validate_postings
|
42
|
+
if existing_postings.map(&:keepr_account_id).uniq.length < 2
|
43
|
+
errors.add(:base, 'At least two accounts have to be booked!')
|
44
|
+
elsif existing_postings.sum(&:raw_amount) != 0
|
45
|
+
errors.add(:base, 'Debit does not match credit!')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
class Keepr::Posting < ActiveRecord::Base
|
2
|
+
self.table_name = 'keepr_postings'
|
3
|
+
|
4
|
+
validates_presence_of :keepr_account_id, :amount
|
5
|
+
validate :cost_center_validation
|
6
|
+
|
7
|
+
belongs_to :keepr_account, :class_name => 'Keepr::Account'
|
8
|
+
belongs_to :keepr_journal, :class_name => 'Keepr::Journal'
|
9
|
+
belongs_to :keepr_cost_center, :class_name => 'Keepr::CostCenter'
|
10
|
+
|
11
|
+
SIDE_DEBIT = 'debit'
|
12
|
+
SIDE_CREDIT = 'credit'
|
13
|
+
|
14
|
+
scope :debits, -> { where('amount >= 0') }
|
15
|
+
scope :credits, -> { where('amount < 0') }
|
16
|
+
|
17
|
+
def side
|
18
|
+
@side || begin
|
19
|
+
(raw_amount < 0 ? SIDE_CREDIT : SIDE_DEBIT) if raw_amount
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def side=(value)
|
24
|
+
@side = value
|
25
|
+
|
26
|
+
if credit?
|
27
|
+
self.raw_amount = -amount if amount
|
28
|
+
elsif debit?
|
29
|
+
self.raw_amount = amount if amount
|
30
|
+
else
|
31
|
+
raise ArgumentError
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def debit?
|
36
|
+
side == SIDE_DEBIT
|
37
|
+
end
|
38
|
+
|
39
|
+
def credit?
|
40
|
+
side == SIDE_CREDIT
|
41
|
+
end
|
42
|
+
|
43
|
+
def raw_amount
|
44
|
+
read_attribute(:amount)
|
45
|
+
end
|
46
|
+
|
47
|
+
def raw_amount=(value)
|
48
|
+
write_attribute(:amount, value)
|
49
|
+
end
|
50
|
+
|
51
|
+
def amount
|
52
|
+
raw_amount.try(:abs)
|
53
|
+
end
|
54
|
+
|
55
|
+
def amount=(value)
|
56
|
+
raise ArgumentError.new('Negative amount not allowed!') if value.to_f < 0
|
57
|
+
@side ||= SIDE_DEBIT
|
58
|
+
|
59
|
+
if credit?
|
60
|
+
self.raw_amount = -value
|
61
|
+
else
|
62
|
+
self.raw_amount = value
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
def cost_center_validation
|
68
|
+
if keepr_cost_center
|
69
|
+
unless keepr_account.profit_and_loss?
|
70
|
+
errors.add(:keepr_cost_center_id, 'allowed for expense or revenue accounts only')
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/keepr/tax.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
class Keepr::Tax < ActiveRecord::Base
|
2
|
+
self.table_name = 'keepr_taxes'
|
3
|
+
|
4
|
+
validates_presence_of :name, :value, :keepr_account_id
|
5
|
+
validates_numericality_of :value
|
6
|
+
|
7
|
+
belongs_to :keepr_account, :class_name => 'Keepr::Account'
|
8
|
+
has_many :keepr_accounts, :class_name => 'Keepr::Account', :foreign_key => 'keepr_tax_id', :dependent => :restrict_with_error
|
9
|
+
|
10
|
+
validate do |tax|
|
11
|
+
tax.errors.add(:keepr_account_id, 'circular reference') if tax.keepr_account.try(:keepr_tax) == tax
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Keepr::Account do
|
5
|
+
describe :number_as_string do
|
6
|
+
it "should return number with leading zeros for low values" do
|
7
|
+
account = Keepr::Account.new(:number => 999)
|
8
|
+
expect(account.number_as_string).to eq('0999')
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should return number unchanged for high values" do
|
12
|
+
account = Keepr::Account.new(:number => 70000)
|
13
|
+
expect(account.number_as_string).to eq('70000')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe :to_s do
|
18
|
+
it "should format" do
|
19
|
+
account = Keepr::Account.new(:number => 27, :name => 'Software')
|
20
|
+
expect(account.to_s).to eq('0027 (Software)')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe Keepr::Account do
|
26
|
+
let!(:account_1000) { FactoryGirl.create(:account, :number => 1000) }
|
27
|
+
let!(:account_1200) { FactoryGirl.create(:account, :number => 1200) }
|
28
|
+
|
29
|
+
before :each do
|
30
|
+
Keepr::Journal.create! :date => Date.yesterday,
|
31
|
+
:keepr_postings_attributes => [
|
32
|
+
{ :keepr_account => account_1000, :amount => 20, :side => 'debit' },
|
33
|
+
{ :keepr_account => account_1200, :amount => 20, :side => 'credit' }
|
34
|
+
]
|
35
|
+
|
36
|
+
Keepr::Journal.create! :date => Date.yesterday,
|
37
|
+
:keepr_postings_attributes => [
|
38
|
+
{ :keepr_account => account_1000, :amount => 10, :side => 'credit' },
|
39
|
+
{ :keepr_account => account_1200, :amount => 10, :side => 'debit' },
|
40
|
+
]
|
41
|
+
|
42
|
+
Keepr::Journal.create! :date => Date.today,
|
43
|
+
:keepr_postings_attributes => [
|
44
|
+
{ :keepr_account => account_1000, :amount => 200, :side => 'debit' },
|
45
|
+
{ :keepr_account => account_1200, :amount => 200, :side => 'credit' }
|
46
|
+
]
|
47
|
+
|
48
|
+
Keepr::Journal.create! :date => Date.today,
|
49
|
+
:keepr_postings_attributes => [
|
50
|
+
{ :keepr_account => account_1000, :amount => 100, :side => 'credit' },
|
51
|
+
{ :keepr_account => account_1200, :amount => 100, :side => 'debit' },
|
52
|
+
]
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "with group" do
|
56
|
+
let!(:result_group) { FactoryGirl.create(:group, :is_result => true) }
|
57
|
+
let!(:normal_group) { FactoryGirl.create(:group, :is_result => false) }
|
58
|
+
|
59
|
+
it "should not be assigned to result group" do
|
60
|
+
account = FactoryGirl.build(:account, :number => 123, :keepr_group => result_group)
|
61
|
+
expect(account).to_not be_valid
|
62
|
+
expect(account.errors[:keepr_group_id]).to be_present
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should be assigned to normal group" do
|
66
|
+
account = FactoryGirl.build(:account, :number => 123, :keepr_group => normal_group)
|
67
|
+
expect(account).to be_valid
|
68
|
+
expect(account.errors[:keepr_group_id]).to be_blank
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe :balance do
|
73
|
+
it 'should calc total' do
|
74
|
+
expect(account_1000.balance).to eq(110)
|
75
|
+
expect(account_1200.balance).to eq(-110)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should calc total for a given date (including)' do
|
79
|
+
expect(account_1000.balance(Date.today)).to eq(110)
|
80
|
+
expect(account_1200.balance(Date.today)).to eq(-110)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'should calc total for a given date (excluding)' do
|
84
|
+
expect(account_1000.balance(Date.yesterday)).to eq(10)
|
85
|
+
expect(account_1200.balance(Date.yesterday)).to eq(-10)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should calc total for Range' do
|
89
|
+
expect(account_1000.balance(Date.yesterday...Date.today)).to eq(110)
|
90
|
+
expect(account_1200.balance(Date.yesterday...Date.today)).to eq(-110)
|
91
|
+
|
92
|
+
expect(account_1000.balance(Date.today...Date.tomorrow)).to eq(100)
|
93
|
+
expect(account_1200.balance(Date.today...Date.tomorrow)).to eq(-100)
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should fail for other param' do
|
97
|
+
expect { account_1000.balance(0) }.to raise_error(ArgumentError)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe :with_sums do
|
102
|
+
it 'should work without param' do
|
103
|
+
account1, account2 = Keepr::Account.with_sums.having('sum_amount <> 0')
|
104
|
+
|
105
|
+
expect(account1.number).to eq(1000)
|
106
|
+
expect(account1.balance).to eq(110)
|
107
|
+
expect(account2.number).to eq(1200)
|
108
|
+
expect(account2.balance).to eq(-110)
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'should work with Date' do
|
112
|
+
account1, account2 = Keepr::Account.with_sums(Date.yesterday).having('sum_amount <> 0')
|
113
|
+
|
114
|
+
expect(account1.number).to eq(1000)
|
115
|
+
expect(account1.sum_amount).to eq(10)
|
116
|
+
expect(account2.number).to eq(1200)
|
117
|
+
expect(account2.sum_amount).to eq(-10)
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should work with Range' do
|
121
|
+
account1, account2 = Keepr::Account.with_sums(Date.today..Date.tomorrow).having('sum_amount <> 0')
|
122
|
+
|
123
|
+
expect(account1.number).to eq(1000)
|
124
|
+
expect(account1.sum_amount).to eq(100)
|
125
|
+
expect(account2.number).to eq(1200)
|
126
|
+
expect(account2.sum_amount).to eq(-100)
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should raise for other param' do
|
130
|
+
expect { Keepr::Account.with_sums(Time.current) }.to raise_error(ArgumentError)
|
131
|
+
expect { Keepr::Account.with_sums(0) }.to raise_error(ArgumentError)
|
132
|
+
expect { Keepr::Account.with_sums(:foo) }.to raise_error(ArgumentError)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe Keepr::Account, 'with subaccounts' do
|
138
|
+
let!(:account_1400) { FactoryGirl.create(:account, :number => 1400) }
|
139
|
+
let!(:account_10000) { FactoryGirl.create(:account, :number => 10000, :parent => account_1400) }
|
140
|
+
let!(:account_8400) { FactoryGirl.create(:account, :number => 8400) }
|
141
|
+
|
142
|
+
before :each do
|
143
|
+
Keepr::Journal.create! :date => Date.yesterday,
|
144
|
+
:keepr_postings_attributes => [
|
145
|
+
{ :keepr_account => account_10000, :amount => 20, :side => 'debit' },
|
146
|
+
{ :keepr_account => account_8400, :amount => 20, :side => 'credit' }
|
147
|
+
]
|
148
|
+
end
|
149
|
+
|
150
|
+
describe :keepr_postings do
|
151
|
+
it 'should include postings from descendant accounts' do
|
152
|
+
expect(account_1400.keepr_postings.size).to eq(1)
|
153
|
+
expect(account_10000.keepr_postings.size).to eq(1)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
describe :balance do
|
158
|
+
it 'should include postings from descendant accounts' do
|
159
|
+
expect(account_1400.reload.balance).to eq(20)
|
160
|
+
expect(account_10000.reload.balance).to eq(20)
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'should include postings from descendant accounts with date given' do
|
164
|
+
expect(account_1400.balance(Date.today)).to eq(20)
|
165
|
+
expect(account_10000.balance(Date.today)).to eq(20)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
describe :with_sums do
|
170
|
+
it 'should calc balance' do
|
171
|
+
expect(Keepr::Account.with_sums.
|
172
|
+
select { |a| (a.sum_amount || 0) != 0 }.
|
173
|
+
map { |a| [a.number, a.sum_amount] }).
|
174
|
+
to eq([[8400, -20], [10000, 20]])
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
describe :merged_with_sums do
|
179
|
+
it 'should calc merged balance' do
|
180
|
+
expect(Keepr::Account.merged_with_sums.
|
181
|
+
select { |a| (a.sum_amount || 0) != 0 }.
|
182
|
+
map { |a| [a.number, a.sum_amount] }).
|
183
|
+
to eq([[1400, 20], [8400, -20]])
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
describe Keepr::Account, 'with tax' do
|
189
|
+
let!(:tax_account) { Keepr::Account.create! :number => 1776,
|
190
|
+
:name => 'Umsatzsteuer 19%',
|
191
|
+
:kind => :asset }
|
192
|
+
|
193
|
+
let!(:tax) { Keepr::Tax.create! :name => 'USt19',
|
194
|
+
:description => 'Umsatzsteuer 19%',
|
195
|
+
:value => 19.0,
|
196
|
+
:keepr_account => tax_account }
|
197
|
+
|
198
|
+
it "should link to tax" do
|
199
|
+
account = Keepr::Account.new :number => 8400,
|
200
|
+
:name => 'Erlöse 19% USt',
|
201
|
+
:kind => :revenue,
|
202
|
+
:keepr_tax => tax
|
203
|
+
expect(tax_account).to be_valid
|
204
|
+
end
|
205
|
+
|
206
|
+
it "should avoid circular reference" do
|
207
|
+
tax_account.keepr_tax_id = tax.id
|
208
|
+
expect(tax_account).to be_invalid
|
209
|
+
end
|
210
|
+
end
|