spree_invoice 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2012 [name of plugin creator]
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+ * Neither the name Spree nor the names of its contributors may be used to
13
+ endorse or promote products derived from this software without specific
14
+ prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ SpreeInvoice
2
+ =======
3
+ This gem provides model responsible for generating pdf from html file.
4
+
5
+
6
+ Basic Installation
7
+ ------------------
8
+
9
+ 1. Add the following to your Gemfile
10
+ <pre>
11
+ gem 'spree_invoice', '~> 1.1.0'
12
+ </pre>
13
+ 2. Run `bundle install`
14
+ 3. To copy and apply migrations run:
15
+ <pre>
16
+ rails g spree_invoice:install
17
+ </pre>
18
+
19
+
20
+ Configuration
21
+ -----
22
+
23
+ In file config/initializers/spree_invoice.rb please check your configuration for wkhtmltopdf bin path.
24
+ For more see: [wicked_pdf](https://github.com/mileszs/wicked_pdf)
25
+
26
+
27
+ Usage
28
+ -----
29
+
30
+ 1. Print Invoice directly
31
+ <pre>
32
+ Spree::Invoice.find_by_order_id('some id').try(:generate_pdf)
33
+ </pre>
34
+ 2. Print Invoice from order
35
+ <pre>
36
+ Order.last.invoice.generate_pdf
37
+ </pre>
38
+ 3. Print Invoice from User
39
+ <pre>
40
+ pdfs = []
41
+ User.last.invoices.each { |e| pdfs << e.generate_pdf }
42
+ </pre>
43
+
44
+ You can also check how many times invoice was generated - column: counter
45
+
46
+ Copyright (c) 2012 [Damiano Giacomello], released under the New BSD License
@@ -0,0 +1,23 @@
1
+ module Spree
2
+ class InvoiceController < Spree::BaseController
3
+
4
+ def show
5
+ order_id = params[:order_id].to_i
6
+ @order = Order.find_by_id(order_id)
7
+ @address = @order.bill_address
8
+ @invoice_print = current_user.has_role?(:admin) ? Spree::Invoice.find_or_create_by_order_id({:order_id => order_id, :user_id => @order ? @order.user_id : nil}) : current_user.invoices.find_or_create_by_order_id(order_id)
9
+ if @invoice_print
10
+ respond_to do |format|
11
+ format.pdf { send_data @invoice_print.generate_pdf, :filename => "#{@invoice_print.invoice_number}.pdf", :type => 'application/pdf' }
12
+ format.html { render :file => SpreeInvoice.invoice_template_path.to_s, :layout => false }
13
+ end
14
+ else
15
+ if current_user.has_role?(:admin)
16
+ return redirect_to(admin_orders_path, :notice => t(:no_such_order_found, :scope => :spree))
17
+ else
18
+ return redirect_to(orders_path, :alert => t(:no_such_order_found, :scope => :spree))
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ module Spree
2
+ OrderMailer.class_eval do
3
+
4
+ def confirm_email(order, resend = false)
5
+ if SpreeInvoice.on_confirm_email && !SpreeInvoice.except_payment.include?(order.payment_method.type)
6
+ inv_print = Spree::Invoice.find_or_create_by_order_id({:order_id => order.id, :user_id => order.user_id})
7
+ attachments["#{inv_print.invoice_number}.pdf"] = {
8
+ :content => inv_print.generate_pdf,
9
+ :mime_type => 'application/pdf'
10
+ } if inv_print
11
+ end
12
+ @order = order
13
+ subject = (resend ? "[#{t(:resend).upcase}] " : "")
14
+ subject += "#{Config[:site_name]} #{t('order_mailer.confirm_email.subject')} ##{order.number}"
15
+ mail(:to => order.email, :subject => subject)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,42 @@
1
+ module Spree
2
+ class Invoice < ActiveRecord::Base
3
+ belongs_to :user
4
+ belongs_to :order
5
+
6
+ before_create :generate_invoice_number
7
+
8
+ scope :from_current_year, where(["created_at > ? AND created_at < ?", Time.now.at_beginning_of_year, Time.now.at_end_of_year])
9
+
10
+ attr_accessible :user, :order, :order_id, :user_id, :invoice_number, :counter
11
+
12
+ def generate_pdf
13
+ self.update_attribute(:counter, self.counter + 1)
14
+ WickedPdf.new.pdf_from_string(
15
+ StaticRender.render_erb(SpreeInvoice.invoice_template_path, {
16
+ :@order => self.order,
17
+ :@address => self.order.bill_address,
18
+ :@invoice_print => self
19
+ }), {
20
+ :margin => SpreeInvoice.wkhtmltopdf_margin
21
+ }
22
+ )
23
+ end
24
+
25
+ private
26
+ def generate_invoice_number
27
+ write_attribute(:invoice_number, SpreeInvoice.invoice_number_generation_method.call(Spree::Invoice.from_current_year.length + 1))
28
+ end
29
+ end
30
+
31
+ class StaticRender < ActionController::Base
32
+ def self.render_erb(template_path, locals = {})
33
+ view = ActionView::Base.new(ActionController::Base.view_paths, {})
34
+ class << view
35
+ include ApplicationHelper
36
+ include WickedPdfHelper::Assets
37
+ include Spree::BaseHelper
38
+ end
39
+ view.render(:file => template_path, :locals => locals, :layout => nil)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,11 @@
1
+ Spree::Order.class_eval do
2
+ has_one :invoice, :dependent => :destroy
3
+ after_update :add_invoice
4
+
5
+ private
6
+ def add_invoice
7
+ # Only create an invoice if the order is completed!
8
+ # And only create it if there is no invoice yet.
9
+ self.create_invoice(user: user) if self.completed? && self.invoice.blank?
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ Spree::User.class_eval do
2
+ has_many :invoice
3
+ end
@@ -0,0 +1,15 @@
1
+ # Admin Panel buttons
2
+ Deface::Override.new(:virtual_path => %q{spree/admin/orders/index},
3
+ :insert_after => "[data-hook='admin_orders_index_header_actions']",
4
+ :name => "invoice_print_header",
5
+ :text => "<th><%= t(:invoice, :scope => :spree) %></th>")
6
+
7
+ Deface::Override.new(:virtual_path => %q{spree/admin/orders/index},
8
+ :insert_after => "[data-hook='admin_orders_index_row_actions']",
9
+ :name => "invoice_print_link",
10
+ :text => %q{<td><%= link_to "#{image_tag('admin/icons/receipt.png')} #{t(:show, :scope => :spree)}".html_safe, pdf_invoice_path(:order_id => order.id, :format => :html), :onclick => "window.open(this.href, '#{t(:invoice, :scope => :spree)}', 'width=745,height=892,left=100,top=100,menubar=no,toolbar=yes,scrollbars=yes,location=no,hotkeys=yes'); return false;" %>&nbsp;<%= link_to "#{image_tag('admin/icons/pdf.png')} #{t(:download, :scope => :spree)}".html_safe, pdf_invoice_path(:order_id => order.id, :format => :pdf) %></td>})
11
+
12
+ Deface::Override.new(:virtual_path => %q{spree/admin/orders/show},
13
+ :insert_bottom => "[data-hook='admin_order_show_buttons']",
14
+ :name => "invoice_print_show_link",
15
+ :text => %q{<%= button_link_to t(:print_invoice, :scope => :spree), pdf_invoice_path(:order_id => @order.id, :format => :pdf), :icon => 'pdf' %>})
@@ -0,0 +1,10 @@
1
+ # User Show Account buttons
2
+ Deface::Override.new(:virtual_path => %q{spree/users/show},
3
+ :insert_after => "table.order-summary thead tr th:last",
4
+ :name => "invoice_print_user_header",
5
+ :text => "<th><%= t(:invoice, :scope => :spree) %></th>")
6
+
7
+ Deface::Override.new(:virtual_path => %q{spree/users/show},
8
+ :insert_after => "table.order-summary tbody tr td:last",
9
+ :name => "invoice_print_user_link",
10
+ :text => %q{<td><%= link_to t(:show, :scope => :spree), pdf_invoice_path(:order_id => order.id, :format => :html), :onclick => "window.open(this.href, '#{t(:invoice, :scope => :spree)}', 'width=745,height=892,left=100,top=100,menubar=no,toolbar=yes,scrollbars=yes,location=no,hotkeys=yes'); return false;" %><%= link_to t(:download, :scope => :spree), pdf_invoice_path(:order_id => order.id, :format => :pdf) %></td>})
@@ -0,0 +1,7 @@
1
+ en:
2
+ spree:
3
+ invoice: Invoice
4
+ show: show
5
+ download: PDF
6
+ print_invoice: Print Invoice
7
+ no_such_order_found: "No such order found."
@@ -0,0 +1,7 @@
1
+ it:
2
+ spree:
3
+ invoice: Fattura
4
+ show: visualizza
5
+ download: PDF
6
+ print_invoice: Stampa fattura
7
+ no_such_order_found: "Questo ordine non è stato trovato."
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ Spree::Core::Engine.routes.draw do
2
+ match '/invoice/show/:order_id' => 'invoice#show', :as => :pdf_invoice
3
+ end
@@ -0,0 +1,17 @@
1
+ class CreateInvoices < ActiveRecord::Migration
2
+ def up
3
+ create_table :spree_invoices do |t|
4
+ t.integer :counter, :default => 0
5
+ t.string :invoice_number
6
+
7
+ t.references :order, :user
8
+
9
+ t.timestamps
10
+ end
11
+ add_index :spree_invoice, :invoice_number
12
+ end
13
+
14
+ def down
15
+ drop_table :spree_invoice
16
+ end
17
+ end
@@ -0,0 +1,44 @@
1
+ module SpreeInvoice
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../templates", __FILE__)
5
+ def self.source_root
6
+ @source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
7
+ end
8
+
9
+ def add_migrations
10
+ run 'bundle exec rake railties:install:migrations FROM=spree_invoice'
11
+ end
12
+
13
+ def run_migrations
14
+ res = ask ">> Would you like to run the migrations now? [Y/n]"
15
+ if res == "" || res.downcase == "y"
16
+ run 'bundle exec rake db:migrate'
17
+ else
18
+ puts ">> Skiping rake db:migrate, don't forget to run it!"
19
+ end
20
+ end
21
+
22
+ def copy_templates_file
23
+ puts ">> Copy invoice template"
24
+ copy_file "invoice_template.html.erb", "app/views/spree/invoices/invoice_template.html.erb"
25
+ end
26
+
27
+ def copy_initializer_file
28
+ puts ">> Copy config file"
29
+ copy_file "initializer.rb", "config/initializers/spree_invoice.rb"
30
+ puts "\n>>> Don't forget to check your config file! <<<"
31
+ end
32
+
33
+ def generate_missing_records
34
+ res = ask ">> Would you like to run the generating missing orders now? [Y/n]"
35
+ if res == "" || res.downcase == "y"
36
+ puts ">> Generating missing records..."
37
+ run 'bundle exec rake spree_invoice:generate'
38
+ else
39
+ puts ">> Skiping rake spree_invoice:generate, don't forget to run it!"
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,30 @@
1
+ require 'wicked_pdf'
2
+
3
+ WickedPdf.config = {
4
+ :exe_path => SpreeInvoice::WKHTMLToPDF.bin_path
5
+ }
6
+
7
+ SpreeInvoice.setup do |config|
8
+ config.on_confirm_email = true
9
+ config.invoice_number_generation_method = lambda { |next_invoice_count|
10
+ number = "%04d" % next_invoice_count.to_s
11
+ "R-#{Time.now.year}-#{number}"
12
+ }
13
+
14
+ config.invoice_template_path = "app/views/spree/invoices/invoice_template.html.erb"
15
+ config.except_payment = ['Spree::PaymentMethod::Check']
16
+ config.wkhtmltopdf_margin = {
17
+ :top => 10,
18
+ :bottom => 10,
19
+ :left => 15,
20
+ :right => 15
21
+ }
22
+ config.invoice_seller_details = %Q|
23
+ Spree Demo
24
+ P.IVA: 12345678901
25
+ C.F.: 12345678901
26
+ Street Address, 12
27
+ 00000 City (STATE)
28
+ |
29
+ config.invoice_seller_logo = Spree::Config[:admin_interface_logo]
30
+ end
@@ -0,0 +1,19 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
7
+ </head>
8
+ <body>
9
+ <div id="wrapper">
10
+ <div id="header">
11
+ <%= wicked_pdf_image_tag(SpreeInvoice.invoice_seller_logo) %>
12
+ </div>
13
+ <div id="content">
14
+ <%= SpreeInvoice.invoice_seller_details %><br />
15
+ <%= @order.id %>
16
+ </div>
17
+ </div>
18
+ </body>
19
+ </html>
@@ -0,0 +1,29 @@
1
+ # move it to main file responsible for require
2
+ require File.join(File.dirname(__FILE__), 'wkhtmltopdf')
3
+
4
+ module SpreeInvoice
5
+ class Engine < Rails::Engine
6
+ require 'spree/core'
7
+ isolate_namespace Spree
8
+ engine_name 'spree_invoice'
9
+
10
+ config.autoload_paths += %W(#{config.root}/lib)
11
+
12
+ # use rspec for tests
13
+ config.generators do |g|
14
+ g.test_framework :rspec
15
+ end
16
+
17
+ def self.activate
18
+ Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')) do |c|
19
+ Rails.configuration.cache_classes ? require(c) : load(c)
20
+ end
21
+
22
+ Dir.glob(File.join(File.dirname(__FILE__), "../../app/overrides/*.rb")) do |c|
23
+ Rails.application.config.cache_classes ? require(c) : load(c)
24
+ end
25
+ end
26
+
27
+ config.to_prepare &method(:activate).to_proc
28
+ end
29
+ end
@@ -0,0 +1,10 @@
1
+ require 'spree_invoice'
2
+ require 'rails'
3
+
4
+ module SpreeInvoice
5
+ class Railtie < Rails::Railtie
6
+ rake_tasks do
7
+ require '../tasks/spree_invoice.rake'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ module SpreeInvoice
2
+ VERSION = "1.1.0"
3
+ end
@@ -0,0 +1,10 @@
1
+ module SpreeInvoice
2
+
3
+ module WKHTMLToPDF
4
+ def self.bin_path
5
+ bin_path = `which wkhtmltopdf`
6
+ raise LoadError, "WKHTMLtoPDF not found. Please install it first (http://code.google.com/p/wkhtmltopdf/)" if bin_path.empty?
7
+ bin_path.gsub(/\n/, '')
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,33 @@
1
+ require 'spree_core'
2
+ require 'spree_invoice/engine'
3
+
4
+ module SpreeInvoice
5
+ ## CONFIGURATION OPTIONS
6
+ mattr_accessor :on_confirm_email
7
+ @@on_confirm_email = true
8
+
9
+ mattr_accessor :invoice_seller_details
10
+ @@invoice_seller_details = nil
11
+
12
+ mattr_accessor :invoice_seller_logo
13
+ @@invoice_seller_logo = nil
14
+
15
+ mattr_accessor :invoice_template_path
16
+ @@invoice_template_path = "app/views/spree/invoices/invoice_template.html.erb"
17
+
18
+ mattr_accessor :except_payment
19
+ @@except_payment = ['Spree::PaymentMethod::Check']
20
+
21
+ mattr_accessor :wkhtmltopdf_margin
22
+ @@wkhtmltopdf_margin = {:top => 10, :bottom => 10, :left => 15, :right => 15}
23
+
24
+ mattr_accessor :invoice_number_generation_method
25
+ @@invoice_number_generation_method = lambda { |next_invoice_count|
26
+ number = "%04d" % next_invoice_count.to_s
27
+ "R-#{Time.now.year}-#{number}"
28
+ }
29
+
30
+ def self.setup
31
+ yield self
32
+ end
33
+ end
@@ -0,0 +1,14 @@
1
+ namespace :spree_invoice do
2
+ desc "Migrating and connecting Spree::Orders with InvoicePrints"
3
+ task :generate => :environment do
4
+ sum = Spree::Order.count
5
+ counter = 0
6
+ Spree::Order.all.each do |e|
7
+ e.send(:add_invoice)
8
+ counter += 1
9
+ print "\r#{counter}/#{sum}"
10
+ end
11
+
12
+ print "\nDone.\n"
13
+ end
14
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spree_invoice
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Damiano Giacomello
9
+ - Peter Gębala
10
+ - Thomas von Deyen
11
+ autorequire:
12
+ bindir: bin
13
+ cert_chain: []
14
+ date: 2012-11-06 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: spree_core
18
+ requirement: !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ! '>='
22
+ - !ruby/object:Gem::Version
23
+ version: '0'
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ none: false
28
+ requirements:
29
+ - - ! '>='
30
+ - !ruby/object:Gem::Version
31
+ version: '0'
32
+ - !ruby/object:Gem::Dependency
33
+ name: wicked_pdf
34
+ requirement: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ - !ruby/object:Gem::Dependency
49
+ name: rspec-rails
50
+ requirement: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ description: This gem provides invoice pdf generation from a html template via wkhtmltopdf.
65
+ email:
66
+ - damiano.giacomello@diginess.it
67
+ executables: []
68
+ extensions: []
69
+ extra_rdoc_files: []
70
+ files:
71
+ - README.md
72
+ - LICENSE
73
+ - lib/generators/spree_invoice/install/install_generator.rb
74
+ - lib/generators/spree_invoice/install/templates/initializer.rb
75
+ - lib/generators/spree_invoice/install/templates/invoice_template.html.erb
76
+ - lib/spree_invoice/engine.rb
77
+ - lib/spree_invoice/railtie.rb
78
+ - lib/spree_invoice/version.rb
79
+ - lib/spree_invoice/wkhtmltopdf.rb
80
+ - lib/spree_invoice.rb
81
+ - lib/tasks/spree_invoice.rake
82
+ - app/assets/images/admin/icons/receipt.png
83
+ - app/controllers/spree/invoice_controller.rb
84
+ - app/mailers/spree/order_mailer_decorator.rb
85
+ - app/models/spree/invoice.rb
86
+ - app/models/spree/order_decorator.rb
87
+ - app/models/spree/user_decorator.rb
88
+ - app/overrides/add_button_to_admin_panel.rb
89
+ - app/overrides/add_button_to_customer_panel.rb
90
+ - db/migrate/20120207124038_create_invoices.rb
91
+ - config/locales/en.yml
92
+ - config/locales/it.yml
93
+ - config/routes.rb
94
+ homepage: https://github.com/damianogiacomello/spree_invoice_generator
95
+ licenses: []
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: 1.8.7
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ requirements:
113
+ - wkhtmltopdf
114
+ rubyforge_project:
115
+ rubygems_version: 1.8.22
116
+ signing_key:
117
+ specification_version: 3
118
+ summary: Spree invoice PDF generation extension.
119
+ test_files: []