sk_calc 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.
- data/.gitignore +9 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +36 -0
- data/LICENSE +22 -0
- data/README.rdoc +32 -0
- data/Rakefile +35 -0
- data/VERSION +1 -0
- data/ci/Gemfile +8 -0
- data/lib/sk_calc.rb +35 -0
- data/lib/sk_calc/helper.rb +29 -0
- data/lib/sk_calc/item.rb +163 -0
- data/lib/sk_calc/items.rb +84 -0
- data/lib/sk_calc/version.rb +5 -0
- data/sk_calc.gemspec +33 -0
- data/spec/sk_calc/item_spec.rb +88 -0
- data/spec/sk_calc/items_spec.rb +46 -0
- data/spec/spec_helper.rb +5 -0
- metadata +152 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
sk_calc (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
activesupport (3.1.3)
|
10
|
+
multi_json (~> 1.0)
|
11
|
+
diff-lcs (1.1.3)
|
12
|
+
json (1.6.4)
|
13
|
+
multi_json (1.0.4)
|
14
|
+
rake (0.9.2.2)
|
15
|
+
rcov (0.9.11)
|
16
|
+
rdoc (3.12)
|
17
|
+
json (~> 1.4)
|
18
|
+
rspec (2.7.0)
|
19
|
+
rspec-core (~> 2.7.0)
|
20
|
+
rspec-expectations (~> 2.7.0)
|
21
|
+
rspec-mocks (~> 2.7.0)
|
22
|
+
rspec-core (2.7.1)
|
23
|
+
rspec-expectations (2.7.0)
|
24
|
+
diff-lcs (~> 1.1.2)
|
25
|
+
rspec-mocks (2.7.0)
|
26
|
+
|
27
|
+
PLATFORMS
|
28
|
+
ruby
|
29
|
+
|
30
|
+
DEPENDENCIES
|
31
|
+
activesupport
|
32
|
+
rake (>= 0.9.2)
|
33
|
+
rcov
|
34
|
+
rdoc
|
35
|
+
rspec
|
36
|
+
sk_calc!
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2011 Michael Bumann
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
= SalesKing Calculation
|
2
|
+
|
3
|
+
Why?
|
4
|
+
|
5
|
+
1. We have had enough of "How do you calculate?"-Questions
|
6
|
+
2. Ever stumbled upon rounding problems, when calculating totals?
|
7
|
+
3. Wouldn't it be nice to change a calculation strategy?
|
8
|
+
|
9
|
+
We decided to open-source this part, so everybody can transparently see
|
10
|
+
how we calculate item and document totals.
|
11
|
+
|
12
|
+
You can take advantage of this lib for example when using our API and
|
13
|
+
mixing it into your local classes.
|
14
|
+
|
15
|
+
|
16
|
+
== Install
|
17
|
+
|
18
|
+
gem install sk_calc
|
19
|
+
|
20
|
+
|
21
|
+
== Classes
|
22
|
+
|
23
|
+
|
24
|
+
== Usage
|
25
|
+
|
26
|
+
Comming ..
|
27
|
+
|
28
|
+
require 'sk_calc'
|
29
|
+
|
30
|
+
== Tests
|
31
|
+
|
32
|
+
Copyright (c) 2011 Georg Leciejewski, released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require 'rake'
|
3
|
+
require 'rdoc/task'
|
4
|
+
require 'rspec'
|
5
|
+
require 'rspec/core/rake_task'
|
6
|
+
|
7
|
+
desc 'Default: run specs.'
|
8
|
+
task :default => :spec
|
9
|
+
|
10
|
+
desc "Run specs"
|
11
|
+
RSpec::Core::RakeTask.new do |t|
|
12
|
+
t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
|
13
|
+
# Put spec opts in a file named .rspec in root
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "Generate code coverage"
|
17
|
+
RSpec::Core::RakeTask.new(:coverage) do |t|
|
18
|
+
t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
|
19
|
+
t.rcov = true
|
20
|
+
t.rcov_opts = ['--exclude', 'spec']
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'Generate documentation.'
|
24
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
25
|
+
rdoc.rdoc_dir = 'rdoc'
|
26
|
+
rdoc.title = 'SalesKing Calculation'
|
27
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
28
|
+
rdoc.rdoc_files.include('README')
|
29
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
30
|
+
end
|
31
|
+
|
32
|
+
#require "bundler/gem_tasks"
|
33
|
+
########### to be dropped when we go public
|
34
|
+
require "bundler/gem_helper"
|
35
|
+
Bundler::GemHelper.install_tasks
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/ci/Gemfile
ADDED
data/lib/sk_calc.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'bigdecimal'
|
2
|
+
require "active_support/core_ext/enumerable"
|
3
|
+
module SK
|
4
|
+
# calculation module
|
5
|
+
# == Usage
|
6
|
+
#
|
7
|
+
# class LineItem
|
8
|
+
# calculates :item
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# class Invoice
|
12
|
+
# calculates :items
|
13
|
+
# end
|
14
|
+
module Calc
|
15
|
+
|
16
|
+
def self.included(base)
|
17
|
+
autoload :Helper, 'sk_calc/helper'
|
18
|
+
autoload :Item, 'sk_calc/item'
|
19
|
+
autoload :Items, 'sk_calc/items'
|
20
|
+
base.extend(ClassMethods)
|
21
|
+
# base.send(:include, InstanceMethods)
|
22
|
+
end
|
23
|
+
|
24
|
+
module ClassMethods
|
25
|
+
|
26
|
+
def calculates(kind, opts={})
|
27
|
+
include Item if kind == :item
|
28
|
+
include Items if kind == :items
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
module InstanceMethods; end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Helper methods to
|
2
|
+
# - convert empty or integer values into BigDecimals
|
3
|
+
module SK::Calc::Helper
|
4
|
+
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
# Init price single with 0 if nil and cast to BigDecimal
|
9
|
+
# == Return
|
10
|
+
# <BigDecimal>
|
11
|
+
def conv_price_single
|
12
|
+
to_bd(price_single || 0)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Init tax with 0 if nil and cast to BigDecimal
|
16
|
+
# == Return
|
17
|
+
# <BigDecimal>
|
18
|
+
def conv_tax
|
19
|
+
to_bd(tax || 0)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Cast a val to BigDecimal
|
23
|
+
# == Return
|
24
|
+
# <BigDecimal>
|
25
|
+
def to_bd(val)
|
26
|
+
val.is_a?(BigDecimal) ? val : BigDecimal.new("#{val}")
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/lib/sk_calc/item.rb
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
# Calculate totals for a single item
|
2
|
+
# Including class MUST respond to:
|
3
|
+
#
|
4
|
+
# - discount
|
5
|
+
# - price_single
|
6
|
+
# - quantity
|
7
|
+
# - tax
|
8
|
+
#
|
9
|
+
# == Information
|
10
|
+
#
|
11
|
+
# base data
|
12
|
+
# price_single
|
13
|
+
# quantity
|
14
|
+
# discount %
|
15
|
+
# tax %
|
16
|
+
#
|
17
|
+
# unrounded calculations
|
18
|
+
# total price_single * quantity
|
19
|
+
# net_total_base total * discount
|
20
|
+
# tax_total_base net_total_base * tax
|
21
|
+
#
|
22
|
+
# rounded calculations
|
23
|
+
# net_total
|
24
|
+
# tax_total
|
25
|
+
# gross_total
|
26
|
+
#
|
27
|
+
# informative: should not be used in totals calc
|
28
|
+
# net_single
|
29
|
+
# gross_single
|
30
|
+
# discount_total
|
31
|
+
#
|
32
|
+
module SK::Calc::Item
|
33
|
+
include SK::Calc::Helper
|
34
|
+
|
35
|
+
def self.round_mode
|
36
|
+
@rmd || BigDecimal::ROUND_HALF_UP
|
37
|
+
end
|
38
|
+
def self.round_mode=(mode)
|
39
|
+
@rmd = mode
|
40
|
+
end
|
41
|
+
|
42
|
+
############################################
|
43
|
+
### BASE VALUES
|
44
|
+
############################################
|
45
|
+
### These values are used for calculations.
|
46
|
+
### Use values under DISPLAY VALUES section
|
47
|
+
### for displaying values to the end user!
|
48
|
+
|
49
|
+
# Total unrounded net basis incl discount
|
50
|
+
# Use this internally to do calculations! Differs from net_total_base which is
|
51
|
+
# used to output the rounded & formatted values
|
52
|
+
# ==== Returns
|
53
|
+
# <BigDecimal>::
|
54
|
+
def net_total_base
|
55
|
+
(100 - discount) * total / 100
|
56
|
+
end
|
57
|
+
|
58
|
+
# ==== Returns
|
59
|
+
# <BigDecimal>:: total amount of tax
|
60
|
+
def tax_total_base
|
61
|
+
(net_total_base * conv_tax) / 100
|
62
|
+
end
|
63
|
+
|
64
|
+
# Single net price with discount applied
|
65
|
+
# DO NOT use this method to calculate(eg. totals for a document) use net_total
|
66
|
+
# or gross_total instead
|
67
|
+
# ==== Returns
|
68
|
+
# <BigDecimal>:: rounded 2 decimals
|
69
|
+
def net_single_base
|
70
|
+
conv_price_single * ( 1 - (discount / 100 ) )
|
71
|
+
end
|
72
|
+
|
73
|
+
def gross_single_base
|
74
|
+
net_single_base * ( 1 + conv_tax / 100)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Total gross price incl. discount
|
78
|
+
# ==== Returns
|
79
|
+
# <BigDecimal>:: total gross base
|
80
|
+
def gross_total_base
|
81
|
+
net_total_base + tax_total_base
|
82
|
+
end
|
83
|
+
|
84
|
+
# The discount amount unrounded
|
85
|
+
# ==== Returns
|
86
|
+
# <BigDecimal>:: rounded
|
87
|
+
def discount_total_base
|
88
|
+
total * (discount / 100)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Unrounded item total price * quantity, excl discount
|
92
|
+
# Use it to do calculations!
|
93
|
+
# ==== Returns
|
94
|
+
# <BigDecimal>::
|
95
|
+
def total
|
96
|
+
conv_price_single * ( quantity || 0)
|
97
|
+
end
|
98
|
+
|
99
|
+
############################################
|
100
|
+
### DISPLAY VALUES
|
101
|
+
############################################
|
102
|
+
### These values are used only to display to a user.
|
103
|
+
### Use values under BASE VALUES section
|
104
|
+
### for calculations!
|
105
|
+
|
106
|
+
# Total gross price incl. discount
|
107
|
+
# ==== Returns
|
108
|
+
# <BigDecimal>:: rounded 2 decimals
|
109
|
+
def gross_total
|
110
|
+
gross_total_base.round(2)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Total net price(2 decimals) incl. discount
|
114
|
+
# ==== Returns
|
115
|
+
# <BigDecimal>:: rounded 2 decimals
|
116
|
+
def net_total
|
117
|
+
net_total_base.round(2)
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
# ==== Returns
|
122
|
+
# <BigDecimal>:: rounded 2 decimals
|
123
|
+
def tax_total
|
124
|
+
tax_total_base.round(2)
|
125
|
+
end
|
126
|
+
|
127
|
+
# The discount amount
|
128
|
+
# ==== Returns
|
129
|
+
# <BigDecimal>:: rounded 2 decimals
|
130
|
+
def discount_total
|
131
|
+
discount_total_base.round(2)
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
# Single net price with discount applied rounded 2.
|
136
|
+
# DO NOT use this method to calculate(eg. totals for a document) use net_total
|
137
|
+
# or gross_total instead
|
138
|
+
# ==== Returns
|
139
|
+
# <BigDecimal>:: rounded 2 decimals
|
140
|
+
def net_single
|
141
|
+
net_single_base.round(2)
|
142
|
+
end
|
143
|
+
|
144
|
+
# Single gross price rounded 2.
|
145
|
+
# DONT use this method to calculate(eg. totals for a document) use net_total
|
146
|
+
# or gross_total instead
|
147
|
+
# ==== Returns
|
148
|
+
# <BigDecimal>:: rounded 2 decimals
|
149
|
+
def gross_single
|
150
|
+
gross_single_base.round(2)
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
private
|
155
|
+
|
156
|
+
# Init price single with 0 if nil and cast to BigDecimal
|
157
|
+
# == Return
|
158
|
+
# <BigDecimal>
|
159
|
+
def conv_price_single
|
160
|
+
to_bd(price_single || 0)
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# Calculate totals for a multiple items eg in an invoice
|
2
|
+
# Including class MUST respond to:
|
3
|
+
# - price_total
|
4
|
+
# - precision
|
5
|
+
# - price_tax
|
6
|
+
# - line_items
|
7
|
+
module SK::Calc::Items
|
8
|
+
include SK::Calc::Helper
|
9
|
+
# Gross total always rounded to 2 decimals
|
10
|
+
def gross_total
|
11
|
+
val = (net_total_base || 0) + conv_tax
|
12
|
+
val.round(2)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Net total rounded to 2 decimals, the taxation base
|
16
|
+
def net_total
|
17
|
+
net_total_base.round(2)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Unrounded net total so one can see the base sum of the line items before
|
21
|
+
# rounding
|
22
|
+
def net_total_base
|
23
|
+
conv_price_total
|
24
|
+
end
|
25
|
+
|
26
|
+
# Rounded price_tax to 2 decimals
|
27
|
+
def tax_total
|
28
|
+
conv_tax.round(2)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Save items sums of net total and summed taxes into the price_total,
|
32
|
+
# tax_total
|
33
|
+
def sum_items(items=nil)
|
34
|
+
items ||= line_items
|
35
|
+
# Sum up all the total prices of the items.
|
36
|
+
# .to_a to get out of activerecord collection into enum
|
37
|
+
self.price_total = items.to_a.sum(&:net_total_base)
|
38
|
+
# Sum up the tax, but use the tax_grouped to prevent rounding errors
|
39
|
+
self.price_tax = tax_grouped(items).sum { |tax_group| tax_group[1] }
|
40
|
+
end
|
41
|
+
|
42
|
+
# Sums up the tax price of the line items, grouped by tax
|
43
|
+
# Results a sorted hash (=array) like [ [ 7, 3.50 ], [ 19, 47.50 ] ]
|
44
|
+
#==Example
|
45
|
+
# a sorted array like [ [ 7, 3.50 ], [ 19, 47.50 ] ] for each price/tax combination
|
46
|
+
# So if you are using two kinds of tax (7%/19%) in an document:
|
47
|
+
#
|
48
|
+
# [0] =>
|
49
|
+
# [0] => 7 # the tax percentage
|
50
|
+
# [1] => 14.00 # tax sum of all line item with this tax (items summ is 200.00)
|
51
|
+
# [1] =>
|
52
|
+
# [0] => 19 # the tax percentage
|
53
|
+
# [1] => 57 # tax sum of all line item with this tax(items sum = 300)
|
54
|
+
#
|
55
|
+
#
|
56
|
+
# Sum up the price_total and calculate the tax -
|
57
|
+
# don't sum price_tax because of rounding errors!
|
58
|
+
#
|
59
|
+
def tax_grouped(items=nil)
|
60
|
+
items ||= line_items
|
61
|
+
result = {}
|
62
|
+
items.group_by(&:tax).each do |tax, item_group|
|
63
|
+
net_total_sum = item_group.to_a.sum(&:net_total_base)
|
64
|
+
result[tax] = (net_total_sum * tax / 100.0) unless tax.zero?
|
65
|
+
end
|
66
|
+
result.sort
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
# Init price single with 0 if nil and cast to BigDecimal
|
72
|
+
# == Return
|
73
|
+
# <BigDecimal>
|
74
|
+
def conv_price_total
|
75
|
+
to_bd(price_total || 0)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Init tax with 0 if nil and cast to BigDecimal .. same in helper
|
79
|
+
# == Return
|
80
|
+
# <BigDecimal>
|
81
|
+
def conv_tax
|
82
|
+
to_bd(price_tax || 0)
|
83
|
+
end
|
84
|
+
end
|
data/sk_calc.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
require 'sk_calc/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = %q{sk_calc}
|
7
|
+
s.version = SK::Calc::VERSION
|
8
|
+
|
9
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
10
|
+
s.authors = ["Georg Leciejewski"]
|
11
|
+
s.date = %q{2011-12-17}
|
12
|
+
s.description = %q{Calculate document and line item totals. This moule is used inside SalesKIng and outsourced for transparency and reusability.}
|
13
|
+
s.email = %q{gl@salesking.eu}
|
14
|
+
s.homepage = %q{http://github.com/salesking/sk_calc}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.rdoc"
|
17
|
+
]
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
21
|
+
|
22
|
+
s.require_paths = ["lib"]
|
23
|
+
s.rubygems_version = %q{1.6.2}
|
24
|
+
s.summary = %q{SalesKing Calculation Module}
|
25
|
+
|
26
|
+
s.add_development_dependency 'rspec'
|
27
|
+
s.add_development_dependency 'rcov'
|
28
|
+
s.add_development_dependency 'rdoc'
|
29
|
+
s.add_development_dependency 'activesupport'
|
30
|
+
s.add_development_dependency 'rake', '>= 0.9.2'
|
31
|
+
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class LineItem
|
4
|
+
include SK::Calc
|
5
|
+
attr_accessor :price_single, :tax, :quantity, :discount
|
6
|
+
calculates :item
|
7
|
+
end
|
8
|
+
|
9
|
+
describe SK::Calc do
|
10
|
+
|
11
|
+
describe 'item calculations' do
|
12
|
+
|
13
|
+
before :each do
|
14
|
+
@i = LineItem.new
|
15
|
+
@i.price_single = 10.0
|
16
|
+
@i.discount = 0
|
17
|
+
@i.quantity = 1
|
18
|
+
@i.tax = 19.0
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should calc net_single" do
|
22
|
+
@i.net_single.should == 10.00
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should calc gross_single" do
|
26
|
+
@i.gross_single.should == 11.90
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should calc total" do
|
30
|
+
@i.total.should == 10.0
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should calc net_total" do
|
34
|
+
@i.net_total.should == 10.0
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should calc gross_total" do
|
38
|
+
@i.gross_total.should == 11.90
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should calc net_total_base" do
|
42
|
+
@i.net_total_base.should == 10.00
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should calc tax_total" do
|
46
|
+
@i.tax_total.should == 1.90
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'calculates 15.00 gross price' do
|
51
|
+
|
52
|
+
before :each do
|
53
|
+
@i = LineItem.new
|
54
|
+
@i.price_single = 12.605
|
55
|
+
@i.discount = 0
|
56
|
+
@i.quantity = 1
|
57
|
+
@i.tax = 19.0
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should calc total" do
|
61
|
+
@i.total.should == 12.605
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should calc net_total" do
|
65
|
+
@i.net_total.to_f.should == 12.61
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should calc gross_total" do
|
69
|
+
@i.gross_total.should == 15.0
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should calc net_total_base" do
|
73
|
+
@i.net_total_base.should == 12.605
|
74
|
+
end
|
75
|
+
it "should calc net_total" do
|
76
|
+
@i.net_total.should == 12.61
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should calc tax_total_base" do
|
80
|
+
@i.tax_total_base.should == 2.39495
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should calc tax_total" do
|
84
|
+
@i.tax_total.should == 2.39
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class LineItem
|
4
|
+
include SK::Calc
|
5
|
+
attr_accessor :price_single, :tax, :quantity, :discount
|
6
|
+
calculates :item
|
7
|
+
end
|
8
|
+
|
9
|
+
class Doc
|
10
|
+
include SK::Calc
|
11
|
+
attr_accessor :price_total, :price_tax, :line_items, :precision
|
12
|
+
calculates :items
|
13
|
+
end
|
14
|
+
|
15
|
+
describe SK::Calc, 'items calculations' do
|
16
|
+
|
17
|
+
before :each do
|
18
|
+
@i = LineItem.new
|
19
|
+
@i.price_single = 10.0
|
20
|
+
@i.discount = 0
|
21
|
+
@i.quantity = 1
|
22
|
+
@i.tax = 19.0
|
23
|
+
|
24
|
+
@doc = Doc.new
|
25
|
+
@doc.line_items = [@i]
|
26
|
+
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should calc net_total" do
|
31
|
+
@doc.sum_items
|
32
|
+
@doc.net_total.should == 10.0
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should calc gross_total" do
|
36
|
+
@doc.sum_items
|
37
|
+
@doc.gross_total.should == 11.90
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should sum totals" do
|
41
|
+
@doc.sum_items
|
42
|
+
@doc.price_total.should == 10.0
|
43
|
+
@doc.price_tax.should == 1.90
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sk_calc
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Georg Leciejewski
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-12-17 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rcov
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 3
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
version: "0"
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rdoc
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
type: :development
|
61
|
+
version_requirements: *id003
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: activesupport
|
64
|
+
prerelease: false
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
hash: 3
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
74
|
+
type: :development
|
75
|
+
version_requirements: *id004
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: rake
|
78
|
+
prerelease: false
|
79
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
hash: 63
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
- 9
|
88
|
+
- 2
|
89
|
+
version: 0.9.2
|
90
|
+
type: :development
|
91
|
+
version_requirements: *id005
|
92
|
+
description: Calculate document and line item totals. This moule is used inside SalesKIng and outsourced for transparency and reusability.
|
93
|
+
email: gl@salesking.eu
|
94
|
+
executables: []
|
95
|
+
|
96
|
+
extensions: []
|
97
|
+
|
98
|
+
extra_rdoc_files:
|
99
|
+
- README.rdoc
|
100
|
+
files:
|
101
|
+
- .gitignore
|
102
|
+
- Gemfile
|
103
|
+
- Gemfile.lock
|
104
|
+
- LICENSE
|
105
|
+
- README.rdoc
|
106
|
+
- Rakefile
|
107
|
+
- VERSION
|
108
|
+
- ci/Gemfile
|
109
|
+
- lib/sk_calc.rb
|
110
|
+
- lib/sk_calc/helper.rb
|
111
|
+
- lib/sk_calc/item.rb
|
112
|
+
- lib/sk_calc/items.rb
|
113
|
+
- lib/sk_calc/version.rb
|
114
|
+
- sk_calc.gemspec
|
115
|
+
- spec/sk_calc/item_spec.rb
|
116
|
+
- spec/sk_calc/items_spec.rb
|
117
|
+
- spec/spec_helper.rb
|
118
|
+
homepage: http://github.com/salesking/sk_calc
|
119
|
+
licenses: []
|
120
|
+
|
121
|
+
post_install_message:
|
122
|
+
rdoc_options: []
|
123
|
+
|
124
|
+
require_paths:
|
125
|
+
- lib
|
126
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
127
|
+
none: false
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
hash: 3
|
132
|
+
segments:
|
133
|
+
- 0
|
134
|
+
version: "0"
|
135
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
|
+
none: false
|
137
|
+
requirements:
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
hash: 3
|
141
|
+
segments:
|
142
|
+
- 0
|
143
|
+
version: "0"
|
144
|
+
requirements: []
|
145
|
+
|
146
|
+
rubyforge_project:
|
147
|
+
rubygems_version: 1.8.15
|
148
|
+
signing_key:
|
149
|
+
specification_version: 3
|
150
|
+
summary: SalesKing Calculation Module
|
151
|
+
test_files: []
|
152
|
+
|