taxedo 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -0
- data/LICENSE +7 -0
- data/README.md +57 -0
- data/Rakefile +11 -0
- data/data/README.md +41 -0
- data/data/regions.yml +41 -0
- data/languages/en.yml +18 -0
- data/languages/fr.yml +18 -0
- data/lib/taxedo.rb +32 -0
- data/lib/taxedo/builder.rb +5 -0
- data/lib/taxedo/builder/base.rb +26 -0
- data/lib/taxedo/builder/hash.rb +13 -0
- data/lib/taxedo/builder/html.rb +48 -0
- data/lib/taxedo/builder/json.rb +7 -0
- data/lib/taxedo/builder/price.rb +23 -0
- data/lib/taxedo/builder/text.rb +15 -0
- data/lib/taxedo/implants.rb +6 -0
- data/lib/taxedo/implants/action_controller.rb +11 -0
- data/lib/taxedo/implants/railtie.rb +13 -0
- data/lib/taxedo/receipt.rb +73 -0
- data/lib/taxedo/region.rb +42 -0
- data/lib/taxedo/tax.rb +28 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/taxedo/builder/hash_spec.rb +20 -0
- data/spec/taxedo/builder/html_spec.rb +14 -0
- data/spec/taxedo/builder/json_spec.rb +15 -0
- data/spec/taxedo/builder/price_spec.rb +11 -0
- data/spec/taxedo/builder/text_spec.rb +15 -0
- data/spec/taxedo/receipt_spec.rb +42 -0
- data/spec/taxedo/region_spec.rb +36 -0
- data/spec/taxedo/tax_spec.rb +26 -0
- data/spec/taxedo_spec.rb +11 -0
- metadata +113 -0
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (c) 2012 De Marque inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
Taxedo [![Build Status](https://secure.travis-ci.org/demarque/taxedo.png?branch=master)](http://travis-ci.org/demarque/taxedo)
|
2
|
+
===============
|
3
|
+
|
4
|
+
Taxedo is a small tool to easily calculate sales tax for different regions.
|
5
|
+
It also provide helper methods to generate html, text or json reports.
|
6
|
+
|
7
|
+
Install
|
8
|
+
-------
|
9
|
+
|
10
|
+
```
|
11
|
+
gem install taxedo
|
12
|
+
```
|
13
|
+
|
14
|
+
### Rails 3
|
15
|
+
|
16
|
+
In your Gemfile:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
gem 'taxedo'
|
20
|
+
```
|
21
|
+
|
22
|
+
Usage
|
23
|
+
-----
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
Taxedo.tax_for 'quebec', 1000
|
27
|
+
```
|
28
|
+
|
29
|
+
### Rails 3
|
30
|
+
|
31
|
+
Taxedo gives you access to a helper method `tax_for` in the controller and in the views.
|
32
|
+
This is the same thing as calling `Taxedo.tax_for`.
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
tax_for 'quebec', 1000, format: :html
|
36
|
+
```
|
37
|
+
|
38
|
+
### Parameters
|
39
|
+
|
40
|
+
* **region**: Region of the tax. *See [regions documentation](https://github.com/demarque/taxedo/blob/master/data/README.md)*.
|
41
|
+
* **amount**: Amount in cents.
|
42
|
+
* **options**: Set of options. *See below*.
|
43
|
+
|
44
|
+
### Options
|
45
|
+
|
46
|
+
* **format**: Format of the output ( _hash, html, json, **text**_ ).
|
47
|
+
* **on**: Date parameter. Taxedo should use tax rate active for a particular date.
|
48
|
+
* **html_options**: hash of options for the html output
|
49
|
+
* **format**: Format of the output ( _lines, rows, **table**_ ).
|
50
|
+
* **columns**: Number of colspan in the row. Only available with the ouput **rows**.
|
51
|
+
* **custom_content**: Content of the first column. Only availabie with the output **rows**.
|
52
|
+
|
53
|
+
|
54
|
+
Copyright
|
55
|
+
---------
|
56
|
+
|
57
|
+
Copyright (c) 2012 De Marque inc. See LICENSE for further details.
|
data/Rakefile
ADDED
data/data/README.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
Taxedo Regions
|
2
|
+
===============
|
3
|
+
|
4
|
+
## How to add a region
|
5
|
+
|
6
|
+
The region management is a simple YAML file. Here's an overview of each keys defining a region.
|
7
|
+
We will use quebec as an example :
|
8
|
+
|
9
|
+
```yaml
|
10
|
+
# ID of the region. When using a country use the ISO 3166-1 alpha-3
|
11
|
+
quebec:
|
12
|
+
# Currency for the region
|
13
|
+
currency: cad
|
14
|
+
|
15
|
+
# Indicate whether the tax are included or not in the price
|
16
|
+
included: false
|
17
|
+
|
18
|
+
# These are the tax rules.
|
19
|
+
# Most of the time it should be the standard rules but on some product there can be exeptions.
|
20
|
+
rules:
|
21
|
+
standard: ['gst', 'qst']
|
22
|
+
books: ['gst']
|
23
|
+
|
24
|
+
taxes:
|
25
|
+
# ID of the tax
|
26
|
+
gst:
|
27
|
+
# The value represent the rate of the tax and the key the beginning of the application. 7.25% = 725
|
28
|
+
19910101: 700
|
29
|
+
20060701: 600
|
30
|
+
20080101: 500
|
31
|
+
qst:
|
32
|
+
19940513: 650
|
33
|
+
19980101: 750
|
34
|
+
20110101: 850
|
35
|
+
20120101: 950
|
36
|
+
```
|
37
|
+
|
38
|
+
## Currently Supported Regions
|
39
|
+
|
40
|
+
* Canada
|
41
|
+
* Canada : Quebec
|
data/data/regions.yml
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
taxedo:
|
2
|
+
regions:
|
3
|
+
|
4
|
+
#*************************************************************************
|
5
|
+
# CANADA
|
6
|
+
#*************************************************************************
|
7
|
+
can:
|
8
|
+
currency: cad
|
9
|
+
included: false
|
10
|
+
|
11
|
+
rules:
|
12
|
+
standard: ['gst']
|
13
|
+
|
14
|
+
taxes:
|
15
|
+
gst:
|
16
|
+
19910101: 700
|
17
|
+
20060701: 600
|
18
|
+
20080101: 500
|
19
|
+
|
20
|
+
|
21
|
+
#*************************************************************************
|
22
|
+
# CANADA => QUEBEC
|
23
|
+
#*************************************************************************
|
24
|
+
quebec:
|
25
|
+
currency: cad
|
26
|
+
included: false
|
27
|
+
|
28
|
+
rules:
|
29
|
+
standard: ['gst', 'qst']
|
30
|
+
books: ['gst']
|
31
|
+
|
32
|
+
taxes:
|
33
|
+
gst:
|
34
|
+
19910101: 700
|
35
|
+
20060701: 600
|
36
|
+
20080101: 500
|
37
|
+
qst:
|
38
|
+
19940513: 650
|
39
|
+
19980101: 750
|
40
|
+
20110101: 850
|
41
|
+
20120101: 950
|
data/languages/en.yml
ADDED
data/languages/fr.yml
ADDED
data/lib/taxedo.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module Taxedo
|
2
|
+
def self.base_path(name)
|
3
|
+
File.expand_path("../../#{name}", __FILE__) + '/'
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.base_data_path
|
7
|
+
base_path 'data'
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.base_languages_path
|
11
|
+
base_path 'languages'
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.region(region_id)
|
15
|
+
Taxedo::Region.new(region_id)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.tax_for(region_id, amount, options={})
|
19
|
+
options = { format: :text, on: Time.now, rule: 'standard', html_options: {} }.merge(options)
|
20
|
+
|
21
|
+
receipt = Taxedo.region(region_id).calculate(amount, on: options[:on], rule: options[:rule])
|
22
|
+
|
23
|
+
return case options[:format]
|
24
|
+
when :hash then receipt.to_hash
|
25
|
+
when :html then receipt.to_html options[:html_options]
|
26
|
+
when :json then receipt.to_json
|
27
|
+
else receipt.to_text
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
['region', 'receipt', 'tax', 'builder', 'implants'].each { |f| require "taxedo/#{f}"}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Taxedo::Builder::Base
|
2
|
+
def initialize(receipt)
|
3
|
+
@receipt = receipt
|
4
|
+
@content = []
|
5
|
+
end
|
6
|
+
|
7
|
+
def price(amount)
|
8
|
+
Taxedo::Builder::Price.price(amount, unit: @receipt.currency)
|
9
|
+
end
|
10
|
+
|
11
|
+
def subtotal
|
12
|
+
@receipt.subtotal
|
13
|
+
end
|
14
|
+
|
15
|
+
def t(path)
|
16
|
+
@receipt.t(path)
|
17
|
+
end
|
18
|
+
|
19
|
+
def taxes
|
20
|
+
@receipt.taxes
|
21
|
+
end
|
22
|
+
|
23
|
+
def total
|
24
|
+
@receipt.total
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class Taxedo::Builder::Hash < Taxedo::Builder::Base
|
2
|
+
def generate
|
3
|
+
{ subtotal: subtotal, taxes: generate_taxes, total: total }
|
4
|
+
end
|
5
|
+
|
6
|
+
def generate_taxes
|
7
|
+
taxes.map{ |t| generate_tax t }
|
8
|
+
end
|
9
|
+
|
10
|
+
def generate_tax(tax)
|
11
|
+
{ id: tax.id, name: tax.name, amount: tax.amount }
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class Taxedo::Builder::Html < Taxedo::Builder::Base
|
2
|
+
def generate(format, options={})
|
3
|
+
case format
|
4
|
+
when :lines then lines
|
5
|
+
when :rows then table_rows options[:columns], options[:custom_content]
|
6
|
+
else table
|
7
|
+
end
|
8
|
+
|
9
|
+
return @content.join("\n")
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def lines
|
15
|
+
line t('subtotal'), subtotal, :class => 'subtotal'
|
16
|
+
taxes.each { |tax| line tax.name, tax.amount, :class => "tax #{tax.id}" }
|
17
|
+
line t('total'), total, :class => 'total'
|
18
|
+
end
|
19
|
+
|
20
|
+
def line(label, value, options={})
|
21
|
+
options = { :class => '' }.merge(options)
|
22
|
+
|
23
|
+
@content << ('<div class="line ' + options[:class] + '"><label>' + label + '</label><span>' + price(value) + '</span></div>')
|
24
|
+
end
|
25
|
+
|
26
|
+
def table
|
27
|
+
@content << '<table class="receipt-footer"><tbody>'
|
28
|
+
table_rows
|
29
|
+
@content << '</tbody></table>'
|
30
|
+
end
|
31
|
+
|
32
|
+
def table_rows(columns=0, custom_content='')
|
33
|
+
table_row t('subtotal'), subtotal, :class => 'subtotal', :custom_columns => columns, :custom_content => custom_content
|
34
|
+
taxes.each { |tax| table_row tax.name, tax.amount, :class => "tax #{tax.id}" }
|
35
|
+
table_row t('total'), total, :class => 'total'
|
36
|
+
end
|
37
|
+
|
38
|
+
def table_row(label, value, options={})
|
39
|
+
options = { :class => '', :custom_columns => 0, :custom_content => '' }.merge(options)
|
40
|
+
|
41
|
+
content = ['<tr class="' + options[:class] + '">']
|
42
|
+
content << '<td class="custom" rowspan="4" colspan="' + options[:custom_columns].to_s + '">' + options[:custom_content] + '</td>' if options[:custom_columns] > 0
|
43
|
+
content << '<td class="label">' + label + '</td><td class="value">' + price(value) + '</td></tr>'
|
44
|
+
|
45
|
+
@content << content.join
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Taxedo::Builder::Price
|
3
|
+
|
4
|
+
def self.currency_symbol(unit)
|
5
|
+
return case unit.downcase
|
6
|
+
when 'cad', 'usd' then '$'
|
7
|
+
when 'eur' then '€'
|
8
|
+
when 'chf' then 'CHF'
|
9
|
+
else ''
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.price(amount, options={})
|
14
|
+
options = { separator: ',', format: '%n%u', unit: 'cad' }.merge(options)
|
15
|
+
|
16
|
+
result = amount.to_s.rjust(3,'0')
|
17
|
+
result = result[0..-3] + options[:separator] + result[-2..-1]
|
18
|
+
result = options[:format].gsub('%u', currency_symbol(options[:unit])).gsub('%n', result) if options[:unit]
|
19
|
+
|
20
|
+
return result
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Taxedo::Builder::Text < Taxedo::Builder::Base
|
2
|
+
def generate
|
3
|
+
line t('subtotal'), subtotal
|
4
|
+
taxes.each { |tax| line tax.name, tax.amount }
|
5
|
+
line t('total'), total
|
6
|
+
|
7
|
+
return @content.join("\n")
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def line(label, value)
|
13
|
+
@content << (label + ' ').ljust(15, '.') + ' ' + price(value).rjust(6)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'taxedo/implants/action_controller'
|
2
|
+
|
3
|
+
module Taxedo::Implants
|
4
|
+
class Railtie < Rails::Railtie
|
5
|
+
initializer "taxedo" do |app|
|
6
|
+
|
7
|
+
ActiveSupport.on_load :action_controller do
|
8
|
+
include Taxedo::Implants::ActionController
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
class Taxedo::Receipt
|
2
|
+
attr_accessor :currency
|
3
|
+
|
4
|
+
def initialize(region_id, amount)
|
5
|
+
@region_id = region_id
|
6
|
+
@amount = amount
|
7
|
+
@taxes = []
|
8
|
+
|
9
|
+
load_translations
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_tax(id, rate)
|
13
|
+
tax = Taxedo::Tax.new(id)
|
14
|
+
tax.name = tax_name(id)
|
15
|
+
tax.rate = rate
|
16
|
+
tax.source_amount = (@taxes.empty? ? @amount : @taxes.last.subtotal)
|
17
|
+
|
18
|
+
@taxes << tax
|
19
|
+
end
|
20
|
+
|
21
|
+
def subtotal
|
22
|
+
@amount
|
23
|
+
end
|
24
|
+
|
25
|
+
def t(path)
|
26
|
+
text = @translations
|
27
|
+
|
28
|
+
path.split('.').each { |p| text = text[p] }
|
29
|
+
|
30
|
+
return text.to_s
|
31
|
+
end
|
32
|
+
|
33
|
+
def taxes
|
34
|
+
@taxes
|
35
|
+
end
|
36
|
+
|
37
|
+
def total
|
38
|
+
@total = subtotal
|
39
|
+
@taxes.each { |t| @total += t.amount }
|
40
|
+
|
41
|
+
return @total
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_hash
|
45
|
+
Taxedo::Builder::Hash.new(self).generate
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_html(options={})
|
49
|
+
options = { columns: 0, custom_content: '', format: :table }.merge(options)
|
50
|
+
|
51
|
+
return Taxedo::Builder::Html.new(self).generate(options[:format], options)
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_json
|
55
|
+
Taxedo::Builder::Json.new(self).generate
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_text
|
59
|
+
Taxedo::Builder::Text.new(self).generate
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def load_translations
|
65
|
+
language = defined?(I18n) ? I18n.locale.to_s : 'fr'
|
66
|
+
|
67
|
+
@translations = YAML.load_file(Taxedo.base_languages_path + "#{language}.yml")['taxedo'][language]
|
68
|
+
end
|
69
|
+
|
70
|
+
def tax_name(tax_id)
|
71
|
+
t("regions.#{@region_id}.taxes.#{tax_id}.short")
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'time'
|
2
|
+
|
3
|
+
class Taxedo::Region
|
4
|
+
def initialize(id)
|
5
|
+
@id = id
|
6
|
+
@data = YAML.load_file(Taxedo.base_data_path + "regions.yml")['taxedo']['regions'][@id]
|
7
|
+
end
|
8
|
+
|
9
|
+
def calculate(amount, options={})
|
10
|
+
options = { :on => Time.now, :rule => 'standard' }.merge(options)
|
11
|
+
|
12
|
+
receipt = Taxedo::Receipt.new(@id, amount)
|
13
|
+
receipt.currency = @data['currency']
|
14
|
+
|
15
|
+
taxes(options[:rule], options[:on]).each do |tax|
|
16
|
+
receipt.add_tax tax[0], tax[1]
|
17
|
+
end
|
18
|
+
|
19
|
+
return receipt
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def tax_from_start_date(tax_id, start_at)
|
25
|
+
selection = Time.at(0)
|
26
|
+
|
27
|
+
@data['taxes'][tax_id].each do |tax_start_at, tax_rate|
|
28
|
+
tax_start_at = Time.parse(tax_start_at.to_s)
|
29
|
+
selection = tax_start_at if tax_start_at <= start_at and tax_start_at > selection
|
30
|
+
end
|
31
|
+
|
32
|
+
return selection.strftime('%Y%m%d').to_i
|
33
|
+
end
|
34
|
+
|
35
|
+
def taxes(rule, start_at)
|
36
|
+
@data['rules'][rule].map do |tax_id|
|
37
|
+
tax_key = tax_from_start_date(tax_id, start_at)
|
38
|
+
|
39
|
+
[tax_id, @data['taxes'][tax_id][tax_key]]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/taxedo/tax.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
class Taxedo::Tax
|
2
|
+
attr_accessor :name, :rate
|
3
|
+
attr_reader :id, :source_amount
|
4
|
+
|
5
|
+
def initialize(id)
|
6
|
+
@id = id
|
7
|
+
@amount = 0
|
8
|
+
end
|
9
|
+
|
10
|
+
def amount
|
11
|
+
@amount
|
12
|
+
end
|
13
|
+
|
14
|
+
def source_amount=(sa)
|
15
|
+
@source_amount = sa
|
16
|
+
@amount = calculate_amount
|
17
|
+
end
|
18
|
+
|
19
|
+
def subtotal
|
20
|
+
@source_amount + @amount
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def calculate_amount
|
26
|
+
((@source_amount * @rate).round / 10000)
|
27
|
+
end
|
28
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler/setup"
|
3
|
+
|
4
|
+
require 'rspec'
|
5
|
+
require 'rspec-aspic'
|
6
|
+
|
7
|
+
require File.expand_path('../../lib/taxedo', __FILE__)
|
8
|
+
|
9
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.mock_with :rspec
|
13
|
+
config.include RSpecAspic
|
14
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Taxedo::Builder::Hash do
|
4
|
+
#*************************************************************************************
|
5
|
+
# PUBLIC INSTANCE METHODS
|
6
|
+
#*************************************************************************************
|
7
|
+
context "with a quebec receipt of 10,00$" do
|
8
|
+
let(:receipt) { Taxedo::Region.new('quebec').calculate(1000) }
|
9
|
+
|
10
|
+
describe "#generate" do
|
11
|
+
let(:hash) { Taxedo::Builder::Hash.new(receipt).generate }
|
12
|
+
|
13
|
+
the("hash[:subtotal]") { should eql 1000 }
|
14
|
+
the("hash[:taxes][0][:id]") { should eql 'gst' }
|
15
|
+
the("hash[:taxes][0][:amount]") { should eql 50 }
|
16
|
+
the("hash[:taxes][1][:id]") { should eql 'qst' }
|
17
|
+
the("hash[:total]") { should eql 1149 }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Taxedo::Builder::Html do
|
4
|
+
#*************************************************************************************
|
5
|
+
# PUBLIC INSTANCE METHODS
|
6
|
+
#*************************************************************************************
|
7
|
+
context "with a quebec receipt of 10,00$" do
|
8
|
+
let(:receipt) { Taxedo::Region.new('quebec').calculate(1000) }
|
9
|
+
|
10
|
+
describe "#generate" do
|
11
|
+
pending "TOTEST"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Taxedo::Builder::Json do
|
4
|
+
#*************************************************************************************
|
5
|
+
# PUBLIC INSTANCE METHODS
|
6
|
+
#*************************************************************************************
|
7
|
+
context "with a quebec receipt of 10,00$" do
|
8
|
+
let(:receipt) { Taxedo::Region.new('quebec').calculate(1000) }
|
9
|
+
|
10
|
+
describe "#generate" do
|
11
|
+
subject { Taxedo::Builder::Json.new(receipt).generate }
|
12
|
+
it { should eql '{"subtotal":1000,"taxes":[{"id":"gst","name":"TPS","amount":50},{"id":"qst","name":"TVQ","amount":99}],"total":1149}' }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Taxedo::Builder::Text do
|
4
|
+
#*************************************************************************************
|
5
|
+
# PUBLIC INSTANCE METHODS
|
6
|
+
#*************************************************************************************
|
7
|
+
context "with a quebec receipt of 10,00$" do
|
8
|
+
let(:receipt) { Taxedo::Region.new('quebec').calculate(1000) }
|
9
|
+
|
10
|
+
describe "#generate" do
|
11
|
+
subject { Taxedo::Builder::Text.new(receipt).generate }
|
12
|
+
it { should eql "Sous-total .... 10,00$\nTPS ........... 0,50$\nTVQ ........... 0,99$\nTotal ......... 11,49$" }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Taxedo::Receipt do
|
4
|
+
#*************************************************************************************
|
5
|
+
# PUBLIC INSTANCE METHODS
|
6
|
+
#*************************************************************************************
|
7
|
+
describe "#add_tax" do
|
8
|
+
pending "TOTEST"
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#subtotal" do
|
12
|
+
pending "TOTEST"
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#t" do
|
16
|
+
pending "TOTEST"
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#taxes" do
|
20
|
+
pending "TOTEST"
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#total" do
|
24
|
+
pending "TOTEST"
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#to_hash" do
|
28
|
+
pending "TOTEST"
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#to_html" do
|
32
|
+
pending "TOTEST"
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#to_json" do
|
36
|
+
pending "TOTEST"
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#to_text" do
|
40
|
+
pending "TOTEST"
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Taxedo::Region do
|
4
|
+
#*************************************************************************************
|
5
|
+
# PUBLIC INSTANCE METHODS
|
6
|
+
#*************************************************************************************
|
7
|
+
describe "#calculate" do
|
8
|
+
context "with the quebec region" do
|
9
|
+
let(:region) { Taxedo::Region.new('quebec') }
|
10
|
+
|
11
|
+
context "when calculating taxes on 10.00$" do
|
12
|
+
let(:result) { region.calculate(1000) }
|
13
|
+
|
14
|
+
the("result.taxes.length") { should eql 2 }
|
15
|
+
the("result.total") { should eql 1149 }
|
16
|
+
|
17
|
+
context "in July 1994" do
|
18
|
+
let(:result) { region.calculate(1000, :on => Time.parse('1994-07-01')) }
|
19
|
+
the("result.total") { should eql 1139 }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "with the can region" do
|
25
|
+
let(:region) { Taxedo::Region.new('can') }
|
26
|
+
|
27
|
+
context "when calculating taxes on 10.00$" do
|
28
|
+
let(:result) { region.calculate(1000) }
|
29
|
+
|
30
|
+
the("result.taxes.length") { should eql 1 }
|
31
|
+
the("result.total") { should eql 1050 }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Taxedo::Tax do
|
4
|
+
#*************************************************************************************
|
5
|
+
# PUBLIC INSTANCE METHODS
|
6
|
+
#*************************************************************************************
|
7
|
+
describe "#amount" do
|
8
|
+
specify { Taxedo::Tax.new('gst').amount.should eql 0 }
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:tax) { Taxedo::Tax.new('gst') }
|
12
|
+
|
13
|
+
context "having a tax rate of 7% and a source amount of 10$" do
|
14
|
+
before { tax.rate = 700 }
|
15
|
+
before { tax.source_amount = 1000 }
|
16
|
+
|
17
|
+
describe "#source_amount" do
|
18
|
+
the("tax.amount") { should eql 70 }
|
19
|
+
the("tax.source_amount") { should eql 1000 }
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#subtotal" do
|
23
|
+
the("tax.subtotal") { should eql 1070 }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/spec/taxedo_spec.rb
ADDED
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: taxedo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Sebastien Rosa
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-22 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: &2151824180 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.8.7
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2151824180
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
requirement: &2151823460 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2151823460
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rspec-aspic
|
38
|
+
requirement: &2151822780 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.0.2
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2151822780
|
47
|
+
description: ''
|
48
|
+
email:
|
49
|
+
- sebastien@demarque.com
|
50
|
+
executables: []
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files:
|
53
|
+
- LICENSE
|
54
|
+
- README.md
|
55
|
+
files:
|
56
|
+
- data/README.md
|
57
|
+
- data/regions.yml
|
58
|
+
- languages/en.yml
|
59
|
+
- languages/fr.yml
|
60
|
+
- lib/taxedo/builder/base.rb
|
61
|
+
- lib/taxedo/builder/hash.rb
|
62
|
+
- lib/taxedo/builder/html.rb
|
63
|
+
- lib/taxedo/builder/json.rb
|
64
|
+
- lib/taxedo/builder/price.rb
|
65
|
+
- lib/taxedo/builder/text.rb
|
66
|
+
- lib/taxedo/builder.rb
|
67
|
+
- lib/taxedo/implants/action_controller.rb
|
68
|
+
- lib/taxedo/implants/railtie.rb
|
69
|
+
- lib/taxedo/implants.rb
|
70
|
+
- lib/taxedo/receipt.rb
|
71
|
+
- lib/taxedo/region.rb
|
72
|
+
- lib/taxedo/tax.rb
|
73
|
+
- lib/taxedo.rb
|
74
|
+
- spec/spec_helper.rb
|
75
|
+
- spec/taxedo/builder/hash_spec.rb
|
76
|
+
- spec/taxedo/builder/html_spec.rb
|
77
|
+
- spec/taxedo/builder/json_spec.rb
|
78
|
+
- spec/taxedo/builder/price_spec.rb
|
79
|
+
- spec/taxedo/builder/text_spec.rb
|
80
|
+
- spec/taxedo/receipt_spec.rb
|
81
|
+
- spec/taxedo/region_spec.rb
|
82
|
+
- spec/taxedo/tax_spec.rb
|
83
|
+
- spec/taxedo_spec.rb
|
84
|
+
- LICENSE
|
85
|
+
- README.md
|
86
|
+
- Rakefile
|
87
|
+
- Gemfile
|
88
|
+
homepage: https://github.com/demarque/taxedo
|
89
|
+
licenses:
|
90
|
+
- MIT
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options: []
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ! '>='
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
none: false
|
103
|
+
requirements:
|
104
|
+
- - ! '>='
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubyforge_project: taxedo
|
109
|
+
rubygems_version: 1.8.17
|
110
|
+
signing_key:
|
111
|
+
specification_version: 3
|
112
|
+
summary: ''
|
113
|
+
test_files: []
|