Merge pull request #5184 from Matt-Yorkley/inventory-loading

Inventory loading
This commit is contained in:
Luis Ramos
2020-04-09 13:26:12 +01:00
committed by GitHub
7 changed files with 115 additions and 27 deletions

View File

@@ -2,19 +2,24 @@ angular.module("admin.indexUtils").factory "PagedFetcher", (dataFetcher) ->
new class PagedFetcher
# Given a URL like http://example.com/foo?page=::page::&per_page=20
# And the response includes an attribute pages with the number of pages to fetch
# Fetch each page async, and call the processData callback with the resulting data
fetch: (url, processData, onLastPageComplete) ->
dataFetcher(@urlForPage(url, 1)).then (data) =>
processData data
# Fetch each page async, and call the pageCallback callback with the resulting data
# Developer note: this class should not be re-used!
page: 1
last_page: 1
if data.pages > 1
for page in [2..data.pages]
lastPromise = dataFetcher(@urlForPage(url, page)).then (data) ->
processData data
onLastPageComplete && lastPromise.then onLastPageComplete
return
else
onLastPageComplete && onLastPageComplete()
fetch: (url, pageCallback) ->
@fetchPages(url, @page, pageCallback)
urlForPage: (url, page) ->
url.replace("::page::", page)
fetchPages: (url, page, pageCallback) ->
dataFetcher(@urlForPage(url, page)).then (data) =>
@page++
@last_page = data.pages
pageCallback(data) if pageCallback
if @page <= @last_page
@fetchPages(url, @page, pageCallback)

View File

@@ -43,12 +43,11 @@ angular.module("admin.variantOverrides").controller "AdminVariantOverridesCtrl",
$scope.fetchProducts = ->
url = "/api/products/overridable?page=::page::;per_page=100"
PagedFetcher.fetch url, (data) => $scope.addProducts data.products
PagedFetcher.fetch url, $scope.addProducts
$scope.addProducts = (products) ->
$scope.products = $scope.products.concat products
VariantOverrides.ensureDataFor hubs, products
$scope.addProducts = (data) ->
$scope.products = $scope.products.concat data.products
VariantOverrides.ensureDataFor hubs, data.products
$scope.displayDirty = ->
if DirtyVariantOverrides.count() > 0

View File

@@ -69,12 +69,12 @@ module Api
end
def overridable
producers = OpenFoodNetwork::Permissions.new(current_api_user).
variant_override_producers.by_name
producer_ids = OpenFoodNetwork::Permissions.new(current_api_user).
variant_override_producers.by_name.select('enterprises.id')
@products = paged_products_for_producers producers
@products = paged_products_for_producers producer_ids
render_paged_products @products
render_paged_products @products, ::Api::Admin::ProductSimpleSerializer
end
# POST /api/products/:product_id/clone
@@ -118,19 +118,20 @@ module Api
]
end
def paged_products_for_producers(producers)
def paged_products_for_producers(producer_ids)
Spree::Product.scoped.
merge(product_scope).
where(supplier_id: producers).
includes(variants: [:product, :default_price, :stock_items]).
where(supplier_id: producer_ids).
by_producer.by_name.
ransack(params[:q]).result.
page(params[:page]).per(params[:per_page])
end
def render_paged_products(products)
def render_paged_products(products, product_serializer = ::Api::Admin::ProductSerializer)
serializer = ActiveModel::ArraySerializer.new(
products,
each_serializer: ::Api::Admin::ProductSerializer
each_serializer: product_serializer
)
render text: {

View File

@@ -0,0 +1,36 @@
# frozen_string_literal: true
module Spree
module Stock
class Quantifier
attr_reader :stock_items
def initialize(variant)
@variant = variant
@stock_items = fetch_stock_items
end
def total_on_hand
stock_items.sum(&:count_on_hand)
end
def backorderable?
stock_items.any?(&:backorderable)
end
def can_supply?(required)
total_on_hand >= required || backorderable?
end
private
def fetch_stock_items
# Don't re-fetch associated stock items from the DB if we've already eager-loaded them
return @variant.stock_items.to_a if @variant.stock_items.loaded?
Spree::StockItem.joins(:stock_location).
where(:variant_id => @variant, Spree::StockLocation.table_name => { active: true })
end
end
end
end

View File

@@ -0,0 +1,15 @@
# frozen_string_literal: true
module Api
module Admin
class ProductSimpleSerializer < ActiveModel::Serializer
attributes :id, :name, :producer_id
has_many :variants, key: :variants, serializer: Api::Admin::VariantSimpleSerializer
def producer_id
object.supplier_id
end
end
end
end

View File

@@ -0,0 +1,32 @@
# frozen_string_literal: true
module Api
module Admin
class VariantSimpleSerializer < ActiveModel::Serializer
attributes :id, :name, :import_date,
:options_text, :unit_value, :unit_description, :unit_to_display,
:display_as, :display_name, :name_to_display,
:price, :on_demand, :on_hand
has_many :variant_overrides
def name
if object.full_name.present?
"#{object.name} - #{object.full_name}"
else
object.name
end
end
def on_hand
return 0 if object.on_hand.nil?
object.on_hand
end
def price
object.price.nil? ? 0.to_f : object.price
end
end
end
end

View File

@@ -51,9 +51,9 @@ describe "VariantOverridesCtrl", ->
it "adds products", ->
spyOn(VariantOverrides, "ensureDataFor")
expect(scope.products).toEqual []
scope.addProducts ['a', 'b']
scope.addProducts { products: ['a', 'b'] }
expect(scope.products).toEqual ['a', 'b']
scope.addProducts ['c', 'd']
scope.addProducts { products: ['c', 'd'] }
expect(scope.products).toEqual ['a', 'b', 'c', 'd']
expect(VariantOverrides.ensureDataFor).toHaveBeenCalled()