mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-16 04:24:23 +00:00
Merge pull request #2733 from kristinalim/fix-subscription_should_not_require_future_oc
Reduce restrictions for adding a variant to a subscription
This commit is contained in:
@@ -6,7 +6,11 @@ angular.module("admin.subscriptions").controller "SubscriptionController", ($sco
|
||||
$scope.schedules = Schedules.all
|
||||
$scope.paymentMethods = PaymentMethods.all
|
||||
$scope.shippingMethods = ShippingMethods.all
|
||||
$scope.distributor_id = $scope.subscription.shop_id # variant selector requires distributor_id
|
||||
|
||||
# Variant selector requires these
|
||||
$scope.distributor_id = $scope.subscription.shop_id
|
||||
$scope.eligible_for_subscriptions = true
|
||||
|
||||
$scope.view = if $scope.subscription.id? then 'review' else 'details'
|
||||
$scope.nextCallbacks = {}
|
||||
$scope.backCallbacks = {}
|
||||
|
||||
@@ -22,6 +22,7 @@ angular.module("admin.utils").directive "variantAutocomplete", ($timeout) ->
|
||||
q: term
|
||||
distributor_id: scope.distributor_id
|
||||
order_cycle_id: scope.order_cycle_id
|
||||
eligible_for_subscriptions: scope.eligible_for_subscriptions
|
||||
results: (data, page) ->
|
||||
results: data
|
||||
formatResult: (variant) ->
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
@import '../variables';
|
||||
|
||||
.admin-subscription-form-subscription-line-items {
|
||||
.not-in-open-and-upcoming-order-cycles-warning {
|
||||
color: $warning-red;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
@import '../variables';
|
||||
|
||||
.admin-subscription-review-subscription-line-items {
|
||||
.not-in-open-and-upcoming-order-cycles-warning {
|
||||
color: $warning-red;
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,8 @@ module Admin
|
||||
def build
|
||||
@subscription_line_item.assign_attributes(params[:subscription_line_item])
|
||||
@subscription_line_item.price_estimate = price_estimate
|
||||
render json: @subscription_line_item, serializer: Api::Admin::SubscriptionLineItemSerializer
|
||||
render json: @subscription_line_item, serializer: Api::Admin::SubscriptionLineItemSerializer,
|
||||
shop: @shop, schedule: @schedule
|
||||
end
|
||||
|
||||
private
|
||||
@@ -26,7 +27,7 @@ module Admin
|
||||
@shop = Enterprise.managed_by(spree_current_user).find_by_id(params[:shop_id])
|
||||
@schedule = permissions.editable_schedules.find_by_id(params[:schedule_id])
|
||||
@order_cycle = @schedule.andand.current_or_next_order_cycle
|
||||
@variant = Spree::Variant.stockable_by(@shop).find_by_id(params[:subscription_line_item][:variant_id])
|
||||
@variant = variant_if_eligible(params[:subscription_line_item][:variant_id]) if @shop.present?
|
||||
end
|
||||
|
||||
def new_actions
|
||||
@@ -50,5 +51,9 @@ module Admin
|
||||
OpenFoodNetwork::ScopeVariantToHub.new(@shop).scope(@variant)
|
||||
@variant.price + fee_calculator.indexed_fees_for(@variant)
|
||||
end
|
||||
|
||||
def variant_if_eligible(variant_id)
|
||||
SubscriptionVariantsService.eligible_variants(@shop).find_by_id(variant_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
module Api
|
||||
module Admin
|
||||
class SubscriptionLineItemSerializer < ActiveModel::Serializer
|
||||
attributes :id, :variant_id, :quantity, :description, :price_estimate
|
||||
attributes :id, :variant_id, :quantity, :description, :price_estimate,
|
||||
:in_open_and_upcoming_order_cycles
|
||||
|
||||
def description
|
||||
"#{object.variant.product.name} - #{object.variant.full_name}"
|
||||
@@ -10,6 +11,22 @@ module Api
|
||||
def price_estimate
|
||||
object.price_estimate.andand.to_f || "?"
|
||||
end
|
||||
|
||||
def in_open_and_upcoming_order_cycles
|
||||
SubscriptionVariantsService.in_open_and_upcoming_order_cycles?(option_or_assigned_shop,
|
||||
option_or_assigned_schedule,
|
||||
object.variant)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def option_or_assigned_shop
|
||||
@options[:shop] || object.subscription.andand.shop
|
||||
end
|
||||
|
||||
def option_or_assigned_schedule
|
||||
@options[:schedule] || object.subscription.andand.schedule
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -97,15 +97,12 @@ class SubscriptionValidator
|
||||
errors.add(:subscription_line_items, :not_available, name: name)
|
||||
end
|
||||
|
||||
# TODO: Extract this into a separate class
|
||||
def available_variant_ids
|
||||
@available_variant_ids ||=
|
||||
Spree::Variant.joins(exchanges: { order_cycle: :schedules })
|
||||
.where(id: subscription_line_items.map(&:variant_id))
|
||||
.where(schedules: { id: schedule }, exchanges: { incoming: false, receiver_id: shop })
|
||||
.merge(OrderCycle.not_closed)
|
||||
.select('DISTINCT spree_variants.id')
|
||||
.pluck(:id)
|
||||
return @available_variant_ids if @available_variant_ids.present?
|
||||
|
||||
subscription_variant_ids = subscription_line_items.map(&:variant_id)
|
||||
@available_variant_ids = SubscriptionVariantsService.eligible_variants(shop)
|
||||
.where(id: subscription_variant_ids).pluck(:id)
|
||||
end
|
||||
|
||||
def build_msg_from(k, msg)
|
||||
|
||||
39
app/services/subscription_variants_service.rb
Normal file
39
app/services/subscription_variants_service.rb
Normal file
@@ -0,0 +1,39 @@
|
||||
class SubscriptionVariantsService
|
||||
# Includes the following variants:
|
||||
# - Variants of permitted producers
|
||||
# - Variants of hub
|
||||
# - Variants that are in outgoing exchanges where the hub is receiver
|
||||
def self.eligible_variants(distributor)
|
||||
variant_conditions = ["spree_products.supplier_id IN (?)", permitted_producer_ids(distributor)]
|
||||
exchange_variant_ids = outgoing_exchange_variant_ids(distributor)
|
||||
if exchange_variant_ids.present?
|
||||
variant_conditions[0] << " OR spree_variants.id IN (?)"
|
||||
variant_conditions << exchange_variant_ids
|
||||
end
|
||||
|
||||
Spree::Variant.joins(:product).where(is_master: false).where(*variant_conditions)
|
||||
end
|
||||
|
||||
def self.in_open_and_upcoming_order_cycles?(distributor, schedule, variant)
|
||||
scope = ExchangeVariant.joins(exchange: { order_cycle: :schedules })
|
||||
.where(variant_id: variant, exchanges: { incoming: false, receiver_id: distributor })
|
||||
.merge(OrderCycle.not_closed)
|
||||
scope = scope.where(schedules: { id: schedule })
|
||||
scope.any?
|
||||
end
|
||||
|
||||
def self.permitted_producer_ids(distributor)
|
||||
other_permitted_producer_ids = EnterpriseRelationship.joins(:parent)
|
||||
.permitting(distributor).with_permission(:add_to_order_cycle)
|
||||
.merge(Enterprise.is_primary_producer)
|
||||
.pluck(:parent_id)
|
||||
|
||||
other_permitted_producer_ids | [distributor.id]
|
||||
end
|
||||
|
||||
def self.outgoing_exchange_variant_ids(distributor)
|
||||
ExchangeVariant.select("DISTINCT exchange_variants.variant_id").joins(:exchange)
|
||||
.where(exchanges: { incoming: false, receiver_id: distributor.id })
|
||||
.pluck(:variant_id)
|
||||
end
|
||||
end
|
||||
@@ -56,7 +56,7 @@
|
||||
%input#edit-products{ type: "button", value: t(:edit), ng: { click: "setView('products')" } }
|
||||
.row
|
||||
.seven.columns.alpha.omega
|
||||
%table#subscription-line-items
|
||||
%table#subscription-line-items.admin-subscription-review-subscription-line-items
|
||||
%colgroup
|
||||
%col{:style => "width: 62%;"}/
|
||||
%col{:style => "width: 14%;"}/
|
||||
@@ -71,7 +71,10 @@
|
||||
%span= t(:total)
|
||||
%tbody
|
||||
%tr.item{ id: "sli_{{$index}}", ng: { repeat: "item in subscription.subscription_line_items | filter:{ _destroy: '!true' }", class: { even: 'even', odd: 'odd' } } }
|
||||
%td.description {{ item.description }}
|
||||
%td
|
||||
.description {{ item.description }}
|
||||
.not-in-open-and-upcoming-order-cycles-warning{ ng: { if: '!item.in_open_and_upcoming_order_cycles' } }
|
||||
= t(".no_open_or_upcoming_order_cycle")
|
||||
%td.price.align-center {{ item.price_estimate | currency }}
|
||||
%td.quantity {{ item.quantity }}
|
||||
%td.total.align-center {{ (item.price_estimate * item.quantity) | currency }}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
%table#subscription-line-items
|
||||
%table#subscription-line-items.admin-subscription-form-subscription-line-items
|
||||
%colgroup
|
||||
%col{:style => "width: 49%;"}/
|
||||
%col{:style => "width: 14%;"}/
|
||||
@@ -15,7 +15,10 @@
|
||||
%th.orders-actions.actions
|
||||
%tbody
|
||||
%tr.item{ id: "sli_{{$index}}", ng: { repeat: "item in subscription.subscription_line_items | filter:{ _destroy: '!true' }", class: { even: 'even', odd: 'odd' } } }
|
||||
%td.description {{ item.description }}
|
||||
%td
|
||||
.description {{ item.description }}
|
||||
.not-in-open-and-upcoming-order-cycles-warning{ ng: { if: '!item.in_open_and_upcoming_order_cycles' } }
|
||||
= t(".not_in_open_and_upcoming_order_cycles_warning")
|
||||
%td.price.align-center {{ item.price_estimate | currency }}
|
||||
%td.quantity
|
||||
%input{ name: 'quantity', type: 'number', min: 0, ng: { model: 'item.quantity' } }
|
||||
|
||||
Reference in New Issue
Block a user