diff --git a/lib/reporting/reports/orders_and_distributors/base.rb b/lib/reporting/reports/orders_and_distributors/base.rb index 2f54235d5e..8de02541fe 100644 --- a/lib/reporting/reports/orders_and_distributors/base.rb +++ b/lib/reporting/reports/orders_and_distributors/base.rb @@ -32,27 +32,27 @@ module Reporting # rubocop:enable Metrics/AbcSize def search - permissions.visible_orders.select("DISTINCT spree_orders.*"). - complete.not_state(:canceled). - ransack(ransack_params) + report_line_items.orders end def query_result - orders = search.result - # Mask non editable order details - editable_orders_ids = permissions.editable_orders.select(&:id).map(&:id) - orders - .filter { |order| order.in?(editable_orders_ids) } - .each { |order| Orders::MaskDataService.new(order).call } - # Get Line Items - orders.map(&:line_items).flatten + report_line_items.list(line_item_includes) end private + def line_item_includes + [{ variant: { product: :supplier }, + order: [:bill_address, :payments, { distributor: :address }] }] + end + def permissions @permissions ||= ::Permissions::Order.new(user, ransack_params) end + + def report_line_items + @report_line_items ||= Reporting::LineItems.new(permissions, params) + end end end end diff --git a/spec/lib/reports/orders_and_distributors_report_spec.rb b/spec/lib/reports/orders_and_distributors_report_spec.rb index 37fd4de00e..0f3d046638 100644 --- a/spec/lib/reports/orders_and_distributors_report_spec.rb +++ b/spec/lib/reports/orders_and_distributors_report_spec.rb @@ -2,110 +2,152 @@ require 'spec_helper' -module Reporting - module Reports - module OrdersAndDistributors - RSpec.describe Base do - describe 'orders and distributors report' do - it 'should return a header row describing the report' do - subject = Base.new nil +RSpec.describe Reporting::Reports::OrdersAndDistributors::Base do + describe 'orders and distributors report' do + subject { described_class.new nil } - expect(subject.table_headers).to eq( - [ - 'Order date', 'Order Id', - 'Customer Name', 'Customer Email', 'Customer Phone', 'Customer City', - 'SKU', 'Item name', 'Variant', 'Quantity', 'Max Quantity', 'Cost', 'Shipping Cost', - 'Payment Method', - 'Distributor', 'Distributor address', 'Distributor city', 'Distributor postcode', - 'Shipping Method', 'Shipping instructions' - ] - ) + it 'should return a header row describing the report' do + expect(subject.table_headers).to eq( + [ + 'Order date', 'Order Id', + 'Customer Name', 'Customer Email', 'Customer Phone', 'Customer City', + 'SKU', 'Item name', 'Variant', 'Quantity', 'Max Quantity', 'Cost', 'Shipping Cost', + 'Payment Method', + 'Distributor', 'Distributor address', 'Distributor city', 'Distributor postcode', + 'Shipping Method', 'Shipping instructions' + ] + ) + end + + context 'as a supplier, with completed order' do + let(:bill_address) { create(:address) } + let(:distributor) { create(:distributor_enterprise) } + let(:distributor1) { create(:distributor_enterprise) } + let(:supplier) { create(:supplier_enterprise) } + let(:user) { create(:admin_user) } + let(:product) { create(:product, supplier:) } + let(:shipping_method) { create(:shipping_method) } + let(:shipping_instructions) { 'pick up on thursday please!' } + let(:order) { + create(:order, + state: 'complete', completed_at: Time.zone.now, + distributor:, bill_address:, + special_instructions: shipping_instructions) + } + let(:payment_method) { create(:payment_method, distributors: [distributor]) } + let(:payment) { create(:payment, payment_method:, order:) } + let(:line_item) { create(:line_item_with_shipment, product:, order:) } + subject { described_class.new user } + + before do + order.select_shipping_method(shipping_method.id) + order.payments << payment + order.line_items << line_item + end + + it 'should denormalise order and distributor details for display as csv' do + allow(subject).to receive(:unformatted_render?).and_return(true) + table = subject.table_rows + + expect(table.size).to eq 1 + expect(table[0]).to eq([ + order.reload.completed_at.strftime("%F %T"), + order.id, + bill_address.full_name, + order.email, + bill_address.phone, + bill_address.city, + line_item.product.sku, + line_item.product.name, + line_item.options_text, + line_item.quantity, + line_item.max_quantity, + line_item.price * line_item.quantity, + line_item.distribution_fee, + payment_method.name, + distributor.name, + distributor.address.address1, + distributor.address.city, + distributor.address.zipcode, + shipping_method.name, + shipping_instructions + ]) + end + + it "prints one row per line item" do + create(:line_item_with_shipment, order:) + + table = subject.table_rows + expect(table.size).to eq 2 + end + + context "filtering by distributor" do + it do + create(:line_item_with_shipment, order:) + + report1 = described_class.new(create(:admin_user), {}) + table = report1.table_rows + expect(table.size).to eq 2 + + report2 = described_class.new(create(:admin_user), + { q: { distributor_id_in: [distributor.id] } }) + table2 = report2.table_rows + expect(table2.size).to eq 2 + + report3 = described_class.new(create(:admin_user), + { q: { distributor_id_in: [distributor1.id] } }) + table3 = report3.table_rows + expect(table3.size).to eq 0 + end + end + + context "as a supplier, who has granted P-OC to the distributor" do + let(:user) { create(:enterprise_user, enterprises: [supplier]) } + let(:bill_address) { + create(:address, first_name: "FirstName", last_name: "LastName", phone: "123-456", + city: "City") + } + let(:row) { subject.table_rows.first } + + before do + create(:enterprise_relationship, parent: supplier, child: distributor, + permissions_list: [:add_to_order_cycle]) + end + + it "shows line items supplied by my producers, with contact details hidden" do + expect(row).not_to include("FirstName LastName") + expect(row).not_to include("123-456", "City", order.email) + expect(row[2..5]).to eq ["HIDDEN", "HIDDEN", "", ""] + end + + context "where the distributor allows suppliers to see customer names" do + before do + distributor.update_columns show_customer_names_to_suppliers: true end - context 'with completed order' do - let(:bill_address) { create(:address) } - let(:distributor) { create(:distributor_enterprise) } - let(:distributor1) { create(:distributor_enterprise) } - let(:product) { create(:product) } - let(:shipping_method) { create(:shipping_method) } - let(:shipping_instructions) { 'pick up on thursday please!' } - let(:order) { - create(:order, - state: 'complete', completed_at: Time.zone.now, - distributor:, bill_address:, - special_instructions: shipping_instructions) - } - let(:payment_method) { create(:payment_method, distributors: [distributor]) } - let(:payment) { create(:payment, payment_method:, order:) } - let(:line_item) { create(:line_item_with_shipment, product:, order:) } - - before do - order.select_shipping_method(shipping_method.id) - order.payments << payment - order.line_items << line_item - end - - it 'should denormalise order and distributor details for display as csv' do - subject = Base.new create(:admin_user), {} - allow(subject).to receive(:unformatted_render?).and_return(true) - table = subject.table_rows - - expect(table.size).to eq 1 - expect(table[0]).to eq([ - order.reload.completed_at.strftime("%F %T"), - order.id, - bill_address.full_name, - order.email, - bill_address.phone, - bill_address.city, - line_item.product.sku, - line_item.product.name, - line_item.options_text, - line_item.quantity, - line_item.max_quantity, - line_item.price * line_item.quantity, - line_item.distribution_fee, - payment_method.name, - distributor.name, - distributor.address.address1, - distributor.address.city, - distributor.address.zipcode, - shipping_method.name, - shipping_instructions - ]) - end - - it "prints one row per line item" do - create(:line_item_with_shipment, order:) - - subject = Base.new(create(:admin_user)) - - table = subject.table_rows - expect(table.size).to eq 2 - end - - context "filtering by distributor" do - it do - create(:line_item_with_shipment, order:) - - report1 = Base.new(create(:admin_user), {}) - table = report1.table_rows - expect(table.size).to eq 2 - - report2 = Base.new(create(:admin_user), - { q: { distributor_id_in: [distributor.id] } }) - table2 = report2.table_rows - expect(table2.size).to eq 2 - - report3 = Base.new(create(:admin_user), - { q: { distributor_id_in: [distributor1.id] } }) - table3 = report3.table_rows - expect(table3.size).to eq 0 - end - end + it "shows line items supplied by my producers, with only contact names shown" do + expect(row).to include("FirstName LastName") + expect(row).not_to include("123-456", "City", order.email) + expect(row[2..5]).to eq [bill_address.full_name, "HIDDEN", "", ""] end end end + + it "minimises database queries" do + subject # build context first + + expect { subject.table_rows }.to query_database [ + "Spree::Role Exists?", + "Spree::Role Exists?", + "SQL", + "Spree::LineItem Load", + "Spree::PaymentMethod Load", + "Spree::Calculator Load", + "Spree::Shipment Load", + "Spree::ShippingRate Load", + "Spree::ShippingMethod Load", + ] + end end end end