From c23002102cc4b7b1593cf4e86023a435e4e03199 Mon Sep 17 00:00:00 2001 From: Kristina Lim Date: Mon, 17 Sep 2018 01:14:40 +1000 Subject: [PATCH] Add warning for unavailable subscription items --- .../admin/pages/subscription_form.css.scss | 5 +++ .../admin/pages/subscription_review.css.scss | 5 +++ .../subscription_line_items_controller.rb | 3 +- .../subscription_line_item_serializer.rb | 19 ++++++++++- .../admin/subscriptions/_review.html.haml | 7 ++-- .../_subscription_line_items.html.haml | 7 ++-- config/locales/en.yml | 2 ++ lib/open_food_network/subscription_service.rb | 8 +++++ spec/features/admin/subscriptions_spec.rb | 9 +++++ .../subscription_service_spec.rb | 34 +++++++++++++++++++ 10 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 app/assets/stylesheets/admin/pages/subscription_form.css.scss create mode 100644 app/assets/stylesheets/admin/pages/subscription_review.css.scss diff --git a/app/assets/stylesheets/admin/pages/subscription_form.css.scss b/app/assets/stylesheets/admin/pages/subscription_form.css.scss new file mode 100644 index 0000000000..02c9fd783e --- /dev/null +++ b/app/assets/stylesheets/admin/pages/subscription_form.css.scss @@ -0,0 +1,5 @@ +.admin-subscription-form-subscription-line-items { + .not-in-open-and-upcoming-order-cycles-warning { + color: $warning-red; + } +} diff --git a/app/assets/stylesheets/admin/pages/subscription_review.css.scss b/app/assets/stylesheets/admin/pages/subscription_review.css.scss new file mode 100644 index 0000000000..ba3280aa2b --- /dev/null +++ b/app/assets/stylesheets/admin/pages/subscription_review.css.scss @@ -0,0 +1,5 @@ +.admin-subscription-review-subscription-line-items { + .not-in-open-and-upcoming-order-cycles-warning { + color: $warning-red; + } +} diff --git a/app/controllers/admin/subscription_line_items_controller.rb b/app/controllers/admin/subscription_line_items_controller.rb index 8c0432578d..378b73b990 100644 --- a/app/controllers/admin/subscription_line_items_controller.rb +++ b/app/controllers/admin/subscription_line_items_controller.rb @@ -14,7 +14,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 diff --git a/app/serializers/api/admin/subscription_line_item_serializer.rb b/app/serializers/api/admin/subscription_line_item_serializer.rb index 23f4c6bc52..ca8028d7b5 100644 --- a/app/serializers/api/admin/subscription_line_item_serializer.rb +++ b/app/serializers/api/admin/subscription_line_item_serializer.rb @@ -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 + OpenFoodNetwork::SubscriptionService + .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 diff --git a/app/views/admin/subscriptions/_review.html.haml b/app/views/admin/subscriptions/_review.html.haml index e1591e6210..7e97bd02aa 100644 --- a/app/views/admin/subscriptions/_review.html.haml +++ b/app/views/admin/subscriptions/_review.html.haml @@ -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 }} diff --git a/app/views/admin/subscriptions/_subscription_line_items.html.haml b/app/views/admin/subscriptions/_subscription_line_items.html.haml index 0be91f2c93..b80b95a85b 100644 --- a/app/views/admin/subscriptions/_subscription_line_items.html.haml +++ b/app/views/admin/subscriptions/_subscription_line_items.html.haml @@ -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' } } diff --git a/config/locales/en.yml b/config/locales/en.yml index 0bde4fb005..366a481bac 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1088,6 +1088,7 @@ en: this_is_an_estimate: | The displayed prices are only an estimate and calculated at the time the subscription is changed. If you change prices or fees, orders will be updated, but the subscription will still display the old values. + not_in_open_and_upcoming_order_cycles_warning: "There are no open or upcoming order cycles for this product." details: details: Details invalid_error: Oops! Please fill in all of the required fields... @@ -1102,6 +1103,7 @@ en: details: Details address: Address products: Products + no_open_or_upcoming_order_cycle: "No Upcoming OC" product_already_in_order: This product has already been added to the order. Please edit the quantity directly. orders: number: Number diff --git a/lib/open_food_network/subscription_service.rb b/lib/open_food_network/subscription_service.rb index e3479275c1..e4f48aa67a 100644 --- a/lib/open_food_network/subscription_service.rb +++ b/lib/open_food_network/subscription_service.rb @@ -24,5 +24,13 @@ module OpenFoodNetwork 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 end end diff --git a/spec/features/admin/subscriptions_spec.rb b/spec/features/admin/subscriptions_spec.rb index 0a03d629f4..f51de02e5f 100644 --- a/spec/features/admin/subscriptions_spec.rb +++ b/spec/features/admin/subscriptions_spec.rb @@ -465,9 +465,13 @@ feature 'Subscriptions' do # Add products expect(page).to have_content "NAME OR SKU" add_variant_to_subscription shop_variant, 3 + expect(page).to have_content variant_not_in_open_or_upcoming_order_cycle_warning, count: 1 add_variant_to_subscription permitted_supplier_variant, 4 + expect(page).to have_content variant_not_in_open_or_upcoming_order_cycle_warning, count: 2 add_variant_to_subscription incoming_exchange_variant, 5 + expect(page).to have_content variant_not_in_open_or_upcoming_order_cycle_warning, count: 3 add_variant_to_subscription outgoing_exchange_variant, 6 + expect(page).to have_content variant_not_in_open_or_upcoming_order_cycle_warning, count: 3 click_button "Next" # Submit form @@ -509,4 +513,9 @@ feature 'Subscriptions' do click_link "Add" expect(page).to have_selector("#subscription-line-items .item", count: row_count + 1) end + + def variant_not_in_open_or_upcoming_order_cycle_warning + I18n.t("not_in_open_and_upcoming_order_cycles_warning", + scope: "admin.subscriptions.subscription_line_items") + end end diff --git a/spec/lib/open_food_network/subscription_service_spec.rb b/spec/lib/open_food_network/subscription_service_spec.rb index 7df860cf03..63ef72707d 100644 --- a/spec/lib/open_food_network/subscription_service_spec.rb +++ b/spec/lib/open_food_network/subscription_service_spec.rb @@ -95,5 +95,39 @@ module OpenFoodNetwork end end end + + describe "checking if variant in open and upcoming order cycles" do + let!(:shop) { create(:enterprise) } + let!(:product) { create(:product) } + let!(:variant) { product.variants.first } + let!(:schedule) { create(:schedule) } + + context "if the variant is involved in an exchange" do + let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop) } + let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) } + + context "if it is an incoming exchange where the shop is the receiver" do + let!(:incoming_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: true, variants: [variant]) } + + it "is is false" do + expect(described_class).not_to be_in_open_and_upcoming_order_cycles(shop, schedule, variant) + end + end + + context "if it is an outgoing exchange where the shop is the receiver" do + let!(:outgoing_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: false, variants: [variant]) } + + it "is true" do + expect(described_class).to be_in_open_and_upcoming_order_cycles(shop, schedule, variant) + end + end + end + + context "if the variant is unrelated" do + it "is false" do + expect(described_class).to_not be_in_open_and_upcoming_order_cycles(shop, schedule, variant) + end + end + end end end