diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 326b9fe003..3076bddba9 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -176,6 +176,7 @@ Metrics/BlockLength: - 'spec/support/cancan_helper.rb' - 'spec/support/matchers/select2_matchers.rb' - 'spec/support/matchers/table_matchers.rb' + - 'spec/swagger_helper.rb' - 'spec/system/consumer/shopping/checkout_spec.rb' - 'spec/system/consumer/shopping/checkout_stripe_spec.rb' - 'spec/system/consumer/shopping/variant_overrides_spec.rb' @@ -234,6 +235,7 @@ Metrics/ClassLength: - 'lib/reporting/reports/enterprise_fee_summary/enterprise_fees_with_tax_report_by_order.rb' - 'lib/reporting/reports/enterprise_fee_summary/scope.rb' - 'lib/reporting/reports/xero_invoices/base.rb' + - 'lib/reporting/reports/enterprise_fee_summary/enterprise_fees_with_tax_report_by_producer.rb' # Offense count: 34 # Configuration parameters: AllowedMethods, AllowedPatterns, Max. diff --git a/app/views/admin/reports/filters/_enterprise_fees_with_tax_report_by_producer.html.haml b/app/views/admin/reports/filters/_enterprise_fees_with_tax_report_by_producer.html.haml new file mode 100644 index 0000000000..1c19788df6 --- /dev/null +++ b/app/views/admin/reports/filters/_enterprise_fees_with_tax_report_by_producer.html.haml @@ -0,0 +1,27 @@ +.row + .alpha.two.columns= label_tag nil, t(:report_hubs) + .omega.fourteen.columns= f.collection_select(:distributor_id_in, @data.distributors, :id, :name, {}, {class: "select2 fullwidth", multiple: true}) + +.row + .alpha.two.columns= label_tag nil, t(:report_producers) + .omega.fourteen.columns= select_tag(:supplier_id_in, options_from_collection_for_select(@data.orders_suppliers, :id, :name, params[:supplier_id_in]), {class: "select2 fullwidth", multiple: true}) + +.row + .alpha.two.columns= label_tag nil, t(:report_customers_cycle) + .omega.fourteen.columns + = f.select(:order_cycle_id_in, report_order_cycle_options(@data.order_cycles), {selected: params.dig(:q, :order_cycle_id_in)}, {class: "select2 fullwidth", multiple: true}) + +.row + .alpha.two.columns= label_tag nil, t(:fee_name) + .omega.fourteen.columns + = f.select(:enterprise_fee_id_in, fee_name_options(@report.search.result), {selected: params.dig(:q, :enterprise_fee_id_in)}, {class: "select2 fullwidth", multiple: true}) + +.row + .alpha.two.columns= label_tag nil, t(:fee_owner) + .omega.fourteen.columns + = f.select(:enterprise_fee_owner_id_in, fee_owner_options(@report.search.result), {selected: params.dig(:q, :enterprise_fee_owner_id_in)}, {class: "select2 fullwidth", multiple: true}) + +.row + .alpha.two.columns= label_tag nil, t(:report_customers) + .omega.fourteen.columns + = f.select(:customer_id_in, customer_email_options(@data.order_customers), {selected: params.dig(:q, :customer_id_in)}, {class: "select2 fullwidth", multiple: true}) diff --git a/config/locales/en.yml b/config/locales/en.yml index 7652de335b..245f23ea60 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1577,6 +1577,7 @@ en: name: "Enterprise Fee Summary" description: "Summary of Enterprise Fees collected" enterprise_fees_with_tax_report_by_order: "Enterprise Fees With Tax Report By Order" + enterprise_fees_with_tax_report_by_producer: "Enterprise Fees With Tax Report By Producer" errors: no_report_type: "Please specify a report type" report_not_found: "Report not found" @@ -1760,10 +1761,10 @@ en: orders: failed_to_update: "Failed to update order" query_param: - error: + error: title: Invalid query parameter - extra_fields: "Unsupported fields: %{fields}" - + extra_fields: "Unsupported fields: %{fields}" + # Frontend views # @@ -2137,8 +2138,8 @@ en: cancel: Back to Your details voucher: voucher: "%{voucher_amount} Voucher" - apply_voucher: Apply voucher - apply: Apply + apply_voucher: Apply voucher + apply: Apply placeholder: Enter voucher code remove_code: Remove code confirm_delete: Are you sure you want to remove the voucher? @@ -3036,7 +3037,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using report_header_distributor_address: Distributor address report_header_distributor_city: Distributor city report_header_distributor_postcode: Distributor postcode - report_header_distributor_tax_status: Distributor Tax Status + report_header_distributor_tax_status: Distributor Tax Status report_header_delivery_address: Delivery Address report_header_delivery_postcode: Delivery Postcode report_header_bulk_unit_size: Bulk Unit Size @@ -3095,6 +3096,8 @@ See the %{link} to find out more about %{sitename}'s features and to start using report_header_transaction_fee: Transaction Fee (no tax) report_header_total_untaxable_admin: Total untaxable admin adjustments (no tax) report_header_total_taxable_admin: Total taxable admin adjustments (tax inclusive) + report_line_cost_of_produce: Cost of produce + report_line_line_items: line items report_xero_configuration: Xero Configuration initial_invoice_number: "Initial invoice number" invoice_date: "Invoice date" diff --git a/lib/reporting/reports/enterprise_fee_summary/enterprise_fees_with_tax_report_by_producer.rb b/lib/reporting/reports/enterprise_fee_summary/enterprise_fees_with_tax_report_by_producer.rb new file mode 100644 index 0000000000..d7aa97d9b2 --- /dev/null +++ b/lib/reporting/reports/enterprise_fee_summary/enterprise_fees_with_tax_report_by_producer.rb @@ -0,0 +1,445 @@ +# frozen_string_literal: true + +module Reporting + module Reports + module EnterpriseFeeSummary + class EnterpriseFeesWithTaxReportByProducer < ReportTemplate + attr_accessor :permissions + + def initialize(user, params = {}, render: false) + super(user, params, render:) + @permissions = Permissions.new(user) + end + + def search + report_line_items.orders + end + + def order_permissions + @order_permissions ||= ::Permissions::Order.new(user, ransack_params) + end + + def report_line_items + @report_line_items ||= Reporting::LineItems.new(order_permissions, params) + end + + def supplier_ids_filter(line_item) + return true if params[:supplier_id_in].blank? + + params[:supplier_id_in].include?(line_item.supplier.id.to_s) + end + + def enterprise_fee_filtered_ids + return @enterprise_fee_filtered_ids unless @enterprise_fee_filtered_ids.nil? + + @enterprise_fee_filtered_ids = EnterpriseFee.where(nil) + unless enterprise_fee_ids_filter.empty? + @enterprise_fee_filtered_ids = @enterprise_fee_filtered_ids.where( + id: enterprise_fee_ids_filter + ) + end + unless enterprise_fee_owner_ids_filter.empty? + @enterprise_fee_filtered_ids = @enterprise_fee_filtered_ids.where( + enterprise_id: enterprise_fee_owner_ids_filter + ) + end + @enterprise_fee_filtered_ids = @enterprise_fee_filtered_ids.pluck(:id) + end + + def enterprise_fee_filters? + enterprise_fee_ids_filter + enterprise_fee_owner_ids_filter != [] + end + + def enterprise_fee_ids_filter + ransack_params["enterprise_fee_id_in"]&.filter(&:present?) || [] + end + + def enterprise_fee_owner_ids_filter + ransack_params["enterprise_fee_owner_id_in"]&.filter(&:present?) || [] + end + + def query_result + # The objective is to group the orders by + # [tax_rate, entreprise_fee, supplier_id, distributor_id and order_cycle_id] + + # The order.all_adjustment describes + # - the enterprise fees applied on the order + # - the enterprise fees applied on the line items + # - all the taxes including, the taxes applied on the enterprise fees + # The access to enterprise fee tax rates is done in two steps + # 1.we'll need to store two attributes for each order.all_adjustemnt.enterprise_fee + # a. originator_id will refer to the enterprise fee instance + # b. id of the adjustment + # 2. order.all_adjustemnt.tax.where(adjustment_id: id,"Spree::Adjustment") + # - this will return the tax applied on the enterprise fees + orders = report_line_items.list.map(&:order).uniq + orders.flat_map(&join_enterprise_fee) + .flat_map(&join_tax_rate) + .flat_map(&join_supplier) + .group_by(&group_keys) + .each(&change_root_to_order) + end + + def join_enterprise_fee + proc do |order| + query = order + .all_adjustments + .enterprise_fee + .where(originator_id: enterprise_fees_related_to_incoming_exchanges_ids(order)) + + if enterprise_fee_filters? + query = query.where(originator_id: enterprise_fee_filtered_ids) + end + query.group('originator_id') + .pluck("originator_id", 'array_agg(id)') + .map do |enterprise_fee_id, enterprise_fee_adjustment_ids| + { + enterprise_fee_id:, + enterprise_fee_adjustment_ids:, + order: + } + end + end + end + + def enterprise_fees_related_to_incoming_exchanges_ids(order) + order + .order_cycle + .exchanges + .incoming + .flat_map(&:enterprise_fee_ids) + .uniq + end + + def join_tax_rate + proc do |item| + tax_rate_ids = item[:order].all_adjustments.tax.where( + adjustable_id: item[:enterprise_fee_adjustment_ids], + adjustable_type: "Spree::Adjustment" + ).pluck(:originator_id) + + tax_rate_ids << nil if tax_rate_ids.empty? + tax_rate_ids.map do |tax_rate_id| + { + tax_rate_id:, + enterprise_fee_id: item[:enterprise_fee_id], + order: item[:order], + } + end + end + end + + # For every supplier, we want to show the enteprise fees + # applied to at least one of his products + def join_supplier + proc do |item| + order = item[:order] + enterprise_fees_per_variant = enterprise_fees_per_variant(order) + filtered_line_items(order) + .filter do |line_item| + item[:enterprise_fee_id].in?( + enterprise_fees_per_variant[line_item.variant] + ) + end + .map do |line_item| + { + tax_rate_id: item[:tax_rate_id], + enterprise_fee_id: item[:enterprise_fee_id], + supplier_id: line_item.supplier.id, + order: + } + end + end + end + + def filtered_line_items(order) + order + .line_items + .filter(&method(:supplier_ids_filter)) + end + + # { variant: [enterprise_fee_ids] } + def enterprise_fees_per_variant(order) + hash = {} + order.order_cycle.exchanges.each do |exchange| + exchange.variants.each do |variant| + hash[variant] ||= order.order_cycle.coordinator_fee_ids + hash[variant] += exchange.enterprise_fee_ids + end + end + hash + end + + def group_keys + proc do |hash| + [ + hash[:tax_rate_id], + hash[:enterprise_fee_id], + hash[:supplier_id], + hash[:order].distributor_id, + hash[:order].order_cycle_id + ] + end + end + + def change_root_to_order + proc do |_, v| + v.map!{ |item| item[:order] } + end + end + + def columns + { + distributor: :distributor, + producer: :producer, + producer_tax_status: :producer_tax_status, + order_cycle: :order_cycle, + enterprise_fee_name: :enterprise_fee_name, + enterprise_fee_type: :enterprise_fee_type, + enterprise_fee_owner: :enterprise_fee_owner, + tax_category: :tax_category, + tax_rate_name: :tax_rate_name, + tax_rate: :tax_rate_amount, + total_excl_tax: :total_excl_tax, + tax: :tax, + total_incl_tax: :total_incl_tax + } + end + + def rules + [ + { group_by: :distributor }, + { group_by: :producer }, + { + # TOTAL (appear second) + group_by: :order_cycle, + summary_row: order_cycle_totals_row, + }, + { + # Cost of produce (appear first) + group_by: :order_cycle, + summary_row_class: nil, + summary_row_label: nil, + summary_row: order_cycle_line_items_row, + }, + ] + end + + def order_cycle_totals_row + proc do |_key, items, rows| + supplier_id = items.first.first[2] # supplier id used in the grouped line items + line_items = items.flat_map(&:second).uniq.map(&:line_items).flatten + .filter do |line_item| + line_item.supplier_id == supplier_id + end + + tax_for_enterprise_fees = rows.map(&:tax).sum + total_excl_tax = total_fees_excl_tax(items) + line_items_excl_tax(line_items) + tax = tax_for_enterprise_fees + tax_for_line_items(line_items) + { + total_excl_tax:, + tax:, + total_incl_tax: total_excl_tax + tax + } + end + end + + def order_cycle_line_items_row + proc do |key, items, _rows| + supplier_id = items.first.first[2] # supplier id used in the grouped line items + line_items = items.flat_map(&:last).uniq.map(&:line_items).flatten + .filter do |line_item| + line_item.supplier_id == supplier_id + end + producer = producer(items.first) + + total_excl_tax = line_items_excl_tax(line_items) + tax = tax_for_line_items(line_items) + { + distributor: distributor(items.first), + producer:, + producer_tax_status: producer_tax_status(items.first), + order_cycle: key, + enterprise_fee_name: I18n.t('report_line_cost_of_produce'), + enterprise_fee_type: I18n.t('report_line_line_items'), + enterprise_fee_owner: producer, + total_excl_tax:, + tax:, + total_incl_tax: total_excl_tax + tax, + } + end + end + + def total_fees_excl_tax(items) + order_ids = items.flat_map(&:second).map(&:id).uniq + enterprise_fee_ids = items.map(&:first).map(&:second) + enterprise_fees_amount_for_orders( + order_ids, enterprise_fee_ids + ) - included_tax_for_order_ids( + order_ids, enterprise_fee_ids + ) + end + + def line_items_excl_tax(line_items) + cost_of_line_items(line_items) - line_items.sum(&:included_tax) + end + + def cost_of_line_items(line_items) + line_items.sum(&:amount) + end + + # This query gets called twice for each set of line_items, ideally it would be cached. + def tax_for_line_items(line_items) + line_items.map do |line_item| + line_item.adjustments.eligible.tax.sum('amount') + end.sum + end + + def included_tax_for_order_ids(order_ids, enterprise_fee_ids) + Spree::Adjustment.tax + .where(order: order_ids) + .where(included: true) + .where(adjustable_type: 'Spree::Adjustment') + .where(adjustable_id: enterprise_fee_adjustment_ids_for_orders(order_ids, + enterprise_fee_ids)) + .pick("sum(amount)") || 0 + end + + def enterprise_fee_adjustment_ids_for_orders(order_ids, enterprise_fee_ids) + enterprise_fee_adjustments_for_orders(order_ids, enterprise_fee_ids).pluck(:id) + end + + def enterprise_fees_amount_for_orders(order_ids, enterprise_fee_ids) + enterprise_fee_adjustments_for_orders( + order_ids, enterprise_fee_ids + ).pick("sum(amount)") || 0 + end + + def enterprise_fee_adjustments_for_orders(order_ids, enterprise_fee_ids) + enterprise_fees = Spree::Adjustment.enterprise_fee + .where(order_id: order_ids) + .where(originator_id: enterprise_fee_ids) + return enterprise_fees unless enterprise_fee_filters? + + enterprise_fees.where( + originator_id: enterprise_fee_filtered_ids + ) + end + + def distributor(query_result_row) + first_order(query_result_row).distributor&.name + end + + def producer(query_result_row) + Enterprise.where(id: supplier_id(query_result_row)).pick(:name) + end + + def producer_tax_status(query_result_row) + Enterprise.where(id: supplier_id(query_result_row)).pick(:charges_sales_tax) + end + + def order_cycle(query_result_row) + first_order(query_result_row).order_cycle&.name + end + + def enterprise_fee_name(query_result_row) + enterprise_fee(query_result_row).name + end + + def enterprise_fee_type(query_result_row) + enterprise_fee(query_result_row).fee_type + end + + def enterprise_fee_owner(query_result_row) + enterprise_fee(query_result_row).enterprise.name + end + + def tax_category(query_result_row) + tax_rate(query_result_row)&.tax_category&.name + end + + def tax_rate_name(query_result_row) + tax_rate(query_result_row)&.name + end + + def tax_rate_amount(query_result_row) + tax_rate(query_result_row)&.amount + end + + def total_excl_tax(query_result_row) + order_ids = orders(query_result_row).map(&:id) + enterprise_fee_id = enterprise_fee_id(query_result_row) + amount = Spree::Adjustment.enterprise_fee + .where(order_id: order_ids) + .where(originator_id: enterprise_fee_id) + .pick("sum(amount)") + amount - tax(query_result_row, all: true, included: true) + end + + def tax(query_result_row, all: false, included: nil) + order_ids = orders(query_result_row).map(&:id) + adjustment_ids = enterprise_fee_adjustemnt_ids(query_result_row) + query = Spree::Adjustment.tax + query = query.where(included: true) unless included.nil? + query = query.where(originator_id: tax_rate_id(query_result_row)) unless all == true + query = query.where(order_id: order_ids) + .where(adjustable_type: 'Spree::Adjustment') + .where(adjustable_id: adjustment_ids) + .pluck("sum(amount)") + + query.first || 0 + end + + def total_incl_tax(query_result_row) + total_excl_tax(query_result_row) + tax(query_result_row, all: false) + end + + def enterprise_fee_adjustemnt_ids(query_result_row) + order_ids = orders(query_result_row).map(&:id) + enterprise_fee_id = enterprise_fee_id(query_result_row) + Spree::Adjustment.enterprise_fee + .where(order_id: order_ids) + .where(originator_id: enterprise_fee_id) + .pluck(:id) + end + + def enterprise_fee(query_result_row) + first_order(query_result_row).all_adjustments + .enterprise_fee + .find_by(originator_id: enterprise_fee_id(query_result_row)) + .originator + end + + def tax_rate(query_result_row) + return nil if tax_rate_id(query_result_row).nil? + + Spree::TaxRate.find(tax_rate_id(query_result_row)) + end + + def first_order(query_result_row) + orders(query_result_row).first + end + + def tax_rate_id(query_result_row) + keys(query_result_row)[0] + end + + def supplier_id(query_result_row) + keys(query_result_row)[2] + end + + def enterprise_fee_id(query_result_row) + keys(query_result_row)[1] + end + + def keys(query_result_row) + query_result_row.first + end + + def orders(query_result_row) + query_result_row.second + end + end + end + end +end diff --git a/lib/reporting/reports/list.rb b/lib/reporting/reports/list.rb index 84e3a1ed41..5874b70c70 100644 --- a/lib/reporting/reports/list.rb +++ b/lib/reporting/reports/list.rb @@ -2,7 +2,7 @@ module Reporting module Reports - class List + class List # rubocop:disable Metrics/ClassLength # Because it's a simple class def self.all new.all end @@ -66,7 +66,12 @@ module Reporting [ i18n_translate('enterprise_fees_with_tax_report_by_order'), :enterprise_fees_with_tax_report_by_order - ] + ], + [ + i18n_translate('enterprise_fees_with_tax_report_by_producer'), + :enterprise_fees_with_tax_report_by_producer, + { deprecated: true }, # Not supported until specific details are finalised. + ], ] end diff --git a/spec/system/admin/reports/enterprise_summary_fees/enterprise_summary_fee_with_tax_report_by_producer_spec.rb b/spec/system/admin/reports/enterprise_summary_fees/enterprise_summary_fee_with_tax_report_by_producer_spec.rb new file mode 100644 index 0000000000..8fb6731421 --- /dev/null +++ b/spec/system/admin/reports/enterprise_summary_fees/enterprise_summary_fee_with_tax_report_by_producer_spec.rb @@ -0,0 +1,956 @@ +# frozen_string_literal: true + +require 'system_helper' + +describe "Enterprise Summary Fee with Tax Report By Producer" do + # 1 order cycle has: + # - coordinator fees price 20 + # - incoming exchange fees 15 + # - outgoing exchange fees 10 + # - cost of line items 100 (supplier 1) + # - cost of line items 50 (supplier 2) + # tax + # country: 2.5% + # state: 1.5% + + let!(:table_header){ + ["Distributor", "Producer", "Producer Tax Status", "Order Cycle", "Name", "Type", "Owner", + "Tax Category", "Tax Rate Name", "Tax Rate", "Total excl. tax ($)", "Tax", + "Total incl. tax ($)"].join(" ").upcase + } + + let!(:state_zone){ create(:zone_with_state_member) } + let!(:country_zone){ create(:zone_with_member) } + let!(:tax_category){ create(:tax_category, name: 'tax_category') } + let(:included_in_price) { false } + let!(:state_tax_rate){ + create(:tax_rate, zone: state_zone, tax_category:, + name: 'State', amount: 0.015, included_in_price:) + } + let!(:country_tax_rate){ + create(:tax_rate, zone: country_zone, tax_category:, + name: 'Country', amount: 0.025, included_in_price:) + } + let!(:ship_address){ create(:ship_address) } + + let!(:supplier_owner) { create(:user, enterprise_limit: 1) } + let!(:supplier2_owner) { create(:user, enterprise_limit: 1) } + let!(:supplier){ + create(:supplier_enterprise, name: 'Supplier1', charges_sales_tax: true, + owner_id: supplier_owner.id) + } + let!(:supplier2){ + create(:supplier_enterprise, name: 'Supplier2', charges_sales_tax: true, + owner_id: supplier2_owner.id) + } + let!(:product){ create(:simple_product, supplier: ) } + let!(:product2){ create(:simple_product, supplier: supplier2 ) } + let!(:variant){ create(:variant, product_id: product.id, tax_category:) } + let!(:variant2){ create(:variant, product_id: product2.id, tax_category:) } + let!(:distributor_owner) { create(:user, enterprise_limit: 1) } + let!(:distributor){ + distributor = create(:distributor_enterprise_with_tax, name: 'Distributor', + owner_id: distributor_owner.id) + + distributor.shipping_methods << shipping_method + distributor.payment_methods << payment_method + + distributor + } + let!(:payment_method){ create(:payment_method, :flat_rate) } + let!(:shipping_method){ create(:shipping_method, :flat_rate) } + + let!(:order_cycle){ + order_cycle = create(:simple_order_cycle, distributors: [distributor], name: "oc1") + + # creates exchanges for oc1 + order_cycle.exchanges.create! sender: supplier, receiver: distributor, incoming: true + order_cycle.exchanges.create! sender: supplier2, receiver: distributor, incoming: true + + # adds variants to exchanges on oc1 + order_cycle.coordinator_fees << coordinator_fees + order_cycle.exchanges.incoming.first.exchange_fees.create!(enterprise_fee: supplier_fees) + order_cycle.exchanges.incoming.first.exchange_variants.create!(variant:) + order_cycle.exchanges.incoming.second.exchange_fees.create!(enterprise_fee: supplier_fees2) + order_cycle.exchanges.incoming.second.exchange_variants.create!(variant: variant2) + order_cycle.exchanges.outgoing.first.exchange_fees.create!(enterprise_fee: distributor_fee) + order_cycle.exchanges.outgoing.first.exchange_variants.create!(variant:) + order_cycle.exchanges.outgoing.first.exchange_variants.create!(variant: variant2) + + order_cycle + } + let!(:order_cycle2){ + order_cycle2 = create(:simple_order_cycle, distributors: [distributor], name: "oc2") + + # creates exchanges for oc2 + order_cycle2.exchanges.create! sender: supplier, receiver: distributor, incoming: true + order_cycle2.exchanges.create! sender: supplier2, receiver: distributor, incoming: true + + # adds variants to exchanges on oc2 + order_cycle2.coordinator_fees << coordinator_fees + order_cycle2.exchanges.incoming.first.exchange_fees.create!(enterprise_fee: supplier_fees) + order_cycle2.exchanges.incoming.first.exchange_variants.create!(variant:) + order_cycle2.exchanges.incoming.second.exchange_fees.create!(enterprise_fee: supplier_fees2) + order_cycle2.exchanges.incoming.second.exchange_variants.create!(variant: variant2) + order_cycle2.exchanges.outgoing.first.exchange_fees.create!(enterprise_fee: distributor_fee) + order_cycle2.exchanges.outgoing.first.exchange_variants.create!(variant:) + order_cycle2.exchanges.outgoing.first.exchange_variants.create!(variant: variant2) + + order_cycle2 + } + + let!(:enterprise_relationship1) { + create(:enterprise_relationship, parent: supplier, child: distributor, + permissions_list: [:add_to_order_cycle]) + } + let!(:enterprise_relationship2) { + create(:enterprise_relationship, parent: supplier2, child: distributor, + permissions_list: [:add_to_order_cycle]) + } + + let(:admin) { create(:admin_user) } + + let(:coordinator_fees){ + create(:enterprise_fee, :flat_rate, enterprise: distributor, amount: 20, + name: 'Adminstration', + fee_type: 'admin', + tax_category:) + } + let(:supplier_fees){ + create(:enterprise_fee, :per_item, enterprise: supplier, amount: 15, + name: 'Transport', + fee_type: 'transport', + tax_category:) + } + let(:supplier_fees2){ + create(:enterprise_fee, :per_item, enterprise: supplier2, amount: 25, + name: 'Sales', + fee_type: 'sales', + tax_category:) + } + let(:distributor_fee){ + create(:enterprise_fee, :flat_rate, enterprise: distributor, amount: 10, + name: 'Packing', + fee_type: 'packing', + tax_category:) + } + + # creates orders for for oc1 and oc2 + let!(:order) { + order = create(:order_with_distributor, distributor:, order_cycle_id: order_cycle.id, + ship_address_id: ship_address.id) + + order.line_items.create({ variant:, quantity: 1, price: 100 }) + + # This will load the enterprise fees from the order cycle. + # This is needed because the order instance was created + # independently of the order_cycle. + order.recreate_all_fees! + while !order.completed? + break unless order.next! + end + order + } + + let!(:order2) { + order2 = create(:order_with_distributor, distributor:, order_cycle_id: order_cycle2.id, + ship_address_id: ship_address.id) + + order2.line_items.create({ variant: variant2, quantity: 1, price: 50 }) + + # This will load the enterprise fees from the order cycle. + # This is needed because the order instance was created + # independently of the order_cycle. + order2.recreate_all_fees! + while !order2.completed? + break unless order2.next! + end + + order2 + } + + before do + product.update!({ + tax_category_id: tax_category.id, + supplier_id: supplier.id + }) + product2.update!({ + tax_category_id: tax_category.id, + supplier_id: supplier2.id + }) + end + + context 'added tax' do + # 1 order cycle has: + # - coordinator fees (20) 1.5% = 0.30, 2.5% = 0.50 + # 1st - incoming exchange (15) 1.5% = 0.23, 2.5% = 0.38 + # 2nd - incoming exchange (25) 1.5% = 0.38, 2.5% = 0.63 + # - outgoing exchange (10) 1.5% = 0.15, 2.5% = 0.25 + # - line items (50) 1.5% = 0.75, 2.5% = 1.25 + + describe "orders" do + # for supplier 1, oc1 + + let(:coordinator_state_tax1){ + ["Distributor", "Supplier1", "Yes", "oc1", "Adminstration", "admin", "Distributor", + "tax_category", "State", "0.015", "20.0", "0.3", "20.3"].join(" ") + } + let(:coordinator_country_tax1){ + ["Distributor", "Supplier1", "Yes", "oc1", "Adminstration", "admin", "Distributor", + "tax_category", "Country", "0.025", "20.0", "0.5", "20.5"].join(" ") + } + + let(:supplier_state_tax1){ + ["Distributor", "Supplier1", "Yes", "oc1", "Transport", "transport", "Supplier1", + "tax_category", "State", "0.015", "15.0", "0.23", "15.23"].join(" ") + } + let(:supplier_country_tax1){ + ["Distributor", "Supplier1", "Yes", "oc1", "Transport", "transport", "Supplier1", + "tax_category", "Country", "0.025", "15.0", "0.38", "15.38"].join(" ") + } + + let(:distributor_state_tax1){ + ["Distributor", "Supplier1", "Yes", "oc1", "Packing", "packing", "Distributor", + "tax_category", "State", "0.015", "10.0", "0.15", "10.15"].join(" ") + } + let(:distributor_country_tax1){ + ["Distributor", "Supplier1", "Yes", "oc1", "Packing", "packing", "Distributor", + "tax_category", "Country", "0.025", "10.0", "0.25", "10.25"].join(" ") + } + + let(:cost_of_produce1){ + ["Distributor", "Supplier1", "Yes", "oc1", "Cost of produce", "line items", "Supplier1", + "100.0", "4.0", "104.0"].join(" ") + } + let(:summary_row1){ + [ + cost_of_produce1, # Ensure summary row follows the right supplier + "TOTAL", # Fees and line items + "115.0", # Tax excl: 15 + 100 + "4.61", # Tax : (0.23 + 0.38) + (1.50 + 2.50) + "119.61" # Tax incl: 100.00 + 15 + (0.23 + 0.38) + (1.50 + 2.50) + ].join(" ") + } + + # for supplier 2, oc2 + let(:coordinator_state_tax2){ + ["Distributor", "Supplier2", "Yes", "oc2", "Adminstration", "admin", "Distributor", + "tax_category", "State", "0.015", "20.0", "0.3", "20.3"].join(" ") + } + let(:coordinator_country_tax2){ + ["Distributor", "Supplier2", "Yes", "oc2", "Adminstration", "admin", "Distributor", + "tax_category", "Country", "0.025", "20.0", "0.5", "20.5"].join(" ") + } + + let(:supplier_state_tax2){ + ["Distributor", "Supplier2", "Yes", "oc2", "Sales", "sales", "Supplier2", + "tax_category", "State", "0.015", "25.0", "0.38", "25.38"].join(" ") + } + let(:supplier_country_tax2){ + ["Distributor", "Supplier2", "Yes", "oc2", "Sales", "sales", "Supplier2", + "tax_category", "Country", "0.025", "25.0", "0.63", "25.63"].join(" ") + } + + let(:distributor_state_tax2){ + ["Distributor", "Supplier2", "Yes", "oc2", "Packing", "packing", "Distributor", + "tax_category", "State", "0.015", "10.0", "0.15", "10.15"].join(" ") + } + let(:distributor_country_tax2){ + ["Distributor", "Supplier2", "Yes", "oc2", "Packing", "packing", "Distributor", + "tax_category", "Country", "0.025", "10.0", "0.25", "10.25"].join(" ") + } + + let(:cost_of_produce2){ + ["Distributor", "Supplier2", "Yes", "oc2", "Cost of produce", "line items", "Supplier2", + "50.0", "2.0", "52.0"].join(" ") + } + let(:summary_row2){ + [ + cost_of_produce2, # Ensure summary row follows the right supplier + "TOTAL", # Fees and line items + "75.0", # Tax excl: 25 + 50 + "3.01", # Tax : (0.38 + 0.63) + 2 + "78.01" # Tax incl: 25 + 50 + 4.21 + ].join(" ") + } + + context "with line items from a single supplier" do + it 'generates the report and displays fees for the respective suppliers' do + visit_report + click_on "Go" + + expect(page.find("table.report__table thead tr")).to have_content(table_header) + + table = page.find("table.report__table tbody") + expect(table).to have_content(supplier_state_tax1) + expect(table).to have_content(supplier_country_tax1) + expect(table).not_to have_content(distributor_state_tax1) + expect(table).not_to have_content(distributor_country_tax1) + expect(table).not_to have_content(coordinator_state_tax1) + expect(table).not_to have_content(coordinator_country_tax1) + expect(table).to have_content(cost_of_produce1) + expect(table).to have_content(summary_row1) + + expect(table).to have_content(supplier_state_tax2) + expect(table).to have_content(supplier_country_tax2) + expect(table).not_to have_content(distributor_state_tax2) + expect(table).not_to have_content(distributor_country_tax2) + expect(table).not_to have_content(coordinator_state_tax2) + expect(table).not_to have_content(coordinator_country_tax2) + expect(table).to have_content(cost_of_produce2) + expect(table).to have_content(summary_row2) + end + + context "filtering" do + before do + visit_report + end + + it "should filter by distributor and order cycle" do + page.find("#s2id_autogen1").click + find('li', text: distributor.name).click # selects Distributor + + page.find("#s2id_q_order_cycle_id_in").click + find('li', text: order_cycle.name).click + + expect(page).to have_button("Go") + click_on "Go" + expect(page.find("table.report__table thead tr")).to have_content(table_header) + + table = page.find("table.report__table tbody") + + expect(table).to have_content(supplier_state_tax1) + expect(table).to have_content(supplier_country_tax1) + expect(table).not_to have_content(distributor_state_tax1) + expect(table).not_to have_content(distributor_country_tax1) + expect(table).not_to have_content(coordinator_state_tax1) + expect(table).not_to have_content(coordinator_country_tax1) + expect(table).to have_content(cost_of_produce1) + expect(table).to have_content(summary_row1) + end + end + end + + context "with line items from several suppliers" do + # creates oc3 and order + let!(:order_cycle3){ + create(:simple_order_cycle, distributors: [distributor], name: "oc3") + } + let!(:order3) { create(:order_with_distributor, distributor:) } + + # creates exchanges on oc3 + let!(:incoming_exchange5) { + order_cycle3.exchanges.create! sender: supplier, receiver: distributor, incoming: true + } + let!(:incoming_exchange6) { + order_cycle3.exchanges.create! sender: supplier2, receiver: distributor, incoming: true + } + let(:outgoing_exchange3) { + order_cycle3.exchanges.create! sender: distributor, receiver: distributor, + incoming: false + } + + before do + # adds variants to exchanges on oc3 + order_cycle3.coordinator_fees << coordinator_fees + order_cycle3.exchanges.incoming.first.exchange_fees.create!(enterprise_fee: supplier_fees) + order_cycle3.exchanges.incoming.first.exchange_variants.create!(variant:) + order_cycle3.exchanges.incoming.second.exchange_fees + .create!(enterprise_fee: supplier_fees2) + order_cycle3.exchanges.incoming.second.exchange_variants.create!(variant: variant2) + order_cycle3.exchanges.outgoing.first.exchange_fees + .create!(enterprise_fee: distributor_fee) + order_cycle3.exchanges.outgoing.first.exchange_variants.create!(variant:) + order_cycle3.exchanges.outgoing.first.exchange_variants.create!(variant: variant2) + + # adds line items to the order on oc3 + order3.line_items.create({ variant:, quantity: 1, price: 100 }) + order3.line_items.create({ variant: variant2, quantity: 1, price: 50 }) + order3.update!({ + order_cycle_id: order_cycle3.id, + ship_address_id: ship_address.id + }) + # This will load the enterprise fees from the order cycle. + # This is needed because the order instance was created + # independently of the order_cycle. + order3.recreate_all_fees! + while !order3.completed? + break unless order3.next! + end + end + + # table lines for supplier1 + + # for supplier 1, oc3 + + let(:coordinator_state_tax3){ + ["Distributor", "Supplier1", "Yes", "oc3", "Adminstration", "admin", "Distributor", + "tax_category", "State", "0.015", "20.0", "0.3", "20.3"].join(" ") + } + let(:coordinator_country_tax3){ + ["Distributor", "Supplier1", "Yes", "oc3", "Adminstration", "admin", "Distributor", + "tax_category", "Country", "0.025", "20.0", "0.5", "20.5"].join(" ") + } + + let(:supplier_state_tax3){ + ["Distributor", "Supplier1", "Yes", "oc3", "Transport", "transport", "Supplier1", + "tax_category", "State", "0.015", "15.0", "0.23", "15.23"].join(" ") + } + let(:supplier_country_tax3){ + ["Distributor", "Supplier1", "Yes", "oc3", "Transport", "transport", "Supplier1", + "tax_category", "Country", "0.025", "15.0", "0.38", "15.38"].join(" ") + } + + let(:distributor_state_tax3){ + ["Distributor", "Supplier1", "Yes", "oc3", "Packing", "packing", "Distributor", + "tax_category", "State", "0.015", "10.0", "0.15", "10.15"].join(" ") + } + let(:distributor_country_tax3){ + ["Distributor", "Supplier1", "Yes", "oc3", "Packing", "packing", "Distributor", + "tax_category", "Country", "0.025", "10.0", "0.25", "10.25"].join(" ") + } + + let(:cost_of_produce3){ + ["Distributor", "Supplier1", "Yes", "oc3", "Cost of produce", "line items", "Supplier1", + "100.0", "4.0", "104.0"].join(" ") + } + let(:summary_row3){ + [ + cost_of_produce3, # Ensure summary row follows the right supplier + "TOTAL", # Fees and line items + "115.0", # Tax excl: 15 + 100 + "4.61", # Tax : (0.23 + 0.38) + (1.50 + 2.50) + "119.61" # Tax incl: 100.00 + 15 + (0.23 + 0.38) + (1.50 + 2.50) + ].join(" ") + } + + # for supplier 2, oc3 + let(:coordinator_state_tax4){ + ["Distributor", "Supplier2", "Yes", "oc3", "Adminstration", "admin", "Distributor", + "tax_category", "State", "0.015", "20.0", "0.3", "20.3"].join(" ") + } + let(:coordinator_country_tax4){ + ["Distributor", "Supplier2", "Yes", "oc3", "Adminstration", "admin", "Distributor", + "tax_category", "Country", "0.025", "20.0", "0.5", "20.5"].join(" ") + } + + let(:supplier_state_tax4){ + ["Distributor", "Supplier2", "Yes", "oc3", "Sales", "sales", "Supplier2", + "tax_category", "State", "0.015", "25.0", "0.38", "25.38"].join(" ") + } + let(:supplier_country_tax4){ + ["Distributor", "Supplier2", "Yes", "oc3", "Sales", "sales", "Supplier2", + "tax_category", "Country", "0.025", "25.0", "0.63", "25.63"].join(" ") + } + + let(:distributor_state_tax4){ + ["Distributor", "Supplier2", "Yes", "oc3", "Packing", "packing", "Distributor", + "tax_category", "State", "0.015", "10.0", "0.15", "10.15"].join(" ") + } + let(:distributor_country_tax4){ + ["Distributor", "Supplier2", "Yes", "oc3", "Packing", "packing", "Distributor", + "tax_category", "Country", "0.025", "10.0", "0.25", "10.25"].join(" ") + } + + let(:cost_of_produce4){ + ["Distributor", "Supplier2", "Yes", "oc3", "Cost of produce", "line items", "Supplier2", + "50.0", "2.0", "52.0"].join(" ") + } + let(:summary_row4){ + [ + cost_of_produce4, # Ensure summary row follows the right supplier + "TOTAL", # Fees and line items + "75.0", # Tax excl: 25 + 50 + "3.01", # Tax : (0.38 + 0.63) + 2 + "78.01" # Tax incl: 25 + 50 + 4.21 + ].join(" ") + } + + context "filtering" do + let(:fee_name_selector){ "#s2id_q_enterprise_fee_id_in" } + let(:fee_owner_selector){ "#s2id_q_enterprise_fee_owner_id_in" } + + let(:summary_row_after_filtering_by_fee_name){ + [cost_of_produce1, "TOTAL", "120.0", "4.8", "124.8"].join(" ") + } + + let(:summary_row_after_filtering_by_fee_owner){ + [cost_of_produce1, "TOTAL", "115.0", "4.61", "119.61"].join(" ") + } + + before do + visit_report + end + + it "should filter by distributor and order cycle" do + page.find("#s2id_autogen1").click + find('li', text: distributor.name).click # selects Distributor + + page.find("#s2id_q_order_cycle_id_in").click + find('li', text: order_cycle3.name).click + + expect(page).to have_button("Go") + click_on "Go" + expect(page.find("table.report__table thead tr")).to have_content(table_header) + + table = page.find("table.report__table tbody") + + # Supplier1 + expect(table).to have_content(supplier_state_tax3) + expect(table).to have_content(supplier_country_tax3) + expect(table).not_to have_content(distributor_state_tax3) + expect(table).not_to have_content(distributor_country_tax3) + expect(table).not_to have_content(coordinator_state_tax3) + expect(table).not_to have_content(coordinator_country_tax3) + expect(table).to have_content(cost_of_produce3) + expect(table).to have_content(summary_row3) + + # Supplier2 + expect(table).to have_content(supplier_state_tax4) + expect(table).to have_content(supplier_country_tax4) + expect(table).not_to have_content(distributor_state_tax4) + expect(table).not_to have_content(distributor_country_tax4) + expect(table).not_to have_content(coordinator_state_tax4) + expect(table).not_to have_content(coordinator_country_tax4) + expect(table).to have_content(cost_of_produce4) + expect(table).to have_content(summary_row4) + end + + it "should filter by producer" do + page.find("#s2id_supplier_id_in").click + find('li', text: supplier2.name).click + + expect(page).to have_button("Go") + click_on "Go" + expect(page.find("table.report__table thead tr")).to have_content(table_header) + + table = page.find("table.report__table tbody") + + expect(table).to have_content(supplier_state_tax2) + expect(table).to have_content(supplier_country_tax2) + expect(table).not_to have_content(distributor_state_tax2) + expect(table).not_to have_content(distributor_country_tax2) + expect(table).not_to have_content(coordinator_state_tax2) + expect(table).not_to have_content(coordinator_country_tax2) + expect(table).to have_content(cost_of_produce2) + expect(table).to have_content(summary_row2) + + expect(table).to_not have_content(supplier_state_tax1) + expect(table).to_not have_content(supplier_country_tax1) + expect(table).to_not have_content(cost_of_produce1) + expect(table).to_not have_content(summary_row1) + end + + it "should filter by fee name" do + page.find(fee_name_selector).click + find('li', text: supplier_fees.name).click + + expect(page).to have_button("Go") + click_on "Go" + + expect(page.find("table.report__table thead tr")).to have_content(table_header) + + table = page.find("table.report__table tbody") + + expect(table).to have_content(supplier_state_tax1) + expect(table).to have_content(supplier_country_tax1) + expect(table).to_not have_content(distributor_state_tax1) + expect(table).to_not have_content(distributor_country_tax1) + expect(table).to_not have_content(coordinator_state_tax1) + expect(table).to_not have_content(coordinator_country_tax1) + expect(table).to have_content(cost_of_produce1) + expect(table).to have_content(summary_row1) + + expect(table).to have_content(supplier_state_tax3) + expect(table).to have_content(supplier_country_tax3) + expect(table).to_not have_content(distributor_state_tax3) + expect(table).to_not have_content(distributor_country_tax3) + expect(table).to_not have_content(coordinator_state_tax3) + expect(table).to_not have_content(coordinator_country_tax3) + expect(table).to have_content(cost_of_produce3) + expect(table).to have_content(summary_row3) + end + + it "should filter by fee owner" do + page.find(fee_owner_selector).click + find('li', text: supplier.name).click + + expect(page).to have_button("Go") + click_on "Go" + expect(page.find("table.report__table thead tr")).to have_content(table_header) + + table = page.find("table.report__table tbody") + expect(table).to have_content(supplier_state_tax1) + expect(table).to have_content(supplier_country_tax1) + expect(table).to_not have_content(distributor_state_tax1) + expect(table).to_not have_content(distributor_country_tax1) + expect(table).to_not have_content(coordinator_state_tax1) + expect(table).to_not have_content(coordinator_country_tax1) + expect(table).to have_content(cost_of_produce1) + expect(table).to have_content(summary_row_after_filtering_by_fee_owner) + end + end + end + end + end + + context 'included tax' do + # 1 order cycle has: + # - coordinator fees (20) 1.5% = 0.30, 2.5% = 0.50 + # - incoming exchange (15) 1.5% = 0.23, 2.5% = 0.38 + # - outgoing exchange (10) 1.5% = 0.15, 2.5% = 0.25 + # - line items (100) 1.5% = 1.50, 2.5% = 2.50 + # - line items (50) 1.5% = 1.50, 2.5% = 2.50 + + let(:included_in_price) { true } + + let(:coordinator_state_tax1){ + ["Distributor", "Supplier1", "Yes", "oc1", "Adminstration", "admin", "Distributor", + "tax_category", "State", "0.015", "19.21", "0.3", "19.51"].join(" ") + } + let(:coordinator_country_tax1){ + ["Distributor", "Supplier1", "Yes", "oc1", "Adminstration", "admin", "Distributor", + "tax_category", "Country", "0.025", "19.21", "0.49", "19.7"].join(" ") + } + + let(:supplier_state_tax1){ + ["Distributor", "Supplier1", "Yes", "oc1", "Transport", "transport", "Supplier1", + "tax_category", "State", "0.015", "14.41", "0.22", "14.63"].join(" ") + } + let(:supplier_country_tax1){ + ["Distributor", "Supplier1", "Yes", "oc1", "Transport", "transport", "Supplier1", + "tax_category", "Country", "0.025", "14.41", "0.37", "14.78"].join(" ") + } + + let(:distributor_state_tax1){ + ["Distributor", "Supplier1", "Yes", "oc1", "Packing", "packing", "Distributor", + "tax_category", "State", "0.015", "9.61", "0.15", "9.76"].join(" ") + } + let(:distributor_country_tax1){ + ["Distributor", "Supplier1", "Yes", "oc1", "Packing", "packing", "Distributor", + "tax_category", "Country", "0.025", "9.61", "0.24", "9.85"].join(" ") + } + + let(:cost_of_produce1){ + ["Distributor", "Supplier1", "Yes", "oc1", "Cost of produce", "line items", "Supplier1", + "96.08", "3.92", "100.0"].join(" ") + } + let(:summary_row1){ + [ + cost_of_produce1, + "TOTAL", # Fees and line items + "110.49", # Tax excl: 14.41 + 96.08 + "4.51", # Tax : (0.22 + 0.37) + 3.92 + "115.0" # Tax incl: 15 + 100 + ].join(" ") + } + + # for supplier 2, oc3 + let(:coordinator_state_tax2){ + ["Distributor", "Supplier2", "Yes", "oc2", "Adminstration", "admin", "Distributor", + "tax_category", "State", "0.015", "19.21", "0.3", "19.51"].join(" ") + } + let(:coordinator_country_tax2){ + ["Distributor", "Supplier2", "Yes", "oc2", "Adminstration", "admin", "Distributor", + "tax_category", "Country", "0.025", "19.21", "0.49", "19.7"].join(" ") + } + + let(:supplier_state_tax2){ + ["Distributor", "Supplier2", "Yes", "oc2", "Sales", "sales", "Supplier2", + "tax_category", "State", "0.015", "24.02", "0.37", "24.39"].join(" ") + } + let(:supplier_country_tax2){ + ["Distributor", "Supplier2", "Yes", "oc2", "Sales", "sales", "Supplier2", + "tax_category", "Country", "0.025", "24.02", "0.61", "24.63"].join(" ") + } + + let(:distributor_state_tax2){ + ["Distributor", "Supplier2", "Yes", "oc2", "Packing", "packing", "Distributor", + "tax_category", "State", "0.015", "9.61", "0.15", "9.76"].join(" ") + } + let(:distributor_country_tax2){ + ["Distributor", "Supplier2", "Yes", "oc2", "Packing", "packing", "Distributor", + "tax_category", "Country", "0.025", "9.61", "0.24", "9.85"].join(" ") + } + + let(:cost_of_produce2){ + ["Distributor", "Supplier2", "Yes", "oc2", "Cost of produce", "line items", "Supplier2", + "48.04", "1.96", "50.0"].join(" ") + } + let(:summary_row2){ + [ + cost_of_produce2, + "TOTAL", # Fees and line items + "72.06", # Tax excl: 24.02 + 48.04 + "2.94", # Tax : (0.37 + 0.61) + 1.96 + "75.0" # Tax incl: 25 + 50 + ].join(" ") + } + + context "with line items from a single supplier" do + it 'generates the report and displays fees for the respective suppliers' do + visit_report + click_on "Go" + + expect(page.find("table.report__table thead tr")).to have_content(table_header) + + table = page.find("table.report__table tbody") + expect(table).to have_content(supplier_state_tax1) + expect(table).to have_content(supplier_country_tax1) + expect(table).not_to have_content(distributor_state_tax1) + expect(table).not_to have_content(distributor_country_tax1) + expect(table).not_to have_content(coordinator_state_tax1) + expect(table).not_to have_content(coordinator_country_tax1) + expect(table).to have_content(cost_of_produce1) + expect(table).to have_content(summary_row1) + + expect(table).to have_content(supplier_state_tax2) + expect(table).to have_content(supplier_country_tax2) + expect(table).not_to have_content(distributor_state_tax2) + expect(table).not_to have_content(distributor_country_tax2) + expect(table).not_to have_content(coordinator_state_tax2) + expect(table).not_to have_content(coordinator_country_tax2) + expect(table).to have_content(cost_of_produce2) + expect(table).to have_content(summary_row2) + end + end + end + + context 'multiple orders, same enterprise fee, different tax rates' do + let(:another_state) { + Spree::State.find_by(name: "New South Wales") + } + + let(:another_address) { + create(:address, + state: another_state, + country: another_state.country) + } + + let!(:state_zone2){ + create( + :zone, + zone_members: [Spree::ZoneMember.new(zoneable: another_state)] + ) + } + + let!(:state_tax_rate2){ + create(:tax_rate, zone: state_zone2, tax_category:, + name: 'Another State Tax', amount: 0.02, included_in_price:) + } + + let!(:order2) { + # Ensure tax rates set up first + state_tax_rate2 + + order2 = create(:order_with_distributor, distributor:, order_cycle_id: order_cycle.id, + ship_address_id: another_address.id) + + # adds a line items to the order on oc2 + order2.line_items.create({ variant:, quantity: 1, price: 50 }) + order2.recreate_all_fees! + while !order2.completed? + break unless order2.next! + end + + order2 + } + + context "added tax" do + let(:admin_state_tax1){ + [ + "Distributor", "Supplier1", "Yes", "oc1", "Adminstration", "admin", + "Distributor", "tax_category", "State", "0.015", "20.0", "0.3", "20.3" + ].join(" ") + } + let(:admin_country_tax1){ + [ + "Distributor", "Supplier1", "Yes", "oc1", "Adminstration", "admin", + "Distributor", "tax_category", "Country", "0.025", "40.0", "1.0", "41.0" + ].join(" ") + } + let(:transport_state_tax1){ + [ + "Distributor", "Supplier1", "Yes", "oc1", "Transport", "transport", + "Supplier1", "tax_category", "State", "0.015", "15.0", "0.23", "15.23" + ].join(" ") + } + let(:transport_country_tax1){ + [ + "Distributor", "Supplier1", "Yes", "oc1", "Transport", "transport", + "Supplier1", "tax_category", "Country", "0.025", "30.0", "0.76", "30.76" + ].join(" ") + } + let(:packing_state_tax1){ + [ + "Distributor", "Supplier1", "Yes", "oc1", "Packing", "packing", + "Distributor", "tax_category", "State", "0.015", "10.0", "0.15", "10.15" + ].join(" ") + } + let(:packing_country_tax1){ + [ + "Distributor", "Supplier1", "Yes", "oc1", "Packing", "packing", + "Distributor", "tax_category", "Country", "0.025", "20.0", "0.5", "20.5" + ].join(" ") + } + + let(:admin_state_tax2){ + [ + "Distributor", "Supplier1", "Yes", "oc1", "Adminstration", "admin", + "Distributor", "tax_category", "Another State Tax", "0.02", "20.0", "0.4", "20.4" + ].join(" ") + } + let(:transport_state_tax2){ + [ + "Distributor", "Supplier1", "Yes", "oc1", "Transport", "transport", + "Supplier1", "tax_category", "Another State Tax", "0.02", "15.0", "0.3", "15.3" + ].join(" ") + } + let(:packing_state_tax2){ + [ + "Distributor", "Supplier1", "Yes", "oc1", "Packing", "packing", + "Distributor", "tax_category", "Another State Tax", "0.02", "10.0", "0.2", "10.2" + ].join(" ") + } + + let(:supplier1_cost_of_produce_line_items){ + [ + "Distributor", "Supplier1", "Yes", "oc1", "Cost of produce line items", + "Supplier1", "150.0", "6.25", "156.25" + ].join(" ") + } + + let(:summary_row){ + [ + "TOTAL", "180.0", "7.54", "187.54" + ].join(" ") + } + + it 'should list all the tax rates' do + visit_report + click_on "Go" + + expect(page.find("table.report__table thead tr")).to have_content(table_header) + + table = page.find("table.report__table tbody") + expect(table).not_to have_content(admin_state_tax1) + expect(table).not_to have_content(admin_country_tax1) + expect(table).to have_content(transport_state_tax1) + expect(table).to have_content(transport_country_tax1) + expect(table).not_to have_content(packing_state_tax1) + expect(table).not_to have_content(packing_country_tax1) + + expect(table).not_to have_content(admin_state_tax2) + expect(table).to have_content(transport_state_tax2) + expect(table).not_to have_content(packing_state_tax2) + + expect(table).to have_content(supplier1_cost_of_produce_line_items) + expect(table).to have_content(summary_row) + end + end + + context "included tax" do + let(:included_in_price) { true } + + let(:admin_state_tax1){ + [ + "Distributor", "Supplier1", "Yes", "oc1", "Adminstration", "admin", + "Distributor", "tax_category", "State", "0.015", "19.21", "0.3", "19.51" + ].join(" ") + } + let(:admin_country_tax1){ + [ + "Distributor", "Supplier1", "Yes", "oc1", "Adminstration", "admin", + "Distributor", "tax_category", "Country", "0.025", "38.33", "0.98", "39.31" + ].join(" ") + } + let(:transport_state_tax1){ + [ + "Distributor", "Supplier1", "Yes", "oc1", "Transport", "transport", + "Supplier1", "tax_category", "State", "0.015", "14.41", "0.22", "14.63" + ].join(" ") + } + let(:transport_country_tax1){ + [ + "Distributor", "Supplier1", "Yes", "oc1", "Transport", "transport", + "Supplier1", "tax_category", "Country", "0.025", "28.75", "0.74", "29.49" + ].join(" ") + } + let(:packing_state_tax1){ + [ + "Distributor", "Supplier1", "Yes", "oc1", "Packing", "packing", + "Distributor", "tax_category", "State", "0.015", "9.61", "0.15", "9.76" + ].join(" ") + } + let(:packing_country_tax1){ + [ + "Distributor", "Supplier1", "Yes", "oc1", "Packing", "packing", + "Distributor", "tax_category", "Country", "0.025", "19.17", "0.48", "19.65" + ].join(" ") + } + + let(:admin_state_tax2){ + [ + "Distributor", "Supplier1", "Yes", "oc1", "Adminstration", "admin", + "Distributor", "tax_category", "Another State Tax", "0.02", "19.12", "0.39", "19.51" + ].join(" ") + } + let(:transport_state_tax2){ + [ + "Distributor", "Supplier1", "Yes", "oc1", "Transport", "transport", + "Supplier1", "tax_category", "Another State Tax", "0.02", "14.34", "0.29", "14.63" + ].join(" ") + } + let(:packing_state_tax2){ + [ + "Distributor", "Supplier1", "Yes", "oc1", "Packing", "packing", + "Distributor", "tax_category", "Another State Tax", "0.02", "9.56", "0.2", "9.76" + ].join(" ") + } + + let(:supplier1_cost_of_produce_line_items){ + [ + "Distributor", "Supplier1", "Yes", "oc1", "Cost of produce line items", + "Supplier1", "143.88", "6.12", "150.0" + ].join(" ") + } + + let(:summary_row){ + [ + "TOTAL", "172.63", "7.37", "180.0" + ].join(" ") + } + + it 'should list all the tax rates' do + visit_report + click_on "Go" + + expect(page.find("table.report__table thead tr")).to have_content(table_header) + + table = page.find("table.report__table tbody") + expect(table).not_to have_content(admin_state_tax1) + expect(table).not_to have_content(admin_country_tax1) + expect(table).to have_content(transport_state_tax1) + expect(table).to have_content(transport_country_tax1) + expect(table).not_to have_content(packing_state_tax1) + expect(table).not_to have_content(packing_country_tax1) + + expect(table).not_to have_content(admin_state_tax2) + expect(table).to have_content(transport_state_tax2) + expect(table).not_to have_content(packing_state_tax2) + + expect(table).to have_content(supplier1_cost_of_produce_line_items) + expect(table).to have_content(summary_row) + end + end + end + + def visit_report + login_as distributor_owner + visit admin_report_path( + report_type: :enterprise_fee_summary, + report_subtype: :enterprise_fees_with_tax_report_by_producer + ) + expect(page).to have_button("Go") + end +end