diff --git a/.travis.yml b/.travis.yml index 714fdd8f..13070d53 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,6 @@ rvm: sudo: false cache: bundler before_script: - - sh -e /etc/init.d/xvfb start - - export DISPLAY=:99.0 - bundle exec rake test_app script: - bundle exec rspec spec diff --git a/Gemfile b/Gemfile index d0b0c8ec..a7f658f5 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,6 @@ source 'https://rubygems.org' -gem 'spree', github: 'spree/spree' -gem 'spree_auth_devise', github: 'spree/spree_auth_devise' +gem 'spree', github: 'spree/spree', branch: "3-0-stable" +gem 'spree_auth_devise', github: 'spree/spree_auth_devise', branch: "3-0-stable" gemspec diff --git a/README.md b/README.md index bb3fe0ce..cffae158 100644 --- a/README.md +++ b/README.md @@ -25,9 +25,9 @@ Enjoy! Now allow to generate invoices with sequential numbers. 1. Set the logo path preference to include your store / company logo. -```ruby -Spree::PrintInvoice::Config.set(logo_path: '/path/to/public/images/company-logo.png') -``` + ```ruby + Spree::PrintInvoice::Config.set(logo_path: '/path/to/public/images/company-logo.png') + ``` 2. Add your own own footer texts to the locale. The current footer works with `:footer_left1` , `:footer_left2` and `:footer_right1`, `:footer_right2` where the 1 version is on the left in bold, and the 2 version the "value" on the right. @@ -37,26 +37,47 @@ Spree::PrintInvoice::Config.set(logo_path: '/path/to/public/images/company-logo. 5. Many european countries requires numeric and sequential invoices numbers. To use invoices sequential number fill the specific field in "General Settings" or by setting: -```ruby -Spree::PrintInvoice::Config.set(next_number: [1|'your current next invoice number']) -``` + ```ruby + Spree::PrintInvoice::Config.set(next_number: [1|'your current next invoice number']) + ``` -The next invoice number will be the one that you specified. You will able to increase it in any moment, for example, to re-sync invoices number if you are making invoices also in other programs for the same business name. + The next invoice number will be the one that you specified. You will able to increase it in any moment, for example, to re-sync invoices number if you are making invoices also in other programs for the same business name. 6. Enable packaging slips, by setting: -```ruby -Spree::PrintInvoice::Config.set(print_buttons: 'invoice,packaging_slip') # comma separated list -``` + ```ruby + Spree::PrintInvoice::Config.set(print_buttons: 'invoice,packaging_slip') # comma separated list + ``` -Use above feature for your own template if you want. For each button_name, define `button_name_print` text in your locale. + Use above feature for your own template if you want. For each button_name, define `button_name_print` text in your locale. 7. Set page/document options with: -```ruby -Spree::PrintInvoice::Config.set(prawn_options: { page_layout: :landscape, page_size: 'A4', margin: [50, 100, 150, 200] }) + ```ruby + Spree::PrintInvoice::Config.set(prawn_options: { page_layout: :landscape, page_size: 'A4', margin: [50, 100, 150, 200] }) + ``` + +8. Enable PDF storage feature + + PDF files can be stored to disk. This is very handy, if you want to send these files as email attachment. + + ```ruby + Spree::PrintInvoice::Config.set(store_pdf: true) # Default: false + Spree::PrintInvoice::Config.set(storage_path: 'pdfs/orders') # Default: tmp/order_prints + ``` + + *) Inside the `storage_path` a folder for each template will be created. Files will be saved with order number respectively invoice number as file name. + +## Customize templates + +In order to customize the build in invoice and packaging slip templates you need to copy them into your app: + +```sh +$ bundle exec rails g spree_print_invoice:templates ``` +You can then customize them at `app/views/spree/admin/orders/invoice.pdf.prawn` and `app/views/spree/admin/orders/packaging_slip.pdf.prawn`. + --- ## Contributing diff --git a/app/assets/javascripts/spree/backend/print_invoice_settings.coffee b/app/assets/javascripts/spree/backend/print_invoice_settings.coffee new file mode 100644 index 00000000..feb7db11 --- /dev/null +++ b/app/assets/javascripts/spree/backend/print_invoice_settings.coffee @@ -0,0 +1,5 @@ +$ -> + storage_path_field = $('#storage_path') + + $('#store_pdf').click -> + storage_path_field.prop('disabled', !$(this).prop('checked')) diff --git a/app/assets/javascripts/spree/backend/spree_print_invoice.js b/app/assets/javascripts/spree/backend/spree_print_invoice.js index 1424ae2d..411eb0d9 100644 --- a/app/assets/javascripts/spree/backend/spree_print_invoice.js +++ b/app/assets/javascripts/spree/backend/spree_print_invoice.js @@ -1 +1,2 @@ //= require spree/backend +//= require ./print_invoice_settings diff --git a/app/controllers/spree/admin/orders_controller_decorator.rb b/app/controllers/spree/admin/orders_controller_decorator.rb index 89b15293..ca9ac243 100644 --- a/app/controllers/spree/admin/orders_controller_decorator.rb +++ b/app/controllers/spree/admin/orders_controller_decorator.rb @@ -5,23 +5,25 @@ module Admin def show load_order + respond_with(@order) do |format| format.pdf do - template = params[:template] || 'invoice' - update_sequential_number_for(@order) if template == 'invoice' - render layout: false, template: "spree/admin/orders/#{template}.pdf.prawn" + @order.update_invoice_number! + + send_data @order.pdf_file(pdf_template_name), + type: 'application/pdf', disposition: 'inline' end end end private - def update_sequential_number_for(order) - return unless Spree::PrintInvoice::Config.use_sequential_number? - return unless order.invoice_number.present? - order.invoice_number = Spree::PrintInvoice::Config.increase_invoice_number - order.invoice_date = Date.today - order.save! + def pdf_template_name + pdf_template_name = params[:template] || 'invoice' + if !Spree::PrintInvoice::Config.print_templates.include?(pdf_template_name) + raise Spree::PrintInvoice::UnsupportedTemplateError.new(pdf_template_name) + end + pdf_template_name end end end diff --git a/app/models/spree/order_decorator.rb b/app/models/spree/order_decorator.rb new file mode 100644 index 00000000..b2561076 --- /dev/null +++ b/app/models/spree/order_decorator.rb @@ -0,0 +1,99 @@ +Spree::Order.class_eval do + + # Updates +invoice_number+ without calling ActiveRecord callbacks + # + # Only updates if number is not already present and if + # +Spree::PrintInvoice::Config.next_number+ is set and greater than zero. + # + # Also sets +invoice_date+ to current date. + # + def update_invoice_number! + return unless Spree::PrintInvoice::Config.use_sequential_number? + return if invoice_number.present? + + update_columns( + invoice_number: Spree::PrintInvoice::Config.increase_invoice_number, + invoice_date: Date.today + ) + end + + # Returns the given template as pdf binary suitable for Rails send_data + # + # If the file is already present it returns this + # else it generates a new file, stores and returns this. + # + # You can disable the pdf file generation with setting + # + # Spree::PrintInvoice::Config.store_pdf to false + # + def pdf_file(template) + if Spree::PrintInvoice::Config.store_pdf + send_or_create_pdf(template) + else + render_pdf(template) + end + end + + # = The PDF filename + # + # Tries to take invoice_number attribute. + # If this is not present it takes the order number. + # + def pdf_filename + invoice_number.present? ? invoice_number : number + end + + # = PDF file path for template name + # + def pdf_file_path(template) + Rails.root.join(pdf_storage_path(template), "#{pdf_filename}.pdf") + end + + # = PDF storage folder path for given template name + # + # Configure the storage path with +Spree::PrintInvoice::Config.storage_path+ + # + # Each template type gets it own pluralized folder inside + # of +Spree::PrintInvoice::Config.storage_path+ + # + # == Example: + # + # pdf_storage_path('invoice') => "tmp/pdf_prints/invoices" + # + # Creates the folder if it's not present yet. + # + def pdf_storage_path(template) + storage_path = Rails.root.join(Spree::PrintInvoice::Config.storage_path, template.pluralize) + FileUtils.mkdir_p(storage_path) + storage_path + end + + # Renders the prawn template for give template name in context of ActionView. + # + # Prawn templates need to be placed in +app/views/spree/admin/orders/+ folder. + # + # Assigns +@order+ instance variable + # + def render_pdf(template) + ActionView::Base.new( + ActionController::Base.view_paths, + {order: self} + ).render(template: "spree/admin/orders/#{template}.pdf.prawn") + end + + private + + # Sends stored pdf for given template from disk. + # + # Renders and stores it if it's not yet present. + # + def send_or_create_pdf(template) + file_path = pdf_file_path(template) + + unless File.exist?(file_path) + File.open(file_path, "wb") { |f| f.puts render_pdf(template) } + end + + IO.binread(file_path) + end +end diff --git a/app/overrides/add_print_invoice_to_admin_configuration_sidebar.rb b/app/overrides/add_print_invoice_to_admin_configuration_sidebar.rb index 714f1fa4..5b9054cc 100644 --- a/app/overrides/add_print_invoice_to_admin_configuration_sidebar.rb +++ b/app/overrides/add_print_invoice_to_admin_configuration_sidebar.rb @@ -2,5 +2,5 @@ virtual_path: 'spree/admin/shared/sub_menu/_configuration', name: 'print_invoice_admin_configurations_menu', insert_bottom: '[data-hook="admin_configurations_sidebar_menu"]', - text: '<%= configurations_sidebar_menu_item Spree.t(:settings, scope: :print_invoice), edit_admin_print_invoice_settings_path %>' + text: '<%= configurations_sidebar_menu_item Spree.t(:settings, scope: :print_invoice), spree.edit_admin_print_invoice_settings_path %>' ) diff --git a/app/views/spree/admin/orders/invoice.pdf.prawn b/app/views/spree/admin/orders/invoice.pdf.prawn index ab69539b..bd670b9c 100644 --- a/app/views/spree/admin/orders/invoice.pdf.prawn +++ b/app/views/spree/admin/orders/invoice.pdf.prawn @@ -5,9 +5,10 @@ define_grid(columns: 5, rows: 8, gutter: 10) # HEADER repeat(:all) do - im = Rails.application.assets.find_asset(Spree::PrintInvoice::Config[:logo_path]) - if File.exist? im - image im, vposition: :top, height: 40, scale: Spree::PrintInvoice::Config[:logo_scale] + im = asset_path(Spree::PrintInvoice::Config[:logo_path]) + + if im && File.exist?(im.pathname) + image im.filename, vposition: :top, height: 40, scale: Spree::PrintInvoice::Config[:logo_scale] end grid([0,3], [0,4]).bounding_box do @@ -67,8 +68,8 @@ grid([1,0], [6,4]).bounding_box do @order.line_items.each do |item| row = [ - item.variant.product.sku, - item.variant.product.name, + item.variant.sku, + item.variant.name, item.variant.options_text, item.single_display_amount.to_s, item.quantity, diff --git a/app/views/spree/admin/orders/packaging_slip.pdf.prawn b/app/views/spree/admin/orders/packaging_slip.pdf.prawn index 898762da..891192ee 100755 --- a/app/views/spree/admin/orders/packaging_slip.pdf.prawn +++ b/app/views/spree/admin/orders/packaging_slip.pdf.prawn @@ -5,8 +5,9 @@ define_grid(columns: 5, rows: 8, gutter: 10) # HEADER repeat(:all) do - im = Rails.application.assets.find_asset(Spree::PrintInvoice::Config[:logo_path]) - if File.exist? im + im = asset_path(Spree::PrintInvoice::Config[:logo_path]) + + if im && File.exist?(im.pathname) image im, vposition: :top, height: 40, scale: Spree::PrintInvoice::Config[:logo_scale] end @@ -19,7 +20,7 @@ repeat(:all) do text Spree.t(:invoice_number, number: @order.invoice_number, scope: :print_invoice), align: :right move_down 2 - text "#{Spree.t(:invoice_date)} #{I18n.l @order.invoice_date}", align: :right + text "#{Spree.t(:invoice_date, scope: :print_invoice)} #{I18n.l @order.invoice_date}", align: :right else @@ -76,8 +77,8 @@ grid([1,0], [6,4]).bounding_box do @order.line_items.each do |item| row = [ - item.variant.product.sku, - item.variant.product.name, + item.variant.sku, + item.variant.name, item.variant.options_text, item.quantity ] diff --git a/app/views/spree/admin/print_invoice_settings/edit.html.erb b/app/views/spree/admin/print_invoice_settings/edit.html.erb index e7cc51a6..3402b438 100644 --- a/app/views/spree/admin/print_invoice_settings/edit.html.erb +++ b/app/views/spree/admin/print_invoice_settings/edit.html.erb @@ -66,6 +66,20 @@ <%= label_tag :logo_scale, Spree.t(:logo_scale, scope: [:print_invoice, :preferences]) %> <%= number_field_tag(:logo_scale, Spree::PrintInvoice::Config[:logo_scale], in: 1...101, class: 'form-control') %> + +
+
+ <%= label_tag :store_pdf do %> + <%= preference_field_tag(:store_pdf, Spree::PrintInvoice::Config[:store_pdf], type: :boolean) %> + <%= Spree.t(:store_pdf, scope: [:print_invoice, :preferences]) %> + <% end %> +
+
+ +
+ <%= label_tag :storage_path, Spree.t(:storage_path, scope: [:print_invoice, :preferences]) %> + <%= preference_field_tag(:storage_path, Spree::PrintInvoice::Config[:storage_path], class: 'form-control', disabled: !Spree::PrintInvoice::Config[:store_pdf]) %> +
diff --git a/config/locales/de.yml b/config/locales/de.yml index fb616990..e9d4734b 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -4,37 +4,39 @@ de: print_invoice: buttons: invoice: Rechnung drucken - packaging_slip: Warenbegleitschein drucken - invoice: Kundenrechnung + packaging_slip: Lieferschein drucken + invoice: Rechnung item_name: Artikelnamen oder SKU of: aus - via: über + via: per on_date: Bestelldatum - packaging_slip: Packzettel drucken + packaging_slip: Lieferschein page: Seite - payment_via: "%{gateway} Online-Zahlung #%{number} auf %{date}" + payment_via: "%{gateway} Zahlung #%{number} per %{date}" preferences: - next_number: Rechnung drucken nächste Zahl - use_footer: Verwenden Fußzeile - use_page_numbers: Verwenden Sie die Seitenzahlen - anomaly_message: Bestellen Anomalie Nachricht - footer_left: Linke Fußzeile Inhalt + next_number: nächste Rechnungsnummer + use_footer: Fußzeile verwenden + use_page_numbers: Seitenzahlen anzeigen + anomaly_message: Bestellanomalie-Hinweis + footer_left: Inhalt der linken Fußzeile footer_left_info: Z.B. Ihr Firmenname und Adresse. - footer_right: Rechts Fußzeile Inhalt + footer_right: Inhalt der rechten Fußzeile footer_right_info: Z.B. Ihre Telefon-und E-Mail-Adresse. page_layout: Seitenlayout page_size: Seitengröße - print_buttons: Drucktasten - print_buttons_info: Durch Kommata getrennte Liste. - logo_path: Rechnung drucken logo Weg - return_message: Bestellrückmeldung + print_buttons: Anzuzeigende Buttons + print_buttons_info: Durch Kommas getrennte Liste. + logo_path: Dateipfad zum Logo + return_message: Hinweis bei Rückgaben font_face: Schriftart font_size: Schriftgröße - logo_scale: Logo Maßstab - settings: Rechnung drucken Einstellungen - unprocessed: Unverarbeitet + logo_scale: Logo-Skalierung + store_pdf: PDF-Dateien speichern + storage_path: Speicherort für PDF-Dateien + settings: Rechnungsdruck-Einstellungen + unprocessed: offene vat: MwSt. nicht anwendbar - pdf_legend: PDF - invoice_slip_legend: Rechnung / Slip + pdf_legend: PDF-Grundeinstellungen + invoice_slip_legend: PDF-Inhaltseinstellungen invoice_number: 'Rechnungsnummer %{number}' invoice_date: Rechnungsdatum diff --git a/config/locales/en.yml b/config/locales/en.yml index 9c74ac2e..8e54d19c 100755 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -31,6 +31,8 @@ en: font_face: Font Face font_size: Font Size logo_scale: Logo Scale + store_pdf: Store PDF files + storage_path: PDF storage path settings: Print Invoice Settings unprocessed: Unprocessed vat: VAT not applicable diff --git a/config/locales/es.yml b/config/locales/es.yml index 5c0facb9..98736bb6 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -30,7 +30,8 @@ es: return_message: Mensaje de vuelta del pedido font_face: Tipo de letra font_size: Tamaño de letra - logo_scale: Eescala de Logo + store_pdf: Store PDF files + storage_path: PDF storage path settings: Configuración de impresión de facturas unprocessed: No procesado vat: IVA no aplicable diff --git a/config/locales/fr.yml b/config/locales/fr.yml index f2d61466..b7026070 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -31,6 +31,8 @@ fr: font_face: Face à font font_size: Taille de font logo_scale: Échelle de logo + store_pdf: Store PDF files + storage_path: PDF storage path settings: Les paramètres d'impression des factures unprocessed: Non traité vat: "TVA non applicable, article 293 B du Code Général des Impôts" diff --git a/config/locales/it.yml b/config/locales/it.yml new file mode 100644 index 00000000..22cf1893 --- /dev/null +++ b/config/locales/it.yml @@ -0,0 +1,43 @@ +--- +it: + spree: + print_invoice: + documents: Documenti + buttons: + invoice: Ricevuta + packaging_slip: Documento di Trasporto + invoice: Ricevuta per il Cliente + item_name: Nome o codice Articolo + of: di + via: via + on_date: Data Ordine + packaging_slip: Documento di Trasporto + page: Pagina + payment_via: "Pagamento Online %{gateway} #%{number} del %{date}" + preferences: + next_number: Numero successivo Ricevuta + use_footer: Usa Footer + use_page_numbers: Use numeri di pagina + anomaly_message: Messaggio Anomalia Ordine + footer_left: Contenuto footer sinistra + footer_left_info: Es. Nome e indirizzo Azienda. + footer_right: Contenuto footer destra + footer_right_info: Es. numero di telefono e indirizzo email. + page_layout: Layout Pagina + page_size: Dimensione pagina + print_buttons: Bottoni Stampa + print_buttons_info: Lista separata da virgola + logo_path: Percorso logo ricevuta + return_message: Messaggio reso ordine + font_face: Font Face + font_size: Font Size + logo_scale: Scala Logo + store_pdf: Salva File PDF + storage_path: Percorso salvataggio PDF + settings: Impostazioni Stampa Ricevuta + unprocessed: Non processato + vat: IVA non applicabile + pdf_legend: Layout PDF + invoice_slip_legend: Contenuto Ricevuta/Documento di Trasporto + invoice_number: 'Ricevuta Numero %{number}' + invoice_date: 'Data Ricevuta: %{date}' diff --git a/config/locales/sv.yml b/config/locales/sv.yml index d6c727a9..24159e13 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -31,6 +31,8 @@ sv: font_face: Typsnitt font_size: Typsnitt storlek logo_scale: Logo skala + store_pdf: Store PDF files + storage_path: PDF storage path settings: Utskrift inställningar unprocessed: Obearbetad vat: Moms inte tillämpligt diff --git a/config/routes.rb b/config/routes.rb index e91ffd07..3dc759c0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,10 +1,8 @@ Spree::Core::Engine.add_routes do namespace :admin do - resources :orders do - member do - get :show - end - end + # Add orders show-route to routes defined in the Spree Core + # https://github.com/spree/spree/blob/3-0-stable/backend/config/routes.rb#L73 + resources :orders resource :print_invoice_settings, only: [:edit, :update] end end diff --git a/lib/generators/spree_print_invoice/install/install_generator.rb b/lib/generators/spree_print_invoice/install/install_generator.rb index ea9e412c..30e0aa58 100644 --- a/lib/generators/spree_print_invoice/install/install_generator.rb +++ b/lib/generators/spree_print_invoice/install/install_generator.rb @@ -3,6 +3,10 @@ module Generators class InstallGenerator < Rails::Generators::Base class_option :auto_run_migrations, type: :boolean, default: true + def add_javascripts + append_file "vendor/assets/javascripts/spree/backend/all.js", "//= require spree/backend/spree_print_invoice\n" + end + def add_migrations run 'bundle exec rake railties:install:migrations FROM=spree_print_invoice' end diff --git a/lib/generators/spree_print_invoice/templates/templates_generator.rb b/lib/generators/spree_print_invoice/templates/templates_generator.rb new file mode 100644 index 00000000..070c61d4 --- /dev/null +++ b/lib/generators/spree_print_invoice/templates/templates_generator.rb @@ -0,0 +1,12 @@ +module SpreePrintInvoice + module Generators + class TemplatesGenerator < Rails::Generators::Base + source_root File.expand_path("../../../../../app/views/spree/admin/orders", __FILE__) + + def copy_templates + copy_file "invoice.pdf.prawn", "app/views/spree/admin/orders/invoice.pdf.prawn" + copy_file "packaging_slip.pdf.prawn", "app/views/spree/admin/orders/packaging_slip.pdf.prawn" + end + end + end +end diff --git a/lib/prawn_handler.rb b/lib/prawn_handler.rb index e7163759..ae12b27c 100755 --- a/lib/prawn_handler.rb +++ b/lib/prawn_handler.rb @@ -11,7 +11,11 @@ def register alias_method :register!, :register def call(template) - %(extend #{DocumentProxy}; #{template.source}; pdf.render) + <<-PDF + extend #{DocumentProxy} + #{template.source} + pdf.render + PDF end end diff --git a/lib/spree/print_invoice_setting.rb b/lib/spree/print_invoice_setting.rb index 84b0b7d2..babe1fc1 100644 --- a/lib/spree/print_invoice_setting.rb +++ b/lib/spree/print_invoice_setting.rb @@ -14,6 +14,8 @@ class PrintInvoiceSetting < Preferences::Configuration preference :logo_scale, :integer, default: 50 preference :font_face, :string, default: 'Helvetica' preference :font_size, :integer, default: 9 + preference :store_pdf, :boolean, default: false + preference :storage_path, :string, default: 'tmp/order_prints' def page_sizes ::PDF::Core::PageGeometry::SIZES.keys @@ -46,5 +48,9 @@ def font_sizes def logo_scaling logo_scale.to_f / 100 end + + def print_templates + get_preference(:print_buttons).split(',').map(&:strip) + end end end diff --git a/lib/spree_print_invoice.rb b/lib/spree_print_invoice.rb index a5cb000d..f2754ca7 100755 --- a/lib/spree_print_invoice.rb +++ b/lib/spree_print_invoice.rb @@ -2,14 +2,9 @@ require 'spree_print_invoice/engine' require 'spree_print_invoice/version' require 'prawn_handler' -require 'coffee_script' +require 'spree_print_invoice/errors' module Spree module PrintInvoice - module_function - - def config(*) - yield(Spree::PrintInvoice::Config) - end end end diff --git a/lib/spree_print_invoice/engine.rb b/lib/spree_print_invoice/engine.rb index a3f83c80..d2f23e25 100644 --- a/lib/spree_print_invoice/engine.rb +++ b/lib/spree_print_invoice/engine.rb @@ -16,7 +16,7 @@ class Engine < Rails::Engine class << self def activate - cache_klasses = %W(#{config.root}/app/**/*_decorator*.rb #{config.root}/app/overrides/*.rb) + cache_klasses = %W(#{config.root}/app/**/*_decorator*.rb) Dir.glob(cache_klasses) do |klass| Rails.configuration.cache_classes ? require(klass) : load(klass) end diff --git a/lib/spree_print_invoice/errors.rb b/lib/spree_print_invoice/errors.rb new file mode 100644 index 00000000..60266761 --- /dev/null +++ b/lib/spree_print_invoice/errors.rb @@ -0,0 +1,14 @@ +module Spree + module PrintInvoice + class UnsupportedTemplateError < StandardError + def initialize(template_name) + @template_name = template_name + end + + def message + "#{@template_name} is an unsupported pdf template name! \ + Please use one of #{Spree::PrintInvoice::Config.print_templates}." + end + end + end +end diff --git a/spec/controllers/spree/admin/order_controller_decorator_spec.rb b/spec/controllers/spree/admin/order_controller_decorator_spec.rb deleted file mode 100644 index 20de1150..00000000 --- a/spec/controllers/spree/admin/order_controller_decorator_spec.rb +++ /dev/null @@ -1,12 +0,0 @@ -RSpec.describe Spree::Admin::OrdersController, type: :controller do - stub_authorization! - - let(:order) { create(:order_ready_to_ship) } - - context '#show as :pdf' do - it 'returns http success' do - spree_get :show, id: order.number, format: :pdf - expect(response).to be_success - end - end -end diff --git a/spec/controllers/spree/admin/orders_controller_decorator_spec.rb b/spec/controllers/spree/admin/orders_controller_decorator_spec.rb new file mode 100644 index 00000000..f575fb4a --- /dev/null +++ b/spec/controllers/spree/admin/orders_controller_decorator_spec.rb @@ -0,0 +1,44 @@ +RSpec.describe Spree::Admin::OrdersController, type: :controller do + stub_authorization! + + let!(:order) { create(:order_ready_to_ship) } + + before do + allow(controller).to receive(:load_order) + controller.instance_variable_set('@order', order) + end + + describe '#show as :pdf' do + it 'returns http success' do + spree_get :show, id: order.number, format: :pdf + expect(response).to be_success + end + + context 'with next_number set' do + before do + allow(Spree::PrintInvoice::Config).to receive(:next_number).and_return(100) + end + + it 'sets the invoice number' do + expect { + spree_get :show, id: order.number, format: :pdf + }.to change(order, :invoice_number) + end + end + + context 'with wrong template name' do + it 'raises error' do + expect { + spree_get :show, id: order.number, format: :pdf, template: 'foo' + }.to raise_error(Spree::PrintInvoice::UnsupportedTemplateError) + end + end + + context 'with correct template name' do + it 'renders pdf for given template.' do + spree_get :show, id: order.number, format: :pdf, template: 'invoice' + expect(response).to be_success + end + end + end +end diff --git a/spec/features/spree/admin/print_invoice_settings_spec.rb b/spec/features/spree/admin/print_invoice_settings_spec.rb index 97739af9..d7adf7d4 100644 --- a/spec/features/spree/admin/print_invoice_settings_spec.rb +++ b/spec/features/spree/admin/print_invoice_settings_spec.rb @@ -1,7 +1,7 @@ -RSpec.feature 'Settings for Print Invoice', :js do +RSpec.feature 'Settings for Print Invoice' do stub_authorization! - scenario 'can update settings' do + scenario 'can update settings', :js do visit spree.edit_admin_print_invoice_settings_path check 'use_footer' @@ -10,16 +10,19 @@ fill_in 'logo_path', with: '/somewhere/logo.png' fill_in 'print_buttons', with: 'invoice,packaging_slip' fill_in 'next_number', with: '200' - select2 'A4', from: 'Page Size' - select2 'portrait', from: 'Page Layout' - select2 'Courier', from: 'Font Face' - select2 '11', from: 'Font Size' + select 'A4', from: 'Page Size' + select 'portrait', from: 'Page Layout' + select 'Courier', from: 'Font Face' + select '11', from: 'Font Size' fill_in 'logo_scale', with: '99' fill_in 'footer_left', with: 'left text..' fill_in 'footer_right', with: 'right text..' fill_in 'return_message', with: 'Return message..' fill_in 'anomaly_message', with: 'Anomaly message..' + check 'store_pdf' + find('#storage_path').set('pdf/files') # wait for the input to be enabled + click_button 'Update' setting = Spree::PrintInvoiceSetting.new @@ -39,5 +42,7 @@ expect(setting.preferred_footer_right).to eq 'right text..' expect(setting.preferred_return_message).to eq 'Return message..' expect(setting.preferred_anomaly_message).to eq 'Anomaly message..' + expect(setting.preferred_store_pdf).to be(true) + expect(setting.preferred_storage_path).to eq 'pdf/files' end end diff --git a/spec/features/spree/admin/print_invoice_spec.rb b/spec/features/spree/admin/print_invoice_spec.rb index 151c90f6..cc2c6825 100644 --- a/spec/features/spree/admin/print_invoice_spec.rb +++ b/spec/features/spree/admin/print_invoice_spec.rb @@ -1,23 +1,58 @@ -RSpec.feature 'Admin Print Invoice', :js do +RSpec.feature 'Admin print invoice feature' do stub_authorization! - context 'can print' do - background do - @order = create(:completed_order_with_totals) - visit spree.admin_orders_path + let!(:order) { create(:order_ready_to_ship) } + + scenario 'shows print buttons on the order detail page.' do + visit spree.edit_admin_order_path(id: order.number) + + within('#sidebar') do + expect(page).to have_link 'Print Invoice' + expect(page).to have_link 'Print Packaging Slip' + end + end + + context 'with Config.store_pdf set to true' do + before do + allow(Spree::PrintInvoice::Config).to receive(:store_pdf).and_return(true) end - scenario 'completed order' do - expect(@order.completed_at).not_to be_nil + context 'with pdf file already present' do + let(:pdf_file_path) { "spec/fixtures/invoice.pdf" } + + before do + allow_any_instance_of(Spree::Order). + to receive(:pdf_file_path). + and_return(pdf_file_path) + end + + scenario 'sends the stored file.' do + visit spree.admin_order_path(id: order.number, format: :pdf) + expect(page.body).to eq(IO.binread(pdf_file_path)) + end + end - within_table('listing_orders') do - expect(page).to have_text @order.user.email - click_icon :edit + context 'with pdf file not yet present' do + before do + allow(Spree::PrintInvoice::Config).to receive(:storage_path).and_return('tmp/order_prints') + allow(Spree::PrintInvoice::Config).to receive(:next_number).and_return(100) end - within('#sidebar') do - expect(page).to have_link 'Print Invoice' - expect(page).to have_link 'Print Packaging Slip' + + scenario 'sends the stored file.' do + visit spree.admin_order_path(id: order.number, format: :pdf) + expect(page.body).to eq(IO.binread("spec/dummy/tmp/order_prints/invoices/#{order.reload.invoice_number}.pdf")) end end end + + context 'with Config.store_pdf set to false' do + before do + allow(Spree::PrintInvoice::Config).to receive(:store_pdf).and_return(false) + end + + scenario 'sends rendered pdf.' do + visit spree.admin_order_path(id: order.number, format: :pdf) + expect(page.body).to match(/\A%PDF-1\.3/) + end + end end diff --git a/spec/fixtures/invoice.pdf b/spec/fixtures/invoice.pdf new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/test.pdf.prawn b/spec/fixtures/test.pdf.prawn deleted file mode 100644 index 346d369d..00000000 --- a/spec/fixtures/test.pdf.prawn +++ /dev/null @@ -1,2 +0,0 @@ -pdf.explicit_call -implicit_call diff --git a/spec/lib/prawn_handler_spec.rb b/spec/lib/prawn_handler_spec.rb deleted file mode 100644 index 3ee6afb6..00000000 --- a/spec/lib/prawn_handler_spec.rb +++ /dev/null @@ -1,27 +0,0 @@ -module Prawn - class Document - def initialize - @calls = [] - end - - def explicit_call - @calls << :explicit_call - end - - def implicit_call - @calls << :implicit_call - end - - def render - @calls.inspect - end - end -end - -RSpec.describe 'PrawnHandler' do - it 'has compatibility with action view' do - view = ActionView::Base.new - result = view.render file: File.join('spec', 'fixtures', 'test.pdf.prawn') - expect(result).to eq '[:explicit_call, :implicit_call]' - end -end diff --git a/spec/lib/spree/print_invoice_setting_spec.rb b/spec/lib/spree/print_invoice_setting_spec.rb index 9b086d18..29a12a60 100644 --- a/spec/lib/spree/print_invoice_setting_spec.rb +++ b/spec/lib/spree/print_invoice_setting_spec.rb @@ -1,33 +1,39 @@ RSpec.describe Spree::PrintInvoiceSetting do subject { described_class.new } - context '.page_sizes' do + describe '#page_sizes' do it 'has a list of page sizes' do expect(subject.page_sizes).to be_a(Array) expect(subject.page_sizes.size).to be(50) end end - context '.page_layouts' do + describe '#page_layouts' do it 'has a list of layouts' do expect(subject.page_layouts).to be_a(Array) expect(subject.page_layouts).to match_array %w(landscape portrait) end end - context '.use_sequential_number?' do - it 'uses sequential number when :next_number set' do - subject.next_number = 100 - expect(subject.use_sequential_number?).to be(true) + describe '#use_sequential_number?' do + context 'when :next_number set' do + before { subject.next_number = 100 } + + it 'uses sequential number' do + expect(subject.use_sequential_number?).to be(true) + end end - it 'does not use sequential number when :next_number nil' do - subject.next_number = nil - expect(subject.use_sequential_number?).to be(false) + context 'when :next_number nil' do + before { subject.next_number = nil } + + it 'does not use sequential number' do + expect(subject.use_sequential_number?).to be(false) + end end end - context '.increase_invoice_number' do + describe '#increase_invoice_number' do it 'increases invoice numer by one' do subject.next_number = 100 subject.increase_invoice_number @@ -35,14 +41,14 @@ end end - context '.font_faces' do + describe '#font_faces' do it 'has a list of font faces' do expect(subject.font_faces).to be_a(Array) expect(subject.font_faces).to match_array %w(Courier Helvetica Times-Roman) end end - context '.font_sizes' do + describe '#font_sizes' do it 'has a list of font sizes' do expect(subject.font_sizes).to be_a(Array) expect(subject.font_sizes.first).to be(7) @@ -50,10 +56,42 @@ end end - context '.logo_scaling' do + describe '#logo_scaling' do it 'converts logo scale to percent' do subject.logo_scale = 100 expect(subject.logo_scaling).to be(1.0) end end + + describe '#print_templates' do + before { @print_buttons = subject.print_buttons } + + it 'returns array of print template names from print buttons string' do + subject.print_buttons = 'foo,baz' + expect(subject.print_templates).to eq(%w(foo baz)) + end + + context 'when print buttons has spaces' do + it 'ignores them' do + subject.print_buttons = ' foo , baz ' + expect(subject.print_templates).to eq(%w(foo baz)) + end + end + + context 'when print buttons are empty' do + it 'returns empty array' do + subject.print_buttons = '' + expect(subject.print_templates).to eq([]) + end + end + + context 'when print buttons are nil' do + it 'returns empty array' do + subject.print_buttons = nil + expect(subject.print_templates).to eq([]) + end + end + + after { subject.print_buttons = @print_buttons } + end end diff --git a/spec/models/spree/order_spec.rb b/spec/models/spree/order_spec.rb new file mode 100644 index 00000000..f8adefd4 --- /dev/null +++ b/spec/models/spree/order_spec.rb @@ -0,0 +1,56 @@ +RSpec.describe Spree::Order do + let(:order) { create(:order_ready_to_ship) } + + describe '#update_invoice_number!' do + + it 'updates invoice number' do + expect { + order.update_invoice_number! + }.to change(order, :invoice_number) + end + + it 'updates invoice date' do + expect { + order.update_invoice_number! + }.to change(order, :invoice_date) + end + + context 'with invoice number present' do + before do + order.invoice_number = "1000" + end + + it 'does not update invoice number' do + expect { + order.update_invoice_number! + }.to_not change(order, :invoice_number) + end + + it 'does not update invoice date' do + expect { + order.update_invoice_number! + }.to_not change(order, :invoice_date) + end + end + + context 'with use_sequential_number? disabled' do + before do + allow(Spree::PrintInvoice::Config). + to receive(:use_sequential_number?). + and_return(false) + end + + it 'does not update invoice number' do + expect { + order.update_invoice_number! + }.to_not change(order, :invoice_number) + end + + it 'does not update invoice date' do + expect { + order.update_invoice_number! + }.to_not change(order, :invoice_date) + end + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 65b50112..881e107b 100755 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -3,6 +3,7 @@ add_filter 'spec' add_group 'Controllers', 'app/controllers' add_group 'Overrides', 'app/overrides' + add_group 'Models', 'app/models' add_group 'Libraries', 'lib' end diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb index bbce3ee0..b4740069 100644 --- a/spec/support/capybara.rb +++ b/spec/support/capybara.rb @@ -8,10 +8,4 @@ Capybara.register_driver(:poltergeist) do |app| Capybara::Poltergeist::Driver.new app, js_errors: true, timeout: 90 end - - config.before(:each, :js) do - if Capybara.javascript_driver == :selenium - page.driver.browser.manage.window.maximize - end - end end diff --git a/spec/support/matchers/have_text_like.rb b/spec/support/matchers/have_text_like.rb deleted file mode 100644 index 85f1c3cc..00000000 --- a/spec/support/matchers/have_text_like.rb +++ /dev/null @@ -1,7 +0,0 @@ -RSpec::Matchers.define :have_text_like do |expected| - match { have_text(/#{expected}/iu) } - - failure_message do - "expected that text would exist with '#{expected}'" - end -end diff --git a/spec/support/spree.rb b/spec/support/spree.rb index 8736755e..ffdfdef8 100644 --- a/spec/support/spree.rb +++ b/spec/support/spree.rb @@ -6,7 +6,7 @@ require 'spree/testing_support/capybara_ext' RSpec.configure do |config| - config.include Spree::TestingSupport::ControllerRequests + config.include Spree::TestingSupport::ControllerRequests, type: :controller config.include Spree::TestingSupport::Preferences config.include Spree::TestingSupport::UrlHelpers end diff --git a/spree-print-invoice.gemspec b/spree-print-invoice.gemspec index c6574057..4eb5e2f2 100755 --- a/spree-print-invoice.gemspec +++ b/spree-print-invoice.gemspec @@ -23,11 +23,10 @@ Gem::Specification.new do |s| s.requirements << 'none' s.add_runtime_dependency 'prawn', '~> 1.0.0' - s.add_runtime_dependency 'spree_core', '~> 3.0.0.beta' + s.add_runtime_dependency 'spree_core', '~> 3.0.0' s.add_development_dependency 'capybara', '~> 2.4.4' - s.add_development_dependency 'selenium-webdriver', '>= 2.41' - s.add_development_dependency 'poltergeist', '~> 1.5.0' + s.add_development_dependency 'poltergeist', '~> 1.5' s.add_development_dependency 'factory_girl', '~> 4.4' s.add_development_dependency 'rspec-rails', '~> 3.1.0' s.add_development_dependency 'simplecov', '~> 0.9.0'