invoicing 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig CHANGED
Binary file
data/History.txt CHANGED
@@ -1,3 +1,13 @@
1
+ == 0.2.1
2
+
3
+ * 2 minor enhancements:
4
+ * Added option to LedgerItem#account_summary which enables inclusion of open/pending
5
+ ledger items in the summary
6
+ * Improved robustness and documentation for test suite
7
+ * 2 bugfixes:
8
+ * Compatibility with recent versions of ActiveRecord
9
+ * Cleaned up unnecessary gem dependencies (mocha, uuid)
10
+
1
11
  == 0.2.0 2009-04-20
2
12
 
3
13
  * 4 major enhancements:
data/README.rdoc CHANGED
@@ -20,6 +20,9 @@ Please see {the website}[http://ept.github.com/invoicing/] for an introduction
20
20
  to using Invoicing, and check the
21
21
  {API reference}[http://invoicing.rubyforge.org/doc/] for in-depth details.
22
22
 
23
+ If you're interested in contributing to the invoicing gem itself, please see the file
24
+ {HACKING.md}[http://github.com/ept/invoicing/blob/master/HACKING.md].
25
+
23
26
  == FEATURES
24
27
 
25
28
  * TODO
data/Rakefile CHANGED
@@ -1,4 +1,4 @@
1
- %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
1
+ %w[rubygems rake rake/clean fileutils newgem rubigen hoe].each { |f| require f }
2
2
  require File.dirname(__FILE__) + '/lib/invoicing'
3
3
 
4
4
  # Hoe calls Ruby with the "-w" set by default; unfortunately, ActiveRecord (at version 2.2.2
@@ -6,16 +6,21 @@ require File.dirname(__FILE__) + '/lib/invoicing'
6
6
  # the output. Comment out the following four lines to see those warnings.
7
7
  class Hoe
8
8
  RUBY_FLAGS = ENV['RUBY_FLAGS'] || "-I#{%w(lib test).join(File::PATH_SEPARATOR)}" +
9
- (RUBY_DEBUG ? " #{RUBY_DEBUG}" : '')
9
+ ((defined?(RUBY_DEBUG) && RUBY_DEBUG) ? " #{RUBY_DEBUG}" : '')
10
10
  end
11
11
 
12
12
  # Generate all the Rake tasks
13
13
  # Run 'rake -T' to see list of generated tasks (from gem root directory)
14
- $hoe = Hoe.new('invoicing', Invoicing::VERSION) do |p|
15
- p.developer('Martin Kleppmann', 'rubyforge@eptcomputing.com')
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")
16
20
  p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
17
21
  p.post_install_message = 'PostInstall.txt'
18
22
  p.rubyforge_name = p.name
23
+
19
24
  p.extra_deps = [
20
25
  ['activerecord', '>= 2.1.0'],
21
26
  ['builder', '>= 2.0']
@@ -28,6 +33,7 @@ $hoe = Hoe.new('invoicing', Invoicing::VERSION) do |p|
28
33
  p.test_globs = %w[test/*_test.rb] # do not include test/models/*.rb
29
34
  p.clean_globs |= %w[**/.DS_Store tmp *.log coverage]
30
35
  p.rsync_args = '-av --delete --ignore-errors'
36
+ p.remote_rdoc_dir = 'doc'
31
37
  end
32
38
 
33
39
  require 'newgem/tasks' # load /tasks/*.rake
data/lib/invoicing.rb CHANGED
@@ -1,3 +1,6 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
1
4
  require 'activerecord'
2
5
 
3
6
  require 'invoicing/class_info' # load first because other modules depend on this
@@ -3,12 +3,24 @@ module Invoicing
3
3
  module UK
4
4
  # Extremely simplistic implementation of UK VAT. This needs to be fixed.
5
5
  class VAT
6
+ def tax_rate(params)
7
+ params[:model_object].send(:tax_rate)
8
+ end
9
+
10
+ def tax_factor(params)
11
+ BigDecimal('1') + tax_rate(params).rate
12
+ end
13
+
14
+ def tax_percent(params)
15
+ BigDecimal('100') * tax_rate(params).rate
16
+ end
17
+
6
18
  def apply_tax(params)
7
- params[:value] * BigDecimal('1.15')
19
+ params[:value] * tax_factor(params)
8
20
  end
9
21
 
10
22
  def remove_tax(params)
11
- params[:value] / BigDecimal('1.15')
23
+ params[:value] / tax_factor(params)
12
24
  end
13
25
 
14
26
  def tax_info(params)
@@ -16,7 +28,7 @@ module Invoicing
16
28
  end
17
29
 
18
30
  def tax_details(params)
19
- "(including VAT at 15%)"
31
+ "(including VAT at #{tax_percent(params).to_s}%)"
20
32
  end
21
33
  end
22
34
  end
@@ -430,6 +430,8 @@ module Invoicing
430
430
  # Make sure ledger_item association is assigned -- the CurrencyValue
431
431
  # getters depend on it to fetch the currency
432
432
  info.set(line, :ledger_item, self)
433
+ line.valid? # Ensure any before_validation hooks are called
434
+
433
435
  net_amount = info.get(line, :net_amount)
434
436
  tax_amount = info.get(line, :tax_amount)
435
437
  net_total += net_amount unless net_amount.nil?
@@ -615,7 +617,13 @@ module Invoicing
615
617
  #
616
618
  # If +other_id+ is +nil+, this method aggregates the accounts of +self_id+ with *all* other
617
619
  # parties.
618
- def account_summary(self_id, other_id=nil)
620
+ #
621
+ # Also accepts options:
622
+ #
623
+ # <tt>:with_status</tt>:: List of ledger item status strings; only ledger items whose status
624
+ # is one of these will be taken into account. Default:
625
+ # <tt>["closed", "cleared"]</tt>.
626
+ def account_summary(self_id, other_id=nil, options={})
619
627
  info = ledger_item_class_info
620
628
  self_id = self_id.to_i
621
629
  other_id = [nil, ''].include?(other_id) ? nil : other_id.to_i
@@ -623,7 +631,7 @@ module Invoicing
623
631
  if other_id.nil?
624
632
  result = {}
625
633
  # Sum over all others, grouped by currency
626
- account_summaries(self_id).each_pair do |other_id, hash|
634
+ account_summaries(self_id, options).each_pair do |other_id, hash|
627
635
  hash.each_pair do |currency, summary|
628
636
  if result[currency]
629
637
  result[currency] += summary
@@ -638,7 +646,7 @@ module Invoicing
638
646
  conditions = {info.method(:sender_id) => [self_id, other_id],
639
647
  info.method(:recipient_id) => [self_id, other_id]}
640
648
  with_scope(:find => {:conditions => conditions}) do
641
- account_summaries(self_id)[other_id] || {}
649
+ account_summaries(self_id, options)[other_id] || {}
642
650
  end
643
651
  end
644
652
  end
@@ -661,7 +669,13 @@ module Invoicing
661
669
  # q3_2008 = ['issue_date >= ? AND issue_date < ?', DateTime.parse('2008-07-01'), DateTime.parse('2008-10-01')]
662
670
  # LedgerItem.scoped(:conditions => q3_2008).account_summaries(1)
663
671
  #
664
- def account_summaries(self_id)
672
+ #
673
+ # Also accepts options:
674
+ #
675
+ # <tt>:with_status</tt>:: List of ledger item status strings; only ledger items whose status
676
+ # is one of these will be taken into account. Default:
677
+ # <tt>["closed", "cleared"]</tt>.
678
+ def account_summaries(self_id, options={})
665
679
  info = ledger_item_class_info
666
680
  ext = Invoicing::ConnectionAdapterExt
667
681
  scope = scope(:find)
@@ -681,8 +695,9 @@ module Invoicing
681
695
  sender_is_self = merge_conditions({info.method(:sender_id) => self_id})
682
696
  recipient_is_self = merge_conditions({info.method(:recipient_id) => self_id})
683
697
  other_id_column = ext.conditional_function(sender_is_self, cols[:recipient_id], cols[:sender_id])
684
- filter_conditions = "#{cols[:status]} IN ('closed','cleared') AND (#{sender_is_self} OR #{recipient_is_self})"
685
-
698
+ accept_status = sanitize_sql_hash_for_conditions(info.method(:status) => (options[:with_status] || %w(closed cleared)))
699
+ filter_conditions = "#{accept_status} AND (#{sender_is_self} OR #{recipient_is_self})"
700
+
686
701
  sql = "SELECT #{other_id_column} AS other_id, #{cols[:currency]} AS currency, " +
687
702
  "SUM(#{ext.conditional_function(debit_when_sent, cols[:total_amount], 0)}) AS sales, " +
688
703
  "SUM(#{ext.conditional_function(debit_when_received, cols[:total_amount], 0)}) AS purchase_payments, " +
@@ -190,7 +190,8 @@ module Invoicing
190
190
  end
191
191
 
192
192
  def default_identifier_label
193
- "Invoice no.:"
193
+ label = (factor == BigDecimal('-1')) ? invoke_credit_note_label : invoke_invoice_label
194
+ "#{label} no.:"
194
195
  end
195
196
 
196
197
  def default_issue_date_label
@@ -90,7 +90,7 @@ module Invoicing
90
90
  invoice.cbc :ID, identifier
91
91
  invoice.cbc :UUID, uuid if uuid
92
92
 
93
- issue_date_formatted, issue_time_formatted = (issue_date || Time.now).in_time_zone.xmlschema.split('T')
93
+ issue_date_formatted, issue_time_formatted = date_and_time(issue_date || Time.now)
94
94
  invoice.cbc :IssueDate, issue_date_formatted
95
95
  invoice.cbc :IssueTime, issue_time_formatted
96
96
 
@@ -173,8 +173,8 @@ module Invoicing
173
173
  # <cbc:EndDate>2008-07-02</cbc:EndDate>
174
174
  # <cbc:EndTime>01:02:03+02:00</cbc:EndTime>
175
175
  def build_period(xml, start_datetime, end_datetime)
176
- start_date, start_time = start_datetime.in_time_zone.xmlschema.split('T')
177
- end_date, end_time = end_datetime.in_time_zone.xmlschema.split('T')
176
+ start_date, start_time = date_and_time(start_datetime)
177
+ end_date, end_time = date_and_time(end_datetime)
178
178
  xml.cbc :StartDate, start_date
179
179
  xml.cbc :StartTime, start_time
180
180
  xml.cbc :EndDate, end_date
@@ -247,7 +247,10 @@ module Invoicing
247
247
  quantity_tag = [:Invoice, :SelfBilledInvoice].include?(doc_type) ? :InvoicedQuantity : :CreditedQuantity
248
248
  invoice_line.cbc quantity_tag, quantity_of(line_item) if quantity_of(line_item)
249
249
  invoice_line.cbc :LineExtensionAmount, (factor*net_amount_of(line_item)).to_s, :currencyID => currency
250
- invoice_line.cbc :TaxPointDate, tax_point_of(line_item).in_time_zone.strftime('%Y-%m-%d') if tax_point_of(line_item)
250
+ if tax_point_of(line_item)
251
+ tax_point_date, tax_point_time = date_and_time(tax_point_of(line_item))
252
+ invoice_line.cbc :TaxPointDate, tax_point_date
253
+ end
251
254
 
252
255
  invoice_line.cac :TaxTotal do |tax_total|
253
256
  tax_total.cbc :TaxAmount, (factor*tax_amount_of(line_item)).to_s, :currencyID => currency
@@ -263,6 +266,14 @@ module Invoicing
263
266
 
264
267
  #cac:Price
265
268
  end
269
+
270
+ private
271
+
272
+ # Returns an array of two strings, <tt>[date, time]</tt> in the format specified by UBL,
273
+ # for a given datetime value.
274
+ def date_and_time(value)
275
+ value.in_time_zone(Time.zone || 'Etc/UTC').xmlschema.split('T')
276
+ end
266
277
  end
267
278
  end
268
279
  end
@@ -149,6 +149,8 @@ module Invoicing
149
149
  # Set the 'amount' columns to act as currency values
150
150
  acts_as_currency_value(info.method(:net_amount), info.method(:tax_amount))
151
151
 
152
+ before_validation :calculate_tax_amount
153
+
152
154
  extend Invoicing::FindSubclasses
153
155
 
154
156
  # Dynamically created named scopes
@@ -192,6 +194,11 @@ module Invoicing
192
194
  ledger_item.send(:ledger_item_class_info).get(ledger_item, :currency)
193
195
  end
194
196
 
197
+ def calculate_tax_amount
198
+ return unless respond_to? :net_amount_taxed
199
+ self.tax_amount = net_amount_taxed - net_amount
200
+ end
201
+
195
202
  # The sum of +net_amount+ and +tax_amount+.
196
203
  def gross_amount
197
204
  net_amount = line_item_class_info.get(self, :net_amount)
@@ -212,6 +219,8 @@ module Invoicing
212
219
  raise RuntimeError, "You need to define an association like 'belongs_to :ledger_item' on #{self.class.name}. If you " +
213
220
  "have defined the association with a different name, pass the option :ledger_item => :your_association_name to " +
214
221
  "acts_as_line_item."
222
+ elsif method_name =~ /^amount/
223
+ send("net_#{method_name}", *args)
215
224
  else
216
225
  super
217
226
  end
@@ -2,8 +2,21 @@ module Invoicing
2
2
  module TaxRate
3
3
  module ActMethods
4
4
  def acts_as_tax_rate(*args)
5
+ Invoicing::ClassInfo.acts_as(Invoicing::TaxRate, self, args)
6
+ info = tax_rate_class_info
5
7
 
8
+ if info.previous_info.nil? # Called for the first time?
9
+ # Import TimeDependent functionality
10
+ acts_as_time_dependent :value => :rate
11
+ end
6
12
  end
7
13
  end
14
+
15
+ # Stores state in the ActiveRecord class object
16
+ class ClassInfo < Invoicing::ClassInfo::Base #:nodoc:
17
+ def initialize(model_class, previous_info, args)
18
+ super
19
+ end
20
+ end
8
21
  end
9
22
  end
@@ -2,7 +2,7 @@ module Invoicing
2
2
  module Version
3
3
  MAJOR = 0
4
4
  MINOR = 2
5
- BUILD = 0
5
+ BUILD = 1
6
6
 
7
7
  def to_a
8
8
  [MAJOR, MINOR, BUILD]
@@ -9,11 +9,19 @@ class ConnectionAdapterExtTest < Test::Unit::TestCase
9
9
  end
10
10
 
11
11
  def using_database(database_type)
12
- begin
13
- ActiveRecord::Base.establish_connection(TEST_DB_CONFIG[database_type.to_sym])
12
+ if database_type.to_sym == database_used_for_testing
13
+ # If the test is for the main database type of this test suite, just run it
14
14
  yield
15
- ensure
16
- connect_to_testing_database
15
+
16
+ elsif test_in_all_databases
17
+ # Run the test having connected to the requested database type, or skip it
18
+ # if we're not trying to test all database types
19
+ begin
20
+ ActiveRecord::Base.establish_connection(TEST_DB_CONFIG[database_type.to_sym])
21
+ yield
22
+ ensure
23
+ connect_to_testing_database
24
+ end
17
25
  end
18
26
  end
19
27
 
@@ -68,4 +76,4 @@ class ConnectionAdapterExtTest < Test::Unit::TestCase
68
76
  end
69
77
  end
70
78
 
71
- end
79
+ end
@@ -218,11 +218,11 @@ class LedgerItemTest < Test::Unit::TestCase
218
218
 
219
219
  def test_uuid_gem_not_present
220
220
  begin
221
- real_uuid = Object.send(:remove_const, :UUID)
221
+ real_uuid = Object.send(:remove_const, :UUID) rescue nil
222
222
  UUIDNotPresentLedgerItem.acts_as_ledger_item(LedgerItemMethods::RENAMED_METHODS)
223
223
  assert_nil UUIDNotPresentLedgerItem.new.get_class_info.uuid_generator
224
224
  ensure
225
- Object.send(:const_set, :UUID, real_uuid)
225
+ Object.send(:const_set, :UUID, real_uuid) unless real_uuid.nil?
226
226
  end
227
227
  end
228
228
 
@@ -362,7 +362,17 @@ class LedgerItemTest < Test::Unit::TestCase
362
362
  assert_equal BigDecimal('0.00'), summary[:GBP].purchase_payments
363
363
  assert_equal BigDecimal('-666807.63'), summary[:GBP].balance
364
364
  end
365
-
365
+
366
+ def test_account_summary_with_include_open_option
367
+ summary = MyLedgerItem.account_summary(1, nil, :with_status => %w(open closed cleared))
368
+ assert_equal [:GBP], summary.keys
369
+ assert_equal BigDecimal('269.00'), summary[:GBP].sales
370
+ assert_equal BigDecimal('666808.63'), summary[:GBP].purchases
371
+ assert_equal BigDecimal('256.50'), summary[:GBP].sale_receipts
372
+ assert_equal BigDecimal('0.00'), summary[:GBP].purchase_payments
373
+ assert_equal BigDecimal('-666796.13'), summary[:GBP].balance
374
+ end
375
+
366
376
  def test_account_summary_to_s
367
377
  assert_equal "sales = £257.50; purchases = £666,808.63; sale_receipts = £256.50; " +
368
378
  "purchase_payments = £0.00; balance = −£666,807.63", MyLedgerItem.account_summary(1)[:GBP].to_s
@@ -99,11 +99,11 @@ class LineItemTest < Test::Unit::TestCase
99
99
 
100
100
  def test_uuid_gem_not_present
101
101
  begin
102
- real_uuid = Object.send(:remove_const, :UUID)
102
+ real_uuid = Object.send(:remove_const, :UUID) rescue nil
103
103
  UUIDNotPresentLineItem.acts_as_line_item(LineItemMethods::RENAMED_METHODS)
104
104
  assert_nil UUIDNotPresentLineItem.new.get_class_info.uuid_generator
105
105
  ensure
106
- Object.send(:const_set, :UUID, real_uuid)
106
+ Object.send(:const_set, :UUID, real_uuid) unless real_uuid.nil?
107
107
  end
108
108
  end
109
109
 
@@ -38,7 +38,7 @@
38
38
  </table>
39
39
  <table class="invoice metadata">
40
40
  <tr class="identifier">
41
- <th>Invoice no.:</th>
41
+ <th>Credit Note no.:</th>
42
42
  <td>putain!</td>
43
43
  </tr>
44
44
  <tr class="issue-date">
@@ -28,6 +28,7 @@ class RenderHTMLTest < Test::Unit::TestCase
28
28
  expected[0] = "<h1>INVOICE</h1>"
29
29
  expected[3] = " <th class=\"recipient\">Customer</th>"
30
30
  expected[4] = " <th class=\"sender\">Supplier</th>"
31
+ expected[40] = " <th>INVOICE no.:</th>"
31
32
  rendered = MyInvoice.find(1).render_html {|i|
32
33
  i.invoice_label{ "INVOICE" }
33
34
  i.sender_label "Supplier"
@@ -7,20 +7,32 @@ class RenderUBLTest < Test::Unit::TestCase
7
7
  def reference_output(filename)
8
8
  IO.readlines(File.join(File.dirname(__FILE__), 'ref-output', filename)).join
9
9
  end
10
-
10
+
11
+ # Compares two strings, each being a serialised XML document, while ignoring
12
+ # the order of attributes within elements.
13
+ # TODO: this could generate much nicer error messages on failure.
14
+ def assert_equivalent_xml(doc1, doc2)
15
+ doc1, doc2 = [doc1, doc2].map do |doc|
16
+ doc.gsub(/(<[^\s>]+\s+)([^>]+)(>)/) do |match|
17
+ $1.to_s + $2.to_s.split(/\s+/).sort.join(' ') + $3.to_s
18
+ end
19
+ end
20
+ assert_equal doc1, doc2
21
+ end
22
+
11
23
  def test_render_ubl_invoice
12
- assert_equal reference_output('invoice1.xml'), MyInvoice.find(1).render_ubl
24
+ assert_equivalent_xml reference_output('invoice1.xml'), MyInvoice.find(1).render_ubl
13
25
  end
14
26
 
15
27
  def test_render_ubl_self_billed_invoice
16
- assert_equal reference_output('invoice2.xml'), MyInvoice.find(2).render_ubl
28
+ assert_equivalent_xml reference_output('invoice2.xml'), MyInvoice.find(2).render_ubl
17
29
  end
18
30
 
19
31
  def test_render_ubl_credit_note
20
32
  #File.open(File.join(File.dirname(__FILE__), 'ref-output', 'debug3.xml'), 'w') do |f|
21
33
  # f.syswrite(MyCreditNote.find(3).render_ubl)
22
34
  #end
23
- assert_equal reference_output('creditnote3.xml'), MyCreditNote.find(3).render_ubl
35
+ assert_equivalent_xml reference_output('creditnote3.xml'), MyCreditNote.find(3).render_ubl
24
36
  end
25
37
 
26
38
  def test_cannot_render_unknown_ledger_item_subtype
data/test/test_helper.rb CHANGED
@@ -3,7 +3,6 @@ require 'rubygems'
3
3
  require 'activerecord'
4
4
  require 'activesupport'
5
5
  require 'flexmock/test_unit'
6
- require 'mocha'
7
6
 
8
7
  $: << File.join(File.dirname(__FILE__), '..', 'lib')
9
8
 
@@ -11,20 +10,45 @@ ActiveSupport::Dependencies.load_paths << File.join(File.dirname(__FILE__), 'mod
11
10
 
12
11
  require 'invoicing'
13
12
 
13
+ # Overridden by ../../config/database.yml if it exists.
14
14
  TEST_DB_CONFIG = {
15
15
  :postgresql => {:adapter => "postgresql", :host => "localhost", :database => "invoicing_test",
16
- :username => "postgres", :password => ""},
16
+ :username => "invoicing", :password => "password"},
17
17
  :mysql => {:adapter => "mysql", :host => "localhost", :database => "invoicing_test",
18
- :username => "root", :password => ""},
19
- :sqlite3 => {:adapter => "sqlite3", :database => Tempfile.new('invoicing_sqlite').path}
18
+ :username => "root", :password => ""}
20
19
  }
20
+ TEST_DB_CONFIG_FILE = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'config', 'database.yml'))
21
+
22
+ def database_used_for_testing
23
+ (ENV['DATABASE'] || :mysql).to_sym
24
+ end
25
+
26
+ def test_in_all_databases
27
+ !!ENV['TEST_ALL_DATABASES']
28
+ end
21
29
 
22
30
  def connect_to_testing_database
23
- ActiveRecord::Base.establish_connection(TEST_DB_CONFIG[(ENV['DATABASE'] || :mysql).to_sym])
31
+ db_config = TEST_DB_CONFIG[database_used_for_testing]
32
+ db_config_from_file = false
33
+
34
+ if File.exists? TEST_DB_CONFIG_FILE
35
+ yaml = YAML::load File.open(TEST_DB_CONFIG_FILE)
36
+ if yaml && yaml['test'] && (yaml['test']['adapter'].to_s == database_used_for_testing.to_s)
37
+ db_config = yaml['test']
38
+ db_config_from_file = true
39
+ end
40
+ end
41
+
42
+ puts "Connecting to #{database_used_for_testing} with config #{db_config.inspect}" +
43
+ (db_config_from_file ? " from #{TEST_DB_CONFIG_FILE}" : "")
44
+ ActiveRecord::Base.establish_connection(db_config)
24
45
  end
25
46
 
26
47
  connect_to_testing_database
27
48
 
49
+ require 'setup'
50
+
51
+
28
52
  ENV['TZ'] = 'Etc/UTC' # timezone of values in database
29
53
  ActiveRecord::Base.default_timezone = :utc # timezone of created_at and updated_at
30
54
  Time.zone = 'Etc/UTC' # timezone for output (when using Time#in_time_zone)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: invoicing
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Kleppmann
@@ -30,7 +30,7 @@ cert_chain:
30
30
  jT4Qh3sYJbvqWGFAQcuOIf4spvpNiA==
31
31
  -----END CERTIFICATE-----
32
32
 
33
- date: 2009-04-20 00:00:00 +01:00
33
+ date: 2009-08-26 00:00:00 +01:00
34
34
  default_executable:
35
35
  dependencies:
36
36
  - !ruby/object:Gem::Dependency
@@ -71,7 +71,7 @@ dependencies:
71
71
  requirements:
72
72
  - - ">="
73
73
  - !ruby/object:Gem::Version
74
- version: 1.8.0
74
+ version: 2.3.2
75
75
  version:
76
76
  description: This is a framework for generating and displaying invoices (ideal for commercial Rails apps). It allows for flexible business logic; provides tools for tax handling, commission calculation etc. It aims to be both developer-friendly and accountant-friendly. The Ruby Invoicing Framework is based on {ActiveRecord}[http://api.rubyonrails.org/classes/ActiveRecord/Base.html]. Please see {the website}[http://ept.github.com/invoicing/] for an introduction to using Invoicing, and check the {API reference}[http://invoicing.rubyforge.org/doc/] for in-depth details.
77
77
  email:
@@ -84,7 +84,6 @@ extra_rdoc_files:
84
84
  - History.txt
85
85
  - Manifest.txt
86
86
  - PostInstall.txt
87
- - README.rdoc
88
87
  files:
89
88
  - History.txt
90
89
  - LICENSE
@@ -149,11 +148,11 @@ files:
149
148
  - test/test_helper.rb
150
149
  - test/time_dependent_test.rb
151
150
  has_rdoc: true
152
- homepage: "{Ruby Invoicing Framework website}[http://ept.github.com/invoicing/]"
151
+ homepage:
153
152
  post_install_message: PostInstall.txt
154
153
  rdoc_options:
155
154
  - --main
156
- - README.rdoc
155
+ - README.txt
157
156
  require_paths:
158
157
  - lib
159
158
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -174,7 +173,7 @@ rubyforge_project: invoicing
174
173
  rubygems_version: 1.3.1
175
174
  signing_key:
176
175
  specification_version: 2
177
- summary: This is a framework for generating and displaying invoices (ideal for commercial Rails apps)
176
+ summary: This is a framework for generating and displaying invoices (ideal for commercial Rails apps). It allows for flexible business logic; provides tools for tax handling, commission calculation etc. It aims to be both developer-friendly and accountant-friendly.
178
177
  test_files:
179
178
  - test/cached_record_test.rb
180
179
  - test/class_info_test.rb
metadata.gz.sig CHANGED
@@ -1,3 +1,4 @@
1
- � -T"Q�;�!�嬈�C��4�H�`=�s��g^�(�v�PD��aOe<�QY
2
- 3�i!f�\gA}������]:�:c��gܣ���y��S,�3m�.9R(�}Z� �4Ҿ�� ?N/�x_�����E#���s�O�9��)wC�מ�B�H�K=P6�J�%��z�>"?�ї#N)��P��w;W�_�ѯ���`z��}��Cv
3
- �hJ�ڐ��V��w���Ac����$Uۘ}��ޮ��v&ͭ�y"
1
+ 9V��g贵��QV�
2
+ Ĺ���!�2ګ��iw���X��"�NBz�#��P��m�r%����iJ��e0wA���|��j���+=X.��v����_��%��bà
3
+ �MQ�����/����e��ْ�NQ�6[�m��5vc��$0
4
+ Te�kX{%v���Җ|��P3� �–������(��oTYE�dg��و��ќK�7��h-HB� �ZH,ư��c����&Wx����5A���A�t7i}���