invoicing_generator 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. data.tar.gz.sig +0 -0
  2. data/History.txt +21 -0
  3. data/LICENSE +20 -0
  4. data/Manifest.txt +29 -0
  5. data/PostInstall.txt +10 -0
  6. data/README.rdoc +55 -0
  7. data/Rakefile +25 -0
  8. data/lib/invoicing_generator.rb +18 -0
  9. data/lib/invoicing_generator/generator_extensions.rb +55 -0
  10. data/lib/invoicing_generator/name_tools.rb +83 -0
  11. data/lib/invoicing_generator/option_tools.rb +34 -0
  12. data/rails_generators/invoicing_ledger/USAGE +20 -0
  13. data/rails_generators/invoicing_ledger/invoicing_ledger_generator.rb +107 -0
  14. data/rails_generators/invoicing_ledger/templates/controller.rb +40 -0
  15. data/rails_generators/invoicing_ledger/templates/credit_note.rb +1 -0
  16. data/rails_generators/invoicing_ledger/templates/initializer.rb +2 -0
  17. data/rails_generators/invoicing_ledger/templates/invoice.rb +1 -0
  18. data/rails_generators/invoicing_ledger/templates/ledger_item.rb +49 -0
  19. data/rails_generators/invoicing_ledger/templates/ledger_view.html +26 -0
  20. data/rails_generators/invoicing_ledger/templates/line_item.rb +7 -0
  21. data/rails_generators/invoicing_ledger/templates/migration.rb +63 -0
  22. data/rails_generators/invoicing_ledger/templates/payment.rb +1 -0
  23. data/rails_generators/invoicing_ledger/templates/statement_view.html +48 -0
  24. data/rails_generators/invoicing_ledger/templates/stylesheet.css +127 -0
  25. data/script/console +10 -0
  26. data/script/destroy +14 -0
  27. data/script/generate +14 -0
  28. data/test/test_generator_helper.rb +36 -0
  29. data/test/test_helper.rb +3 -0
  30. data/test/test_invoicing_ledger_generator.rb +46 -0
  31. metadata +138 -0
  32. metadata.gz.sig +0 -0
Binary file
@@ -0,0 +1,21 @@
1
+ == 0.2.0 2009-04-20
2
+
3
+ * 4 major enhancements:
4
+ * New associated gem invoicing_generator for generating an invoicing component in a Rails project
5
+ (script/generate invoicing_ledger)
6
+ * Generated controller and views for rendering statements and ledger
7
+ * Comes with a nice default stylesheet out of the box
8
+ * More flexible formatting of currency values
9
+ * 1 bugfix:
10
+ * Accidental overwriting of total_amount value on payment LedgerItems without LineItems
11
+
12
+ == 0.1.0 2009-02-10
13
+
14
+ * 2 major enhancements:
15
+ * Core API is now usable
16
+ * RCov reports 100% test coverage
17
+
18
+ == 0.0.1 2009-01-05
19
+
20
+ * 1 major enhancement:
21
+ * Initial public release
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Martin Kleppmann
2
+ Copyright (c) 2009 Ept Computing Limited
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
5
+ this software and associated documentation files (the "Software"), to deal in
6
+ the Software without restriction, including without limitation the rights to
7
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8
+ of the Software, and to permit persons to whom the Software is furnished to do
9
+ so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ SOFTWARE.
@@ -0,0 +1,29 @@
1
+ History.txt
2
+ LICENSE
3
+ Manifest.txt
4
+ PostInstall.txt
5
+ README.rdoc
6
+ Rakefile
7
+ lib/invoicing_generator.rb
8
+ lib/invoicing_generator/generator_extensions.rb
9
+ lib/invoicing_generator/name_tools.rb
10
+ lib/invoicing_generator/option_tools.rb
11
+ rails_generators/invoicing_ledger/USAGE
12
+ rails_generators/invoicing_ledger/invoicing_ledger_generator.rb
13
+ rails_generators/invoicing_ledger/templates/controller.rb
14
+ rails_generators/invoicing_ledger/templates/credit_note.rb
15
+ rails_generators/invoicing_ledger/templates/initializer.rb
16
+ rails_generators/invoicing_ledger/templates/invoice.rb
17
+ rails_generators/invoicing_ledger/templates/ledger_item.rb
18
+ rails_generators/invoicing_ledger/templates/ledger_view.html
19
+ rails_generators/invoicing_ledger/templates/line_item.rb
20
+ rails_generators/invoicing_ledger/templates/migration.rb
21
+ rails_generators/invoicing_ledger/templates/payment.rb
22
+ rails_generators/invoicing_ledger/templates/statement_view.html
23
+ rails_generators/invoicing_ledger/templates/stylesheet.css
24
+ script/console
25
+ script/destroy
26
+ script/generate
27
+ test/test_generator_helper.rb
28
+ test/test_helper.rb
29
+ test/test_invoicing_ledger_generator.rb
@@ -0,0 +1,10 @@
1
+
2
+ Thanks for trying the Ruby Invoicing Gem. Hope you find it useful.
3
+ Do please blog and tweet about it (tag your posts with #invgem).
4
+
5
+ Now please go to the root of your Rails project and type:
6
+ script/generate invoicing_ledger billing --currency=GBP
7
+ (replace GBP with your currency if you do not use Pounds Sterling).
8
+ For more information please go to http://ept.github.com/invoicing/
9
+
10
+
@@ -0,0 +1,55 @@
1
+ = Ruby Invoicing Framework
2
+
3
+ * {Ruby Invoicing Framework website}[http://ept.github.com/invoicing/]
4
+ * {API Reference Docs}[http://invoicing.rubyforge.org/doc/]
5
+ * {Browse the code on GitHub}[http://github.com/ept/invoicing/]
6
+ * {RubyForge project}[http://rubyforge.org/projects/invoicing/]
7
+ * Email: Martin Kleppmann <ept@rubyforge.org>
8
+
9
+ == DESCRIPTION
10
+
11
+ This is a framework for generating and displaying invoices (ideal for
12
+ commercial Rails apps). It allows for flexible business logic; provides tools
13
+ for tax handling, commission calculation etc. It aims to be both
14
+ developer-friendly and accountant-friendly.
15
+
16
+ The Ruby Invoicing Framework is based on
17
+ {ActiveRecord}[http://api.rubyonrails.org/classes/ActiveRecord/Base.html].
18
+
19
+ Please see {the website}[http://ept.github.com/invoicing/] for an introduction
20
+ to using Invoicing, and check the
21
+ {API reference}[http://invoicing.rubyforge.org/doc/] for in-depth details.
22
+
23
+ == FEATURES
24
+
25
+ * TODO
26
+
27
+ == REQUIREMENTS
28
+
29
+ * ActiveRecord >= 2.1
30
+ * Only MySQL and PostgreSQL databases are currently supported
31
+
32
+ == INSTALL
33
+
34
+ sudo gem install invoicing
35
+
36
+ == STATUS
37
+
38
+ So far, the Ruby Invoicing Framework has been tested with ActiveRecord 2.2.2,
39
+ MySQL 5.0.67 and PostgreSQL 8.3.5. We will be testing it across a wider
40
+ variety of versions soon.
41
+
42
+ == CREDITS
43
+
44
+ The Ruby invoicing framework originated as part of the website
45
+ {Bid for Wine}[http://www.bidforwine.co.uk], developed by Patrick Dietrich,
46
+ Conrad Irwin, Michael Arnold and Martin Kleppmann for Ept Computing Ltd.
47
+ It was extracted from the Bid for Wine codebase and substantially extended
48
+ by Martin Kleppmann.
49
+
50
+ == LICENSE
51
+
52
+ Copyright (c) 2009 Martin Kleppmann, Ept Computing Limited.
53
+
54
+ This gem is made publicly available under the terms of the MIT license.
55
+ See LICENSE and/or COPYING for details.
@@ -0,0 +1,25 @@
1
+ %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
2
+ require File.dirname(__FILE__) + '/lib/invoicing_generator'
3
+
4
+ # Generate all the Rake tasks
5
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
+ $hoe = Hoe.new('invoicing_generator', InvoicingGenerator::VERSION) do |p|
7
+ p.developer('Martin Kleppmann', 'rubyforge@eptcomputing.com')
8
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
9
+ p.post_install_message = 'PostInstall.txt'
10
+ p.rubyforge_name = 'invoicing'
11
+ p.extra_deps = [
12
+ ['invoicing', "= #{InvoicingGenerator::VERSION}"],
13
+ ]
14
+ p.extra_dev_deps = [
15
+ ['newgem', ">= #{::Newgem::VERSION}"]
16
+ ]
17
+
18
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
19
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
20
+ p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
21
+ p.rsync_args = '-av --delete --ignore-errors'
22
+ end
23
+
24
+ require 'newgem/tasks' # load /tasks/*.rake
25
+ Dir['tasks/**/*.rake'].each { |t| load t }
@@ -0,0 +1,18 @@
1
+ [
2
+ File.dirname(__FILE__),
3
+ File.join(File.dirname(__FILE__), '..', '..', 'invoicing', 'lib')
4
+ ].each do |dir|
5
+ unless !File.exists?(dir) || $:.include?(dir) || $:.include?(File.expand_path(dir))
6
+ $:.unshift dir
7
+ end
8
+ end
9
+
10
+ require 'invoicing'
11
+
12
+ require 'invoicing_generator/generator_extensions'
13
+ require 'invoicing_generator/name_tools'
14
+ require 'invoicing_generator/option_tools'
15
+
16
+ module InvoicingGenerator
17
+ VERSION = Invoicing::VERSION
18
+ end
@@ -0,0 +1,55 @@
1
+ # Inject a custom command into the rails generator -- useful for rendering classes
2
+ # nested inside modules.
3
+ module Rails #:nodoc:
4
+ module Generator
5
+ module Commands
6
+ class Create
7
+ # A bit like the 'template' method, but wraps the rendered template output in a Ruby
8
+ # class definition, potentially nested in one or more module definitions.
9
+ # +class_details+ should be a hash in the form returned by
10
+ # InvoicingGenerator::NameTools#extract_name_details, detailing information about
11
+ # the class and to which file it should be written.
12
+ def nested_class_template(relative_source, class_details, template_options = {})
13
+ # Render the relative_source template
14
+ inside_template = render_file(source_path(relative_source), template_options) do |file|
15
+ vars = template_options[:assigns] || {}
16
+ b = binding
17
+ vars.each { |k,v| eval "#{k} = vars[:#{k}] || vars['#{k}']", b }
18
+ # Render the source file with the temporary binding
19
+ ERB.new(file.read, nil, '-').result(b)
20
+ end
21
+
22
+ # Prepare class and module definitions
23
+ nesting = class_details[:class_nesting_array]
24
+ index = -1
25
+ header = nesting.map{|mod| index += 1; (' ' * index) + "module #{mod}\n"}.join
26
+ header << (' ' * nesting.size) + "class #{class_details[:class_name_base]}"
27
+ header << " < #{class_details[:superclass]}" unless [nil, ''].include? class_details[:superclass]
28
+ header << "\n"
29
+ footer = (0..nesting.size).to_a.reverse.map{|n| (' ' * n) + "end\n"}.join
30
+ indent = ' ' * (nesting.size + 1)
31
+
32
+ # Write everything to file
33
+ file(relative_source, class_details[:file_path_full], template_options) do
34
+ header + inside_template.split("\n").map{|line| "#{indent}#{line}"}.join("\n") + "\n" + footer
35
+ end
36
+ end
37
+
38
+ # Based on the 'route_resources' method, but less restrictive. Adds arbitrary lines to
39
+ # the config/routes.rb file.
40
+ def add_routes(*lines)
41
+ text = (lines.flatten.map do |line|
42
+ line.strip!
43
+ logger.route line
44
+ " #{line}\n"
45
+ end).join
46
+
47
+ sentinel = 'ActionController::Routing::Routes.draw do |map|'
48
+ unless options[:pretend]
49
+ gsub_file('config/routes.rb', /(#{Regexp.escape(sentinel)})/mi) {|match| "#{match}\n#{text}" }
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,83 @@
1
+ # Tools for dealing with names of controllers or models, passed to us by the user
2
+ # from the command line when invoking the generator. Designed to be included into
3
+ # a subclass of Rails::Generator::NamedBase.
4
+ #
5
+ # This code is inspired by the generator in restful_authentication.
6
+ module InvoicingGenerator
7
+ module NameTools
8
+
9
+ # Analyses a name provided by the user on the command line, and returns a hash
10
+ # of useful bits of string based on that name:
11
+ # extract_name_details 'MegaBlurb/foo/BAR_BLOBS', :kind => :controller, :extension => '.rb'
12
+ # => {
13
+ # :underscore_base => 'bar_blobs', # last part of the name, underscored
14
+ # :camel_base => 'BarBlobs', # last part of the name, camelized
15
+ # :underscore_singular => 'bar_blob', # underscore_base forced to singular form
16
+ # :camel_singular => 'BarBlob', # camel_base forced to singular form
17
+ # :underscore_plural => 'bar_blobs', # underscore_base forced to plural form
18
+ # :camel_plural => 'BarBlobs', # camel_base forced to plural form
19
+ # :class_path_array => ['mega_blurb', 'foo'], # array of lowercase, underscored directory names
20
+ # :class_path => 'mega_blurb/foo', # class_path_array joined by filesystem separator
21
+ # :class_nesting_array => ['MegaBlurb', 'Foo'], # array of camelized module names
22
+ # :class_nesting => 'MegaBlurb::Foo', # class_nesting_array joined by double colon
23
+ # :nesting_depth => 2, # length of class_path array
24
+ #
25
+ # # The following depend on the given :kind
26
+ #  :file_path_base => 'bar_blobs_controller.rb' # based on underscore_*
27
+ # :file_path_full => 'app/controllers/mega_blurb/foo/bar_blobs_controller.rb', # full file path
28
+ # :class_name_base => 'BarBlobsController', # file_path_base.camelize
29
+ # :class_name_full => 'MegaBlurb::Foo::BarBlobsController', # = class_nesting + class_name_base
30
+ # }
31
+ #
32
+ # Recognised options:
33
+ # :kind => :model -- use conventions for creating a model object from the name
34
+ # :kind => :controller -- use conventions for creating a controller from the name
35
+ def extract_name_details(user_specified_name, options={})
36
+ result = {}
37
+
38
+ # See Rails::Generator::NamedBase#extract_modules
39
+ modules = extract_modules(user_specified_name)
40
+ base_name = modules.shift
41
+ result[:class_path_array] = modules.shift
42
+ file_path = modules.shift
43
+ result[:class_nesting] = modules.shift
44
+ result[:nesting_depth] = modules.shift
45
+ result[:class_path] = File.join(result[:class_path_array])
46
+ result[:class_nesting_array] = result[:class_nesting].split('::')
47
+
48
+ result[:underscore_base] = base_name.underscore
49
+ result[:camel_base] = result[:underscore_base].camelize
50
+ result[:underscore_singular] = result[:underscore_base].singularize
51
+ result[:camel_singular] = result[:underscore_singular].camelize
52
+ result[:underscore_plural] = result[:underscore_singular].pluralize
53
+ result[:camel_plural] = result[:underscore_plural].camelize
54
+
55
+ if options[:kind] == :controller
56
+ result[:file_path_base] = "#{result[:underscore_base]}_controller"
57
+ path_prefix = File.join('app', 'controllers')
58
+ elsif options[:kind] == :model
59
+ result[:file_path_base] = result[:underscore_singular]
60
+ path_prefix = File.join('app', 'models')
61
+ else
62
+ raise 'unknown kind of name'
63
+ end
64
+
65
+ result[:class_name_base] = result[:file_path_base].camelize
66
+ result[:file_path_base] += (options[:extension] || ".rb")
67
+
68
+ if result[:nesting_depth] == 0
69
+ result[:file_path_full] = File.join(path_prefix, result[:file_path_base])
70
+ result[:class_name_full] = result[:class_name_base]
71
+ else
72
+ result[:file_path_full] = File.join(path_prefix, result[:class_path], result[:file_path_base])
73
+ result[:class_name_full] = "#{result[:class_nesting]}::#{result[:class_name_base]}"
74
+ end
75
+
76
+ #result[:routing_name] = result[:singular_name]
77
+ #result[:routing_path] = result[:file_path].singularize
78
+ #result[:controller_name] = result[:plural_name]
79
+
80
+ result
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,34 @@
1
+ # Tools for parsing command line options. Designed to be included into
2
+ # a subclass of Rails::Generator::NamedBase.
3
+ module InvoicingGenerator
4
+ module OptionTools
5
+ protected
6
+
7
+ # Overrides Rails::Generator::Options#add_options!
8
+ # Expects with_or_without_options to be defined in the importing class.
9
+ def add_options!(opt)
10
+ opt.separator ''
11
+ opt.separator 'Optional flags:'
12
+ with_or_without_options.each_pair do |key, val|
13
+ opt.on "--with-#{key}", val + (options[key] ? " (default)" : "") do
14
+ options[key] = true
15
+ end
16
+ opt.on "--without-#{key}", "don't #{val}" + (options[key] ? " (default)" : "") do
17
+ options[key] = false
18
+ end
19
+ end
20
+ opt.on("--debug", "print debugging output") { options[:debug] = true }
21
+ end
22
+
23
+ # Output debugging info
24
+ def dump_details
25
+ name_details.each_pair do |key1, val1|
26
+ puts "#{key1}:"
27
+ val1.each_pair do |key2, val2|
28
+ puts " %-40s %s" % ["#{key2}:", val2.inspect]
29
+ end
30
+ end
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,20 @@
1
+ Description:
2
+ Generates several model classes, a database migration, a controller and a
3
+ few views in a Rails project, constituting the core structure you need in
4
+ order to make use of the invoicing gem in your application.
5
+
6
+ Once you have this structure in place you can start creating your own
7
+ Invoice and LineItem subclasses and store them in the database; the
8
+ generated controller/views will pick these up and present them nicely
9
+ out of the box.
10
+
11
+ You can use the option flags to configure which fields you would like to
12
+ include in your database tables.
13
+
14
+ After running this generator you should take a look at the generated
15
+ controller and model classes and search for occurrences of 'FIXME', since
16
+ a few manual tweaks will be required to integrate the generated code into
17
+ your project.
18
+
19
+ Examples:
20
+ `./script/generate invoicing_ledger billing --currency=GBP`
@@ -0,0 +1,107 @@
1
+ require 'invoicing_generator'
2
+
3
+ # Rails generator which creates the migration, models and a controller to support a basic ledger.
4
+ class InvoicingLedgerGenerator < Rails::Generator::NamedBase
5
+
6
+ include InvoicingGenerator::NameTools
7
+ include InvoicingGenerator::OptionTools
8
+
9
+ default_options :description => true, :period => true, :uuid => true, :due_date => true,
10
+ :tax_point => true, :quantity => true, :creator => true, :identifier => false,
11
+ :timestamps => true, :debug => false
12
+
13
+ attr_reader :name_details
14
+
15
+ def initialize(runtime_args, runtime_options = {})
16
+ super
17
+ @name_details = {
18
+ :controller => extract_name_details(@name, :kind => :controller),
19
+ :ledger_item => extract_name_details(args.shift || 'Billing::LedgerItem', :kind => :model),
20
+ :line_item => extract_name_details(args.shift || 'Billing::LineItem', :kind => :model)
21
+ }
22
+ subclass_nesting = name_details[:ledger_item][:class_nesting]
23
+ subclass_nesting << '::' unless subclass_nesting == ''
24
+ name_details[:invoice] = extract_name_details("#{subclass_nesting}Invoice", :kind => :model)
25
+ name_details[:credit_note] = extract_name_details("#{subclass_nesting}CreditNote", :kind => :model)
26
+ name_details[:payment] = extract_name_details("#{subclass_nesting}Payment", :kind => :model)
27
+
28
+ name_details[:controller ][:superclass] = 'ApplicationController'
29
+ name_details[:ledger_item][:superclass] = 'ActiveRecord::Base'
30
+ name_details[:invoice ][:superclass] = name_details[:ledger_item][:class_name_base]
31
+ name_details[:credit_note][:superclass] = name_details[:ledger_item][:class_name_base]
32
+ name_details[:payment ][:superclass] = name_details[:ledger_item][:class_name_base]
33
+ name_details[:line_item ][:superclass] = 'ActiveRecord::Base'
34
+
35
+ dump_details if options[:debug]
36
+ end
37
+
38
+ def manifest
39
+ record do |m|
40
+ name_details.each_pair do |key, details|
41
+ # Check for class naming collisions.
42
+ m.class_collisions details[:class_path_array], details[:class_name_base]
43
+
44
+ # Create directories
45
+ m.directory File.dirname(details[:file_path_full])
46
+
47
+ # Create classes
48
+ m.nested_class_template "#{key}.rb", details, :assigns => { :name_details => name_details }
49
+ end
50
+
51
+ # Migration
52
+ m.migration_template 'migration.rb', 'db/migrate', :migration_file_name => 'create_invoicing_ledger'
53
+
54
+ # Static files
55
+ m.directory 'config/initializers'
56
+ m.file 'initializer.rb', 'config/initializers/invoicing.rb'
57
+ view_directory = File.join('app/views', name_details[:controller][:underscore_base])
58
+ m.directory view_directory
59
+ m.file 'statement_view.html', File.join(view_directory, 'statement.html.erb')
60
+ m.file 'ledger_view.html', File.join(view_directory, 'ledger.html.erb')
61
+ m.file 'stylesheet.css', File.join('public/stylesheets', 'invoicing_ledger.css')
62
+
63
+ # Routes
64
+ ctrl = name_details[:controller][:underscore_base]
65
+ m.add_routes(
66
+ "map.ledger '#{ctrl}/:id/ledger', :controller => '#{ctrl}', :action => 'ledger'",
67
+ "map.statement '#{ctrl}/:id/:other_id', :controller => '#{ctrl}', :action => 'statement', :id => /\\d+/, :other_id => nil",
68
+ "map.document '#{ctrl}/document/:id', :controller => '#{ctrl}', :action => 'document'"
69
+ )
70
+ end
71
+ end
72
+
73
+ protected
74
+ def banner
75
+ <<-EOS
76
+ Creates the model classes and migration for a ledger of accounting data.
77
+
78
+ USAGE: #{$0} invoicing_ledger ControllerName [LedgerItemsModelName] [LineItemsModelName] [options]
79
+
80
+ The recommended ControllerName is 'Billing'.
81
+ The default model names are 'Billing::LedgerItem' and 'Billing::LineItem', respectively.
82
+ EOS
83
+ end
84
+
85
+ def with_or_without_options
86
+ {
87
+ :description => "create a description column for ledger and line items",
88
+ :period => "create start_period/end_period columns for ledger items",
89
+ :uuid => "create uuid columns for ledger and line items",
90
+ :due_date => "create a due_date column for ledger items",
91
+ :tax_point => "create a tax_point column for line items",
92
+ :quantity => "create a quantity column for line items",
93
+ :creator => "create a creator_id column for line items",
94
+ :identifier => "create an identifier column for ledger items",
95
+ :timestamps => "create created_at/updated_at columns"
96
+ }
97
+ end
98
+
99
+ def add_options!(opt)
100
+ super
101
+ opt.separator ''
102
+ opt.separator 'Optional configuration values:'
103
+ opt.on "--currency=CODE", "set a default currency (3-letter code, e.g. USD or GBP)" do |currency|
104
+ options[:currency] = currency.nil? ? nil : currency.upcase
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,40 @@
1
+ # GET /<%= name_details[:controller][:underscore_base] %>
2
+ def index
3
+ # We suggest that you make this a redirect to the ledger or statement of the currently
4
+ # logged-in party, e.g.
5
+ #redirect_to ledger_url(current_user.company)
6
+ end
7
+
8
+ # Display a summary of sales, purchases, payments and receipts on accounts.
9
+ # GET /<%= name_details[:controller][:underscore_base] %>/1/ledger => From the point of view of party 1
10
+ def ledger
11
+ # FIXME check if the current user is allowed to access this ledger
12
+ @self_id = params[:id].to_i
13
+ @summaries = <%= name_details[:ledger_item][:class_name_full] %>.account_summaries(@self_id)
14
+ @names = <%= name_details[:ledger_item][:class_name_full] %>.sender_recipient_name_map(@self_id, @summaries.keys)
15
+ end
16
+
17
+ # GET /<%= name_details[:controller][:underscore_base] %>/1 => Show list of transactions where 1 is sender_id or recipient_id
18
+ # GET /<%= name_details[:controller][:underscore_base] %>/1/2 => Show list of transactions between parties 1 and 2
19
+ def statement
20
+ # FIXME check if the current user is allowed to access this account statement
21
+ @self_id = params[:id].to_i
22
+ scope = <%= name_details[:ledger_item][:class_name_full] %>.exclude_empty_invoices.sent_or_received_by(@self_id).sorted(:issue_date)
23
+ scope = scope.sent_or_received_by(params[:other_id]) if params[:other_id]
24
+ @in_effect = scope.in_effect.all
25
+ @open_or_pending = scope.open_or_pending.all
26
+ @summary = <%= name_details[:ledger_item][:class_name_full] %>.account_summary(@self_id, params[:other_id])
27
+ end
28
+
29
+ # Display an invoice or credit note.
30
+ # GET /<%= name_details[:controller][:underscore_base] %>/document/1
31
+ # GET /<%= name_details[:controller][:underscore_base] %>/document/1.xml
32
+ def document
33
+ # FIXME check if the current user is allowed to access this ledger item
34
+ @<%= name_details[:ledger_item][:underscore_singular] %> = <%= name_details[:ledger_item][:class_name_full] %>.find(params[:id])
35
+
36
+ respond_to do |format|
37
+ format.html { render :text => @<%= name_details[:ledger_item][:underscore_singular] %>.render_html, :layout => true }
38
+ format.xml { render :xml => @<%= name_details[:ledger_item][:underscore_singular] %>.render_ubl }
39
+ end
40
+ end
@@ -0,0 +1,2 @@
1
+ # Load the invoicing gem
2
+ require 'invoicing'
@@ -0,0 +1,49 @@
1
+ <% if name_details[:line_item][:underscore_plural] != 'line_items' -%>
2
+ acts_as_ledger_item :line_items => :<%= name_details[:line_item][:underscore_plural] %>
3
+ <% else -%>
4
+ acts_as_ledger_item
5
+ <% end -%>
6
+
7
+ has_many :<%= name_details[:line_item][:underscore_plural] %>, :class_name => '<%= name_details[:line_item][:class_name_full] %>'
8
+
9
+ # Change the following associations to refer to your customer or supplier model class
10
+ #belongs_to :sender, :class_name => 'FIXME'
11
+ #belongs_to :recipient, :class_name => 'FIXME'
12
+
13
+ # Returns a hash containing details about the sender of this invoice, credit note or payment. This allows
14
+ # you to integrate the invoicing gem with your existing model objects for users and customers/suppliers.
15
+ #
16
+ # The returned hash should have the following keys:
17
+ # <tt>:is_self</tt>:: +true+ if these details refer to yourself, i.e. the person or organsiation who owns/operates
18
+ # this application. +false+ if these details refer to any other party.
19
+ # <tt>:name</tt>:: The name of the person or organisation whose billing address is defined below.
20
+ # <tt>:contact_name</tt>:: The name of a person/department within the organisation named by <tt>:name</tt>.
21
+ # <tt>:address</tt>:: The body of the billing address (not including city, postcode, state and country); may be
22
+ # a multi-line string, with lines separated by '\n' line breaks.
23
+ # <tt>:city</tt>:: The name of the city or town in the billing address.
24
+ # <tt>:state</tt>:: The state/region/province/county of the billing address as appropriate.
25
+ # <tt>:postal_code</tt>:: The postal code of the billing address (e.g. ZIP code in the US).
26
+ # <tt>:country</tt>:: The billing address country (human-readable).
27
+ # <tt>:country_code</tt>:: The two-letter country code of the billing address, according to
28
+ # ISO-3166-1[http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2].
29
+ # <tt>:tax_number</tt>:: The Value Added Tax registration code of this person or organisation, if they have
30
+ # one, preferably including the country identifier at the beginning. This is important for
31
+ # transactions within the European Union.
32
+ def sender_details
33
+ raise 'FIXME: you must implement <%= name_details[:ledger_item][:class_name_full] %>#sender_details'
34
+ end
35
+
36
+ # Returns a hash containing details about the recipient of this invoice, credit note or payment,
37
+ # in the same format as returned by +sender_details+.
38
+ def recipient_details
39
+ raise 'FIXME: you must implement <%= name_details[:ledger_item][:class_name_full] %>#recipient_details'
40
+ end
41
+
42
+ <% if !options[:identifier] -%>
43
+ # Returns the user-visible identifier for a document, e.g. the invoice number. The default is to simply
44
+ # use the primary key generated by the database, but if you want to customise invoice numbers, you can
45
+ # also create a database column called 'identifier'.
46
+ def identifier
47
+ id
48
+ end
49
+ <% end -%>
@@ -0,0 +1,26 @@
1
+ <h1 class="ledger">Sales and purchase ledger</h1>
2
+
3
+ <table class="ledger">
4
+ <tr>
5
+ <th class="name">Name</th>
6
+ <th class="currency">Currency</th>
7
+ <th class="sales">Sales</th>
8
+ <th class="purchases">Purchases</th>
9
+ <th class="sale-receipts">Sale Receipts</th>
10
+ <th class="purchase-payments">Purchase Payments</th>
11
+ <th class="balance">Balance</th>
12
+ </tr>
13
+ <% @summaries.keys.sort.each do |id| -%>
14
+ <% @summaries[id].keys.sort.each do |currency| -%>
15
+ <tr>
16
+ <td class="name"><%= link_to h(@names[id]), statement_path(:id => @self_id, :other_id => id) %></td>
17
+ <td class="currency"><%=h currency %></td>
18
+ <td class="sales"><%=h @summaries[id][currency].sales_formatted %></td>
19
+ <td class="purchases"><%=h @summaries[id][currency].purchases_formatted %></td>
20
+ <td class="sale-receipts"><%=h @summaries[id][currency].sale_receipts_formatted %></td>
21
+ <td class="purchase-payments"><%=h @summaries[id][currency].purchase_payments_formatted %></td>
22
+ <td class="balance"><%=h @summaries[id][currency].balance_formatted %></td>
23
+ </tr>
24
+ <% end -%>
25
+ <% end -%>
26
+ </table>
@@ -0,0 +1,7 @@
1
+ <% if name_details[:ledger_item][:underscore_singular] != 'ledger_item' -%>
2
+ acts_as_line_item :ledger_item => :<%= name_details[:ledger_item][:underscore_singular] %>
3
+ <% else -%>
4
+ acts_as_line_item
5
+ <% end -%>
6
+
7
+ belongs_to :<%= name_details[:ledger_item][:underscore_singular] %>, :class_name => '<%= name_details[:ledger_item][:class_name_full] %>'
@@ -0,0 +1,63 @@
1
+ class CreateInvoicingLedger < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :<%= name_details[:ledger_item][:underscore_plural] %> do |t|
4
+ t.string :type
5
+ t.integer :sender_id
6
+ t.integer :recipient_id
7
+ t.datetime :issue_date
8
+ t.string :currency, :limit => 3, :null => false<%= options[:currency] ? ", :default => '#{options[:currency]}'" : '' %>
9
+ t.decimal :total_amount, :precision => 20, :scale => 4
10
+ t.decimal :tax_amount, :precision => 20, :scale => 4
11
+ t.string :status, :limit => 20
12
+ <% if options[:identifier] -%>
13
+ t.string :identifier, :limit => 50
14
+ <% end -%>
15
+ <% if options[:description] -%>
16
+ t.string :description
17
+ <% end -%>
18
+ <% if options[:period] -%>
19
+ t.datetime :period_start
20
+ t.datetime :period_end
21
+ <% end -%>
22
+ <% if options[:uuid] -%>
23
+ t.string :uuid, :limit => 40
24
+ <% end -%>
25
+ <% if options[:due_date] -%>
26
+ t.datetime :due_date
27
+ <% end -%>
28
+ <% if options[:timestamps] -%>
29
+ t.timestamps
30
+ <% end -%>
31
+ end
32
+
33
+ create_table :<%= name_details[:line_item][:underscore_plural] %> do |t|
34
+ t.string :type
35
+ t.references :<%= name_details[:ledger_item][:underscore_singular] %>
36
+ t.decimal :net_amount, :precision => 20, :scale => 4
37
+ t.decimal :tax_amount, :precision => 20, :scale => 4
38
+ <% if options[:description] -%>
39
+ t.string :description
40
+ <% end -%>
41
+ <% if options[:uuid] -%>
42
+ t.string :uuid, :limit => 40
43
+ <% end -%>
44
+ <% if options[:tax_point] -%>
45
+ t.datetime :tax_point
46
+ <% end -%>
47
+ <% if options[:quantity] -%>
48
+ t.decimal :quantity, :precision => 20, :scale => 4
49
+ <% end -%>
50
+ <% if options[:creator] -%>
51
+ t.integer :creator_id
52
+ <% end -%>
53
+ <% if options[:timestamps] -%>
54
+ t.timestamps
55
+ <% end -%>
56
+ end
57
+ end
58
+
59
+ def self.down
60
+ drop_table :<%= name_details[:line_item][:underscore_plural] %>
61
+ drop_table :<%= name_details[:ledger_item][:underscore_plural] %>
62
+ end
63
+ end
@@ -0,0 +1,48 @@
1
+ <h1 class="statement">Account statement</h1>
2
+
3
+ <% unless @in_effect.empty? %>
4
+ <table class="statement in_effect">
5
+ <tr>
6
+ <th class="number">No.</th>
7
+ <th class="date">Date</th>
8
+ <th class="description">Description</th>
9
+ <th class="amount">Amount</th>
10
+ </tr>
11
+ <% for document in @in_effect %>
12
+ <tr>
13
+ <td class="number"><%= h document.identifier %></td>
14
+ <td class="date"><%= h (document.issue_date || document.updated_at).strftime('%Y-%m-%d') %></td>
15
+ <td class="description">
16
+ <% if document.class.is_payment -%>
17
+ <%= h document.description %>
18
+ <% else -%>
19
+ <%= link_to h(document.description), document_path(document) %>
20
+ <% end -%>
21
+ </td>
22
+ <td class="amount"><%= h document.total_amount_formatted(:debit => :negative, :self_id => @self_id) %></td>
23
+ </tr>
24
+ <% end %>
25
+ <% @summary.each_pair do |currency, balances| %>
26
+ <tr class="balance">
27
+ <th colspan="3">Balance due (<%= h currency %>)</th>
28
+ <td class="amount"><%= balances.balance_formatted %></td>
29
+ </tr>
30
+ <% end %>
31
+ </table>
32
+ <% end %>
33
+
34
+ <% unless @open_or_pending.empty? %>
35
+ <h2 class="statement open_or_pending">Charges not yet invoiced</h2>
36
+ <table class="statement open_or_pending">
37
+ <tr>
38
+ <th class="description">Description</th>
39
+ <th class="amount">Amount</th>
40
+ </tr>
41
+ <% for document in @open_or_pending %>
42
+ <tr>
43
+ <td class="description"><%= link_to h(document.description), document_path(document) %></td>
44
+ <td class="amount"><%= h document.total_amount_formatted(:debit => :negative, :self_id => @self_id) %></td>
45
+ </tr>
46
+ <% end %>
47
+ </table>
48
+ <% end %>
@@ -0,0 +1,127 @@
1
+ table.invoice {
2
+ width: 800px;
3
+ }
4
+
5
+ table.invoice td, table.invoice th {
6
+ vertical-align: top;
7
+ }
8
+
9
+ table.invoice.addresses {
10
+ table-layout: fixed;
11
+ text-align: left;
12
+ }
13
+
14
+ table.invoice.addresses td, table.invoice.addresses th {
15
+ padding: 0.5em;
16
+ }
17
+
18
+ table.invoice.addresses td.vcard {
19
+ border: 1px solid black;
20
+ }
21
+
22
+ table.invoice.metadata {
23
+ table-layout: fixed;
24
+ margin: 2em 0 1em 0;
25
+ }
26
+
27
+ table.invoice.metadata tr {
28
+ text-align: right;
29
+ }
30
+
31
+ table.invoice.metadata td {
32
+ width: 20%;
33
+ text-align: left;
34
+ }
35
+
36
+ p.invoice.description {
37
+ font-weight: bold;
38
+ background-color: #eee;
39
+ width: 800px;
40
+ padding: 0.5em;
41
+ }
42
+
43
+ table.invoice.line-items {
44
+ border-collapse: collapse;
45
+ empty-cells: show;
46
+ margin-bottom: 5em;
47
+ }
48
+
49
+ table.invoice.line-items td, table.invoice.line-items th {
50
+ border: 1px solid black;
51
+ padding: 0.5em;
52
+ text-align: left;
53
+ }
54
+
55
+ table.invoice.line-items td.net-amount, table.invoice.line-items th.net-amount,
56
+ table.invoice.line-items td.tax-amount, table.invoice.line-items th.tax-amount {
57
+ text-align: right;
58
+ }
59
+
60
+ table.invoice.line-items tr.subtotal td, table.invoice.line-items tr.subtotal th {
61
+ padding-top: 3em;
62
+ text-align: right;
63
+ }
64
+
65
+ table.invoice.line-items tr.total td, table.invoice.line-items tr.total th {
66
+ padding-top: 2em;
67
+ text-align: right;
68
+ font-weight: bold;
69
+ }
70
+
71
+
72
+
73
+
74
+ table.ledger {
75
+ border-collapse: collapse;
76
+ empty-cells: show;
77
+ margin: 2em 0 5em;
78
+ table-layout: fixed;
79
+ width: 900px;
80
+ }
81
+
82
+ table.ledger td, table.ledger th {
83
+ border: 1px solid black;
84
+ padding: 0.5em;
85
+ text-align: right;
86
+ vertical-align: top;
87
+ }
88
+
89
+ table.ledger td.name, table.ledger th.name {
90
+ text-align: left;
91
+ width: 25%;
92
+ }
93
+
94
+
95
+
96
+ table.statement {
97
+ border-collapse: collapse;
98
+ empty-cells: show;
99
+ margin: 2em 0 5em;
100
+ table-layout: fixed;
101
+ width: 800px;
102
+ }
103
+
104
+ table.statement td, table.statement th {
105
+ border: 1px solid black;
106
+ padding: 0.5em;
107
+ text-align: left;
108
+ vertical-align: top;
109
+ }
110
+
111
+ table.statement td.number, table.statement th.number {
112
+ width: 5%;
113
+ }
114
+
115
+ table.statement td.date, table.statement th.date,
116
+ table.statement td.amount, table.statement th.amount {
117
+ width: 15%;
118
+ }
119
+
120
+ table.statement td.amount, table.statement th.amount {
121
+ text-align: right;
122
+ }
123
+
124
+ table.statement tr.balance td, table.statement tr.balance th {
125
+ text-align: right;
126
+ font-weight: bold;
127
+ }
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/invoicing_generator.rb'}"
9
+ puts "Loading invoicing_generator gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,36 @@
1
+ begin
2
+ require File.dirname(__FILE__) + '/test_helper'
3
+ rescue LoadError
4
+ require 'test/unit'
5
+ end
6
+ require 'fileutils'
7
+
8
+ # Load generator libs in the form needed for generating a new rails project
9
+ gem 'rails'
10
+ require 'rails/version'
11
+ require 'rails_generator'
12
+ require 'rails_generator/scripts/generate'
13
+
14
+ # Configure the path of the temporary rails project in which our component
15
+ # generators will be run in tests.
16
+ TMP_ROOT = File.dirname(__FILE__) + "/tmp" unless defined?(TMP_ROOT)
17
+ PROJECT_NAME = "myproject" unless defined?(PROJECT_NAME)
18
+ app_root = File.join(TMP_ROOT, PROJECT_NAME)
19
+ if defined?(APP_ROOT)
20
+ APP_ROOT.replace(app_root)
21
+ else
22
+ APP_ROOT = app_root
23
+ end
24
+ if defined?(RAILS_ROOT)
25
+ RAILS_ROOT.replace(app_root)
26
+ else
27
+ RAILS_ROOT = app_root
28
+ end
29
+
30
+ begin
31
+ require 'rubigen'
32
+ rescue LoadError
33
+ require 'rubygems'
34
+ require 'rubigen'
35
+ end
36
+ require 'rubigen/helpers/generator_test_helper'
@@ -0,0 +1,3 @@
1
+ require 'stringio'
2
+ require 'test/unit'
3
+ require File.dirname(__FILE__) + '/../lib/invoicing_generator'
@@ -0,0 +1,46 @@
1
+ require File.join(File.dirname(__FILE__), "test_generator_helper.rb")
2
+
3
+ class TestInvoicingLedgerGenerator < Test::Unit::TestCase
4
+ include RubiGen::GeneratorTestHelper
5
+
6
+ def setup
7
+ bare_setup
8
+ Rails::Generator::Base.use_application_sources!
9
+ Rails::Generator::Scripts::Generate.new.run([APP_ROOT], :generator => 'app')
10
+ end
11
+
12
+ def teardown
13
+ bare_teardown
14
+ end
15
+
16
+ # Some generator-related assertions:
17
+ # assert_generated_file(name, &block) # block passed the file contents
18
+ # assert_directory_exists(name)
19
+ # assert_generated_class(name, &block)
20
+ # assert_generated_module(name, &block)
21
+ # assert_generated_test_for(name, &block)
22
+ # The assert_generated_(class|module|test_for) &block is passed the body of the class/module within the file
23
+ # assert_has_method(body, *methods) # check that the body has a list of methods (methods with parentheses not supported yet)
24
+ #
25
+ # Other helper methods are:
26
+ # app_root_files - put this in teardown to show files generated by the test method (e.g. p app_root_files)
27
+ # bare_setup - place this in setup method to create the APP_ROOT folder for each test
28
+ # bare_teardown - place this in teardown method to destroy the TMP_ROOT or APP_ROOT folder after each test
29
+
30
+ def test_generator_without_options
31
+ name = "myapp"
32
+ run_generator('invoicing_ledger', [name], sources)
33
+ assert_directory_exists "some_folder"
34
+ assert_generated_file "some_file_after_erb.rb"
35
+ end
36
+
37
+ private
38
+ def sources
39
+ [RubiGen::PathSource.new(:test, File.join(File.dirname(__FILE__),"..", generator_path))
40
+ ]
41
+ end
42
+
43
+ def generator_path
44
+ "rails_generators"
45
+ end
46
+ end
metadata ADDED
@@ -0,0 +1,138 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: invoicing_generator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Martin Kleppmann
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIDQjCCAiqgAwIBAgIBADANBgkqhkiG9w0BAQUFADBHMRIwEAYDVQQDDAlydWJ5
14
+ Zm9yZ2UxHDAaBgoJkiaJk/IsZAEZFgxlcHRjb21wdXRpbmcxEzARBgoJkiaJk/Is
15
+ ZAEZFgNjb20wHhcNMDkwNDE0MTkwMTIwWhcNMTAwNDE0MTkwMTIwWjBHMRIwEAYD
16
+ VQQDDAlydWJ5Zm9yZ2UxHDAaBgoJkiaJk/IsZAEZFgxlcHRjb21wdXRpbmcxEzAR
17
+ BgoJkiaJk/IsZAEZFgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
18
+ AQDTglrdKabHepgLjgzM1Z52ABCZZ/xsBbn+4pE2jm7aGj2c0fZ+5Uhg0/MfyKsz
19
+ g3jEFjj0GeNFW7l1sHJYf8mTrdCyAuaymyB2LcLwPtte7/3daAWcs6wAJR8nm9xa
20
+ CzoeAFjCLcbhZazNBURMizj1z9eTArxhpfpNw4uSIExxNRoykeiFGZ4iq5Getj5x
21
+ B/JNTdxM7m2KLx+3YKp2LsV0NLL7hRp6zZ6KW1NTWt1mQ58SjDUiRhThfxPfVpCA
22
+ NI3O+ikDERJWo+nLMUNAZXiB6iMimgUNIUm462tbrumloEjQ/wJE6veGyCRS4jfq
23
+ Ldnuf6CKFRIxhb9QaN+cu0lLAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQD
24
+ AgSwMB0GA1UdDgQWBBRR5pYhCiPVxI3rYNDwFcCSqOUGOTANBgkqhkiG9w0BAQUF
25
+ AAOCAQEAnrM8+tf8f5y8icgcWErHTZZ6oInZxbH8DbAbJ9zIdD/u2o8agzykc/ub
26
+ Kza0RLJoINt0f1Bb6hzIja82EPeEEQKgR6BJAwPZlxZLGYBTyZeZRy3PJ8IjQ9Zk
27
+ Fl6OOjmxFfjgF0UGvFHPYUJaNtN8kPs2lyZYmmUrf7qF0n6nwShnVkYePUlvyW0i
28
+ kqloUNEB5PbHhEwmSTSYOseqm2l2rOAgN3aKVzNFWiMjzZn8OwYaETtD83yB9zlK
29
+ hqnkWqtTW1V1mEZRyNIx71QdrsaovPQhIKp0bMFUwntYXklVKqxYGHebwt//Gb++
30
+ jT4Qh3sYJbvqWGFAQcuOIf4spvpNiA==
31
+ -----END CERTIFICATE-----
32
+
33
+ date: 2009-04-20 00:00:00 +01:00
34
+ default_executable:
35
+ dependencies:
36
+ - !ruby/object:Gem::Dependency
37
+ name: invoicing
38
+ type: :runtime
39
+ version_requirement:
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - "="
43
+ - !ruby/object:Gem::Version
44
+ version: 0.2.0
45
+ version:
46
+ - !ruby/object:Gem::Dependency
47
+ name: newgem
48
+ type: :development
49
+ version_requirement:
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 1.3.0
55
+ version:
56
+ - !ruby/object:Gem::Dependency
57
+ name: hoe
58
+ type: :development
59
+ version_requirement:
60
+ version_requirements: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 1.8.0
65
+ version:
66
+ 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.
67
+ email:
68
+ - rubyforge@eptcomputing.com
69
+ executables: []
70
+
71
+ extensions: []
72
+
73
+ extra_rdoc_files:
74
+ - History.txt
75
+ - Manifest.txt
76
+ - PostInstall.txt
77
+ - README.rdoc
78
+ files:
79
+ - History.txt
80
+ - LICENSE
81
+ - Manifest.txt
82
+ - PostInstall.txt
83
+ - README.rdoc
84
+ - Rakefile
85
+ - lib/invoicing_generator.rb
86
+ - lib/invoicing_generator/generator_extensions.rb
87
+ - lib/invoicing_generator/name_tools.rb
88
+ - lib/invoicing_generator/option_tools.rb
89
+ - rails_generators/invoicing_ledger/USAGE
90
+ - rails_generators/invoicing_ledger/invoicing_ledger_generator.rb
91
+ - rails_generators/invoicing_ledger/templates/controller.rb
92
+ - rails_generators/invoicing_ledger/templates/credit_note.rb
93
+ - rails_generators/invoicing_ledger/templates/initializer.rb
94
+ - rails_generators/invoicing_ledger/templates/invoice.rb
95
+ - rails_generators/invoicing_ledger/templates/ledger_item.rb
96
+ - rails_generators/invoicing_ledger/templates/ledger_view.html
97
+ - rails_generators/invoicing_ledger/templates/line_item.rb
98
+ - rails_generators/invoicing_ledger/templates/migration.rb
99
+ - rails_generators/invoicing_ledger/templates/payment.rb
100
+ - rails_generators/invoicing_ledger/templates/statement_view.html
101
+ - rails_generators/invoicing_ledger/templates/stylesheet.css
102
+ - script/console
103
+ - script/destroy
104
+ - script/generate
105
+ - test/test_generator_helper.rb
106
+ - test/test_helper.rb
107
+ - test/test_invoicing_ledger_generator.rb
108
+ has_rdoc: true
109
+ homepage: "{Ruby Invoicing Framework website}[http://ept.github.com/invoicing/]"
110
+ post_install_message: PostInstall.txt
111
+ rdoc_options:
112
+ - --main
113
+ - README.rdoc
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: "0"
121
+ version:
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: "0"
127
+ version:
128
+ requirements: []
129
+
130
+ rubyforge_project: invoicing
131
+ rubygems_version: 1.3.1
132
+ signing_key:
133
+ specification_version: 2
134
+ summary: This is a framework for generating and displaying invoices (ideal for commercial Rails apps)
135
+ test_files:
136
+ - test/test_generator_helper.rb
137
+ - test/test_helper.rb
138
+ - test/test_invoicing_ledger_generator.rb
Binary file