Merge pull request #4455 from luisramos0/oc_prods

In the OC edit page, load products only when each products tab is opened by user
This commit is contained in:
Luis Ramos
2019-12-17 13:40:19 +00:00
committed by GitHub
25 changed files with 364 additions and 232 deletions

View File

@@ -1,5 +1,27 @@
angular.module('admin.orderCycles').controller 'AdminOrderCycleIncomingCtrl', ($scope, $controller, $location, Enterprise, ocInstance) ->
angular.module('admin.orderCycles').controller 'AdminOrderCycleIncomingCtrl', ($scope, $controller, $location, Enterprise, OrderCycle, ocInstance) ->
$controller('AdminOrderCycleExchangesCtrl', {$scope: $scope, ocInstance: ocInstance, $location: $location})
$scope.enterpriseTotalVariants = (enterprise) ->
Enterprise.totalVariants(enterprise)
$scope.view = 'incoming'
$scope.exchangeTotalVariants = (exchange) ->
return unless $scope.enterprises? && $scope.enterprises[exchange.enterprise_id]?
enterprise = $scope.enterprises[exchange.enterprise_id]
return enterprise.numVariants if enterprise.numVariants?
$scope.loadExchangeProducts(exchange)
return unless enterprise.supplied_products?
enterprise.numVariants = $scope.countVariants(enterprise.supplied_products)
$scope.countVariants = (products) ->
return 0 unless products
numVariants = 0
for product in products
numVariants += product.variants.length
numVariants
$scope.addSupplier = ($event) ->
$event.preventDefault()
OrderCycle.addSupplier $scope.new_supplier_id

View File

@@ -1,10 +1,9 @@
angular.module('admin.orderCycles')
.controller 'AdminOrderCycleExchangesCtrl', ($scope, $controller, $filter, $window, $location, $timeout, OrderCycle, Enterprise, EnterpriseFee, Schedules, RequestMonitor, ocInstance, StatusMessage) ->
.controller 'AdminOrderCycleExchangesCtrl', ($scope, $controller, $filter, $window, $location, $timeout, OrderCycle, ExchangeProduct, Enterprise, EnterpriseFee, Schedules, RequestMonitor, ocInstance, StatusMessage) ->
$controller('AdminEditOrderCycleCtrl', {$scope: $scope, ocInstance: ocInstance, $location: $location})
$scope.supplier_enterprises = Enterprise.producer_enterprises
$scope.distributor_enterprises = Enterprise.hub_enterprises
$scope.supplied_products = Enterprise.supplied_products
$scope.exchangeSelectedVariants = (exchange) ->
OrderCycle.exchangeSelectedVariants(exchange)
@@ -29,14 +28,6 @@ angular.module('admin.orderCycles')
OrderCycle.removeExchangeFee(exchange, index)
$scope.order_cycle_form.$dirty = true
$scope.addSupplier = ($event) ->
$event.preventDefault()
OrderCycle.addSupplier($scope.new_supplier_id)
$scope.addDistributor = ($event) ->
$event.preventDefault()
OrderCycle.addDistributor($scope.new_distributor_id)
$scope.setPickupTimeFieldDirty = (index) ->
$timeout ->
pickup_time_field_name = "order_cycle_outgoing_exchange_" + index + "_pickup_time"
@@ -44,3 +35,19 @@ angular.module('admin.orderCycles')
$scope.removeDistributionOfVariant = (variant_id) ->
OrderCycle.removeDistributionOfVariant(variant_id)
$scope.loadExchangeProducts = (exchange) ->
return if $scope.enterprises[exchange.enterprise_id].supplied_products_fetched?
$scope.enterprises[exchange.enterprise_id].supplied_products_fetched = true
incoming = true if $scope.view == 'incoming'
params = { exchange_id: exchange.id, enterprise_id: exchange.enterprise_id, order_cycle_id: $scope.order_cycle.id, incoming: incoming}
ExchangeProduct.index params, (products) ->
$scope.enterprises[exchange.enterprise_id].supplied_products = products
# initialize exchange products panel if not yet done
$scope.exchangeProdutsPanelInitialized = []
$scope.initializeExchangeProductsPanel = (exchange) ->
return if $scope.exchangeProdutsPanelInitialized[exchange.enterprise_id]
$scope.loadExchangeProducts(exchange)
$scope.exchangeProdutsPanelInitialized[exchange.enterprise_id] = true

View File

@@ -1,8 +1,7 @@
angular.module('admin.orderCycles').controller 'AdminOrderCycleOutgoingCtrl', ($scope, $controller, $filter, $location, OrderCycle, ocInstance, StatusMessage) ->
$controller('AdminOrderCycleExchangesCtrl', {$scope: $scope, ocInstance: ocInstance, $location: $location})
$scope.productSuppliedToOrderCycle = (product) ->
OrderCycle.productSuppliedToOrderCycle(product)
$scope.view = 'outgoing'
$scope.variantSuppliedToOrderCycle = (variant) ->
OrderCycle.variantSuppliedToOrderCycle(variant)
@@ -10,6 +9,10 @@ angular.module('admin.orderCycles').controller 'AdminOrderCycleOutgoingCtrl', ($
$scope.incomingExchangeVariantsFor = (enterprise_id) ->
$filter('filterExchangeVariants')(OrderCycle.incomingExchangesVariants(), $scope.order_cycle.visible_variants_for_outgoing_exchanges[enterprise_id])
$scope.addDistributor = ($event) ->
$event.preventDefault()
OrderCycle.addDistributor $scope.new_distributor_id
$scope.submit = ($event, destination) ->
$event.preventDefault()
StatusMessage.display 'progress', t('js.saving')

View File

@@ -1,23 +1,33 @@
angular.module('admin.orderCycles').controller "AdminSimpleCreateOrderCycleCtrl", ($scope, $controller, $window, OrderCycle, Enterprise, EnterpriseFee, StatusMessage, Schedules, RequestMonitor, ocInstance) ->
angular.module('admin.orderCycles').controller "AdminSimpleCreateOrderCycleCtrl", ($scope, $controller, $window, OrderCycle, Enterprise, EnterpriseFee, ExchangeProduct, StatusMessage, Schedules, RequestMonitor, ocInstance) ->
$controller('AdminOrderCycleBasicCtrl', {$scope: $scope, ocInstance: ocInstance})
$scope.order_cycle = OrderCycle.new {coordinator_id: ocInstance.coordinator_id}, =>
# TODO: make this a get method, which only fetches one enterprise
$scope.enterprises = Enterprise.index {coordinator_id: ocInstance.coordinator_id}, (enterprises) =>
$scope.init(enterprises)
$scope.enterprise_fees = EnterpriseFee.index(coordinator_id: ocInstance.coordinator_id)
$scope.init = (enterprises) ->
enterprise = enterprises[Object.keys(enterprises)[0]]
OrderCycle.addSupplier enterprise.id
OrderCycle.addDistributor enterprise.id
OrderCycle.order_cycle.coordinator_id = enterprise.id
OrderCycle.addDistributor enterprise.id, $scope.setOutgoingExchange
OrderCycle.addSupplier enterprise.id, $scope.loadExchangeProducts
$scope.setOutgoingExchange = ->
$scope.outgoing_exchange = OrderCycle.order_cycle.outgoing_exchanges[0]
# All variants start as checked
OrderCycle.setExchangeVariants(OrderCycle.order_cycle.incoming_exchanges[0],
Enterprise.suppliedVariants(enterprise.id), true)
$scope.loadExchangeProducts = ->
$scope.incoming_exchange = OrderCycle.order_cycle.incoming_exchanges[0]
OrderCycle.order_cycle.coordinator_id = enterprise.id
params = { enterprise_id: $scope.incoming_exchange.enterprise_id, incoming: true }
ExchangeProduct.index params, $scope.storeProductsAndSelectAllVariants
$scope.storeProductsAndSelectAllVariants = (products) ->
$scope.enterprises[$scope.incoming_exchange.enterprise_id].supplied_products = products
# All variants start as checked
OrderCycle.setExchangeVariants($scope.incoming_exchange,
Enterprise.suppliedVariants($scope.incoming_exchange.enterprise_id), true)
$scope.removeDistributionOfVariant = angular.noop

View File

@@ -1,4 +1,4 @@
angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl", ($scope, $controller, $location, $window, OrderCycle, Enterprise, EnterpriseFee, Schedules, RequestMonitor, StatusMessage, ocInstance) ->
angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl", ($scope, $controller, $location, $window, OrderCycle, Enterprise, EnterpriseFee, ExchangeProduct, Schedules, RequestMonitor, StatusMessage, ocInstance) ->
$controller('AdminOrderCycleBasicCtrl', {$scope: $scope, ocInstance: ocInstance})
$scope.orderCycleId = ->
@@ -11,6 +11,12 @@ angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl",
$scope.init = ->
$scope.outgoing_exchange = OrderCycle.order_cycle.outgoing_exchanges[0]
$scope.loadExchangeProducts()
$scope.loadExchangeProducts = ->
exchange = OrderCycle.order_cycle.incoming_exchanges[0]
ExchangeProduct.index { exchange_id: exchange.id }, (products) ->
$scope.enterprises[exchange.enterprise_id].supplied_products = products
$scope.removeDistributionOfVariant = angular.noop

View File

@@ -12,7 +12,6 @@ angular.module('admin.orderCycles').factory('Enterprise', ($resource) ->
enterprises: {}
producer_enterprises: []
hub_enterprises: []
supplied_products: []
loaded: false
index: (params={}, callback=null) ->
@@ -22,9 +21,6 @@ angular.module('admin.orderCycles').factory('Enterprise', ($resource) ->
@producer_enterprises.push(enterprise) if enterprise.is_primary_producer
@hub_enterprises.push(enterprise) if enterprise.sells == 'any'
for product in enterprise.supplied_products
@supplied_products.push(product)
@loaded = true
(callback || angular.noop)(@enterprises)
@@ -39,13 +35,4 @@ angular.module('admin.orderCycles').factory('Enterprise', ($resource) ->
variant.id for variant in product.variants
else
[product.master_id]
totalVariants: (enterprise) ->
numVariants = 0
if enterprise
counts = for product in enterprise.supplied_products
numVariants += if product.variants.length == 0 then 1 else product.variants.length
numVariants
})

View File

@@ -0,0 +1,15 @@
angular.module('admin.orderCycles').factory('ExchangeProduct', ($resource) ->
ExchangeProductResource = $resource('/api/exchanges/:exchange_id/products.json', {}, {
'index':
method: 'GET'
isArray: true
})
{
ExchangeProductResource: ExchangeProductResource
loaded: false
index: (params={}, callback=null) ->
ExchangeProductResource.index params, (data) =>
@loaded = true
(callback || angular.noop)(data)
})

View File

@@ -1,4 +1,4 @@
angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, StatusMessage, Panels) ->
angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, $timeout, StatusMessage, Panels) ->
OrderCycleResource = $resource '/admin/order_cycles/:action_name/:order_cycle_id.json', {}, {
'index': { method: 'GET', isArray: true}
'new' : { method: 'GET', params: { action_name: "new" } }
@@ -44,11 +44,15 @@ angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, S
@removeDistributionOfVariant(variant.id) if exchange.incoming
addSupplier: (new_supplier_id) ->
this.order_cycle.incoming_exchanges.push({enterprise_id: new_supplier_id, incoming: true, active: true, variants: {}, enterprise_fees: []})
addSupplier: (new_supplier_id, callback) ->
this.order_cycle.incoming_exchanges.push({enterprise_id: new_supplier_id, incoming: true, active: true, variants: {}, enterprise_fees: []})
$timeout ->
(callback || angular.noop)()
addDistributor: (new_distributor_id) ->
this.order_cycle.outgoing_exchanges.push({enterprise_id: new_distributor_id, incoming: false, active: true, variants: {}, enterprise_fees: []})
addDistributor: (new_distributor_id, callback) ->
this.order_cycle.outgoing_exchanges.push({ enterprise_id: new_distributor_id, incoming: false, active: true, variants: {}, enterprise_fees: [] })
$timeout ->
(callback || angular.noop)()
removeExchange: (exchange) ->
if exchange.incoming
@@ -71,18 +75,6 @@ angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, S
removeExchangeFee: (exchange, index) ->
exchange.enterprise_fees.splice(index, 1)
productSuppliedToOrderCycle: (product) ->
product_variant_ids = (variant.id for variant in product.variants)
variant_ids = [product.master_id].concat(product_variant_ids)
incomingExchangesVariants = this.incomingExchangesVariants()
# TODO: This is an O(n^2) implementation of set intersection and thus is slooow.
# Use a better algorithm if needed.
# Also, incomingExchangesVariants is called every time, when it only needs to be
# called once per change to incoming variants. Some sort of caching?
ids = (variant_id for variant_id in variant_ids when incomingExchangesVariants.indexOf(variant_id) != -1)
ids.length > 0
variantSuppliedToOrderCycle: (variant) ->
this.incomingExchangesVariants().indexOf(variant.id) != -1
@@ -143,7 +135,8 @@ angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, S
delete(service.order_cycle.exchanges)
service.loaded = true
(callback || angular.noop)(service.order_cycle)
$timeout ->
(callback || angular.noop)(service.order_cycle)
this.order_cycle

View File

@@ -1,4 +1,4 @@
.row.exchange-distributed-products
.row.exchange-distributed-products{'ng-init' => 'initializeExchangeProductsPanel(exchange)'}
.sixteen.columns.alpha.omega
.exchange-select-all-variants
%label
@@ -11,7 +11,7 @@
.exchange-products
-# Scope product list based on permissions the current user has to view variants in this exchange
.exchange-product{'ng-repeat' => 'product in supplied_products | filter:productSuppliedToOrderCycle | visibleProducts:exchange:order_cycle.visible_variants_for_outgoing_exchanges' }
.exchange-product{'ng-repeat' => 'product in enterprises[exchange.enterprise_id].supplied_products | filter:visibleProducts:exchange:order_cycle.visible_variants_for_outgoing_exchanges' }
.exchange-product-details
%label
%img{'ng-src' => '{{ product.image_url }}'}

View File

@@ -1,4 +1,4 @@
.row.exchange-supplied-products
.row.exchange-supplied-products{'ng-init' => 'initializeExchangeProductsPanel(exchange)'}
.sixteen.columns.alpha.omega
.exchange-select-all-variants
%label

View File

@@ -0,0 +1,55 @@
# This controller lists products that can be added to an exchange
module Api
class ExchangeProductsController < Api::BaseController
skip_authorization_check only: [:index]
# If exchange_id is present in the URL:
# Lists Products that can be added to that Exchange
#
# If exchange_id is not present in the URL:
# Lists Products of the Enterprise given that can be added to the given Order Cycle
# In this case parameters are: enterprise_id, order_cycle_id and incoming
# (order_cycle_id is not necessary for incoming exchanges)
def index
if params[:exchange_id].present?
load_data_from_exchange
else
load_data_from_other_params
end
render_products
end
private
def render_products
products = ExchangeProductsRenderer.
new(@order_cycle, spree_current_user).
exchange_products(@incoming, @enterprise)
render json: products,
each_serializer: Api::Admin::ForOrderCycle::SuppliedProductSerializer,
order_cycle: @order_cycle,
status: :ok
end
def load_data_from_exchange
exchange = Exchange.find_by_id(params[:exchange_id])
@order_cycle = exchange.order_cycle
@incoming = exchange.incoming
@enterprise = exchange.sender
end
def load_data_from_other_params
@enterprise = Enterprise.find_by_id(params[:enterprise_id])
if params[:order_cycle_id]
@order_cycle = OrderCycle.find_by_id(params[:order_cycle_id])
elsif !params[:incoming]
raise "order_cycle_id is required to list products for new outgoing exchange"
end
@incoming = params[:incoming]
end
end
end

View File

@@ -1,7 +1,7 @@
require 'open_food_network/enterprise_issue_validator'
class Api::Admin::ForOrderCycle::EnterpriseSerializer < ActiveModel::Serializer
attributes :id, :name, :managed, :supplied_products,
attributes :id, :name, :managed,
:issues_summary_supplier, :issues_summary_distributor,
:is_primary_producer, :is_distributor, :sells
@@ -25,12 +25,6 @@ class Api::Admin::ForOrderCycle::EnterpriseSerializer < ActiveModel::Serializer
Enterprise.managed_by(options[:spree_current_user]).include? object
end
def supplied_products
serializer = Api::Admin::ForOrderCycle::SuppliedProductSerializer
ActiveModel::ArraySerializer.new(products, each_serializer: serializer,
order_cycle: order_cycle)
end
private
def products_scope

View File

@@ -14,7 +14,8 @@ class Api::Admin::ForOrderCycle::SuppliedProductSerializer < ActiveModel::Serial
end
def variants
variants = if order_cycle.prefers_product_selection_from_coordinator_inventory_only?
variants = if order_cycle.present? &&
order_cycle.prefers_product_selection_from_coordinator_inventory_only?
object.variants.visible_for(order_cycle.coordinator)
else
object.variants

View File

@@ -0,0 +1,86 @@
class ExchangeProductsRenderer
def initialize(order_cycle, user)
@order_cycle = order_cycle
@user = user
end
def exchange_products(incoming, enterprise)
if incoming
products_for_incoming_exchange(enterprise)
else
products_for_outgoing_exchange
end
end
private
def products_for_incoming_exchange(enterprise)
supplied_products(enterprise.id)
end
def supplied_products(enterprises_query_matcher)
products_relation = Spree::Product.where(supplier_id: enterprises_query_matcher)
if @order_cycle.present? &&
@order_cycle.prefers_product_selection_from_coordinator_inventory_only?
products_relation = products_relation.visible_for(@order_cycle.coordinator)
end
products_relation
end
def products_for_outgoing_exchange
supplied_products(enterprises_for_outgoing_exchange.select(:id)).
includes(:variants).
where("spree_variants.id": incoming_exchanges_variants)
end
def incoming_exchanges_variants
return @incoming_exchanges_variants if @incoming_exchanges_variants.present?
@incoming_exchanges_variants = []
visible_incoming_exchanges.each do |incoming_exchange|
@incoming_exchanges_variants.push(
*incoming_exchange.variants.merge(
visible_incoming_variants(incoming_exchange.sender)
).map(&:id).to_a
)
end
@incoming_exchanges_variants
end
def visible_incoming_exchanges
OpenFoodNetwork::OrderCyclePermissions.
new(@user, @order_cycle).
visible_exchanges.
by_enterprise_name.
incoming
end
def visible_incoming_variants(incoming_exchange_sender)
variants_relation = permitted_incoming_variants(incoming_exchange_sender)
if @order_cycle.prefers_product_selection_from_coordinator_inventory_only?
variants_relation = variants_relation.visible_for(@order_cycle.coordinator)
end
variants_relation
end
def permitted_incoming_variants(incoming_exchange_sender)
OpenFoodNetwork::OrderCyclePermissions.
new(@user, @order_cycle).
visible_variants_for_incoming_exchanges_from(incoming_exchange_sender)
end
def enterprises_for_outgoing_exchange
enterprises = OpenFoodNetwork::OrderCyclePermissions.
new(@user, @order_cycle)
.visible_enterprises
return enterprises if enterprises.empty?
enterprises.includes(
supplied_products: [:supplier, :variants, master: [:images]]
)
end
end

View File

@@ -3,7 +3,7 @@
%td.products.panel-toggle.text-center{ name: "products" }
{{ exchangeSelectedVariants(exchange) }} /
- if type == 'supplier'
{{ enterpriseTotalVariants(enterprises[exchange.enterprise_id]) }}
{{ exchangeTotalVariants(exchange) }}
- else
{{ (incomingExchangeVariantsFor(exchange.enterprise_id)).length }}
= t('.selected')
@@ -35,10 +35,10 @@
- if type == 'supplier'
%tr.panel-row{ object: "exchange",
panels: "{products: 'exchange_supplied_products'}",
locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,suppliedVariants,removeDistributionOfVariant",
locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,suppliedVariants,removeDistributionOfVariant,initializeExchangeProductsPanel",
colspan: 4 }
- if type == 'distributor'
%tr.panel-row{ object: "exchange",
panels: "{products: 'exchange_distributed_products', tags: 'exchange_tags'}",
locals: "$index,order_cycle,exchange,supplied_products,setExchangeVariants,incomingExchangeVariantsFor,productSuppliedToOrderCycle,variantSuppliedToOrderCycle",
locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,incomingExchangeVariantsFor,variantSuppliedToOrderCycle,initializeExchangeProductsPanel",
colspan: 5 }

View File

@@ -43,6 +43,10 @@ Openfoodnetwork::Application.routes.draw do
get :properties, on: :member
end
resources :exchanges, only: [:show], to: 'exchange_products#index' do
get :products, to: 'exchange_products#index'
end
resource :status do
get :job_queue
end

View File

@@ -0,0 +1,36 @@
require 'spec_helper'
module Api
describe ExchangeProductsController, type: :controller do
include AuthenticationWorkflow
let!(:order_cycle) { create(:order_cycle) }
let!(:coordinator) { order_cycle.coordinator }
before do
allow(controller).to receive_messages spree_current_user: coordinator.owner
end
describe "#index" do
describe "for incoming exchanges" do
it "loads data" do
exchange = order_cycle.exchanges.incoming.first
spree_get :index, exchange_id: exchange.id
expect(json_response.first["supplier_name"]).to eq exchange.variants.first.product.supplier.name
end
end
describe "for outgoing exchanges" do
it "loads data" do
exchange = order_cycle.exchanges.outgoing.first
spree_get :index, exchange_id: exchange.id
suppliers = [exchange.variants[0].product.supplier.name, exchange.variants[1].product.supplier.name]
expect(suppliers).to include json_response.first["supplier_name"]
expect(suppliers).to include json_response.second["supplier_name"]
end
end
end
end
end

View File

@@ -38,9 +38,6 @@ describe 'AdminEditOrderCycleCtrl', ->
expect(EnterpriseFee.index).toHaveBeenCalled()
expect(scope.enterprise_fees).toEqual('enterprise fees list')
it 'Loads order cycles', ->
expect(OrderCycle.load).toHaveBeenCalledWith('27')
it 'Removes coordinator fees', ->
scope.removeCoordinatorFee(event, 0)
expect(event.preventDefault).toHaveBeenCalled()

View File

@@ -13,14 +13,35 @@ describe 'AdminOrderCycleIncomingCtrl', ->
location =
absUrl: ->
'example.com/admin/order_cycles/27/edit'
Enterprise =
totalVariants: jasmine.createSpy('totalVariants').and.returnValue('variants total')
event =
preventDefault: jasmine.createSpy('preventDefault')
OrderCycle =
addSupplier: jasmine.createSpy('addSupplier')
ocInstance = {}
module('admin.orderCycles')
inject ($controller) ->
ctrl = $controller 'AdminOrderCycleIncomingCtrl', {$scope: scope, $location: location, OrderCycle: OrderCycle, Enterprise: Enterprise, EnterpriseFee: EnterpriseFee, ocInstance: ocInstance}
it 'Delegates totalVariants to Enterprise', ->
expect(scope.enterpriseTotalVariants('enterprise')).toEqual('variants total')
expect(Enterprise.totalVariants).toHaveBeenCalledWith('enterprise')
it 'counts total variants in a list of products', ->
products = [
{variants: [{}]},
{variants: [{}]},
{variants: [{}, {}, {}]}
]
expect(scope.countVariants(products)).toEqual(5)
it 'returns zero when products list is null', ->
expect(scope.countVariants(null)).toEqual(0)
it 'returns zero when products list is empty', ->
expect(scope.countVariants([])).toEqual(0)
it 'adds order cycle suppliers', ->
scope.new_supplier_id = 'new supplier id'
scope.addSupplier(event)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.addSupplier).toHaveBeenCalledWith('new supplier id')

View File

@@ -19,14 +19,11 @@ describe 'AdminOrderCycleExchangesCtrl', ->
OrderCycle =
exchangeSelectedVariants: jasmine.createSpy('exchangeSelectedVariants').and.returnValue('variants selected')
exchangeDirection: jasmine.createSpy('exchangeDirection').and.returnValue('exchange direction')
addSupplier: jasmine.createSpy('addSupplier')
addDistributor: jasmine.createSpy('addDistributor')
removeExchange: jasmine.createSpy('removeExchange')
addExchangeFee: jasmine.createSpy('addExchangeFee')
removeExchangeFee: jasmine.createSpy('removeExchangeFee')
removeDistributionOfVariant: jasmine.createSpy('removeDistributionOfVariant')
Enterprise =
supplied_products: 'supplied products'
Enterprise = {}
EnterpriseFee =
forEnterprise: jasmine.createSpy('forEnterprise').and.returnValue('enterprise fees for enterprise')
ocInstance = {}
@@ -35,9 +32,6 @@ describe 'AdminOrderCycleExchangesCtrl', ->
inject ($controller) ->
ctrl = $controller 'AdminOrderCycleExchangesCtrl', {$scope: scope, $location: location, OrderCycle: OrderCycle, Enterprise: Enterprise, EnterpriseFee: EnterpriseFee, ocInstance: ocInstance}
it 'Loads supplied products', ->
expect(scope.supplied_products).toEqual('supplied products')
it 'Delegates exchangeSelectedVariants to OrderCycle', ->
expect(scope.exchangeSelectedVariants('exchange')).toEqual('variants selected')
expect(OrderCycle.exchangeSelectedVariants).toHaveBeenCalledWith('exchange')
@@ -77,18 +71,6 @@ describe 'AdminOrderCycleExchangesCtrl', ->
expect(OrderCycle.removeExchangeFee).toHaveBeenCalledWith('exchange', 0)
expect(scope.order_cycle_form.$dirty).toEqual true
it 'Adds order cycle suppliers', ->
scope.new_supplier_id = 'new supplier id'
scope.addSupplier(event)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.addSupplier).toHaveBeenCalledWith('new supplier id')
it 'Adds order cycle distributors', ->
scope.new_distributor_id = 'new distributor id'
scope.addDistributor(event)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.addDistributor).toHaveBeenCalledWith('new distributor id')
it 'Removes distribution of a variant', ->
scope.removeDistributionOfVariant('variant')
expect(OrderCycle.removeDistributionOfVariant).toHaveBeenCalledWith('variant')

View File

@@ -13,19 +13,25 @@ describe 'AdminOrderCycleOutgoingCtrl', ->
location =
absUrl: ->
'example.com/admin/order_cycles/27/edit'
event =
preventDefault: jasmine.createSpy('preventDefault')
OrderCycle =
productSuppliedToOrderCycle: jasmine.createSpy('productSuppliedToOrderCycle').and.returnValue('product supplied')
variantSuppliedToOrderCycle: jasmine.createSpy('variantSuppliedToOrderCycle').and.returnValue('variant supplied')
addDistributor: jasmine.createSpy('addDistributor')
ocInstance = {}
module('admin.orderCycles')
inject ($controller) ->
ctrl = $controller 'AdminOrderCycleOutgoingCtrl', {$scope: scope, $location: location, OrderCycle: OrderCycle, Enterprise: Enterprise, EnterpriseFee: EnterpriseFee, ocInstance: ocInstance}
it 'Delegates productSuppliedToOrderCycle to OrderCycle', ->
expect(scope.productSuppliedToOrderCycle('product')).toEqual('product supplied')
expect(OrderCycle.productSuppliedToOrderCycle).toHaveBeenCalledWith('product')
it 'Delegates variantSuppliedToOrderCycle to OrderCycle', ->
expect(scope.variantSuppliedToOrderCycle('variant')).toEqual('variant supplied')
expect(OrderCycle.variantSuppliedToOrderCycle).toHaveBeenCalledWith('variant')
it 'Adds order cycle distributors', ->
scope.new_distributor_id = 'new distributor id'
scope.addDistributor(event)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.addDistributor).toHaveBeenCalledWith('new distributor id')

View File

@@ -1,8 +1,9 @@
describe "AdminSimpleCreateOrderCycleCtrl", ->
ctrl = null
scope = {}
scope = null
OrderCycle = {}
Enterprise = {}
ExchangeProduct = {}
EnterpriseFee = {}
incoming_exchange = {}
outgoing_exchange = {}
@@ -10,27 +11,32 @@ describe "AdminSimpleCreateOrderCycleCtrl", ->
beforeEach ->
scope =
$watch: jasmine.createSpy('$watch')
setOutgoingExchange: jasmine.createSpy('setOutgoingExchange')
loadExchangeProducts: jasmine.createSpy('loadExchangeProducts')
storeProductsAndSelectAllVariants: jasmine.createSpy('storeProductsAndSelectAllVariants')
order_cycle =
coordinator_id: 123
incoming_exchanges: [incoming_exchange]
outgoing_exchanges: [outgoing_exchange]
OrderCycle =
order_cycle: order_cycle
addSupplier: jasmine.createSpy()
addDistributor: jasmine.createSpy()
setExchangeVariants: jasmine.createSpy()
addSupplier: jasmine.createSpy('addSupplier')
addDistributor: jasmine.createSpy('addDistributor')
setExchangeVariants: jasmine.createSpy('setExchangeVariants')
new: jasmine.createSpy().and.returnValue order_cycle
Enterprise =
get: jasmine.createSpy().and.returnValue {id: 123}
index: jasmine.createSpy()
suppliedVariants: jasmine.createSpy().and.returnValue('supplied variants')
ExchangeProduct =
index: jasmine.createSpy()
EnterpriseFee =
index: jasmine.createSpy()
ocInstance = {}
module('admin.orderCycles')
inject ($controller) ->
ctrl = $controller 'AdminSimpleCreateOrderCycleCtrl', {$scope: scope, OrderCycle: OrderCycle, Enterprise: Enterprise, EnterpriseFee: EnterpriseFee, ocInstance: ocInstance}
ctrl = $controller 'AdminSimpleCreateOrderCycleCtrl', {$scope: scope, OrderCycle: OrderCycle, Enterprise: Enterprise, EnterpriseFee: EnterpriseFee, ExchangeProduct: ExchangeProduct, ocInstance: ocInstance}
describe "initialisation", ->
enterprise = {id: 123}
@@ -39,15 +45,26 @@ describe "AdminSimpleCreateOrderCycleCtrl", ->
beforeEach ->
scope.init(enterprises)
it "sets up an incoming and outgoing exchange", ->
expect(OrderCycle.addSupplier).toHaveBeenCalledWith(enterprise.id)
expect(OrderCycle.addDistributor).toHaveBeenCalledWith(enterprise.id)
expect(scope.outgoing_exchange).toEqual outgoing_exchange
it "adds enterprise as both the supplier and the distributor", ->
expect(OrderCycle.addSupplier).toHaveBeenCalledWith(enterprise.id, scope.loadExchangeProducts)
expect(OrderCycle.addDistributor).toHaveBeenCalledWith(enterprise.id, scope.setOutgoingExchange)
it "loads exchange products", ->
incoming_exchange.enterprise_id = enterprise.id
scope.loadExchangeProducts()
expect(ExchangeProduct.index).toHaveBeenCalledWith({ enterprise_id: enterprise.id, incoming: true }, scope.storeProductsAndSelectAllVariants)
it "stores products and selects all variants", ->
scope.incoming_exchange = incoming_exchange
incoming_exchange.enterprise_id = enterprise.id
scope.enterprises = { "#{enterprise.id}": {}}
scope.storeProductsAndSelectAllVariants()
it "selects all variants", ->
expect(Enterprise.suppliedVariants).
toHaveBeenCalledWith(enterprise.id)
expect(OrderCycle.setExchangeVariants).
toHaveBeenCalledWith(incoming_exchange, 'supplied variants', true)

View File

@@ -8,18 +8,18 @@ describe 'Enterprise service', ->
Enterprise = $injector.get('Enterprise')
$httpBackend = _$httpBackend_
$httpBackend.whenGET('/admin/enterprises/for_order_cycle.json').respond [
{id: 1, name: 'One', supplied_products: [1, 2], is_primary_producer: true}
{id: 2, name: 'Two', supplied_products: [3, 4]}
{id: 3, name: 'Three', supplied_products: [5, 6], sells: 'any'}
{id: 1, name: 'One', is_primary_producer: true}
{id: 2, name: 'Two'}
{id: 3, name: 'Three', sells: 'any'}
]
it 'loads enterprises as a hash', ->
enterprises = Enterprise.index()
$httpBackend.flush()
expect(enterprises).toEqual
1: new Enterprise.Enterprise({id: 1, name: 'One', supplied_products: [1, 2], is_primary_producer: true})
2: new Enterprise.Enterprise({id: 2, name: 'Two', supplied_products: [3, 4]})
3: new Enterprise.Enterprise({id: 3, name: 'Three', supplied_products: [5, 6], sells: 'any'})
1: new Enterprise.Enterprise({id: 1, name: 'One', is_primary_producer: true})
2: new Enterprise.Enterprise({id: 2, name: 'Two'})
3: new Enterprise.Enterprise({id: 3, name: 'Three', sells: 'any'})
it 'reports its loadedness', ->
expect(Enterprise.loaded).toBe(false)
@@ -30,22 +30,18 @@ describe 'Enterprise service', ->
it 'loads producers as an array', ->
Enterprise.index()
$httpBackend.flush()
expect(Enterprise.producer_enterprises).toEqual [new Enterprise.Enterprise({id: 1, name: 'One', supplied_products: [1, 2], is_primary_producer: true})]
expect(Enterprise.producer_enterprises).toEqual [new Enterprise.Enterprise({id: 1, name: 'One', is_primary_producer: true})]
it 'loads hubs as an array', ->
Enterprise.index()
$httpBackend.flush()
expect(Enterprise.hub_enterprises).toEqual [new Enterprise.Enterprise({id: 3, name: 'Three', supplied_products: [5, 6], sells: 'any'})]
it 'collates all supplied products', ->
enterprises = Enterprise.index()
$httpBackend.flush()
expect(Enterprise.supplied_products).toEqual [1, 2, 3, 4, 5, 6]
expect(Enterprise.hub_enterprises).toEqual [new Enterprise.Enterprise({id: 3, name: 'Three', sells: 'any'})]
it "finds supplied variants for an enterprise", ->
spyOn(Enterprise, 'variantsOf').and.returnValue(10)
Enterprise.index()
enterprises = Enterprise.index()
$httpBackend.flush()
Enterprise.enterprises[1].supplied_products = [1, 2]
expect(Enterprise.suppliedVariants(1)).toEqual [10, 10]
describe "finding the variants of a product", ->
@@ -60,16 +56,3 @@ describe 'Enterprise service', ->
master_id: 1
variants: [{id: 2}, {id: 3}]
expect(Enterprise.variantsOf(p)).toEqual [2, 3]
it 'counts total variants supplied by an enterprise', ->
enterprise =
supplied_products: [
{variants: []},
{variants: []},
{variants: [{}, {}, {}]}
]
expect(Enterprise.totalVariants(enterprise)).toEqual(5)
it 'returns zero when enterprise is null', ->
expect(Enterprise.totalVariants(null)).toEqual(0)

View File

@@ -232,42 +232,6 @@ describe 'OrderCycle service', ->
]
expect(OrderCycle.incomingExchangesVariants()).toEqual [1, 4, 5]
describe 'checking whether a product is supplied to the order cycle', ->
product_master_present = product_variant_present = product_master_absent = product_variant_absent = null
beforeEach ->
product_master_present =
name: "Linseed (500g)"
master_id: 1
variants: []
product_variant_present =
name: "Linseed (500g)"
master_id: 2
variants: [{id: 3}, {id: 4}]
product_master_absent =
name: "Linseed (500g)"
master_id: 5
variants: []
product_variant_absent =
name: "Linseed (500g)"
master_id: 6
variants: [{id: 7}, {id: 8}]
spyOn(OrderCycle, 'incomingExchangesVariants').and.returnValue([1, 3])
it 'returns true for products whose master is supplied', ->
expect(OrderCycle.productSuppliedToOrderCycle(product_master_present)).toBeTruthy()
it 'returns true for products for whom a variant is supplied', ->
expect(OrderCycle.productSuppliedToOrderCycle(product_variant_present)).toBeTruthy()
it 'returns false for products whose master is not supplied', ->
expect(OrderCycle.productSuppliedToOrderCycle(product_master_absent)).toBeFalsy()
it 'returns false for products whose variants are not supplied', ->
expect(OrderCycle.productSuppliedToOrderCycle(product_variant_absent)).toBeFalsy()
describe 'checking whether a variant is supplied to the order cycle', ->
beforeEach ->
spyOn(OrderCycle, 'incomingExchangesVariants').and.returnValue([1, 3])

View File

@@ -1,57 +0,0 @@
require "spec_helper"
describe Api::Admin::ForOrderCycle::EnterpriseSerializer do
let(:coordinator) { create(:distributor_enterprise) }
let(:order_cycle) { double(:order_cycle, coordinator: coordinator) }
let(:enterprise) { create(:distributor_enterprise) }
let(:non_inventory_product) { create(:simple_product, supplier: enterprise) }
let!(:non_inventory_variant) { non_inventory_product.variants.first }
let(:inventory_product) { create(:simple_product, supplier: enterprise) }
let(:inventory_variant) { inventory_product.variants.first }
let(:deleted_product) { create(:product, supplier: enterprise, deleted_at: 24.hours.ago ) }
let(:deleted_variant) { deleted_product.variants.first }
let(:serialized_enterprise) do
Api::Admin::ForOrderCycle::EnterpriseSerializer.new(
enterprise.reload, # load the products that were created after the enterprise
order_cycle: order_cycle,
spree_current_user: enterprise.owner
).to_json
end
let!(:inventory_item1) { create(:inventory_item, enterprise: coordinator, variant: inventory_variant, visible: true) }
let!(:inventory_item2) { create(:inventory_item, enterprise: coordinator, variant: deleted_variant, visible: true) }
context "when order cycle shows only variants in the coordinator's inventory" do
before do
allow(order_cycle).to receive(:prefers_product_selection_from_coordinator_inventory_only?) { true }
end
describe "supplied products" do
it "renders only non-deleted variants that are in the coordinators inventory" do
expect(serialized_enterprise).to have_json_size(1).at_path 'supplied_products'
expect(serialized_enterprise).to have_json_size(1).at_path 'supplied_products/0/variants'
expect(serialized_enterprise).to be_json_eql(inventory_variant.id).at_path 'supplied_products/0/variants/0/id'
end
end
end
context "when order cycle shows all available products" do
before do
allow(order_cycle).to receive(:prefers_product_selection_from_coordinator_inventory_only?) { false }
end
describe "supplied products" do
it "renders variants that are not in the coordinators inventory but not variants of deleted products" do
expect(serialized_enterprise).to have_json_size(2).at_path 'supplied_products'
expect(serialized_enterprise).to have_json_size(1).at_path 'supplied_products/0/variants'
expect(serialized_enterprise).to have_json_size(1).at_path 'supplied_products/1/variants'
variant_ids = parse_json(serialized_enterprise)['supplied_products'].map{ |p| p['variants'].first['id'] }
expect(variant_ids).to include non_inventory_variant.id, inventory_variant.id
end
end
end
end