invoicing 0.2.1 → 1.0.0

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.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +1 -0
  3. data/README.md +57 -0
  4. data/Rakefile +16 -37
  5. data/lib/invoicing.rb +20 -10
  6. data/lib/invoicing/cached_record.rb +9 -6
  7. data/lib/invoicing/class_info.rb +34 -34
  8. data/lib/invoicing/connection_adapter_ext.rb +4 -4
  9. data/lib/invoicing/countries/uk.rb +6 -6
  10. data/lib/invoicing/currency_value.rb +39 -32
  11. data/lib/invoicing/find_subclasses.rb +40 -15
  12. data/lib/invoicing/ledger_item.rb +166 -145
  13. data/lib/invoicing/ledger_item/pdf_generator.rb +108 -0
  14. data/lib/invoicing/ledger_item/render_html.rb +76 -73
  15. data/lib/invoicing/ledger_item/render_ubl.rb +37 -35
  16. data/lib/invoicing/line_item.rb +43 -38
  17. data/lib/invoicing/price.rb +1 -1
  18. data/lib/invoicing/tax_rate.rb +3 -6
  19. data/lib/invoicing/taxable.rb +37 -32
  20. data/lib/invoicing/time_dependent.rb +40 -40
  21. data/lib/invoicing/version.rb +4 -4
  22. data/lib/rails/generators/invoicing/invoicing_generator.rb +14 -0
  23. data/lib/rails/generators/invoicing/ledger_item/ledger_item_generator.rb +17 -0
  24. data/lib/rails/generators/invoicing/ledger_item/templates/migration.rb +25 -0
  25. data/lib/rails/generators/invoicing/ledger_item/templates/model.rb +5 -0
  26. data/lib/rails/generators/invoicing/line_item/line_item_generator.rb +17 -0
  27. data/lib/rails/generators/invoicing/line_item/templates/migration.rb +20 -0
  28. data/lib/rails/generators/invoicing/line_item/templates/model.rb +5 -0
  29. data/lib/rails/generators/invoicing/tax_rate/tax_rate_generator.rb +17 -0
  30. data/lib/rails/generators/invoicing/tax_rate/templates/migration.rb +14 -0
  31. data/lib/rails/generators/invoicing/tax_rate/templates/model.rb +3 -0
  32. metadata +110 -153
  33. data.tar.gz.sig +0 -1
  34. data/History.txt +0 -31
  35. data/Manifest.txt +0 -62
  36. data/PostInstall.txt +0 -10
  37. data/README.rdoc +0 -58
  38. data/script/console +0 -10
  39. data/script/destroy +0 -14
  40. data/script/generate +0 -14
  41. data/tasks/rcov.rake +0 -4
  42. data/test/cached_record_test.rb +0 -100
  43. data/test/class_info_test.rb +0 -253
  44. data/test/connection_adapter_ext_test.rb +0 -79
  45. data/test/currency_value_test.rb +0 -209
  46. data/test/find_subclasses_test.rb +0 -120
  47. data/test/fixtures/README +0 -7
  48. data/test/fixtures/cached_record.sql +0 -22
  49. data/test/fixtures/class_info.sql +0 -28
  50. data/test/fixtures/currency_value.sql +0 -29
  51. data/test/fixtures/find_subclasses.sql +0 -43
  52. data/test/fixtures/ledger_item.sql +0 -39
  53. data/test/fixtures/line_item.sql +0 -33
  54. data/test/fixtures/price.sql +0 -4
  55. data/test/fixtures/tax_rate.sql +0 -4
  56. data/test/fixtures/taxable.sql +0 -14
  57. data/test/fixtures/time_dependent.sql +0 -35
  58. data/test/ledger_item_test.rb +0 -444
  59. data/test/line_item_test.rb +0 -139
  60. data/test/models/README +0 -4
  61. data/test/models/test_subclass_in_another_file.rb +0 -3
  62. data/test/models/test_subclass_not_in_database.rb +0 -6
  63. data/test/price_test.rb +0 -9
  64. data/test/ref-output/creditnote3.html +0 -82
  65. data/test/ref-output/creditnote3.xml +0 -89
  66. data/test/ref-output/invoice1.html +0 -93
  67. data/test/ref-output/invoice1.xml +0 -111
  68. data/test/ref-output/invoice2.html +0 -86
  69. data/test/ref-output/invoice2.xml +0 -98
  70. data/test/ref-output/invoice_null.html +0 -36
  71. data/test/render_html_test.rb +0 -70
  72. data/test/render_ubl_test.rb +0 -44
  73. data/test/setup.rb +0 -37
  74. data/test/tax_rate_test.rb +0 -9
  75. data/test/taxable_test.rb +0 -180
  76. data/test/test_helper.rb +0 -72
  77. data/test/time_dependent_test.rb +0 -180
  78. metadata.gz.sig +0 -4
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 460fa683bd1ba56dede941135a9db41b2b7236cf
4
+ data.tar.gz: 0ab573110cdf7d5c6bb424b2f69880f2f3a6d347
5
+ SHA512:
6
+ metadata.gz: cf54abdd39ade52d2c41ad3757cd4b4b482853bb189e0ac0fe8371a6b5641de5f702557159a61a3d0332a012493b0258420ed7624306b5ff8cb6edb8e306c7b8
7
+ data.tar.gz: 4a41f9ba2236663d0463348cf5880a89e4d54e4d342e59ba147de4d8d33a4a1ba607422112e6b6db2d18d86d68c7c4eeb124eace3c2c9af7ed81451026466edc
data/LICENSE CHANGED
@@ -1,5 +1,6 @@
1
1
  Copyright (c) 2009 Martin Kleppmann
2
2
  Copyright (c) 2009 Ept Computing Limited
3
+ Copyright (c) 2014 Codemancers Tech Pvt Limited
3
4
 
4
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of
5
6
  this software and associated documentation files (the "Software"), to deal in
@@ -0,0 +1,57 @@
1
+ # Ruby Invoicing Framework
2
+ [![Build Status](https://travis-ci.org/code-mancers/invoicing.svg?branch=master)](https://travis-ci.org/code-mancers/invoicing)
3
+ [![Code Climate](https://codeclimate.com/github/code-mancers/invoicing.png)](https://codeclimate.com/github/code-mancers/invoicing)
4
+
5
+ ## Description
6
+
7
+ This is a framework for generating and displaying invoices (ideal for commercial
8
+ Rails apps). It allows for flexible business logic; provides tools for tax handling,
9
+ commission calculation etc. It aims to be both developer-friendly and
10
+ accountant-friendly. Please visit invoicing [page](http://invoicing.codemancers.com/)
11
+ for more information about how to install and use.
12
+
13
+ ## Features
14
+
15
+ 1. Store any number of different types of invoice, credit note and payment
16
+ record
17
+ 2. Represent customer accounts, supplier accounts, and even complicated
18
+ multi-party billing relationships
19
+ 3. Automatically format currency values beautifully
20
+ 4. Automatically round currency values to the customary precision for that
21
+ particular currency, e.g. based on the smallest coin in circulation
22
+ 5. Support any number of different currencies simultaneously
23
+ 6. Render invoices, account statements etc. into HTML (fully styleable and
24
+ internationalisable)
25
+ 7. Export into the UBL XML format for sharing data with other systems
26
+ 8. Provide you with a default Value Added Tax (VAT) implementation, but you
27
+ can also easily plug in your own tax logic
28
+ 9. Dynamically display tax-inclusive or tax-exclusive prices depending on
29
+ your customer's location and preferences
30
+ 10. Deal with tax rates or prices changing over time, and automatically
31
+ switch to the new rate at the right moment
32
+ 11. Efficiently summarise account balances, sales statements etc. under
33
+ arbitrary conditions (e.g. data from one quarter, or payments due at a
34
+ particular date)
35
+
36
+ ## TODOs
37
+
38
+ 1. Slowly move away from `acts-as` model.
39
+ 2. Multiple taxes can be applied on goodies.
40
+ 3. Improve documentation for taxes
41
+
42
+
43
+ ## Credits
44
+
45
+ The Ruby invoicing framework originated as part of the website
46
+ [Bid for Wine](http://www.bidforwine.co.uk), developed by Patrick Dietrich,
47
+ Conrad Irwin, Michael Arnold and Martin Kleppmann for Ept Computing Ltd.
48
+ It was extracted from the Bid for Wine codebase and substantially extended
49
+ by Martin Kleppmann.
50
+
51
+ ## License
52
+
53
+ Copyright (c) 2009 Martin Kleppmann, Ept Computing Limited.
54
+ Copyright (c) 2014 Codemancers Tech Pvt Ltd
55
+
56
+ This gem is made publicly available under the terms of the MIT license.
57
+ See LICENSE and/or COPYING for details.
data/Rakefile CHANGED
@@ -1,43 +1,22 @@
1
- %w[rubygems rake rake/clean fileutils newgem rubigen hoe].each { |f| require f }
2
- require File.dirname(__FILE__) + '/lib/invoicing'
3
-
4
- # Hoe calls Ruby with the "-w" set by default; unfortunately, ActiveRecord (at version 2.2.2
5
- # at least) causes a lot of warnings internally, by no fault of our own, which clutters
6
- # the output. Comment out the following four lines to see those warnings.
7
- class Hoe
8
- RUBY_FLAGS = ENV['RUBY_FLAGS'] || "-I#{%w(lib test).join(File::PATH_SEPARATOR)}" +
9
- ((defined?(RUBY_DEBUG) && RUBY_DEBUG) ? " #{RUBY_DEBUG}" : '')
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
10
5
  end
11
6
 
12
- # Generate all the Rake tasks
13
- # Run 'rake -T' to see list of generated tasks (from gem root directory)
14
- $hoe = Hoe.spec 'invoicing' do |p|
15
- p.version = Invoicing::VERSION
16
- p.developer 'Martin Kleppmann', 'rubyforge@eptcomputing.com'
17
-
18
- p.summary = p.paragraphs_of('README.rdoc', 3).join
19
- p.description = p.paragraphs_of('README.rdoc', 3..5).join("\n\n")
20
- p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
21
- p.post_install_message = 'PostInstall.txt'
22
- p.rubyforge_name = p.name
7
+ require 'rubygems'
8
+ require 'rake'
9
+ require 'rake/clean'
10
+ require 'fileutils'
11
+ require 'rake/testtask'
23
12
 
24
- p.extra_deps = [
25
- ['activerecord', '>= 2.1.0'],
26
- ['builder', '>= 2.0']
27
- ]
28
- p.extra_dev_deps = [
29
- ['newgem', ">= #{::Newgem::VERSION}"]
30
- #['invoicing_generator', "= #{Invoicing::VERSION}"] - causes a circular dependency in rubygems < 1.2
31
- ]
13
+ # Tasks to run by default
14
+ task :default => [:test]
32
15
 
33
- p.test_globs = %w[test/*_test.rb] # do not include test/models/*.rb
34
- p.clean_globs |= %w[**/.DS_Store tmp *.log coverage]
35
- p.rsync_args = '-av --delete --ignore-errors'
36
- p.remote_rdoc_dir = 'doc'
16
+ Rake::TestTask.new do |t|
17
+ t.libs << "test"
18
+ t.test_files = FileList['test/**/*_test.rb']
19
+ t.warning = false
37
20
  end
38
21
 
39
- require 'newgem/tasks' # load /tasks/*.rake
40
- Dir['tasks/**/*.rake'].each { |t| load t }
41
-
42
- # Tasks to run by default
43
- # task :default => [:spec, :features]
22
+ Bundler::GemHelper.install_tasks
@@ -1,12 +1,22 @@
1
- $:.unshift(File.dirname(__FILE__)) unless
2
- $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
1
+ require "active_record"
3
2
 
4
- require 'activerecord'
3
+ require "invoicing/class_info" # load first because other modules depend on this
4
+ require "invoicing/cached_record"
5
+ require "invoicing/connection_adapter_ext"
6
+ require "invoicing/currency_value"
7
+ require "invoicing/find_subclasses"
8
+ require "invoicing/ledger_item"
9
+ require "invoicing/line_item"
10
+ require "invoicing/price"
11
+ require "invoicing/tax_rate"
12
+ require "invoicing/taxable"
13
+ require "invoicing/time_dependent"
5
14
 
6
- require 'invoicing/class_info' # load first because other modules depend on this
7
- Dir.glob(File.join(File.dirname(__FILE__), 'invoicing/**/*.rb')).sort.each {|f| require f }
8
-
9
- # Mix all modules Invoicing::*::ActMethods into ActiveRecord::Base as class methods
10
- Invoicing.constants.map{|c| Invoicing.const_get(c) }.select{|m| m.is_a?(Module) && m.const_defined?('ActMethods') }.each{
11
- |m| ActiveRecord::Base.send(:extend, m.const_get('ActMethods'))
12
- }
15
+ ActiveRecord::Base.send(:extend, Invoicing::CachedRecord::ActMethods)
16
+ ActiveRecord::Base.send(:extend, Invoicing::CurrencyValue::ActMethods)
17
+ ActiveRecord::Base.send(:extend, Invoicing::LedgerItem::ActMethods)
18
+ ActiveRecord::Base.send(:extend, Invoicing::LineItem::ActMethods)
19
+ ActiveRecord::Base.send(:extend, Invoicing::Price::ActMethods)
20
+ ActiveRecord::Base.send(:extend, Invoicing::TaxRate::ActMethods)
21
+ ActiveRecord::Base.send(:extend, Invoicing::Taxable::ActMethods)
22
+ ActiveRecord::Base.send(:extend, Invoicing::TimeDependent::ActMethods)
@@ -1,3 +1,5 @@
1
+ require 'active_support/concern'
2
+
1
3
  module Invoicing
2
4
  # == Aggressive ActiveRecord cache
3
5
  #
@@ -20,6 +22,7 @@ module Invoicing
20
22
  # To activate +CachedRecord+, call +acts_as_cached_record+ in the scope of an
21
23
  # <tt>ActiveRecord::Base</tt> class.
22
24
  module CachedRecord
25
+ extend ActiveSupport::Concern
23
26
 
24
27
  module ActMethods
25
28
  # Call +acts_as_cached_record+ on an <tt>ActiveRecord::Base</tt> class to declare
@@ -63,7 +66,7 @@ module Invoicing
63
66
  def cached_record_list
64
67
  cached_record_class_info.list
65
68
  end
66
-
69
+
67
70
  # Reloads the cached objects from the database.
68
71
  def reload_cache
69
72
  cached_record_class_info.reload_cache
@@ -78,12 +81,12 @@ module Invoicing
78
81
  super
79
82
  reload_cache
80
83
  end
81
-
84
+
82
85
  def reload_cache
83
86
  @cache = {}
84
- model_class.find(:all).each {|obj| @cache[get(obj, :id)] = obj }
87
+ model_class.all.each {|obj| @cache[get(obj, :id)] = obj }
85
88
  end
86
-
89
+
87
90
  # Returns one object from the cache, given its ID.
88
91
  def find_one(id, options)
89
92
  if result = @cache[id]
@@ -92,12 +95,12 @@ module Invoicing
92
95
  raise ::ActiveRecord::RecordNotFound, "Couldn't find #{model_class.name} with ID=#{id}"
93
96
  end
94
97
  end
95
-
98
+
96
99
  # Returns a list of objects from the cache, given a list of IDs.
97
100
  def find_some(ids, options)
98
101
  ids.map{|id| find_one(id, options) }
99
102
  end
100
-
103
+
101
104
  # Returns a list of all objects in the cache.
102
105
  def list
103
106
  @cache.values
@@ -18,19 +18,19 @@ module Invoicing
18
18
  # Invoicing::ClassInfo.acts_as(MyNamespace::Teleporter, self, args)
19
19
  # end
20
20
  # end
21
- #
21
+ #
22
22
  # def transmogrify_the_instance # will become an instance method of the class on which the
23
23
  # info = teleporter_class_info # acts_as_ method is called.
24
24
  # info.do_transmogrify
25
25
  # end
26
- #
26
+ #
27
27
  # module ClassMethods
28
28
  # def transmogrify_the_class # will become a class method of the class on which the
29
29
  # info = teleporter_class_info # acts_as_ method is called.
30
30
  # info.do_transmogrify
31
31
  # end
32
32
  # end
33
- #
33
+ #
34
34
  # class ClassInfo < Invoicing::ClassInfo::Base
35
35
  # def do_transmogrify
36
36
  # case all_options[:transmogrification]
@@ -40,7 +40,7 @@ module Invoicing
40
40
  # end
41
41
  # end
42
42
  # end
43
- #
43
+ #
44
44
  # ActiveRecord::Base.send(:extend, MyNamespace::Teleporter::ActMethods)
45
45
  #
46
46
  #
@@ -51,11 +51,11 @@ module Invoicing
51
51
  # class Teleporter < ActiveRecord::Base
52
52
  # acts_as_teleporter 'Zoom2020', :transmogrification => :total
53
53
  # end
54
- #
54
+ #
55
55
  # Teleporter.transmogrify_the_class # both return "Transmogrified by Zoom2020"
56
56
  # Teleporter.find(42).transmogrify_the_instance
57
57
  module ClassInfo
58
-
58
+
59
59
  # Provides the main implementation pattern for an +acts_as_+ method. See the example above
60
60
  # for usage.
61
61
  # +source_module+:: The module object which is using the +ClassInfo+ pattern
@@ -65,28 +65,28 @@ module Invoicing
65
65
  # The name by which the particular module using ClassInfo is known
66
66
  module_name = source_module.name.split('::').last.underscore
67
67
  class_info_method = "#{module_name}_class_info"
68
-
69
- previous_info = if calling_class.private_instance_methods(true).include?(class_info_method)
70
- # acts_as has been called before on the same class, or a superclass
71
- calling_class.send(class_info_method)
72
- else
73
- # acts_as is being called for the first time -- do the mixins!
74
- calling_class.send(:include, source_module)
75
- calling_class.send(:extend, source_module.const_get('ClassMethods')) if source_module.constants.include? 'ClassMethods'
76
- nil # no previous_info
77
- end
78
-
68
+
69
+ previous_info =
70
+ if calling_class.respond_to?(class_info_method, true)
71
+ # acts_as has been called before on the same class, or a superclass
72
+ calling_class.send(class_info_method) || calling_class.superclass.send(class_info_method)
73
+ else
74
+ # acts_as is being called for the first time -- do the mixins!
75
+ calling_class.send(:include, source_module)
76
+ nil # no previous_info
77
+ end
78
+
79
79
  # Instantiate the ClassInfo::Base subclass and assign it to an instance variable in calling_class
80
80
  class_info_class = source_module.const_get('ClassInfo')
81
81
  class_info = class_info_class.new(calling_class, previous_info, args)
82
82
  calling_class.instance_variable_set("@#{class_info_method}", class_info)
83
-
83
+
84
84
  # Define a getter class method on calling_class through which the ClassInfo::Base
85
85
  # instance can be accessed.
86
86
  calling_class.class_eval <<-CLASSEVAL
87
87
  class << self
88
88
  def #{class_info_method}
89
- if superclass.private_instance_methods(true).include?("#{class_info_method}")
89
+ if superclass.respond_to?("#{class_info_method}", true)
90
90
  @#{class_info_method} ||= superclass.send("#{class_info_method}")
91
91
  end
92
92
  @#{class_info_method}
@@ -94,7 +94,7 @@ module Invoicing
94
94
  private "#{class_info_method}"
95
95
  end
96
96
  CLASSEVAL
97
-
97
+
98
98
  # For convenience, also define an instance method which does the same as the class method
99
99
  calling_class.class_eval do
100
100
  define_method class_info_method do
@@ -103,8 +103,8 @@ module Invoicing
103
103
  private class_info_method
104
104
  end
105
105
  end
106
-
107
-
106
+
107
+
108
108
  # Base class for +ClassInfo+ objects, from which you need to derive a subclass in each module where
109
109
  # you want to use +ClassInfo+. An instance of a <tt>ClassInfo::Base</tt> subclass is created every
110
110
  # time an +acts_as_+ method is called, and that instance can be accessed through the
@@ -112,27 +112,27 @@ module Invoicing
112
112
  class Base
113
113
  # The class on which the +acts_as_+ method was called
114
114
  attr_reader :model_class
115
-
115
+
116
116
  # The <tt>ClassInfo::Base</tt> instance created by the last +acts_as_+ method
117
117
  # call on the same class (or its superclass); +nil+ if this is the first call.
118
118
  attr_reader :previous_info
119
-
119
+
120
120
  # The list of arguments passed to the current +acts_as_+ method call (excluding the final options hash)
121
121
  attr_reader :current_args
122
-
122
+
123
123
  # Union of +current_args+ and <tt>previous_info.all_args</tt>
124
124
  attr_reader :all_args
125
-
125
+
126
126
  # <tt>self.all_args - previous_info.all_args</tt>
127
127
  attr_reader :new_args
128
-
128
+
129
129
  # The options hash passed to the current +acts_as_+ method call
130
130
  attr_reader :current_options
131
-
131
+
132
132
  # Hash of options with symbolized keys, with +option_defaults+ overridden by +previous_info+ options,
133
133
  # in turn overridden by +current_options+.
134
134
  attr_reader :all_options
135
-
135
+
136
136
  # Initialises a <tt>ClassInfo::Base</tt> instance and parses arguments.
137
137
  # If subclasses override +initialize+ they should call +super+.
138
138
  # +model_class+:: The class on which the +acts_as+ method was called
@@ -150,26 +150,26 @@ module Invoicing
150
150
  @current_options = args.extract_options!.symbolize_keys
151
151
  @all_options = (@previous_info.nil? ? option_defaults : @previous_info.all_options).clone
152
152
  @all_options.update(@current_options)
153
-
153
+
154
154
  @all_args = @new_args = @current_args = args.flatten.uniq
155
155
  unless @previous_info.nil?
156
156
  @all_args = (@previous_info.all_args + @all_args).uniq
157
157
  @new_args = @all_args - previous_info.all_args
158
158
  end
159
159
  end
160
-
160
+
161
161
  # Override this method to return a hash of default option values.
162
162
  def option_defaults
163
163
  {}
164
164
  end
165
-
165
+
166
166
  # If there is an option with the given key, returns the associated value; otherwise returns
167
167
  # the key. This is useful for mapping method names to their renamed equivalents through options.
168
168
  def method(name)
169
169
  name = name.to_sym
170
170
  (all_options[name] || name).to_s
171
171
  end
172
-
172
+
173
173
  # Returns the value returned by calling +method_name+ (renamed through options using +method+)
174
174
  # on +object+. Returns +nil+ if +object+ is +nil+ or +object+ does not respond to that method.
175
175
  def get(object, method_name)
@@ -184,4 +184,4 @@ module Invoicing
184
184
  end
185
185
  end
186
186
  end
187
- end
187
+ end
@@ -2,20 +2,20 @@ module Invoicing
2
2
  # Extensions specific to certain database adapters. Currently only MySQL and PostgreSQL are
3
3
  # supported.
4
4
  class ConnectionAdapterExt
5
-
5
+
6
6
  # Creates a database-specific SQL fragment for evaluating a three-legged conditional function
7
7
  # in a query.
8
8
  def self.conditional_function(condition, value_if_true, value_if_false)
9
9
  case ActiveRecord::Base.connection.adapter_name
10
10
  when "MySQL"
11
11
  "IF(#{condition}, #{value_if_true}, #{value_if_false})"
12
- when "PostgreSQL"
12
+ when "PostgreSQL", "SQLite"
13
13
  "CASE WHEN #{condition} THEN #{value_if_true} ELSE #{value_if_false} END"
14
14
  else
15
15
  raise "Database adapter #{ActiveRecord::Base.connection.adapter_name} not supported by invoicing gem"
16
16
  end
17
17
  end
18
-
18
+
19
19
  # Suppose <tt>A has_many B</tt>, and you want to select all As, counting for each A how many
20
20
  # Bs it has. In MySQL you can just say:
21
21
  # SELECT A.*, COUNT(B.id) AS number_of_bs FROM A LEFT JOIN B on A.id = B.a_id GROUP BY A.id
@@ -32,7 +32,7 @@ module Invoicing
32
32
  when "MySQL"
33
33
  model_class.quoted_table_name + "." +
34
34
  ActiveRecord::Base.connection.quote_column_name(model_class.primary_key)
35
- when "PostgreSQL"
35
+ when "PostgreSQL", "SQLite"
36
36
  model_class.column_names.map{ |column|
37
37
  model_class.quoted_table_name + "." + ActiveRecord::Base.connection.quote_column_name(column)
38
38
  }.join(', ')
@@ -6,27 +6,27 @@ module Invoicing
6
6
  def tax_rate(params)
7
7
  params[:model_object].send(:tax_rate)
8
8
  end
9
-
9
+
10
10
  def tax_factor(params)
11
11
  BigDecimal('1') + tax_rate(params).rate
12
12
  end
13
-
13
+
14
14
  def tax_percent(params)
15
15
  BigDecimal('100') * tax_rate(params).rate
16
16
  end
17
-
17
+
18
18
  def apply_tax(params)
19
19
  params[:value] * tax_factor(params)
20
20
  end
21
-
21
+
22
22
  def remove_tax(params)
23
23
  params[:value] / tax_factor(params)
24
24
  end
25
-
25
+
26
26
  def tax_info(params)
27
27
  "(inc. VAT)"
28
28
  end
29
-
29
+
30
30
  def tax_details(params)
31
31
  "(including VAT at #{tax_percent(params).to_s}%)"
32
32
  end