mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-23 05:28:53 +00:00
Merge branch 'master' into 2-0-stable-nov-8th
This commit is contained in:
@@ -54,12 +54,14 @@
|
||||
//= require i18n/translations
|
||||
//= require darkswarm/i18n.translate.js
|
||||
//= require moment
|
||||
//= require moment/de.js
|
||||
//= require moment/en-gb.js
|
||||
//= require moment/es.js
|
||||
//= require moment/fr.js
|
||||
//= require moment/it.js
|
||||
//= require moment/nb.js
|
||||
//= require moment/pt-br.js
|
||||
//= require moment/pt.js
|
||||
//= require moment/sv.js
|
||||
//= require ../shared/mm-foundation-tpls-0.9.0-20180826174721.min.js
|
||||
//= require angularjs-file-upload
|
||||
|
||||
@@ -65,13 +65,6 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
DirtyProducts.clear()
|
||||
StatusMessage.clear()
|
||||
|
||||
# $scope.matchProducer = (product) ->
|
||||
# for producer in $scope.producers
|
||||
# if angular.equals(producer.id, product.producer)
|
||||
# product.producer = producer
|
||||
# break
|
||||
|
||||
|
||||
$scope.updateOnHand = (product) ->
|
||||
on_demand_variants = []
|
||||
if product.variants
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("admin.customers").directive 'editAddressDialog', ($compile, $templateCache, $filter, DialogDefaults, Customers, StatusMessage) ->
|
||||
angular.module("admin.customers").directive 'editAddressDialog', ($compile, $templateCache, DialogDefaults, Customers, StatusMessage, CountryStates) ->
|
||||
restrict: 'A'
|
||||
scope: true
|
||||
link: (scope, element, attr) ->
|
||||
@@ -6,9 +6,10 @@ angular.module("admin.customers").directive 'editAddressDialog', ($compile, $tem
|
||||
scope.errors = []
|
||||
|
||||
scope.$watch 'address.country_id', (newCountryID) ->
|
||||
if newCountryID
|
||||
scope.states = scope.filterStates(newCountryID)
|
||||
scope.clearState() unless scope.addressStateMatchesCountry()
|
||||
return unless newCountryID
|
||||
scope.states = CountryStates.statesFor(scope.availableCountries, newCountryID)
|
||||
unless CountryStates.addressStateMatchesCountryStates(scope.states, scope.address.state_id)
|
||||
scope.address.state_id = ""
|
||||
|
||||
scope.updateAddress = ->
|
||||
scope.edit_address_form.$setPristine()
|
||||
@@ -27,19 +28,9 @@ angular.module("admin.customers").directive 'editAddressDialog', ($compile, $tem
|
||||
else
|
||||
scope.addressType = 'ship_address'
|
||||
scope.address = scope.customer[scope.addressType]
|
||||
scope.states = scope.filterStates(scope.address?.country_id)
|
||||
scope.states = CountryStates.statesFor(scope.availableCountries, scope.address?.country_id)
|
||||
|
||||
template = $compile($templateCache.get('admin/edit_address_dialog.html'))(scope)
|
||||
template.dialog(DialogDefaults)
|
||||
template.dialog('open')
|
||||
scope.$apply()
|
||||
|
||||
scope.filterStates = (countryID) ->
|
||||
return [] unless countryID
|
||||
$filter('filter')(scope.availableCountries, {id: parseInt(countryID)}, true)[0].states
|
||||
|
||||
scope.clearState = ->
|
||||
scope.address.state_id = ""
|
||||
|
||||
scope.addressStateMatchesCountry = ->
|
||||
scope.states.some (state) -> state.id == scope.address.state_id
|
||||
@@ -3,7 +3,7 @@ angular.module("admin.productImport").controller "ImportFormCtrl", ($scope, $htt
|
||||
$scope.entries = {}
|
||||
$scope.update_counts = {}
|
||||
$scope.reset_counts = {}
|
||||
$scope.supplier_product_counts = ams_data.supplier_product_counts
|
||||
$scope.enterprise_product_counts = ams_data.enterprise_product_counts
|
||||
|
||||
$scope.updates = {}
|
||||
$scope.updated_total = 0
|
||||
@@ -19,7 +19,7 @@ angular.module("admin.productImport").controller "ImportFormCtrl", ($scope, $htt
|
||||
}
|
||||
|
||||
$scope.countResettable = () ->
|
||||
angular.forEach $scope.supplier_product_counts, (value, key) ->
|
||||
angular.forEach $scope.enterprise_product_counts, (value, key) ->
|
||||
$scope.reset_counts[key] = value
|
||||
if $scope.update_counts[key]
|
||||
$scope.reset_counts[key] -= $scope.update_counts[key]
|
||||
|
||||
@@ -17,7 +17,7 @@ angular.module("admin.productImport").controller "ImportOptionsFormCtrl", ($scop
|
||||
confirmed = confirm t('js.product_import.confirmation') if checked
|
||||
|
||||
if confirmed or !checked
|
||||
ProductImportService.updateResetAbsent($scope.supplierId, $scope.reset_counts[$scope.supplierId], checked)
|
||||
ProductImportService.updateResetAbsent($scope.enterpriseId, $scope.reset_counts[$scope.enterpriseId], checked)
|
||||
else
|
||||
$scope.settings['reset_all_absent'] = false
|
||||
|
||||
|
||||
@@ -18,15 +18,15 @@ angular.module("admin.productImport").filter 'entriesFilterValid', ->
|
||||
|
||||
filtered
|
||||
|
||||
angular.module("admin.productImport").filter 'entriesFilterSupplier', ->
|
||||
(entries, supplier) ->
|
||||
if supplier == 'all'
|
||||
angular.module("admin.productImport").filter 'entriesFilterEnterprise', ->
|
||||
(entries, enterprise) ->
|
||||
if enterprise == 'all'
|
||||
return entries
|
||||
|
||||
filtered = {}
|
||||
|
||||
angular.forEach entries, (entry, line_number) ->
|
||||
if supplier == entry.attributes['supplier']
|
||||
if enterprise == entry.attributes['enterprise']
|
||||
filtered[line_number] = entry
|
||||
|
||||
filtered
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
angular.module("admin.productImport").factory "ProductImportService", ($rootScope) ->
|
||||
new class ProductImportService
|
||||
suppliers: {}
|
||||
enterprises: {}
|
||||
resetTotal: 0
|
||||
settings: {}
|
||||
|
||||
updateResetAbsent: (supplierId, resetCount, resetAbsent) ->
|
||||
updateResetAbsent: (enterpriseId, resetCount, resetAbsent) ->
|
||||
if resetAbsent
|
||||
@suppliers[supplierId] = resetCount
|
||||
@enterprises[enterpriseId] = resetCount
|
||||
@resetTotal += resetCount
|
||||
else
|
||||
@suppliers[supplierId] = null
|
||||
@enterprises[enterpriseId] = null
|
||||
@resetTotal -= resetCount
|
||||
|
||||
$rootScope.resetTotal = @resetTotal
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
angular.module("admin.resources").factory 'OrderResource', ($resource) ->
|
||||
$resource('/admin/orders/:id/:action.json', {}, {
|
||||
'index':
|
||||
url: '/api/orders.json'
|
||||
method: 'GET'
|
||||
'update':
|
||||
method: 'PUT'
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
angular.module("admin.subscriptions").controller "AddressController", ($scope, $filter, StatusMessage, availableCountries) ->
|
||||
angular.module("admin.subscriptions").controller "AddressController", ($scope, StatusMessage, availableCountries, CountryStates) ->
|
||||
$scope.countries = availableCountries
|
||||
$scope.statesFor = (country_id) ->
|
||||
return [] unless country_id
|
||||
$filter('filter')(availableCountries, {id: country_id})[0].states
|
||||
$scope.billStates = $scope.statesFor($scope.subscription.bill_address.country_id)
|
||||
$scope.shipStates = $scope.statesFor($scope.subscription.ship_address.country_id)
|
||||
|
||||
$scope.billStates = CountryStates.statesFor(availableCountries, $scope.subscription.bill_address.country_id)
|
||||
$scope.shipStates = CountryStates.statesFor(availableCountries, $scope.subscription.ship_address.country_id)
|
||||
|
||||
$scope.$watch 'subscription.bill_address.country_id', (newCountryID) ->
|
||||
return unless newCountryID
|
||||
$scope.billStates = CountryStates.statesFor(availableCountries, newCountryID)
|
||||
unless CountryStates.addressStateMatchesCountryStates($scope.billStates, $scope.subscription.bill_address.state_id)
|
||||
$scope.subscription.bill_address.state_id = ""
|
||||
|
||||
$scope.$watch 'subscription.ship_address.country_id', (newCountryID) ->
|
||||
return unless newCountryID
|
||||
$scope.shipStates = CountryStates.statesFor(availableCountries, newCountryID)
|
||||
unless CountryStates.addressStateMatchesCountryStates($scope.shipStates, $scope.subscription.ship_address.state_id)
|
||||
$scope.subscription.ship_address.state_id = ""
|
||||
|
||||
$scope.registerNextCallback 'address', ->
|
||||
$scope.subscription_form.$submitted = true
|
||||
@@ -18,9 +28,3 @@ angular.module("admin.subscriptions").controller "AddressController", ($scope, $
|
||||
$scope.registerBackCallback 'address', ->
|
||||
StatusMessage.clear()
|
||||
$scope.setView('details')
|
||||
|
||||
$scope.$watch 'subscription.bill_address.country_id', (newValue, oldValue) ->
|
||||
$scope.billStates = $scope.statesFor(newValue) if newValue?
|
||||
|
||||
$scope.$watch 'subscription.ship_address.country_id', (newValue, oldValue) ->
|
||||
$scope.shipStates = $scope.statesFor(newValue) if newValue?
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
angular.module("admin.utils").factory "CountryStates", ($filter) ->
|
||||
new class CountryStates
|
||||
|
||||
statesFor: (countries, country_id) ->
|
||||
return [] unless country_id
|
||||
country = $filter('filter')(countries, {id: parseInt(country_id)}, true)[0]
|
||||
return [] unless country
|
||||
country.states
|
||||
|
||||
addressStateMatchesCountryStates: (countryStates, stateId) ->
|
||||
countryStates.some (state) -> state.id == stateId
|
||||
@@ -25,12 +25,14 @@
|
||||
#= require angular-flash.min.js
|
||||
#
|
||||
#= require moment
|
||||
#= require moment/de.js
|
||||
#= require moment/en-gb.js
|
||||
#= require moment/es.js
|
||||
#= require moment/fr.js
|
||||
#= require moment/it.js
|
||||
#= require moment/nb.js
|
||||
#= require moment/pt-br.js
|
||||
#= require moment/pt.js
|
||||
#= require moment/sv.js
|
||||
#
|
||||
#= require modernizr
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# Extend the "offCanvasWrap" directive in "angular-foundation" to disable hiding of the off-canvas
|
||||
# upon window resize.
|
||||
#
|
||||
# In some browsers for mobile devices, the address bar is automatically hidden when scrolling down
|
||||
# the page. This is not workable if the height of the contents of the off-canvas exceeds the height
|
||||
# of the screen, because the latter portion of the contents stays hidden to the user.
|
||||
#
|
||||
# However, for screens over 1024px width for which the off-canvas is not styled to be visible, we
|
||||
# can proceed to hide this.
|
||||
#
|
||||
# https://github.com/openfoodfoundation/angular-foundation/blob/0.9.0-20180826174721/src/offcanvas/offcanvas.js
|
||||
angular.module('mm.foundation.offcanvas').directive 'offCanvasWrap', ($window) ->
|
||||
{
|
||||
restrict: 'C'
|
||||
priority: 1
|
||||
link: ($scope, element, attrs) ->
|
||||
win = angular.element($window)
|
||||
|
||||
# Get the scope used by the "offCanvasWrap" directive:
|
||||
# https://github.com/openfoodfoundation/angular-foundation/blob/0.9.0-20180826174721/src/offcanvas/offcanvas.js#L2
|
||||
isolatedScope = element.isolateScope()
|
||||
|
||||
# Unbind hiding of the off-canvas upon window resize.
|
||||
win.unbind('resize.body', isolatedScope.hide)
|
||||
|
||||
# Bind hiding of the off-canvas that only happens when screen width is over 1024px.
|
||||
win.bind 'resize.body', ->
|
||||
isolatedScope.hide() if $(window).width() > 1024
|
||||
}
|
||||
@@ -90,7 +90,7 @@ module Admin
|
||||
{
|
||||
filepath: @filepath,
|
||||
item_count: @importer.item_count,
|
||||
supplier_product_counts: @importer.supplier_products,
|
||||
enterprise_product_counts: @importer.enterprise_products,
|
||||
import_url: main_app.admin_product_import_process_async_path,
|
||||
save_url: main_app.admin_product_import_save_async_path,
|
||||
reset_url: main_app.admin_product_import_reset_async_path,
|
||||
|
||||
23
app/controllers/api/orders_controller.rb
Normal file
23
app/controllers/api/orders_controller.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
module Api
|
||||
class OrdersController < BaseController
|
||||
def index
|
||||
authorize! :admin, Spree::Order
|
||||
|
||||
search_results = SearchOrders.new(params, spree_current_user)
|
||||
|
||||
render json: {
|
||||
orders: serialized_orders(search_results.orders),
|
||||
pagination: search_results.pagination_data
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def serialized_orders(orders)
|
||||
ActiveModel::ArraySerializer.new(
|
||||
orders,
|
||||
each_serializer: Api::Admin::OrderSerializer
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -20,51 +20,11 @@ Spree::Admin::OrdersController.class_eval do
|
||||
|
||||
before_filter :require_distributor_abn, only: :invoice
|
||||
|
||||
|
||||
respond_to :html, :json
|
||||
|
||||
# Mostly the original Spree method, tweaked to allow us to ransack with completed_at in a sane way
|
||||
def index
|
||||
params[:q] ||= {}
|
||||
params[:q][:completed_at_not_null] ||= '1' if Spree::Config[:show_only_complete_orders_by_default]
|
||||
@show_only_completed = params[:q][:completed_at_not_null].present?
|
||||
params[:q][:s] ||= @show_only_completed ? 'completed_at desc' : 'created_at desc'
|
||||
|
||||
# As date params are deleted if @show_only_completed, store
|
||||
# the original date so we can restore them into the params
|
||||
# after the search
|
||||
created_at_gt = params[:q][:created_at_gt]
|
||||
created_at_lt = params[:q][:created_at_lt]
|
||||
|
||||
if !params[:q][:created_at_gt].blank?
|
||||
params[:q][:created_at_gt] = Time.zone.parse(params[:q][:created_at_gt]).beginning_of_day rescue ""
|
||||
end
|
||||
|
||||
if !params[:q][:created_at_lt].blank?
|
||||
params[:q][:created_at_lt] = Time.zone.parse(params[:q][:created_at_lt]).end_of_day rescue ""
|
||||
end
|
||||
|
||||
# Changed this to stop completed_at being overriden when present
|
||||
if @show_only_completed
|
||||
params[:q][:completed_at_gt] = params[:q].delete(:created_at_gt) unless params[:q][:completed_at_gt]
|
||||
params[:q][:completed_at_lt] = params[:q].delete(:created_at_lt) unless params[:q][:completed_at_gt]
|
||||
end
|
||||
|
||||
@orders = orders
|
||||
|
||||
# Restore dates
|
||||
params[:q][:created_at_gt] = created_at_gt
|
||||
params[:q][:created_at_lt] = created_at_lt
|
||||
|
||||
respond_with(@orders) do |format|
|
||||
format.html
|
||||
format.json do
|
||||
render json: {
|
||||
orders: ActiveModel::ArraySerializer.new(@orders, each_serializer: Api::Admin::OrderSerializer),
|
||||
pagination: pagination_data
|
||||
}
|
||||
end
|
||||
end
|
||||
# Overriding the action so we only render the page template. An angular request
|
||||
# within the page then fetches the data it needs from Api::OrdersController
|
||||
end
|
||||
|
||||
# Overwrite to use confirm_email_for_customer instead of confirm_email.
|
||||
@@ -100,42 +60,6 @@ Spree::Admin::OrdersController.class_eval do
|
||||
|
||||
private
|
||||
|
||||
def orders
|
||||
if json_request?
|
||||
@search = OpenFoodNetwork::Permissions.new(spree_current_user).editable_orders.ransack(params[:q])
|
||||
else
|
||||
@search = Spree::Order.accessible_by(current_ability, :index).ransack(params[:q])
|
||||
|
||||
# Replaced this search to filter orders to only show those distributed by current user (or all for admin user)
|
||||
@search.result.includes([:user, :shipments, :payments]).distributed_by_user(spree_current_user)
|
||||
end
|
||||
|
||||
search_results
|
||||
end
|
||||
|
||||
def search_results
|
||||
if using_pagination?
|
||||
@search.result.page(params[:page]).per(params[:per_page] || Spree::Config[:orders_per_page])
|
||||
else
|
||||
@search.result
|
||||
end
|
||||
end
|
||||
|
||||
def using_pagination?
|
||||
params[:per_page]
|
||||
end
|
||||
|
||||
def pagination_data
|
||||
if using_pagination?
|
||||
{
|
||||
results: @orders.total_count,
|
||||
pages: @orders.num_pages,
|
||||
page: params[:page].to_i,
|
||||
per_page: params[:per_page].to_i
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def require_distributor_abn
|
||||
unless @order.distributor.abn.present?
|
||||
flash[:error] = t(:must_have_valid_business_number, enterprise_name: @order.distributor.name)
|
||||
@@ -163,5 +87,4 @@ Spree::Admin::OrdersController.class_eval do
|
||||
render 'set_distribution', locals: { order: @order }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -76,7 +76,11 @@ Spree::Api::ProductsController.class_eval do
|
||||
end
|
||||
|
||||
def render_paged_products(products)
|
||||
render text: { products: ActiveModel::ArraySerializer.new(products, each_serializer: Api::Admin::ProductSerializer), pages: products.num_pages }.to_json
|
||||
end
|
||||
serializer = ActiveModel::ArraySerializer.new(
|
||||
products,
|
||||
each_serializer: Api::Admin::ProductSerializer
|
||||
)
|
||||
|
||||
render text: { products: serializer, pages: products.num_pages }.to_json
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
class Spree::StoreController
|
||||
layout 'darkswarm'
|
||||
|
||||
include I18nHelper
|
||||
before_filter :set_locale
|
||||
|
||||
def unauthorized
|
||||
render 'shared/unauthorized', :status => 401
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module OpenFoodNetwork
|
||||
class Calculator::Weight < Spree::Calculator
|
||||
preference :per_kg, :decimal, :default => 0.0
|
||||
module Calculator
|
||||
class Weight < Spree::Calculator
|
||||
preference :per_kg, :decimal, default: 0.0
|
||||
attr_accessible :preferred_per_kg
|
||||
|
||||
def self.description
|
||||
@@ -10,14 +10,15 @@ module OpenFoodNetwork
|
||||
def compute(object)
|
||||
line_items = line_items_for object
|
||||
total_weight = line_items.sum { |li| ((li.variant.andand.weight || 0) * li.quantity) }
|
||||
total_weight * self.preferred_per_kg
|
||||
total_weight * preferred_per_kg
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def line_items_for(object)
|
||||
if object.respond_to? :line_items
|
||||
if object.respond_to? :order
|
||||
object.order.line_items
|
||||
elsif object.respond_to? :line_items
|
||||
object.line_items
|
||||
elsif object.respond_to?(:variant) && object.respond_to?(:quantity)
|
||||
[object]
|
||||
@@ -80,6 +80,8 @@ class Enterprise < ActiveRecord::Base
|
||||
before_validation :set_unused_address_fields
|
||||
after_validation :geocode_address
|
||||
|
||||
validates :instagram, format: /\A@[a-zA-Z0-9._]{1,30}\z/, allow_blank: true
|
||||
|
||||
after_touch :touch_distributors
|
||||
after_create :set_default_contact
|
||||
after_create :relate_to_owners_enterprises
|
||||
@@ -330,6 +332,10 @@ class Enterprise < ActiveRecord::Base
|
||||
abn.present?
|
||||
end
|
||||
|
||||
def instagram=(value)
|
||||
write_attribute(:instagram, value.try(:gsub, instagram_regex, '@\1'))
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def devise_mailer
|
||||
@@ -338,6 +344,10 @@ class Enterprise < ActiveRecord::Base
|
||||
|
||||
private
|
||||
|
||||
def instagram_regex
|
||||
%r{\A(?:https?://)?(?:www\.)?instagram\.com/([a-zA-Z0-9._]{1,30})/?\z}
|
||||
end
|
||||
|
||||
def name_is_unique
|
||||
dups = Enterprise.where(name: name)
|
||||
dups = dups.where('id != ?', id) unless new_record?
|
||||
|
||||
@@ -6,7 +6,8 @@ class EnterpriseRelationship < ActiveRecord::Base
|
||||
validates_presence_of :parent_id, :child_id
|
||||
validates_uniqueness_of :child_id, scope: :parent_id, message: I18n.t('validation_msg_relationship_already_established')
|
||||
|
||||
after_save :apply_variant_override_permissions
|
||||
after_save :update_permissions_of_child_variant_overrides
|
||||
before_destroy :revoke_all_child_variant_overrides
|
||||
|
||||
scope :with_enterprises,
|
||||
joins('LEFT JOIN enterprises AS parent_enterprises ON parent_enterprises.id = enterprise_relationships.parent_id').
|
||||
@@ -26,7 +27,6 @@ class EnterpriseRelationship < ActiveRecord::Base
|
||||
|
||||
scope :by_name, with_enterprises.order('child_enterprises.name, parent_enterprises.name')
|
||||
|
||||
|
||||
# Load an array of the relatives of each enterprise (ie. any enterprise related to it in
|
||||
# either direction). This array is split into distributors and producers, and has the format:
|
||||
# {enterprise_id => {distributors: [id, ...], producers: [id, ...]} }
|
||||
@@ -76,14 +76,24 @@ class EnterpriseRelationship < ActiveRecord::Base
|
||||
|
||||
private
|
||||
|
||||
def apply_variant_override_permissions
|
||||
variant_overrides = VariantOverride.unscoped.for_hubs(child)
|
||||
.joins(variant: :product).where("spree_products.supplier_id IN (?)", parent)
|
||||
|
||||
def update_permissions_of_child_variant_overrides
|
||||
if has_permission?(:create_variant_overrides)
|
||||
variant_overrides.update_all(permission_revoked_at: nil)
|
||||
allow_all_child_variant_overrides
|
||||
else
|
||||
variant_overrides.update_all(permission_revoked_at: Time.now)
|
||||
revoke_all_child_variant_overrides
|
||||
end
|
||||
end
|
||||
|
||||
def allow_all_child_variant_overrides
|
||||
child_variant_overrides.update_all(permission_revoked_at: nil)
|
||||
end
|
||||
|
||||
def revoke_all_child_variant_overrides
|
||||
child_variant_overrides.update_all(permission_revoked_at: Time.now)
|
||||
end
|
||||
|
||||
def child_variant_overrides
|
||||
VariantOverride.unscoped.for_hubs(child)
|
||||
.joins(variant: :product).where("spree_products.supplier_id IN (?)", parent)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
module ProductImport
|
||||
class EntryProcessor
|
||||
attr_reader :inventory_created, :inventory_updated, :products_created,
|
||||
:variants_created, :variants_updated, :supplier_products,
|
||||
:total_supplier_products, :products_reset_count
|
||||
:variants_created, :variants_updated, :enterprise_products,
|
||||
:total_enterprise_products, :products_reset_count
|
||||
|
||||
def initialize(importer, validator, import_settings, spreadsheet_data, editable_enterprises, import_time, updated_ids)
|
||||
@importer = importer
|
||||
@@ -23,13 +23,13 @@ module ProductImport
|
||||
@variants_created = 0
|
||||
@variants_updated = 0
|
||||
@products_reset_count = 0
|
||||
@supplier_products = {}
|
||||
@total_supplier_products = 0
|
||||
@enterprise_products = {}
|
||||
@total_enterprise_products = 0
|
||||
end
|
||||
|
||||
def save_all(entries)
|
||||
entries.each do |entry|
|
||||
if import_into_inventory?(entry)
|
||||
if settings.importing_into_inventory?
|
||||
save_to_inventory(entry)
|
||||
else
|
||||
save_to_product_list(entry)
|
||||
@@ -40,24 +40,24 @@ module ProductImport
|
||||
end
|
||||
|
||||
def count_existing_items
|
||||
@spreadsheet_data.suppliers_index.each do |_supplier_name, attrs|
|
||||
supplier_id = attrs[:id]
|
||||
next unless supplier_id && permission_by_id?(supplier_id)
|
||||
@spreadsheet_data.enterprises_index.each do |_enterprise_name, attrs|
|
||||
enterprise_id = attrs[:id]
|
||||
next unless enterprise_id && permission_by_id?(enterprise_id)
|
||||
|
||||
products_count =
|
||||
if settings.importing_into_inventory?
|
||||
VariantOverride.where('variant_overrides.hub_id IN (?)', supplier_id).count
|
||||
VariantOverride.for_hubs([enterprise_id]).count
|
||||
else
|
||||
Spree::Variant.
|
||||
not_deleted.
|
||||
not_master.
|
||||
joins(:product).
|
||||
where('spree_products.supplier_id IN (?)', supplier_id).
|
||||
where('spree_products.supplier_id IN (?)', enterprise_id).
|
||||
count
|
||||
end
|
||||
|
||||
@supplier_products[supplier_id] = products_count
|
||||
@total_supplier_products += products_count
|
||||
@enterprise_products[enterprise_id] = products_count
|
||||
@total_enterprise_products += products_count
|
||||
end
|
||||
end
|
||||
|
||||
@@ -88,8 +88,8 @@ module ProductImport
|
||||
@products_created + @variants_created + @variants_updated + @inventory_created + @inventory_updated
|
||||
end
|
||||
|
||||
def permission_by_id?(supplier_id)
|
||||
@editable_enterprises.value?(Integer(supplier_id))
|
||||
def permission_by_id?(enterprise_id)
|
||||
@editable_enterprises.value?(Integer(enterprise_id))
|
||||
end
|
||||
|
||||
private
|
||||
@@ -121,10 +121,6 @@ module ProductImport
|
||||
@variants_updated += 1
|
||||
end
|
||||
|
||||
def import_into_inventory?(entry)
|
||||
entry.supplier_id && settings.importing_into_inventory?
|
||||
end
|
||||
|
||||
def save_new_inventory_item(entry)
|
||||
new_item = entry.product_object
|
||||
assign_defaults(new_item, entry)
|
||||
@@ -158,14 +154,17 @@ module ProductImport
|
||||
# If we've already added a new product with these attributes
|
||||
# from this spreadsheet, mark this entry as a new variant with
|
||||
# the new product id, as this is a now variant of that product...
|
||||
if @already_created[entry.supplier_id] && @already_created[entry.supplier_id][entry.name]
|
||||
product_id = @already_created[entry.supplier_id][entry.name]
|
||||
if @already_created[entry.enterprise_id] &&
|
||||
@already_created[entry.enterprise_id][entry.name]
|
||||
|
||||
product_id = @already_created[entry.enterprise_id][entry.name]
|
||||
@validator.mark_as_new_variant(entry, product_id)
|
||||
return
|
||||
end
|
||||
|
||||
product = Spree::Product.new
|
||||
product.assign_attributes(entry.attributes.except('id'))
|
||||
product.supplier_id = entry.producer_id
|
||||
assign_defaults(product, entry)
|
||||
|
||||
if product.save
|
||||
@@ -176,7 +175,7 @@ module ProductImport
|
||||
assign_errors product.errors.full_messages, entry.line_number
|
||||
end
|
||||
|
||||
@already_created[entry.supplier_id] = { entry.name => product.id }
|
||||
@already_created[entry.enterprise_id] = { entry.name => product.id }
|
||||
end
|
||||
|
||||
def save_variant(entry)
|
||||
@@ -214,7 +213,10 @@ module ProductImport
|
||||
when 'overwrite_all'
|
||||
object.assign_attributes(attribute => setting['value'])
|
||||
when 'overwrite_empty'
|
||||
if object.public_send(attribute).blank? || ((attribute == 'on_hand' || attribute == 'count_on_hand') && entry.on_hand_nil)
|
||||
if object.public_send(attribute).blank? ||
|
||||
((attribute == 'on_hand' || attribute == 'count_on_hand') &&
|
||||
entry.on_hand_nil)
|
||||
|
||||
object.assign_attributes(attribute => setting['value'])
|
||||
end
|
||||
end
|
||||
@@ -223,7 +225,10 @@ module ProductImport
|
||||
|
||||
def display_in_inventory(variant_override, is_new = false)
|
||||
unless is_new
|
||||
existing_item = InventoryItem.where(variant_id: variant_override.variant_id, enterprise_id: variant_override.hub_id).first
|
||||
existing_item = InventoryItem.where(
|
||||
variant_id: variant_override.variant_id,
|
||||
enterprise_id: variant_override.hub_id
|
||||
).first
|
||||
|
||||
if existing_item
|
||||
existing_item.assign_attributes(visible: true)
|
||||
@@ -232,7 +237,11 @@ module ProductImport
|
||||
end
|
||||
end
|
||||
|
||||
InventoryItem.new(variant_id: variant_override.variant_id, enterprise_id: variant_override.hub_id, visible: true).save
|
||||
InventoryItem.new(
|
||||
variant_id: variant_override.variant_id,
|
||||
enterprise_id: variant_override.hub_id,
|
||||
visible: true
|
||||
).save
|
||||
end
|
||||
|
||||
def ensure_variant_updated(product, entry)
|
||||
|
||||
@@ -27,10 +27,11 @@ module ProductImport
|
||||
|
||||
def validate_all(entries)
|
||||
entries.each do |entry|
|
||||
supplier_validation(entry)
|
||||
assign_enterprise_field(entry)
|
||||
enterprise_validation(entry)
|
||||
unit_fields_validation(entry)
|
||||
|
||||
next if entry.supplier_id.blank?
|
||||
next if entry.enterprise_id.blank?
|
||||
|
||||
if import_into_inventory?
|
||||
producer_validation(entry)
|
||||
@@ -44,6 +45,14 @@ module ProductImport
|
||||
end
|
||||
end
|
||||
|
||||
def assign_enterprise_field(entry)
|
||||
entry.enterprise = entry.public_send(enterprise_field)
|
||||
end
|
||||
|
||||
def enterprise_field
|
||||
import_into_inventory? ? :distributor : :producer
|
||||
end
|
||||
|
||||
def mark_as_new_variant(entry, product_id)
|
||||
new_variant = Spree::Variant.new(entry.attributes.except('id', 'product_id'))
|
||||
new_variant.product_id = product_id
|
||||
@@ -59,37 +68,56 @@ module ProductImport
|
||||
|
||||
private
|
||||
|
||||
def supplier_validation(entry)
|
||||
def enterprise_validation(entry)
|
||||
return if name_presence_error entry
|
||||
return if enterprise_not_found_error entry
|
||||
return if permissions_error entry
|
||||
return if primary_producer_error entry
|
||||
|
||||
entry.supplier_id = @spreadsheet_data.suppliers_index[entry.supplier][:id]
|
||||
entry.enterprise_id =
|
||||
@spreadsheet_data.enterprises_index[entry.enterprise][:id]
|
||||
|
||||
entry.public_send(
|
||||
"#{enterprise_field}_id=",
|
||||
@spreadsheet_data.enterprises_index[entry.enterprise][:id]
|
||||
)
|
||||
end
|
||||
|
||||
def name_presence_error(entry)
|
||||
return if entry.supplier.present?
|
||||
mark_as_invalid(entry, attribute: "supplier", error: I18n.t(:error_required))
|
||||
return if entry.enterprise.present?
|
||||
mark_as_invalid(entry,
|
||||
attribute: enterprise_field,
|
||||
error: I18n.t(:error_required))
|
||||
true
|
||||
end
|
||||
|
||||
def enterprise_not_found_error(entry)
|
||||
return if @spreadsheet_data.suppliers_index[entry.supplier][:id]
|
||||
mark_as_invalid(entry, attribute: "supplier", error: I18n.t(:error_not_found_in_database, name: entry.supplier))
|
||||
return if @spreadsheet_data.enterprises_index[entry.enterprise][:id]
|
||||
mark_as_invalid(entry,
|
||||
attribute: enterprise_field,
|
||||
error: I18n.t(:error_not_found_in_database,
|
||||
name: entry.enterprise))
|
||||
true
|
||||
end
|
||||
|
||||
def permissions_error(entry)
|
||||
return if permission_by_name?(entry.supplier)
|
||||
mark_as_invalid(entry, attribute: "supplier", error: I18n.t(:error_no_permission_for_enterprise, name: entry.supplier))
|
||||
return if permission_by_name?(entry.enterprise)
|
||||
mark_as_invalid(entry,
|
||||
attribute: enterprise_field,
|
||||
error: I18n.t(:error_no_permission_for_enterprise,
|
||||
name: entry.enterprise))
|
||||
true
|
||||
end
|
||||
|
||||
def primary_producer_error(entry)
|
||||
return if import_into_inventory?
|
||||
return if @spreadsheet_data.suppliers_index[entry.supplier][:is_primary_producer]
|
||||
mark_as_invalid(entry, attribute: "supplier", error: I18n.t(:error_not_primary_producer, name: entry.supplier))
|
||||
return if @spreadsheet_data.
|
||||
enterprises_index[entry.enterprise][:is_primary_producer]
|
||||
|
||||
mark_as_invalid(entry,
|
||||
attribute: enterprise_field,
|
||||
error: I18n.t(:error_not_primary_producer,
|
||||
name: entry.enterprise))
|
||||
true
|
||||
end
|
||||
|
||||
@@ -126,7 +154,11 @@ module ProductImport
|
||||
return
|
||||
end
|
||||
|
||||
unless inventory_permission?(entry.supplier_id, @spreadsheet_data.producers_index[producer_name])
|
||||
unless inventory_permission?(
|
||||
entry.enterprise_id,
|
||||
@spreadsheet_data.producers_index[producer_name]
|
||||
)
|
||||
|
||||
mark_as_invalid(entry, attribute: "producer", error: "\"#{producer_name}\": #{I18n.t('admin.product_import.model.inventory_no_permission')}")
|
||||
return
|
||||
end
|
||||
@@ -186,7 +218,9 @@ module ProductImport
|
||||
end
|
||||
|
||||
def product_validation(entry)
|
||||
products = Spree::Product.where(supplier_id: entry.supplier_id, name: entry.name, deleted_at: nil)
|
||||
products = Spree::Product.where(supplier_id: entry.enterprise_id,
|
||||
name: entry.name,
|
||||
deleted_at: nil)
|
||||
|
||||
if products.empty?
|
||||
mark_as_new_product(entry)
|
||||
@@ -207,6 +241,7 @@ module ProductImport
|
||||
def mark_as_new_product(entry)
|
||||
new_product = Spree::Product.new
|
||||
new_product.assign_attributes(entry.attributes.except('id'))
|
||||
new_product.supplier_id = entry.producer_id
|
||||
|
||||
if new_product.valid?
|
||||
entry.validates_as = 'new_product' unless entry.errors?
|
||||
@@ -222,7 +257,7 @@ module ProductImport
|
||||
if existing_variant.valid?
|
||||
entry.product_object = existing_variant
|
||||
entry.validates_as = 'existing_variant' unless entry.errors?
|
||||
updates_count_per_supplier(entry.supplier_id) unless entry.errors?
|
||||
updates_count_per_enterprise(entry.enterprise_id) unless entry.errors?
|
||||
else
|
||||
mark_as_invalid(entry, product_validations: existing_variant.errors)
|
||||
end
|
||||
@@ -243,16 +278,18 @@ module ProductImport
|
||||
existing_product.public_send(attribute).blank? && entry.public_send(attribute).blank?
|
||||
end
|
||||
|
||||
def permission_by_name?(supplier_name)
|
||||
@editable_enterprises.key?(supplier_name)
|
||||
def permission_by_name?(enterprise_name)
|
||||
@editable_enterprises.key?(enterprise_name)
|
||||
end
|
||||
|
||||
def permission_by_id?(supplier_id)
|
||||
@editable_enterprises.value?(Integer(supplier_id))
|
||||
def permission_by_id?(enterprise_id)
|
||||
@editable_enterprises.value?(Integer(enterprise_id))
|
||||
end
|
||||
|
||||
def inventory_permission?(supplier_id, producer_id)
|
||||
@current_user.admin? || ( @inventory_permissions[supplier_id] && @inventory_permissions[supplier_id].include?(producer_id) )
|
||||
def inventory_permission?(enterprise_id, producer_id)
|
||||
@current_user.admin? ||
|
||||
( @inventory_permissions[enterprise_id] &&
|
||||
@inventory_permissions[enterprise_id].include?(producer_id) )
|
||||
end
|
||||
|
||||
def mark_as_invalid(entry, options = {})
|
||||
@@ -261,7 +298,7 @@ module ProductImport
|
||||
end
|
||||
|
||||
def import_into_inventory?
|
||||
@import_settings[:settings]['import_into'] == 'inventories'
|
||||
@import_settings[:settings].andand['import_into'] == 'inventories'
|
||||
end
|
||||
|
||||
def validate_inventory_item(entry, variant_override)
|
||||
@@ -273,9 +310,16 @@ module ProductImport
|
||||
end
|
||||
|
||||
def create_inventory_item(entry, existing_variant)
|
||||
existing_variant_override = VariantOverride.where(variant_id: existing_variant.id, hub_id: entry.supplier_id).first
|
||||
existing_variant_override = VariantOverride.where(
|
||||
variant_id: existing_variant.id,
|
||||
hub_id: entry.enterprise_id
|
||||
).first
|
||||
|
||||
variant_override = existing_variant_override || VariantOverride.new(
|
||||
variant_id: existing_variant.id,
|
||||
hub_id: entry.enterprise_id
|
||||
)
|
||||
|
||||
variant_override = existing_variant_override || VariantOverride.new(variant_id: existing_variant.id, hub_id: entry.supplier_id)
|
||||
variant_override.assign_attributes(count_on_hand: entry.on_hand, import_date: @import_time)
|
||||
check_on_hand_nil(entry, variant_override)
|
||||
variant_override.assign_attributes(entry.attributes.slice('price', 'on_demand'))
|
||||
@@ -287,18 +331,20 @@ module ProductImport
|
||||
if variant_override.id
|
||||
entry.validates_as = 'existing_inventory_item'
|
||||
entry.product_object = variant_override
|
||||
updates_count_per_supplier(entry.supplier_id) unless entry.errors?
|
||||
updates_count_per_enterprise(entry.enterprise_id) unless entry.errors?
|
||||
else
|
||||
entry.validates_as = 'new_inventory_item'
|
||||
entry.product_object = variant_override
|
||||
end
|
||||
end
|
||||
|
||||
def updates_count_per_supplier(supplier_id)
|
||||
if @reset_counts[supplier_id] && @reset_counts[supplier_id][:updates_count]
|
||||
@reset_counts[supplier_id][:updates_count] += 1
|
||||
def updates_count_per_enterprise(enterprise_id)
|
||||
if @reset_counts[enterprise_id] &&
|
||||
@reset_counts[enterprise_id][:updates_count]
|
||||
|
||||
@reset_counts[enterprise_id][:updates_count] += 1
|
||||
else
|
||||
@reset_counts[supplier_id] = { updates_count: 1 }
|
||||
@reset_counts[enterprise_id] = { updates_count: 1 }
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ module ProductImport
|
||||
@excluded_items_ids = excluded_items_ids
|
||||
end
|
||||
|
||||
def reset(supplier_ids)
|
||||
@supplier_ids = supplier_ids
|
||||
def reset(enterprise_ids)
|
||||
@enterprise_ids = enterprise_ids
|
||||
|
||||
if supplier_ids.present?
|
||||
if enterprise_ids.present?
|
||||
relation.update_all(count_on_hand: 0)
|
||||
else
|
||||
0
|
||||
@@ -16,10 +16,10 @@ module ProductImport
|
||||
|
||||
private
|
||||
|
||||
attr_reader :excluded_items_ids, :supplier_ids
|
||||
attr_reader :excluded_items_ids, :enterprise_ids
|
||||
|
||||
def relation
|
||||
relation = VariantOverride.where(hub_id: supplier_ids)
|
||||
relation = VariantOverride.where(hub_id: enterprise_ids)
|
||||
return relation if excluded_items_ids.blank?
|
||||
|
||||
relation.where('id NOT IN (?)', excluded_items_ids)
|
||||
|
||||
@@ -65,27 +65,29 @@ module ProductImport
|
||||
end
|
||||
|
||||
def reset_counts
|
||||
# Return indexed data about existing product count, reset count, and updates count per supplier
|
||||
@reset_counts.each do |supplier_id, values|
|
||||
# Return indexed data about existing product count, reset count, and
|
||||
# updates count per enterprise
|
||||
@reset_counts.each do |enterprise_id, values|
|
||||
values[:updates_count] = 0 if values[:updates_count].blank?
|
||||
|
||||
if values[:updates_count] && values[:existing_products]
|
||||
@reset_counts[supplier_id][:reset_count] = values[:existing_products] - values[:updates_count]
|
||||
@reset_counts[enterprise_id][:reset_count] =
|
||||
values[:existing_products] - values[:updates_count]
|
||||
end
|
||||
end
|
||||
@reset_counts
|
||||
end
|
||||
|
||||
def suppliers_index
|
||||
@spreadsheet_data.suppliers_index
|
||||
def enterprises_index
|
||||
@spreadsheet_data.enterprises_index
|
||||
end
|
||||
|
||||
def supplier_products
|
||||
@processor.andand.supplier_products
|
||||
def enterprise_products
|
||||
@processor.andand.enterprise_products
|
||||
end
|
||||
|
||||
def total_supplier_products
|
||||
@processor.total_supplier_products
|
||||
def total_enterprise_products
|
||||
@processor.total_enterprise_products
|
||||
end
|
||||
|
||||
def all_entries
|
||||
@@ -165,8 +167,8 @@ module ProductImport
|
||||
@processor.reset_absent_items
|
||||
end
|
||||
|
||||
def permission_by_id?(supplier_id)
|
||||
@editable_enterprises.value?(Integer(supplier_id))
|
||||
def permission_by_id?(enterprise_id)
|
||||
@editable_enterprises.value?(Integer(enterprise_id))
|
||||
end
|
||||
|
||||
private
|
||||
@@ -180,7 +182,7 @@ module ProductImport
|
||||
build_entries
|
||||
end
|
||||
|
||||
@spreadsheet_data = SpreadsheetData.new(@entries)
|
||||
@spreadsheet_data = SpreadsheetData.new(@entries, @import_settings)
|
||||
@validator = EntryValidator.new(@current_user, @import_time, @spreadsheet_data, @editable_enterprises, @inventory_permissions, @reset_counts, @import_settings)
|
||||
@processor = EntryProcessor.new(self, @validator, @import_settings, @spreadsheet_data, @editable_enterprises, @import_time, @updated_ids)
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ module ProductImport
|
||||
@excluded_items_ids = excluded_items_ids
|
||||
end
|
||||
|
||||
def reset(supplier_ids)
|
||||
@supplier_ids = supplier_ids
|
||||
def reset(enterprise_ids)
|
||||
@enterprise_ids = enterprise_ids
|
||||
|
||||
if supplier_ids.present?
|
||||
if enterprise_ids.present?
|
||||
relation.update_all(count_on_hand: 0)
|
||||
else
|
||||
0
|
||||
@@ -16,13 +16,13 @@ module ProductImport
|
||||
|
||||
private
|
||||
|
||||
attr_reader :excluded_items_ids, :supplier_ids
|
||||
attr_reader :excluded_items_ids, :enterprise_ids
|
||||
|
||||
def relation
|
||||
relation = Spree::Variant
|
||||
.joins(:product)
|
||||
.where(
|
||||
spree_products: { supplier_id: supplier_ids },
|
||||
spree_products: { supplier_id: enterprise_ids },
|
||||
spree_variants: { is_master: false, deleted_at: nil }
|
||||
)
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ module ProductImport
|
||||
|
||||
def defaults(entry)
|
||||
@import_settings.key?(:settings) &&
|
||||
settings[entry.supplier_id.to_s] &&
|
||||
settings[entry.supplier_id.to_s]['defaults']
|
||||
settings[entry.enterprise_id.to_s] &&
|
||||
settings[entry.enterprise_id.to_s]['defaults']
|
||||
end
|
||||
|
||||
def settings
|
||||
|
||||
@@ -7,12 +7,13 @@
|
||||
|
||||
module ProductImport
|
||||
class SpreadsheetData
|
||||
def initialize(entries)
|
||||
def initialize(entries, import_settings)
|
||||
@entries = entries
|
||||
@import_settings = import_settings
|
||||
end
|
||||
|
||||
def suppliers_index
|
||||
@suppliers_index || create_suppliers_index
|
||||
def enterprises_index
|
||||
@enterprises_index || create_enterprises_index
|
||||
end
|
||||
|
||||
def producers_index
|
||||
@@ -33,15 +34,24 @@ module ProductImport
|
||||
|
||||
private
|
||||
|
||||
def create_suppliers_index
|
||||
@suppliers_index = {}
|
||||
def import_into_inventory?
|
||||
@import_settings[:settings].andand['import_into'] == 'inventories'
|
||||
end
|
||||
|
||||
def create_enterprises_index
|
||||
@enterprises_index = {}
|
||||
@entries.each do |entry|
|
||||
supplier_name = entry.supplier
|
||||
next if @suppliers_index.key? supplier_name
|
||||
enterprise = Enterprise.find_by_name(supplier_name, select: 'id, name, is_primary_producer')
|
||||
@suppliers_index[supplier_name] = { id: enterprise.try(:id), is_primary_producer: enterprise.try(:is_primary_producer) }
|
||||
enterprise_name = import_into_inventory? ? entry.distributor : entry.producer
|
||||
|
||||
next if @enterprises_index.key? enterprise_name
|
||||
|
||||
enterprise = Enterprise.find_by_name(enterprise_name, select: 'id, is_primary_producer')
|
||||
|
||||
@enterprises_index[enterprise_name] =
|
||||
{ id: enterprise.try(:id),
|
||||
is_primary_producer: enterprise.try(:is_primary_producer) }
|
||||
end
|
||||
@suppliers_index
|
||||
@enterprises_index
|
||||
end
|
||||
|
||||
def create_producers_index
|
||||
|
||||
@@ -8,13 +8,17 @@ module ProductImport
|
||||
include ActiveModel::Conversion
|
||||
include ActiveModel::Validations
|
||||
|
||||
attr_accessor :line_number, :valid, :validates_as, :product_object, :product_validations, :on_hand_nil,
|
||||
:has_overrides, :units, :unscaled_units, :unit_type, :tax_category, :shipping_category
|
||||
attr_accessor :line_number, :valid, :validates_as, :product_object,
|
||||
:product_validations, :on_hand_nil, :has_overrides, :units,
|
||||
:unscaled_units, :unit_type, :tax_category, :shipping_category
|
||||
|
||||
attr_accessor :id, :product_id, :producer, :producer_id, :supplier, :supplier_id, :name, :display_name, :sku,
|
||||
:unit_value, :unit_description, :variant_unit, :variant_unit_scale, :variant_unit_name,
|
||||
:display_as, :category, :primary_taxon_id, :price, :on_hand, :count_on_hand, :on_demand,
|
||||
:tax_category_id, :shipping_category_id, :description, :import_date
|
||||
attr_accessor :id, :product_id, :producer, :producer_id, :distributor,
|
||||
:distributor_id, :name, :display_name, :sku, :unit_value,
|
||||
:unit_description, :variant_unit, :variant_unit_scale,
|
||||
:variant_unit_name, :display_as, :category, :primary_taxon_id,
|
||||
:price, :on_hand, :count_on_hand, :on_demand,
|
||||
:tax_category_id, :shipping_category_id, :description,
|
||||
:import_date, :enterprise, :enterprise_id
|
||||
|
||||
def initialize(attrs)
|
||||
@validates_as = ''
|
||||
@@ -77,11 +81,16 @@ module ProductImport
|
||||
end
|
||||
|
||||
def non_display_attributes
|
||||
['id', 'product_id', 'unscaled_units', 'variant_id', 'supplier_id', 'primary_taxon', 'primary_taxon_id', 'category_id', 'shipping_category_id', 'tax_category_id', 'variant_unit_scale', 'variant_unit', 'unit_value']
|
||||
['id', 'product_id', 'unscaled_units', 'variant_id', 'enterprise',
|
||||
'enterprise_id', 'producer_id', 'distributor_id', 'primary_taxon',
|
||||
'primary_taxon_id', 'category_id', 'shipping_category_id',
|
||||
'tax_category_id', 'variant_unit_scale', 'variant_unit', 'unit_value']
|
||||
end
|
||||
|
||||
def non_product_attributes
|
||||
['line_number', 'valid', 'errors', 'product_object', 'product_validations', 'inventory_validations', 'validates_as', 'save_type', 'on_hand_nil', 'has_overrides']
|
||||
['line_number', 'valid', 'errors', 'product_object',
|
||||
'product_validations', 'inventory_validations', 'validates_as',
|
||||
'save_type', 'on_hand_nil', 'has_overrides']
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,15 +5,23 @@ class Api::Admin::ProductSerializer < ActiveModel::Serializer
|
||||
|
||||
has_one :supplier, key: :producer_id, embed: :id
|
||||
has_one :primary_taxon, key: :category_id, embed: :id
|
||||
has_many :variants, key: :variants, serializer: Api::Admin::VariantSerializer # embed: ids
|
||||
has_many :variants, key: :variants, serializer: Api::Admin::VariantSerializer
|
||||
has_one :master, serializer: Api::Admin::VariantSerializer
|
||||
|
||||
def image_url
|
||||
object.images.present? ? object.images.first.attachment.url(:product) : "/assets/noimage/product.png"
|
||||
if object.images.present?
|
||||
object.images.first.attachment.url(:product)
|
||||
else
|
||||
"/assets/noimage/product.png"
|
||||
end
|
||||
end
|
||||
|
||||
def thumb_url
|
||||
object.images.present? ? object.images.first.attachment.url(:mini) : "/assets/noimage/mini.png"
|
||||
if object.images.present?
|
||||
object.images.first.attachment.url(:mini)
|
||||
else
|
||||
"/assets/noimage/mini.png"
|
||||
end
|
||||
end
|
||||
|
||||
def on_hand
|
||||
|
||||
41
app/services/search_orders.rb
Normal file
41
app/services/search_orders.rb
Normal file
@@ -0,0 +1,41 @@
|
||||
class SearchOrders
|
||||
attr_reader :orders
|
||||
|
||||
def initialize(params, current_user)
|
||||
@params = params
|
||||
@current_user = current_user
|
||||
|
||||
@orders = fetch_orders
|
||||
end
|
||||
|
||||
def pagination_data
|
||||
return unless using_pagination?
|
||||
{
|
||||
results: @orders.total_count,
|
||||
pages: @orders.num_pages,
|
||||
page: params[:page].to_i,
|
||||
per_page: params[:per_page].to_i
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :params, :current_user
|
||||
|
||||
def fetch_orders
|
||||
@search = OpenFoodNetwork::Permissions.new(current_user).editable_orders.ransack(params[:q])
|
||||
|
||||
return paginated_results if using_pagination?
|
||||
@search.result
|
||||
end
|
||||
|
||||
def paginated_results
|
||||
@search.result
|
||||
.page(params[:page])
|
||||
.per(params[:per_page])
|
||||
end
|
||||
|
||||
def using_pagination?
|
||||
params[:per_page]
|
||||
end
|
||||
end
|
||||
@@ -1,7 +1,7 @@
|
||||
%h5= t('admin.product_import.import.options_and_defaults')
|
||||
%br
|
||||
|
||||
- @importer.suppliers_index.each do |name, attrs|
|
||||
- @importer.enterprises_index.each do |name, attrs|
|
||||
- if name and attrs[:id] and @importer.permission_by_id?(attrs[:id])
|
||||
%div.panel-section.import-settings
|
||||
%div.panel-header{ng: {click: 'togglePanel()', class: '{active: active}'}}
|
||||
@@ -32,7 +32,7 @@
|
||||
%i.fa.fa-warning
|
||||
%div.header-description
|
||||
= t('admin.product_import.import.no_name')
|
||||
%span.header-error= " - #{t('admin.product_import.import.blank_supplier')}"
|
||||
%span.header-error= " - #{t('admin.product_import.import.blank_enterprise')}"
|
||||
|
||||
%br.panels.clearfix
|
||||
%br
|
||||
|
||||
@@ -1,34 +1,36 @@
|
||||
%div{"data-hook" => "admin_orders_index_search"}
|
||||
= search_form_for [:admin, @search], html: { name: "orders_form", "ng-submit" => "fetchResults()"} do |f|
|
||||
= form_tag false, {name: "orders_form", "ng-submit" => "fetchResults()"} do
|
||||
.field-block.alpha.four.columns
|
||||
.date-range-filter.field
|
||||
= label_tag nil, t(:date_range)
|
||||
.date-range-fields
|
||||
= f.text_field :created_at_gt, class: 'datepicker', datepicker: 'q.created_at_gt', 'ng-model' => 'q.created_at_gt', :value => params[:q][:created_at_gt], :placeholder => t(:start)
|
||||
= text_field_tag "q[created_at_gt]", nil, class: 'datepicker', datepicker: 'q.created_at_gt', 'ng-model' => 'q.created_at_gt', :placeholder => t(:start)
|
||||
%span.range-divider
|
||||
%i.icon-arrow-right
|
||||
= f.text_field :created_at_lt, class: 'datepicker', datepicker: 'q.created_at_lt', 'ng-model' => 'q.created_at_lt', :value => params[:q][:created_at_lt], :placeholder => t(:stop)
|
||||
= text_field_tag "q[created_at_lt]", nil, class: 'datepicker', datepicker: 'q.created_at_lt', 'ng-model' => 'q.created_at_lt', :placeholder => t(:stop)
|
||||
.field
|
||||
= label_tag nil, t(:status)
|
||||
= f.select :state_eq, Spree::Order.state_machines[:state].states.collect {|s| [t("order_state.#{s.name}"), s.value]}, {:include_blank => true}, :class => 'select2', 'ng-model' => 'q.state_eq'
|
||||
= select_tag("q[state_eq]",
|
||||
options_for_select(Spree::Order.state_machines[:state].states.collect {|s| [t("order_state.#{s.name}"), s.value]}),
|
||||
{include_blank: true, class: 'select2', 'ng-model' => 'q.state_eq'})
|
||||
.four.columns
|
||||
.field
|
||||
= label_tag nil, t(:order_number)
|
||||
= f.text_field :number_cont, 'ng-model' => 'q.number_cont'
|
||||
= text_field_tag "q[number_cont]", nil, 'ng-model' => 'q.number_cont'
|
||||
.field
|
||||
= label_tag nil, t(:email)
|
||||
= f.email_field :email_cont, 'ng-model' => 'q.email_cont'
|
||||
= email_field_tag "q[email_cont", nil, 'ng-model' => 'q.email_cont'
|
||||
.four.columns
|
||||
.field
|
||||
= label_tag nil, t(:first_name_begins_with)
|
||||
= f.text_field :bill_address_firstname_start, :size => 25, 'ng-model' => 'q.bill_address_firstname_start'
|
||||
= text_field_tag "q[bill_address_firstname_start]", nil, size: 25, 'ng-model' => 'q.bill_address_firstname_start'
|
||||
.field
|
||||
= label_tag nil, t(:last_name_begins_with)
|
||||
= f.text_field :bill_address_lastname_start, :size => 25, 'ng-model' => 'q.bill_address_lastname_start'
|
||||
= text_field_tag "q[bill_address_lastname_start]", nil, size: 25, 'ng-model' => 'q.bill_address_lastname_start'
|
||||
.omega.four.columns
|
||||
.field.checkbox
|
||||
%label
|
||||
= f.check_box :completed_at_not_null, {:checked => @show_only_completed, 'ng-model' => 'q.completed_at_not_null'}, '1', ''
|
||||
= check_box_tag "q[completed_at_not_null]", 1, true, {'ng-model' => 'q.completed_at_not_null'}
|
||||
= t(:show_only_complete_orders)
|
||||
.field-block.alpha.eight.columns
|
||||
= label_tag nil, t(:distributors)
|
||||
|
||||
Reference in New Issue
Block a user