diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index e3ccc8f5fa..13d9769853 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -128,7 +128,6 @@ Layout/LineLength: - 'lib/reporting/reports/payments/payments_report.rb' - 'lib/reporting/reports/products_and_inventory/lettuce_share_report.rb' - 'lib/reporting/reports/sales_tax/sales_tax_report.rb' - - 'lib/reporting/reports/users_and_enterprises/users_and_enterprises_report.rb' - 'lib/reporting/reports/xero_invoices/xero_invoices_report.rb' - 'lib/spree/localized_number.rb' - 'lib/tasks/data.rake' @@ -537,7 +536,6 @@ Metrics/ClassLength: - 'lib/reporting/reports/order_cycle_management/order_cycle_management_report.rb' - 'lib/open_food_network/order_cycle_permissions.rb' - 'lib/reporting/reports/payments/payments_report.rb' - - 'lib/reporting/reports/users_and_enterprises/users_and_enterprises_report.rb' - 'lib/reporting/reports/xero_invoices/xero_invoices_report.rb' - 'lib/reporting/report_grouper.rb' diff --git a/lib/reporting/reports/users_and_enterprises/base.rb b/lib/reporting/reports/users_and_enterprises/base.rb new file mode 100644 index 0000000000..f7d7c52610 --- /dev/null +++ b/lib/reporting/reports/users_and_enterprises/base.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +module Reporting + module Reports + module UsersAndEnterprises + class Base < ReportObjectTemplate + def initialize(user, params = {}) + super(user, params) + end + + def query_result + sort(owners_and_enterprises.concat(managers_and_enterprises)) + end + + def columns + { + user: proc { |x| x.user_email }, + relationship: proc { |x| x.relationship_type }, + enterprise: proc { |x| x.name }, + is_producer: proc { |x| x.is_primary_producer }, + sells: proc { |x| x.sells }, + visible: proc { |x| x.visible }, + confirmation_date: proc { |x| x.created_at } + } + end + + def owners_and_enterprises + query = Enterprise + .joins("LEFT JOIN spree_users AS owner ON enterprises.owner_id = owner.id") + .where("enterprises.id IS NOT NULL") + + query = filter_by_int_list_if_present(query, "enterprises.id", params[:enterprise_id_in]) + query = filter_by_int_list_if_present(query, "owner.id", params[:user_id_in]) + + query_helper(query, :owner, :owns) + end + + def managers_and_enterprises + query = Enterprise + .joins("LEFT JOIN enterprise_roles ON enterprises.id = enterprise_roles.enterprise_id") + .joins("LEFT JOIN spree_users AS managers ON enterprise_roles.user_id = managers.id") + .where("enterprise_id IS NOT NULL") + .where("user_id IS NOT NULL") + + query = filter_by_int_list_if_present(query, "enterprise_id", params[:enterprise_id_in]) + query = filter_by_int_list_if_present(query, "user_id", params[:user_id_in]) + + query_helper(query, :managers, :manages) + end + + def query_helper(query, email_user, relationship_type) + query.order("enterprises.created_at DESC") + .select(["enterprises.name", + "enterprises.sells", + "enterprises.visible", + "enterprises.is_primary_producer", + "enterprises.created_at", + "#{email_user}.email AS user_email", + "'#{relationship_type}' AS relationship_type"]) + .to_a + end + + def filter_by_int_list_if_present(query, filtered_field_name, int_list) + if int_list.present? + query = query.where("#{filtered_field_name} IN (?)", int_list.map(&:to_i)) + end + query + end + + def sort(results) + results.sort do |a, b| + a_date = (a.created_at || Date.new(1970, 1, 1)).in_time_zone + b_date = (b.created_at || Date.new(1970, 1, 1)).in_time_zone + [b_date, a.name, b.relationship_type, a.user_email] <=> + [a_date, b.name, a.relationship_type, b.user_email] + end + end + end + end + end +end diff --git a/lib/reporting/reports/users_and_enterprises/users_and_enterprises_report.rb b/lib/reporting/reports/users_and_enterprises/users_and_enterprises_report.rb deleted file mode 100644 index 26b4d37822..0000000000 --- a/lib/reporting/reports/users_and_enterprises/users_and_enterprises_report.rb +++ /dev/null @@ -1,137 +0,0 @@ -# frozen_string_literal: true - -module Reporting - module Reports - module UsersAndEnterprises - class UsersAndEnterprisesReport < ReportObjectTemplate - def initialize(user, params = {}) - super(user, params) - - # Convert arrays of ids to comma delimited strings - if @params[:enterprise_id_in].is_a? Array - @params[:enterprise_id_in] = @params[:enterprise_id_in].join(',') - end - @params[:user_id_in] = @params[:user_id_in].join(',') if @params[:user_id_in].is_a? Array - end - - def table_headers - [ - I18n.t(:report_header_user), - I18n.t(:report_header_relationship), - I18n.t(:report_header_enterprise), - I18n.t(:report_header_is_producer), - I18n.t(:report_header_sells), - I18n.t(:report_header_visible), - I18n.t(:report_header_confirmation_date), - ] - end - - def table_rows - users_and_enterprises.map do |uae| - [ - uae["user_email"], - uae["relationship_type"], - uae["name"], - to_bool(uae["is_primary_producer"]), - uae["sells"], - uae["visible"], - to_local_datetime(uae["created_at"]) - ] - end - end - - def owners_and_enterprises - query = Enterprise.joins("LEFT JOIN spree_users AS owner ON enterprises.owner_id = owner.id") - .where("enterprises.id IS NOT NULL") - - query = filter_by_int_list_if_present(query, "enterprises.id", params[:enterprise_id_in]) - query = filter_by_int_list_if_present(query, "owner.id", params[:user_id_in]) - - query_helper(query, :owner, :owns) - end - - def managers_and_enterprises - query = Enterprise - .joins("LEFT JOIN enterprise_roles ON enterprises.id = enterprise_roles.enterprise_id") - .joins("LEFT JOIN spree_users AS managers ON enterprise_roles.user_id = managers.id") - .where("enterprise_id IS NOT NULL") - .where("user_id IS NOT NULL") - - query = filter_by_int_list_if_present(query, "enterprise_id", params[:enterprise_id_in]) - query = filter_by_int_list_if_present(query, "user_id", params[:user_id_in]) - - query_helper(query, :managers, :manages) - end - - def query_helper(query, email_user, relationship_type) - query.order("enterprises.created_at DESC") - .select(["enterprises.name", - "enterprises.sells", - "enterprises.visible", - "enterprises.is_primary_producer", - "enterprises.created_at", - "#{email_user}.email AS user_email"]) - .to_a - .map { |x| - { - name: x.name, - sells: x.sells, - visible: (x.visible ? 't' : 'f'), - is_primary_producer: (x.is_primary_producer ? 't' : 'f'), - created_at: x.created_at.utc.iso8601, - relationship_type: relationship_type, - user_email: x.user_email - }.stringify_keys - } - end - - def users_and_enterprises - sort( owners_and_enterprises.concat(managers_and_enterprises) ) - end - - def filter_by_int_list_if_present(query, filtered_field_name, int_list) - if int_list.present? - query = query.where("#{filtered_field_name} IN (?)", split_int_list(int_list)) - end - query - end - - def split_int_list(int_list) - int_list.split(',').map(&:to_i) - end - - def sort(results) - results.sort do |a, b| - if a["created_at"].nil? || b["created_at"].nil? - [(a["created_at"].nil? ? 0 : 1), a["name"], b["relationship_type"], - a["user_email"]] <=> - [(b["created_at"].nil? ? 0 : 1), b["name"], a["relationship_type"], b["user_email"]] - else - [ - DateTime.parse(b["created_at"]).in_time_zone, - a["name"], - b["relationship_type"], - a["user_email"] - ] <=> [ - DateTime.parse(a["created_at"]).in_time_zone, - b["name"], - a["relationship_type"], - b["user_email"] - ] - end - end - end - - def to_bool(value) - ActiveRecord::Type::Boolean.new.cast(value) - end - - def to_local_datetime(date) - return "" if date.nil? - - date.to_datetime.in_time_zone.strftime "%Y-%m-%d %H:%M" - end - end - end - end -end diff --git a/spec/lib/reports/users_and_enterprises_report_spec.rb b/spec/lib/reports/users_and_enterprises_report_spec.rb index 9929a4cb04..0bcc77dc93 100644 --- a/spec/lib/reports/users_and_enterprises_report_spec.rb +++ b/spec/lib/reports/users_and_enterprises_report_spec.rb @@ -5,11 +5,11 @@ require 'spec_helper' module Reporting module Reports module UsersAndEnterprises - describe UsersAndEnterprisesReport do - describe "users_and_enterprises" do + describe Base do + describe "query_result" do let!(:owners_and_enterprises) { double(:owners_and_enterprises) } let!(:managers_and_enterprises) { double(:managers_and_enterprises) } - let!(:subject) { UsersAndEnterprisesReport.new(nil, {}) } + let!(:subject) { Base.new(nil, {}) } before do allow(subject).to receive(:owners_and_enterprises) { owners_and_enterprises } @@ -21,43 +21,51 @@ module Reporting expect(subject).to receive(:managers_and_enterprises).once expect(owners_and_enterprises).to receive(:concat).with(managers_and_enterprises).and_return [] expect(subject).to receive(:sort).with [] - subject.users_and_enterprises + subject.query_result end end describe "sorting results" do - let!(:subject) { UsersAndEnterprisesReport.new(nil, {}) } + let!(:subject) { Base.new(nil, {}) } it "sorts by creation date" do uae_mock = [ - { "created_at" => "2015-01-01", "name" => "bbb" }, - { "created_at" => "2015-01-02", "name" => "aaa" } + OpenStruct.new({ created_at: Date.new(2015, 1, 1), name: "aaa" }), + OpenStruct.new({ created_at: Date.new(2015, 1, 2), name: "bbb" }) + ] + expect(subject.sort(uae_mock)).to eq [uae_mock[1], uae_mock[0]] + end + + it "sorts by creation date when nil date" do + uae_mock = [ + OpenStruct.new({ created_at: nil, name: "aaa" }), + OpenStruct.new({ created_at: Date.new(2015, 1, 2), name: "bbb" }) ] expect(subject.sort(uae_mock)).to eq [uae_mock[1], uae_mock[0]] end it "then sorts by name" do uae_mock = [ - { "name" => "aaa", "relationship_type" => "bbb", "user_email" => "bbb" }, - { "name" => "bbb", "relationship_type" => "aaa", "user_email" => "aaa" } + OpenStruct.new({ name: "aaa", relationship_type: "bbb", user_email: "bbb" }), + OpenStruct.new({ name: "bbb", relationship_type: "aaa", user_email: "aaa" }) ] expect(subject.sort(uae_mock)).to eq [uae_mock[0], uae_mock[1]] end it "then sorts by relationship type (reveresed)" do uae_mock = [ - { "name" => "aaa", "relationship_type" => "bbb", "user_email" => "bbb" }, - { "name" => "aaa", "relationship_type" => "aaa", "user_email" => "aaa" }, - { "name" => "aaa", "relationship_type" => "bbb", "user_email" => "aaa" } + OpenStruct.new({ name: "aaa", relationship_type: "bbb", user_email: "bbb" }), + OpenStruct.new({ name: "aaa", relationship_type: "aaa", user_email: "aaa" }), + OpenStruct.new({ name: "aaa", relationship_type: "bbb", user_email: "aaa" }) ] expect(subject.sort(uae_mock)).to eq [uae_mock[2], uae_mock[0], uae_mock[1]] end it "then sorts by user_email" do uae_mock = [ - { "name" => "aaa", "relationship_type" => "bbb", "user_email" => "aaa" }, - { "name" => "aaa", "relationship_type" => "aaa", "user_email" => "aaa" }, - { "name" => "aaa", "relationship_type" => "aaa", "user_email" => "bbb" } + OpenStruct.new({ name: "aaa", relationship_type: "bbb", user_email: "aaa" }), + OpenStruct.new({ name: "aaa", relationship_type: "aaa", user_email: "aaa" }), + OpenStruct.new({ name: "aaa", relationship_type: "aaa", user_email: "bbb" }) ] expect(subject.sort(uae_mock)).to eq [uae_mock[0], uae_mock[1], uae_mock[2]] end @@ -70,7 +78,7 @@ module Reporting describe "for owners and enterprises" do describe "by enterprise id" do let!(:params) { { enterprise_id_in: [enterprise1.id.to_s] } } - let!(:subject) { UsersAndEnterprisesReport.new nil, params } + let!(:subject) { Base.new nil, params } it "excludes enterprises that are not explicitly requested" do results = subject.owners_and_enterprises.to_a.map{ |oae| oae["name"] } @@ -81,7 +89,7 @@ module Reporting describe "by user id" do let!(:params) { { user_id_in: [enterprise1.owner.id.to_s] } } - let!(:subject) { UsersAndEnterprisesReport.new nil, params } + let!(:subject) { Base.new nil, params } it "excludes enterprises that are not explicitly requested" do results = subject.owners_and_enterprises.to_a.map{ |oae| oae["name"] } @@ -94,7 +102,7 @@ module Reporting describe "for managers and enterprises" do describe "by enterprise id" do let!(:params) { { enterprise_id_in: [enterprise1.id.to_s] } } - let!(:subject) { UsersAndEnterprisesReport.new nil, params } + let!(:subject) { Base.new nil, params } it "excludes enterprises that are not explicitly requested" do results = subject.managers_and_enterprises.to_a.map{ |mae| mae["name"] } @@ -107,7 +115,7 @@ module Reporting let!(:manager1) { create(:user) } let!(:manager2) { create(:user) } let!(:params) { { user_id_in: [manager1.id.to_s] } } - let!(:subject) { UsersAndEnterprisesReport.new nil, params } + let!(:subject) { Base.new nil, params } before do enterprise1.enterprise_roles.build(user: manager1).save