Files
openfoodnetwork/app/services/permissions/order.rb
Ahmed Ejaz ec44947b37 Add special handling for admin users in order permissions
Modifies order and line item permission logic to give admin users full access to all orders and line items, bypassing the regular complex joins queries to get orders editable by producers. These complex joins are needed for regular users but for user admins we need to return all orders.
2025-07-13 05:34:55 +05:00

151 lines
5.0 KiB
Ruby

# frozen_string_literal: true
require 'open_food_network/permissions'
module Permissions
class Order
def initialize(user, search_params = nil)
@user = user
@permissions = OpenFoodNetwork::Permissions.new(@user)
@search_params = search_params
end
# Find orders that the user can see. This includes any order where the producer has permissions
# and has at least *one* of their supplied products in the order. Additional scoping may be
# needed for queries showing line items per producer.
def visible_orders
orders = Spree::Order.
with_line_items_variants_and_products_outer.
where(visible_orders_where_values)
filtered_orders(orders)
end
def managed_or_coordinated_orders_where_clause
Spree::Order.where(
managed_orders_where_values.or(coordinated_orders_where_values)
)
end
# Any orders that the user can edit
def editable_orders
orders = if @user.admin?
# It returns all orders if the user is an admin
managed_or_coordinated_orders_where_clause
else
Spree::Order.joins(:distributor).where(
id: produced_orders.select(:id),
distributor: { enable_producers_to_edit_orders: true }
).or(
managed_or_coordinated_orders_where_clause
)
end
filtered_orders(orders)
end
def visible_line_items
editable_line_items.or(produced_line_items)
end
# Any line items that I can edit
def editable_line_items
managed_or_coordinated_line_items_where_clause = Spree::LineItem.where(
order_id: filtered_orders(managed_or_coordinated_orders_where_clause).select(:id)
)
if @user.admin?
# It returns all line_items if the user is an admin
managed_or_coordinated_line_items_where_clause
else
Spree::LineItem.editable_by_producers(
@permissions.managed_enterprises.select("enterprises.id")
).or(
managed_or_coordinated_line_items_where_clause
)
end
end
private
attr_reader :search_params
def filtered_orders(orders)
return orders unless filter_orders?
orders.complete.not_state(:canceled).ransack(search_params).result
end
def filter_orders?
search_params.present?
end
def visible_orders_where_values
# Grouping keeps the 2 where clauses from produced_orders_where_values inside parentheses
# This way it makes the OR work between the 3 types of orders:
# produced, managed and coordinated
Spree::Order.arel_table.
grouping(produced_orders_where_values).
or(managed_orders_where_values).
or(coordinated_orders_where_values)
end
# Any orders placed through any hub that I manage
def managed_orders_where_values
Spree::Order.
where(distributor_id: @permissions.managed_enterprises.select("enterprises.id")).
where_clause.__send__(:predicates).
reduce(:and)
end
# Any order that is placed through an order cycle one of my managed enterprises coordinates
def coordinated_orders_where_values
Spree::Order.
where(order_cycle_id: @permissions.coordinated_order_cycles.select(:id)).
where_clause.__send__(:predicates).
reduce(:and)
end
def produced_orders
Spree::Order.with_line_items_variants_and_products_outer.
where(
spree_variants: { supplier_id: @permissions.managed_enterprises.select("enterprises.id") }
)
end
def produced_orders_where_values
Spree::Order.with_line_items_variants_and_products_outer.
where(
distributor_id: granted_distributor_ids,
spree_variants: { supplier_id: enterprises_with_associated_orders }
).
where_clause.__send__(:predicates).
reduce(:and)
end
def enterprises_with_associated_orders
# Any orders placed through hubs that my producers have granted P-OC,
# and which contain their products. This is pretty complicated but it's looking for order
# where at least one of my producers has granted P-OC to the distributor
# AND the order contains products of at least one of THE SAME producers
@permissions.related_enterprises_granting(:add_to_order_cycle, to: granted_distributor_ids).
merge(@permissions.managed_enterprises.is_primary_producer)
end
def granted_distributor_ids
@granted_distributor_ids ||= @permissions.related_enterprises_granted(
:add_to_order_cycle,
by: @permissions.managed_enterprises.is_primary_producer.select("enterprises.id")
).select("enterprises.id")
end
# Any from visible orders, where the product is produced by one of my managed producers
def produced_line_items
Spree::LineItem.where(order_id: visible_orders.select("DISTINCT spree_orders.id")).
supplied_by_any(
@permissions.managed_enterprises.is_primary_producer.select("enterprises.id")
)
end
end
end