diff --git a/app/services/customers_with_balance.rb b/app/services/customers_with_balance.rb index 0abd804ff273..2a53ce4510d2 100644 --- a/app/services/customers_with_balance.rb +++ b/app/services/customers_with_balance.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class CustomersWithBalance def initialize(enterprise_id) @enterprise_id = enterprise_id @@ -6,14 +8,22 @@ def initialize(enterprise_id) def query Customer.of(enterprise_id). includes(:bill_address, :ship_address, user: :credit_cards). - joins(:orders). - merge(Spree::Order.complete.not_state(:canceled)). + joins("LEFT JOIN spree_orders ON spree_orders.customer_id = customers.id"). group("customers.id"). select("customers.*"). - select("SUM(total - payment_total) AS balance_value") + select(outstanding_balance) end private attr_reader :enterprise_id + + def outstanding_balance + <<-SQL + SUM( + CASE WHEN state = 'canceled' THEN payment_total + ELSE payment_total - total END + ) AS balance_value + SQL + end end diff --git a/spec/services/customers_with_balance_spec.rb b/spec/services/customers_with_balance_spec.rb new file mode 100644 index 000000000000..687ab5900a76 --- /dev/null +++ b/spec/services/customers_with_balance_spec.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe CustomersWithBalance do + subject(:customers_with_balance) { described_class.new(customer.enterprise.id) } + + describe '#query' do + let(:customer) { create(:customer) } + + context 'when no orders where paid' do + let(:total) { 200.00 } + let(:order_total) { 100.00 } + + before do + create(:order, customer: customer, total: order_total, payment_total: 0) + create(:order, customer: customer, total: order_total, payment_total: 0) + end + + it 'returns the customer balance' do + customer = customers_with_balance.query.first + expect(customer.balance_value).to eq(-total) + end + end + + context 'when an order was paid' do + let(:total) { 200.00 } + let(:order_total) { 100.00 } + let(:payment_total) { order_total } + + before do + create(:order, customer: customer, total: order_total, payment_total: 0) + create(:order, customer: customer, total: order_total, payment_total: payment_total) + end + + it 'returns the customer balance' do + customer = customers_with_balance.query.first + expect(customer.balance_value).to eq(payment_total - total) + end + end + + context 'when an order is canceled' do + let(:total) { 200.00 } + let(:order_total) { 100.00 } + let(:payment_total) { 100.00 } + let(:complete_orders_total) { order_total } + + before do + create(:order, customer: customer, total: order_total, payment_total: 0) + create( + :order, + customer: customer, + total: order_total, + payment_total: order_total, + state: 'canceled' + ) + end + + it 'returns the customer balance' do + customer = customers_with_balance.query.first + expect(customer.balance_value).to eq(payment_total - complete_orders_total) + end + end + end +end