mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-26 20:56:48 +00:00
211 lines
7.4 KiB
Ruby
211 lines
7.4 KiB
Ruby
module OpenFoodNetwork
|
|
class Permissions
|
|
def initialize(user)
|
|
@user = user
|
|
end
|
|
|
|
def can_manage_complex_order_cycles?
|
|
managed_and_related_enterprises_granting(:add_to_order_cycle).any? do |e|
|
|
e.sells == 'any'
|
|
end
|
|
end
|
|
|
|
# Find enterprises that an admin is allowed to add to an order cycle
|
|
def visible_enterprises_for_order_reports
|
|
managed_and_related_enterprises_with :add_to_order_cycle
|
|
end
|
|
|
|
def visible_enterprises
|
|
# Return enterprises that the user manages and those that have granted P-OC to managed enterprises
|
|
managed_and_related_enterprises_granting :add_to_order_cycle
|
|
end
|
|
|
|
# Find enterprises for which an admin is allowed to edit their profile
|
|
def editable_enterprises
|
|
managed_and_related_enterprises_granting :edit_profile
|
|
end
|
|
|
|
def variant_override_hubs
|
|
managed_enterprises.is_distributor
|
|
end
|
|
|
|
def variant_override_producers
|
|
producer_ids = variant_override_enterprises_per_hub.values.flatten.uniq
|
|
Enterprise.where(id: producer_ids)
|
|
end
|
|
|
|
# For every hub that an admin manages, show all the producers for which that hub may
|
|
# override variants
|
|
# {hub1_id => [producer1_id, producer2_id, ...], ...}
|
|
def variant_override_enterprises_per_hub
|
|
hubs = variant_override_hubs
|
|
|
|
# Permissions granted by create_variant_overrides relationship from producer to hub
|
|
permissions = Hash[
|
|
EnterpriseRelationship.
|
|
permitting(hubs).
|
|
with_permission(:create_variant_overrides).
|
|
group_by { |er| er.child_id }.
|
|
map { |child_id, ers| [child_id, ers.map { |er| er.parent_id }] }
|
|
]
|
|
|
|
# Allow a producer hub to override it's own products without explicit permission
|
|
hubs.is_primary_producer.each do |hub|
|
|
permissions[hub.id] ||= []
|
|
permissions[hub.id] |= [hub.id]
|
|
end
|
|
|
|
permissions
|
|
end
|
|
|
|
# Find enterprises that an admin is allowed to add to an order cycle
|
|
def visible_orders
|
|
# Any orders that I can edit
|
|
editable = editable_orders.pluck(:id)
|
|
|
|
# Any orders placed through hubs that my producers have granted P-OC, and which contain my 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
|
|
granted_distributors = related_enterprises_granted(:add_to_order_cycle, by: managed_enterprises.is_primary_producer)
|
|
produced = Spree::Order.with_line_items_variants_and_products_outer.
|
|
where(
|
|
"spree_orders.distributor_id IN (?) AND spree_products.supplier_id IN (?)",
|
|
granted_distributors,
|
|
related_enterprises_granting(:add_to_order_cycle, to: granted_distributors).merge(managed_enterprises.is_primary_producer)
|
|
).pluck(:id)
|
|
|
|
Spree::Order.where(id: editable | produced)
|
|
end
|
|
|
|
# Find enterprises that an admin is allowed to add to an order cycle
|
|
def editable_orders
|
|
# Any orders placed through any hub that I manage
|
|
managed = Spree::Order.where(distributor_id: managed_enterprises.pluck(:id)).pluck(:id)
|
|
|
|
# Any order that is placed through an order cycle one of my managed enterprises coordinates
|
|
coordinated = Spree::Order.where(order_cycle_id: coordinated_order_cycles.pluck(:id)).pluck(:id)
|
|
|
|
Spree::Order.where(id: managed | coordinated )
|
|
end
|
|
|
|
def visible_line_items
|
|
# Any line items that I can edit
|
|
editable = editable_line_items.pluck(:id)
|
|
|
|
# Any from visible orders, where the product is produced by one of my managed producers
|
|
produced = Spree::LineItem.where(order_id: visible_orders.pluck(:id)).joins(:product).
|
|
where('spree_products.supplier_id IN (?)', managed_enterprises.is_primary_producer.pluck(:id))
|
|
|
|
Spree::LineItem.where(id: editable | produced)
|
|
end
|
|
|
|
def editable_line_items
|
|
Spree::LineItem.where(order_id: editable_orders)
|
|
end
|
|
|
|
def editable_products
|
|
managed_enterprise_products_ids = managed_enterprise_products.pluck :id
|
|
permitted_enterprise_products_ids = products_supplied_by(
|
|
related_enterprises_granting(:manage_products).pluck(:id)
|
|
).pluck :id
|
|
Spree::Product.where('spree_products.id IN (?)', managed_enterprise_products_ids | permitted_enterprise_products_ids)
|
|
end
|
|
|
|
def visible_products
|
|
managed_enterprise_products_ids = managed_enterprise_products.pluck :id
|
|
permitted_enterprise_products_ids = products_supplied_by(
|
|
related_enterprises_granting(:manage_products).pluck(:id) | related_enterprises_granting(:add_to_order_cycle).pluck(:id)
|
|
).pluck :id
|
|
Spree::Product.where('spree_products.id IN (?)', managed_enterprise_products_ids | permitted_enterprise_products_ids)
|
|
end
|
|
|
|
def managed_product_enterprises
|
|
managed_and_related_enterprises_granting :manage_products
|
|
end
|
|
|
|
def manages_one_enterprise?
|
|
@user.enterprises.length == 1
|
|
end
|
|
|
|
def editable_schedules
|
|
Schedule.joins(:order_cycles).where(order_cycles: { id: OrderCycle.managed_by(@user).pluck(:id) }).select("DISTINCT schedules.*")
|
|
end
|
|
|
|
def visible_schedules
|
|
Schedule.joins(:order_cycles).where(order_cycles: { id: OrderCycle.accessible_by(@user).pluck(:id) }).select("DISTINCT schedules.*")
|
|
end
|
|
|
|
def editable_subscriptions
|
|
Subscription.where('subscriptions.shop_id IN (?)', managed_enterprises)
|
|
end
|
|
|
|
def visible_subscriptions
|
|
editable_subscriptions
|
|
end
|
|
|
|
private
|
|
|
|
def admin?
|
|
@user.admin?
|
|
end
|
|
|
|
def managed_and_related_enterprises_granting(permission)
|
|
if admin?
|
|
Enterprise.scoped
|
|
else
|
|
managed_enterprise_ids = managed_enterprises.pluck :id
|
|
permitting_enterprise_ids = related_enterprises_granting(permission).pluck :id
|
|
|
|
Enterprise.where('id IN (?)', managed_enterprise_ids + permitting_enterprise_ids)
|
|
end
|
|
end
|
|
|
|
def managed_and_related_enterprises_with(permission)
|
|
if admin?
|
|
Enterprise.scoped
|
|
else
|
|
managed = managed_enterprises.pluck(:id)
|
|
granting = related_enterprises_granting(permission).pluck(:id)
|
|
granted = related_enterprises_granted(permission).pluck(:id)
|
|
Enterprise.where(id: managed | granting | granted)
|
|
end
|
|
end
|
|
|
|
def managed_enterprises
|
|
return @managed_enterprises unless @managed_enterprises.nil?
|
|
@managed_enterprises = Enterprise.managed_by(@user)
|
|
end
|
|
|
|
def coordinated_order_cycles
|
|
return @coordinated_order_cycles unless @coordinated_order_cycles.nil?
|
|
@coordinated_order_cycles = OrderCycle.managed_by(@user)
|
|
end
|
|
|
|
def related_enterprises_granting(permission, options={})
|
|
parent_ids = EnterpriseRelationship.
|
|
permitting(options[:to] || managed_enterprises).
|
|
with_permission(permission).
|
|
pluck(:parent_id)
|
|
|
|
(options[:scope] || Enterprise).where('enterprises.id IN (?)', parent_ids)
|
|
end
|
|
|
|
def related_enterprises_granted(permission, options={})
|
|
child_ids = EnterpriseRelationship.
|
|
permitted_by(options[:by] || managed_enterprises).
|
|
with_permission(permission).
|
|
pluck(:child_id)
|
|
|
|
(options[:scope] || Enterprise).where('enterprises.id IN (?)', child_ids)
|
|
end
|
|
|
|
def managed_enterprise_products
|
|
Spree::Product.managed_by(@user)
|
|
end
|
|
|
|
def products_supplied_by(suppliers)
|
|
Spree::Product.where('supplier_id IN (?)', suppliers)
|
|
end
|
|
end
|
|
end
|