Report Refactor 3: User & Entreprises

This commit is contained in:
Sebastian Castro
2022-04-06 11:01:28 +02:00
committed by Jean-Baptiste Bellet
parent 287e8f5845
commit 88bc417868
4 changed files with 108 additions and 158 deletions

View File

@@ -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'

View File

@@ -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

View File

@@ -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

View File

@@ -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