From 4f6ab69add7cdf5667dc569d7c7cb0ac7dba1d1d Mon Sep 17 00:00:00 2001 From: Mohamed ABDELLANI Date: Tue, 11 Jul 2023 10:42:31 +0100 Subject: [PATCH] implement OrderInvoiceGenerator service --- .../spree/admin/invoices_controller.rb | 21 +------ app/services/order_invoice_generator.rb | 34 +++++++++++ spec/services/order_invoice_generator_spec.rb | 60 +++++++++++++++++++ 3 files changed, 95 insertions(+), 20 deletions(-) create mode 100644 app/services/order_invoice_generator.rb create mode 100644 spec/services/order_invoice_generator_spec.rb diff --git a/app/controllers/spree/admin/invoices_controller.rb b/app/controllers/spree/admin/invoices_controller.rb index c304a63697..397b1a050f 100644 --- a/app/controllers/spree/admin/invoices_controller.rb +++ b/app/controllers/spree/admin/invoices_controller.rb @@ -23,20 +23,7 @@ module Spree def generate @order = Order.find_by(number: params[:order_id]) authorize! :invoice, @order - - @comparator = OrderInvoiceComparator.new(@order) - if @comparator.can_generate_new_invoice? - @order.invoices.create!( - date: Time.zone.today, - number: @order.invoices.count + 1, - data: invoice_data - ) - elsif @comparator.can_update_latest_invoice? - @order.invoices.last.update!( - date: Time.zone.today, - data: invoice_data - ) - end + OrderInvoiceGenerator.new(@order).generate_or_update_latest_invoice redirect_back(fallback_location: spree.admin_dashboard_path) end @@ -56,12 +43,6 @@ module Spree render json: { created: false }, status: :unprocessable_entity end end - - protected - - def invoice_data - @invoice_data ||= InvoiceDataGenerator.new(@order).generate - end end end end diff --git a/app/services/order_invoice_generator.rb b/app/services/order_invoice_generator.rb new file mode 100644 index 0000000000..4e02ccf487 --- /dev/null +++ b/app/services/order_invoice_generator.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +class OrderInvoiceGenerator + def initialize(order) + @order = order + end + + def generate_or_update_latest_invoice + if comparator.can_generate_new_invoice? + order.invoices.create!( + date: Time.zone.today, + number: order.invoices.count + 1, + data: invoice_data + ) + elsif comparator.can_update_latest_invoice? + order.invoices.last.update!( + date: Time.zone.today, + data: invoice_data + ) + end + end + + private + + attr_reader :order + + def comparator + @comparator ||= OrderInvoiceComparator.new(order) + end + + def invoice_data + @invoice_data ||= InvoiceDataGenerator.new(order).generate + end +end diff --git a/spec/services/order_invoice_generator_spec.rb b/spec/services/order_invoice_generator_spec.rb new file mode 100644 index 0000000000..852de2028a --- /dev/null +++ b/spec/services/order_invoice_generator_spec.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe OrderInvoiceGenerator do + let!(:order) { create(:completed_order_with_fees) } + let!(:invoice_data_generator){ InvoiceDataGenerator.new(order) } + let!(:latest_invoice){ + create(:invoice, + order:, + data: invoice_data_generator.serialize_for_invoice) + } + + let(:instance) { described_class.new(order) } + let(:comparator){ double("OrderInvoiceComparator") } + + before do + allow(instance).to receive(:comparator).and_return(comparator) + end + + describe "#generate_or_update_latest_invoice" do + let(:subject) { instance.generate_or_update_latest_invoice } + context "when can generate new invoice" do + before do + expect(comparator).to receive(:can_generate_new_invoice?).and_return(true) + end + + it "should create a new invoice" do + expect(instance).to receive(:invoice_data) + expect{ subject }.to change{ order.invoices.count }.by(1) + expect(order.invoices.order('created_at desc').first.number).to eq(2) + end + end + + context "can update latest invoice" do + before do + allow(comparator).to receive(:can_generate_new_invoice?).and_return(false) + allow(comparator).to receive(:can_update_latest_invoice?).and_return(true) + order.update!(note: "This is an updated note") + end + + it "should update the latest invoice" do + expect{ subject }.to change{ latest_invoice.reload.data } + .and change{ order.invoices.count }.by(0) + end + end + + context "when can't generate new invoice or update latest invoice" do + before do + allow(comparator).to receive(:can_generate_new_invoice?).and_return(false) + allow(comparator).to receive(:can_update_latest_invoice?).and_return(false) + end + + it "should not create or update invoices" do + expect(instance).not_to receive(:invoice_data) + expect{ subject }.to change{ order.invoices.count }.by(0) + end + end + end +end