mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-04-03 06:59:14 +00:00
i18n from berlin hackathon
This commit is contained in:
16
.travis.yml
16
.travis.yml
@@ -14,12 +14,13 @@ env:
|
||||
global:
|
||||
- TZ="Australia/Melbourne"
|
||||
- TIMEZONE="Australia/Melbourne"
|
||||
- CI_NODE_TOTAL=5
|
||||
matrix:
|
||||
- TEST_CASES="./spec/features/admin" GITHUB_DEPLOY="true"
|
||||
- TEST_CASES="./spec/features/consumer ./spec/serializers ./spec/performance"
|
||||
- TEST_CASES="./spec/models"
|
||||
- TEST_CASES="./spec/controllers ./spec/views ./spec/jobs"
|
||||
- TEST_CASES="./spec/requests ./spec/helpers ./spec/mailers ./spec/lib" KARMA="true"
|
||||
- CI_NODE_INDEX=0
|
||||
- CI_NODE_INDEX=1
|
||||
- CI_NODE_INDEX=2
|
||||
- CI_NODE_INDEX=3
|
||||
- CI_NODE_INDEX=4 KARMA="true" GITHUB_DEPLOY="true"
|
||||
|
||||
before_script:
|
||||
- cp config/database.travis.yml config/database.yml
|
||||
@@ -35,8 +36,9 @@ before_script:
|
||||
fi
|
||||
|
||||
script:
|
||||
- '[ "$KARMA" = "true" ] && bundle exec rake karma:run || echo "Skipping karma run"'
|
||||
- "bundle exec rspec $TEST_CASES"
|
||||
- 'if [ "$KARMA" = "true" ]; then bundle exec rake karma:run; else echo "Skipping karma run"; fi'
|
||||
#- "KNAPSACK_GENERATE_REPORT=true bundle exec rspec spec"
|
||||
- "bundle exec rake knapsack:rspec"
|
||||
|
||||
after_success:
|
||||
- >
|
||||
|
||||
1
Gemfile
1
Gemfile
@@ -105,6 +105,7 @@ group :test, :development do
|
||||
gem 'json_spec'
|
||||
gem 'unicorn-rails'
|
||||
gem 'atomic'
|
||||
gem 'knapsack'
|
||||
end
|
||||
|
||||
group :test do
|
||||
|
||||
@@ -122,7 +122,7 @@ GEM
|
||||
rack-test (~> 0.6.1)
|
||||
sprockets (~> 2.2.1)
|
||||
active_link_to (1.0.0)
|
||||
active_model_serializers (0.8.1)
|
||||
active_model_serializers (0.8.3)
|
||||
activemodel (>= 3.0)
|
||||
activemerchant (1.48.0)
|
||||
activesupport (>= 3.2.14, < 5.0.0)
|
||||
@@ -431,6 +431,9 @@ GEM
|
||||
actionpack (>= 3.0.0)
|
||||
activesupport (>= 3.0.0)
|
||||
kgio (2.9.3)
|
||||
knapsack (1.5.1)
|
||||
rake
|
||||
timecop (>= 0.1.0)
|
||||
launchy (2.1.2)
|
||||
addressable (~> 2.3)
|
||||
letter_opener (1.0.0)
|
||||
@@ -684,6 +687,7 @@ DEPENDENCIES
|
||||
immigrant
|
||||
jquery-rails
|
||||
json_spec
|
||||
knapsack
|
||||
letter_opener
|
||||
momentjs-rails
|
||||
newrelic_rpm
|
||||
|
||||
2
Rakefile
2
Rakefile
@@ -5,3 +5,5 @@
|
||||
require File.expand_path('../config/application', __FILE__)
|
||||
|
||||
Openfoodnetwork::Application.load_tasks
|
||||
|
||||
Knapsack.load_tasks if defined?(Knapsack)
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
//= require ./taxons/taxons
|
||||
//= require ./utils/utils
|
||||
//= require ./users/users
|
||||
//= require ./variant_overrides/variant_overrides
|
||||
//= require textAngular.min.js
|
||||
//= require textAngular-sanitize.min.js
|
||||
//= require ../shared/bindonce.min.js
|
||||
|
||||
@@ -352,6 +352,9 @@ filterSubmitVariant = (variant) ->
|
||||
filteredVariant = {}
|
||||
if not variant.deleted_at? and variant.hasOwnProperty("id")
|
||||
filteredVariant.id = variant.id unless variant.id <= 0
|
||||
if variant.hasOwnProperty("sku")
|
||||
filteredVariant.sku = variant.sku
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("on_hand")
|
||||
filteredVariant.on_hand = variant.on_hand
|
||||
hasUpdatableProperty = true
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
angular.module("ofn.admin").controller "AdminVariantOverridesCtrl", ($scope, $timeout, Indexer, SpreeApiAuth, PagedFetcher, StatusMessage, hubs, producers, hubPermissions, VariantOverrides, DirtyVariantOverrides) ->
|
||||
$scope.hubs = hubs
|
||||
$scope.hub = null
|
||||
$scope.products = []
|
||||
$scope.producers = Indexer.index producers
|
||||
$scope.hubPermissions = hubPermissions
|
||||
$scope.variantOverrides = VariantOverrides.variantOverrides
|
||||
$scope.StatusMessage = StatusMessage
|
||||
|
||||
$scope.initialise = ->
|
||||
SpreeApiAuth.authorise()
|
||||
.then ->
|
||||
$scope.spree_api_key_ok = true
|
||||
$scope.fetchProducts()
|
||||
.catch (message) ->
|
||||
$scope.api_error_msg = message
|
||||
|
||||
|
||||
$scope.fetchProducts = ->
|
||||
url = "/api/products/overridable?page=::page::;per_page=100"
|
||||
PagedFetcher.fetch url, (data) => $scope.addProducts data.products
|
||||
|
||||
|
||||
$scope.addProducts = (products) ->
|
||||
$scope.products = $scope.products.concat products
|
||||
VariantOverrides.ensureDataFor hubs, products
|
||||
|
||||
|
||||
$scope.selectHub = ->
|
||||
$scope.hub = (hub for hub in hubs when hub.id == $scope.hub_id)[0]
|
||||
|
||||
|
||||
$scope.displayDirty = ->
|
||||
if DirtyVariantOverrides.count() > 0
|
||||
num = if DirtyVariantOverrides.count() == 1 then "one override" else "#{DirtyVariantOverrides.count()} overrides"
|
||||
StatusMessage.display 'notice', "Changes to #{num} remain unsaved."
|
||||
else
|
||||
StatusMessage.clear()
|
||||
|
||||
|
||||
$scope.update = ->
|
||||
if DirtyVariantOverrides.count() == 0
|
||||
StatusMessage.display 'alert', 'No change to save '
|
||||
else
|
||||
StatusMessage.display 'progress', 'Saving...'
|
||||
DirtyVariantOverrides.save()
|
||||
.success (updatedVos) ->
|
||||
DirtyVariantOverrides.clear()
|
||||
VariantOverrides.updateIds updatedVos
|
||||
$timeout -> StatusMessage.display 'success', 'Changes saved.'
|
||||
.error (data, status) ->
|
||||
$timeout -> StatusMessage.display 'failure', $scope.updateError(data, status)
|
||||
|
||||
|
||||
$scope.updateError = (data, status) ->
|
||||
if status == 401
|
||||
"I couldn't get authorisation to save those changes, so they remain unsaved."
|
||||
|
||||
else if status == 400 && data.errors?
|
||||
errors = []
|
||||
for field, field_errors of data.errors
|
||||
errors = errors.concat field_errors
|
||||
errors = errors.join ', '
|
||||
"I had some trouble saving: #{errors}"
|
||||
|
||||
else
|
||||
"Oh no! I was unable to save your changes."
|
||||
@@ -1,8 +1,9 @@
|
||||
angular.module("admin.dropdown").directive "ofnDropDown", ($document) ->
|
||||
restrict: 'C'
|
||||
link: (scope, element, attrs) ->
|
||||
outsideClickListener = (event) ->
|
||||
unless $(event.target).is("div.ofn_drop_down##{attrs.id} div.menu") ||
|
||||
$(event.target).parents("div.ofn_drop_down##{attrs.id} div.menu").length > 0
|
||||
unless $(event.target).is("div.ofn-drop-down##{attrs.id} div.menu") ||
|
||||
$(event.target).parents("div.ofn-drop-down##{attrs.id} div.menu").length > 0
|
||||
scope.$emit "offClick"
|
||||
|
||||
element.click (event) ->
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
angular.module("admin.indexUtils").directive "ofnSelect2", ($timeout, blankOption) ->
|
||||
require: 'ngModel'
|
||||
restrict: 'C'
|
||||
scope:
|
||||
data: "="
|
||||
minSearch: "@?"
|
||||
text: "@?"
|
||||
blank: "=?"
|
||||
link: (scope, element, attrs, ngModel) ->
|
||||
$timeout ->
|
||||
scope.text ||= 'name'
|
||||
scope.data.unshift(scope.blank) if scope.blank? && typeof scope.blank is "object"
|
||||
element.select2
|
||||
minimumResultsForSearch: scope.minSearch || 0
|
||||
data: { results: scope.data, text: scope.text }
|
||||
initSelection: (element, callback) ->
|
||||
callback scope.data[0]
|
||||
formatSelection: (item) ->
|
||||
item[scope.text]
|
||||
formatResult: (item) ->
|
||||
item[scope.text]
|
||||
|
||||
attrs.$observe 'disabled', (value) ->
|
||||
element.select2('enable', !value)
|
||||
|
||||
ngModel.$formatters.push (value) ->
|
||||
element.select2('val', value)
|
||||
value
|
||||
@@ -1,7 +0,0 @@
|
||||
angular.module("admin.indexUtils").directive "saveBar", ->
|
||||
restrict: "E"
|
||||
scope:
|
||||
save: "&"
|
||||
saving: "&"
|
||||
dirty: "&"
|
||||
templateUrl: "admin/save_bar.html"
|
||||
@@ -0,0 +1,12 @@
|
||||
# Used like a regular angular filter where an object is passed
|
||||
# Adds the additional special case that a value of 0 for the filter
|
||||
# acts as a bypass for that particular attribute
|
||||
angular.module("admin.indexUtils").filter "attrFilter", ($filter) ->
|
||||
return (objects, filters) ->
|
||||
Object.keys(filters).reduce (filtered, attr) ->
|
||||
filter = filters[attr]
|
||||
return filtered if !filter? || filter == 0
|
||||
return $filter('filter')(filtered, (object) ->
|
||||
object[attr] == filter
|
||||
)
|
||||
, objects
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("ofn.admin").factory "dataFetcher", [
|
||||
angular.module("admin.indexUtils").factory "dataFetcher", [
|
||||
"$http", "$q"
|
||||
($http, $q) ->
|
||||
return (dataLocation) ->
|
||||
@@ -9,4 +9,4 @@ angular.module("ofn.admin").factory "dataFetcher", [
|
||||
deferred.reject()
|
||||
|
||||
deferred.promise
|
||||
]
|
||||
]
|
||||
@@ -4,7 +4,7 @@
|
||||
# Indexer.index producers
|
||||
# -> {1: {id: 1, name: 'one'}, 2: {id: 2, name: 'two'}}
|
||||
|
||||
angular.module("ofn.admin").factory 'Indexer', ->
|
||||
angular.module("admin.indexUtils").factory 'Indexer', ->
|
||||
new class Indexer
|
||||
index: (data, key='id') ->
|
||||
index = {}
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("ofn.admin").factory "PagedFetcher", (dataFetcher) ->
|
||||
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
|
||||
@@ -13,4 +13,4 @@ angular.module("ofn.admin").factory "PagedFetcher", (dataFetcher) ->
|
||||
processData data
|
||||
|
||||
urlForPage: (url, page) ->
|
||||
url.replace("::page::", page)
|
||||
url.replace("::page::", page)
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("ofn.admin").factory "SpreeApiAuth", ($q, $http, SpreeApiKey) ->
|
||||
angular.module("admin.indexUtils").factory "SpreeApiAuth", ($q, $http, SpreeApiKey) ->
|
||||
new class SpreeApiAuth
|
||||
authorise: ->
|
||||
deferred = $q.defer()
|
||||
@@ -1,7 +1,6 @@
|
||||
angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout, $http, $q, Columns, Dereferencer, Orders, LineItems, Enterprises, OrderCycles, blankOption, VariantUnitManager, RequestMonitor) ->
|
||||
angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout, $http, $q, StatusMessage, Columns, Dereferencer, Orders, LineItems, Enterprises, OrderCycles, blankOption, VariantUnitManager, RequestMonitor) ->
|
||||
$scope.initialized = false
|
||||
$scope.RequestMonitor = RequestMonitor
|
||||
$scope.saving = false
|
||||
$scope.filteredLineItems = []
|
||||
$scope.confirmDelete = true
|
||||
$scope.startDate = formatDate daysFromToday -7
|
||||
@@ -55,6 +54,7 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
Dereferencer.dereferenceAttr $scope.lineItems, "supplier", Enterprises.enterprisesByID
|
||||
Dereferencer.dereferenceAttr $scope.lineItems, "order", Orders.ordersByID
|
||||
$scope.bulk_order_form.$setPristine()
|
||||
StatusMessage.clear()
|
||||
unless $scope.initialized
|
||||
$scope.initialized = true
|
||||
$timeout ->
|
||||
@@ -62,16 +62,20 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
|
||||
$scope.refreshData()
|
||||
|
||||
$scope.submit = =>
|
||||
$scope.$watch 'bulk_order_form.$dirty', (newVal, oldVal) ->
|
||||
if newVal == true
|
||||
StatusMessage.display 'notice', "You have unsaved changes"
|
||||
|
||||
$scope.submit = ->
|
||||
if $scope.bulk_order_form.$valid
|
||||
$scope.saving = true
|
||||
StatusMessage.display 'progress', "Saving..."
|
||||
$q.all(LineItems.saveAll()).then(->
|
||||
StatusMessage.display 'success', "All changes saved"
|
||||
$scope.bulk_order_form.$setPristine()
|
||||
$scope.saving = false
|
||||
).catch ->
|
||||
alert "#{t("unsaved_changes_warning")}"
|
||||
StatusMessage.display 'failure', #{t("unsaved_changes_warning")}
|
||||
else
|
||||
alert "#{t("unsaved_changes_warning")}"
|
||||
StatusMessage.display 'failure', #{t("unsaved_changes_warning")}
|
||||
|
||||
$scope.deleteLineItem = (lineItem) ->
|
||||
if ($scope.confirmDelete && confirm(t("are_you_sure"))) || !$scope.confirmDelete
|
||||
|
||||
@@ -1 +1 @@
|
||||
angular.module("admin.lineItems", ["admin.indexUtils", "admin.products", "admin.orders", "admin.enterprises", "admin.orderCycles"])
|
||||
angular.module("admin.lineItems", ["admin.indexUtils", "admin.utils", "admin.products", "admin.orders", "admin.enterprises", "admin.orderCycles"])
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
angular.module('admin.orderCycles')
|
||||
.controller 'AdminCreateOrderCycleCtrl', ($scope, $filter, OrderCycle, Enterprise, EnterpriseFee, ocInstance, StatusMessage) ->
|
||||
$scope.enterprises = Enterprise.index(coordinator_id: ocInstance.coordinator_id)
|
||||
$scope.supplier_enterprises = Enterprise.producer_enterprises
|
||||
$scope.distributor_enterprises = Enterprise.hub_enterprises
|
||||
$scope.supplied_products = Enterprise.supplied_products
|
||||
$scope.enterprise_fees = EnterpriseFee.index(coordinator_id: ocInstance.coordinator_id)
|
||||
|
||||
$scope.OrderCycle = OrderCycle
|
||||
$scope.order_cycle = OrderCycle.new({ coordinator_id: ocInstance.coordinator_id})
|
||||
|
||||
$scope.StatusMessage = StatusMessage
|
||||
|
||||
$scope.loaded = ->
|
||||
Enterprise.loaded && EnterpriseFee.loaded
|
||||
|
||||
$scope.suppliedVariants = (enterprise_id) ->
|
||||
Enterprise.suppliedVariants(enterprise_id)
|
||||
|
||||
$scope.exchangeSelectedVariants = (exchange) ->
|
||||
OrderCycle.exchangeSelectedVariants(exchange)
|
||||
|
||||
$scope.setExchangeVariants = (exchange, variants, selected) ->
|
||||
OrderCycle.setExchangeVariants(exchange, variants, selected)
|
||||
|
||||
$scope.enterpriseTotalVariants = (enterprise) ->
|
||||
Enterprise.totalVariants(enterprise)
|
||||
|
||||
$scope.productSuppliedToOrderCycle = (product) ->
|
||||
OrderCycle.productSuppliedToOrderCycle(product)
|
||||
|
||||
$scope.variantSuppliedToOrderCycle = (variant) ->
|
||||
OrderCycle.variantSuppliedToOrderCycle(variant)
|
||||
|
||||
$scope.incomingExchangeVariantsFor = (enterprise_id) ->
|
||||
$filter('filterExchangeVariants')(OrderCycle.incomingExchangesVariants(), $scope.order_cycle.visible_variants_for_outgoing_exchanges[enterprise_id])
|
||||
|
||||
$scope.exchangeDirection = (exchange) ->
|
||||
OrderCycle.exchangeDirection(exchange)
|
||||
|
||||
$scope.enterprisesWithFees = ->
|
||||
$scope.enterprises[id] for id in OrderCycle.participatingEnterpriseIds() when $scope.enterpriseFeesForEnterprise(id).length > 0
|
||||
|
||||
$scope.toggleProducts = ($event, exchange) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.toggleProducts(exchange)
|
||||
|
||||
$scope.enterpriseFeesForEnterprise = (enterprise_id) ->
|
||||
EnterpriseFee.forEnterprise(parseInt(enterprise_id))
|
||||
|
||||
$scope.addSupplier = ($event) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.addSupplier($scope.new_supplier_id)
|
||||
|
||||
$scope.addDistributor = ($event) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.addDistributor($scope.new_distributor_id)
|
||||
|
||||
$scope.removeExchange = ($event, exchange) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.removeExchange(exchange)
|
||||
|
||||
$scope.addCoordinatorFee = ($event) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.addCoordinatorFee()
|
||||
|
||||
$scope.removeCoordinatorFee = ($event, index) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.removeCoordinatorFee(index)
|
||||
|
||||
$scope.addExchangeFee = ($event, exchange) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.addExchangeFee(exchange)
|
||||
|
||||
$scope.removeExchangeFee = ($event, exchange, index) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.removeExchangeFee(exchange, index)
|
||||
|
||||
$scope.removeDistributionOfVariant = (variant_id) ->
|
||||
OrderCycle.removeDistributionOfVariant(variant_id)
|
||||
|
||||
$scope.submit = (destination) ->
|
||||
OrderCycle.create(destination)
|
||||
@@ -0,0 +1,84 @@
|
||||
angular.module('admin.orderCycles')
|
||||
.controller 'AdminEditOrderCycleCtrl', ($scope, $filter, $location, OrderCycle, Enterprise, EnterpriseFee, StatusMessage) ->
|
||||
order_cycle_id = $location.absUrl().match(/\/admin\/order_cycles\/(\d+)/)[1]
|
||||
$scope.enterprises = Enterprise.index(order_cycle_id: order_cycle_id)
|
||||
$scope.supplier_enterprises = Enterprise.producer_enterprises
|
||||
$scope.distributor_enterprises = Enterprise.hub_enterprises
|
||||
$scope.supplied_products = Enterprise.supplied_products
|
||||
$scope.enterprise_fees = EnterpriseFee.index(order_cycle_id: order_cycle_id)
|
||||
|
||||
$scope.OrderCycle = OrderCycle
|
||||
$scope.order_cycle = OrderCycle.load(order_cycle_id)
|
||||
|
||||
$scope.StatusMessage = StatusMessage
|
||||
|
||||
$scope.loaded = ->
|
||||
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded
|
||||
|
||||
$scope.suppliedVariants = (enterprise_id) ->
|
||||
Enterprise.suppliedVariants(enterprise_id)
|
||||
|
||||
$scope.exchangeSelectedVariants = (exchange) ->
|
||||
OrderCycle.exchangeSelectedVariants(exchange)
|
||||
|
||||
$scope.setExchangeVariants = (exchange, variants, selected) ->
|
||||
OrderCycle.setExchangeVariants(exchange, variants, selected)
|
||||
|
||||
$scope.enterpriseTotalVariants = (enterprise) ->
|
||||
Enterprise.totalVariants(enterprise)
|
||||
|
||||
$scope.productSuppliedToOrderCycle = (product) ->
|
||||
OrderCycle.productSuppliedToOrderCycle(product)
|
||||
|
||||
$scope.variantSuppliedToOrderCycle = (variant) ->
|
||||
OrderCycle.variantSuppliedToOrderCycle(variant)
|
||||
|
||||
$scope.incomingExchangeVariantsFor = (enterprise_id) ->
|
||||
$filter('filterExchangeVariants')(OrderCycle.incomingExchangesVariants(), $scope.order_cycle.visible_variants_for_outgoing_exchanges[enterprise_id])
|
||||
|
||||
$scope.exchangeDirection = (exchange) ->
|
||||
OrderCycle.exchangeDirection(exchange)
|
||||
|
||||
$scope.enterprisesWithFees = ->
|
||||
$scope.enterprises[id] for id in OrderCycle.participatingEnterpriseIds() when $scope.enterpriseFeesForEnterprise(id).length > 0
|
||||
|
||||
$scope.toggleProducts = ($event, exchange) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.toggleProducts(exchange)
|
||||
|
||||
$scope.enterpriseFeesForEnterprise = (enterprise_id) ->
|
||||
EnterpriseFee.forEnterprise(parseInt(enterprise_id))
|
||||
|
||||
$scope.addSupplier = ($event) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.addSupplier($scope.new_supplier_id)
|
||||
|
||||
$scope.addDistributor = ($event) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.addDistributor($scope.new_distributor_id)
|
||||
|
||||
$scope.removeExchange = ($event, exchange) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.removeExchange(exchange)
|
||||
|
||||
$scope.addCoordinatorFee = ($event) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.addCoordinatorFee()
|
||||
|
||||
$scope.removeCoordinatorFee = ($event, index) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.removeCoordinatorFee(index)
|
||||
|
||||
$scope.addExchangeFee = ($event, exchange) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.addExchangeFee(exchange)
|
||||
|
||||
$scope.removeExchangeFee = ($event, exchange, index) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.removeExchangeFee(exchange, index)
|
||||
|
||||
$scope.removeDistributionOfVariant = (variant_id) ->
|
||||
OrderCycle.removeDistributionOfVariant(variant_id)
|
||||
|
||||
$scope.submit = (destination) ->
|
||||
OrderCycle.update(destination)
|
||||
@@ -1,204 +0,0 @@
|
||||
angular.module('admin.orderCycles', ['ngResource', 'admin.utils'])
|
||||
.controller('AdminCreateOrderCycleCtrl', ['$scope', '$filter', 'OrderCycle', 'Enterprise', 'EnterpriseFee', 'ocInstance', 'StatusMessage', ($scope, $filter, OrderCycle, Enterprise, EnterpriseFee, ocInstance, StatusMessage) ->
|
||||
$scope.enterprises = Enterprise.index(coordinator_id: ocInstance.coordinator_id)
|
||||
$scope.supplier_enterprises = Enterprise.producer_enterprises
|
||||
$scope.distributor_enterprises = Enterprise.hub_enterprises
|
||||
$scope.supplied_products = Enterprise.supplied_products
|
||||
$scope.enterprise_fees = EnterpriseFee.index(coordinator_id: ocInstance.coordinator_id)
|
||||
|
||||
$scope.OrderCycle = OrderCycle
|
||||
$scope.order_cycle = OrderCycle.new({ coordinator_id: ocInstance.coordinator_id})
|
||||
|
||||
$scope.StatusMessage = StatusMessage
|
||||
|
||||
$scope.loaded = ->
|
||||
Enterprise.loaded && EnterpriseFee.loaded
|
||||
|
||||
$scope.suppliedVariants = (enterprise_id) ->
|
||||
Enterprise.suppliedVariants(enterprise_id)
|
||||
|
||||
$scope.exchangeSelectedVariants = (exchange) ->
|
||||
OrderCycle.exchangeSelectedVariants(exchange)
|
||||
|
||||
$scope.setExchangeVariants = (exchange, variants, selected) ->
|
||||
OrderCycle.setExchangeVariants(exchange, variants, selected)
|
||||
|
||||
$scope.enterpriseTotalVariants = (enterprise) ->
|
||||
Enterprise.totalVariants(enterprise)
|
||||
|
||||
$scope.productSuppliedToOrderCycle = (product) ->
|
||||
OrderCycle.productSuppliedToOrderCycle(product)
|
||||
|
||||
$scope.variantSuppliedToOrderCycle = (variant) ->
|
||||
OrderCycle.variantSuppliedToOrderCycle(variant)
|
||||
|
||||
$scope.incomingExchangeVariantsFor = (enterprise_id) ->
|
||||
$filter('filterExchangeVariants')(OrderCycle.incomingExchangesVariants(), $scope.order_cycle.visible_variants_for_outgoing_exchanges[enterprise_id])
|
||||
|
||||
$scope.exchangeDirection = (exchange) ->
|
||||
OrderCycle.exchangeDirection(exchange)
|
||||
|
||||
$scope.enterprisesWithFees = ->
|
||||
$scope.enterprises[id] for id in OrderCycle.participatingEnterpriseIds() when $scope.enterpriseFeesForEnterprise(id).length > 0
|
||||
|
||||
$scope.toggleProducts = ($event, exchange) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.toggleProducts(exchange)
|
||||
|
||||
$scope.enterpriseFeesForEnterprise = (enterprise_id) ->
|
||||
EnterpriseFee.forEnterprise(parseInt(enterprise_id))
|
||||
|
||||
$scope.addSupplier = ($event) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.addSupplier($scope.new_supplier_id)
|
||||
|
||||
$scope.addDistributor = ($event) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.addDistributor($scope.new_distributor_id)
|
||||
|
||||
$scope.removeExchange = ($event, exchange) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.removeExchange(exchange)
|
||||
|
||||
$scope.addCoordinatorFee = ($event) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.addCoordinatorFee()
|
||||
|
||||
$scope.removeCoordinatorFee = ($event, index) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.removeCoordinatorFee(index)
|
||||
|
||||
$scope.addExchangeFee = ($event, exchange) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.addExchangeFee(exchange)
|
||||
|
||||
$scope.removeExchangeFee = ($event, exchange, index) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.removeExchangeFee(exchange, index)
|
||||
|
||||
$scope.removeDistributionOfVariant = (variant_id) ->
|
||||
OrderCycle.removeDistributionOfVariant(variant_id)
|
||||
|
||||
$scope.submit = (destination) ->
|
||||
OrderCycle.create(destination)
|
||||
])
|
||||
|
||||
.controller('AdminEditOrderCycleCtrl', ['$scope', '$filter', '$location', 'OrderCycle', 'Enterprise', 'EnterpriseFee', 'StatusMessage', ($scope, $filter, $location, OrderCycle, Enterprise, EnterpriseFee, StatusMessage) ->
|
||||
order_cycle_id = $location.absUrl().match(/\/admin\/order_cycles\/(\d+)/)[1]
|
||||
$scope.enterprises = Enterprise.index(order_cycle_id: order_cycle_id)
|
||||
$scope.supplier_enterprises = Enterprise.producer_enterprises
|
||||
$scope.distributor_enterprises = Enterprise.hub_enterprises
|
||||
$scope.supplied_products = Enterprise.supplied_products
|
||||
$scope.enterprise_fees = EnterpriseFee.index(order_cycle_id: order_cycle_id)
|
||||
|
||||
$scope.OrderCycle = OrderCycle
|
||||
$scope.order_cycle = OrderCycle.load(order_cycle_id)
|
||||
|
||||
$scope.StatusMessage = StatusMessage
|
||||
|
||||
$scope.loaded = ->
|
||||
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded
|
||||
|
||||
$scope.suppliedVariants = (enterprise_id) ->
|
||||
Enterprise.suppliedVariants(enterprise_id)
|
||||
|
||||
$scope.exchangeSelectedVariants = (exchange) ->
|
||||
OrderCycle.exchangeSelectedVariants(exchange)
|
||||
|
||||
$scope.setExchangeVariants = (exchange, variants, selected) ->
|
||||
OrderCycle.setExchangeVariants(exchange, variants, selected)
|
||||
|
||||
$scope.enterpriseTotalVariants = (enterprise) ->
|
||||
Enterprise.totalVariants(enterprise)
|
||||
|
||||
$scope.productSuppliedToOrderCycle = (product) ->
|
||||
OrderCycle.productSuppliedToOrderCycle(product)
|
||||
|
||||
$scope.variantSuppliedToOrderCycle = (variant) ->
|
||||
OrderCycle.variantSuppliedToOrderCycle(variant)
|
||||
|
||||
$scope.incomingExchangeVariantsFor = (enterprise_id) ->
|
||||
$filter('filterExchangeVariants')(OrderCycle.incomingExchangesVariants(), $scope.order_cycle.visible_variants_for_outgoing_exchanges[enterprise_id])
|
||||
|
||||
$scope.exchangeDirection = (exchange) ->
|
||||
OrderCycle.exchangeDirection(exchange)
|
||||
|
||||
$scope.enterprisesWithFees = ->
|
||||
$scope.enterprises[id] for id in OrderCycle.participatingEnterpriseIds() when $scope.enterpriseFeesForEnterprise(id).length > 0
|
||||
|
||||
$scope.toggleProducts = ($event, exchange) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.toggleProducts(exchange)
|
||||
|
||||
$scope.enterpriseFeesForEnterprise = (enterprise_id) ->
|
||||
EnterpriseFee.forEnterprise(parseInt(enterprise_id))
|
||||
|
||||
$scope.addSupplier = ($event) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.addSupplier($scope.new_supplier_id)
|
||||
|
||||
$scope.addDistributor = ($event) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.addDistributor($scope.new_distributor_id)
|
||||
|
||||
$scope.removeExchange = ($event, exchange) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.removeExchange(exchange)
|
||||
|
||||
$scope.addCoordinatorFee = ($event) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.addCoordinatorFee()
|
||||
|
||||
$scope.removeCoordinatorFee = ($event, index) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.removeCoordinatorFee(index)
|
||||
|
||||
$scope.addExchangeFee = ($event, exchange) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.addExchangeFee(exchange)
|
||||
|
||||
$scope.removeExchangeFee = ($event, exchange, index) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.removeExchangeFee(exchange, index)
|
||||
|
||||
$scope.removeDistributionOfVariant = (variant_id) ->
|
||||
OrderCycle.removeDistributionOfVariant(variant_id)
|
||||
|
||||
$scope.submit = (destination) ->
|
||||
OrderCycle.update(destination)
|
||||
])
|
||||
|
||||
.config(['$httpProvider', ($httpProvider) ->
|
||||
$httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content')
|
||||
])
|
||||
|
||||
.directive('datetimepicker', ['$parse', ($parse) ->
|
||||
(scope, element, attrs) ->
|
||||
# using $parse instead of scope[attrs.datetimepicker] for cases
|
||||
# where attrs.datetimepicker is 'foo.bar.lol'
|
||||
$(element).datetimepicker
|
||||
dateFormat: 'yy-mm-dd'
|
||||
timeFormat: 'HH:mm:ss'
|
||||
showOn: "button"
|
||||
buttonImage: "<%= asset_path 'datepicker/cal.gif' %>"
|
||||
buttonImageOnly: true
|
||||
stepMinute: 15
|
||||
onSelect: (dateText, inst) ->
|
||||
scope.$apply ->
|
||||
parsed = $parse(attrs.datetimepicker)
|
||||
parsed.assign(scope, dateText)
|
||||
])
|
||||
|
||||
.directive('ofnOnChange', ->
|
||||
(scope, element, attrs) ->
|
||||
element.bind 'change', ->
|
||||
scope.$apply(attrs.ofnOnChange)
|
||||
)
|
||||
|
||||
.directive('ofnSyncDistributions', ->
|
||||
(scope, element, attrs) ->
|
||||
element.bind 'change', ->
|
||||
if !$(this).is(':checked')
|
||||
scope.$apply ->
|
||||
scope.removeDistributionOfVariant(attrs.ofnSyncDistributions)
|
||||
)
|
||||
@@ -1 +1,32 @@
|
||||
angular.module('admin.orderCycles', ['ngResource', 'admin.indexUtils'])
|
||||
angular.module('admin.orderCycles', ['ngResource', 'admin.utils', 'admin.indexUtils'])
|
||||
|
||||
.config ($httpProvider) ->
|
||||
$httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content')
|
||||
|
||||
.directive 'datetimepicker', ($parse) ->
|
||||
(scope, element, attrs) ->
|
||||
# using $parse instead of scope[attrs.datetimepicker] for cases
|
||||
# where attrs.datetimepicker is 'foo.bar.lol'
|
||||
$(element).datetimepicker
|
||||
dateFormat: 'yy-mm-dd'
|
||||
timeFormat: 'HH:mm:ss'
|
||||
showOn: "button"
|
||||
buttonImage: "<%= asset_path 'datepicker/cal.gif' %>"
|
||||
buttonImageOnly: true
|
||||
stepMinute: 15
|
||||
onSelect: (dateText, inst) ->
|
||||
scope.$apply ->
|
||||
parsed = $parse(attrs.datetimepicker)
|
||||
parsed.assign(scope, dateText)
|
||||
|
||||
.directive 'ofnOnChange', ->
|
||||
(scope, element, attrs) ->
|
||||
element.bind 'change', ->
|
||||
scope.$apply(attrs.ofnOnChange)
|
||||
|
||||
.directive 'ofnSyncDistributions', ->
|
||||
(scope, element, attrs) ->
|
||||
element.bind 'change', ->
|
||||
if !$(this).is(':checked')
|
||||
scope.$apply ->
|
||||
scope.removeDistributionOfVariant(attrs.ofnSyncDistributions)
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
angular.module("ofn.admin").factory "StatusMessage", ($timeout) ->
|
||||
new class StatusMessage
|
||||
types:
|
||||
progress: {timeout: false, style: {color: '#ff9906'}}
|
||||
alert: {timeout: 5000, style: {color: 'grey'}}
|
||||
notice: {timeout: false, style: {color: 'grey'}}
|
||||
success: {timeout: 5000, style: {color: '#9fc820'}}
|
||||
failure: {timeout: false, style: {color: '#da5354'}}
|
||||
|
||||
statusMessage:
|
||||
text: ""
|
||||
style: {}
|
||||
|
||||
display: (type, text) ->
|
||||
@statusMessage.text = text
|
||||
@statusMessage.style = @types[type].style
|
||||
$timeout.cancel @statusMessage.timeout if @statusMessage.timeout
|
||||
timeout = @types[type].timeout
|
||||
if timeout
|
||||
@statusMessage.timeout = $timeout =>
|
||||
@clear()
|
||||
, timeout, true
|
||||
|
||||
clear: ->
|
||||
@statusMessage.text = ''
|
||||
@statusMessage.style = {}
|
||||
@@ -1,23 +0,0 @@
|
||||
angular.module("ofn.admin").factory "VariantOverrides", (variantOverrides, Indexer) ->
|
||||
new class VariantOverrides
|
||||
variantOverrides: {}
|
||||
|
||||
constructor: ->
|
||||
for vo in variantOverrides
|
||||
@variantOverrides[vo.hub_id] ||= {}
|
||||
@variantOverrides[vo.hub_id][vo.variant_id] = vo
|
||||
|
||||
ensureDataFor: (hubs, products) ->
|
||||
for hub in hubs
|
||||
@variantOverrides[hub.id] ||= {}
|
||||
for product in products
|
||||
for variant in product.variants
|
||||
@variantOverrides[hub.id][variant.id] ||=
|
||||
variant_id: variant.id
|
||||
hub_id: hub.id
|
||||
price: ''
|
||||
count_on_hand: ''
|
||||
|
||||
updateIds: (updatedVos) ->
|
||||
for vo in updatedVos
|
||||
@variantOverrides[vo.hub_id][vo.variant_id].id = vo.id
|
||||
@@ -0,0 +1,8 @@
|
||||
angular.module("admin.utils").directive "saveBar", (StatusMessage) ->
|
||||
restrict: "E"
|
||||
scope:
|
||||
save: "&"
|
||||
form: "="
|
||||
templateUrl: "admin/save_bar.html"
|
||||
link: (scope, element, attrs) ->
|
||||
scope.StatusMessage = StatusMessage
|
||||
@@ -11,6 +11,9 @@ angular.module("admin.utils").factory "StatusMessage", ($timeout) ->
|
||||
text: ""
|
||||
style: {}
|
||||
|
||||
active: ->
|
||||
@statusMessage.text != ''
|
||||
|
||||
display: (type, text) ->
|
||||
@statusMessage.text = text
|
||||
@statusMessage.style = @types[type].style
|
||||
@@ -20,6 +23,7 @@ angular.module("admin.utils").factory "StatusMessage", ($timeout) ->
|
||||
@statusMessage.timeout = $timeout =>
|
||||
@clear()
|
||||
, timeout, true
|
||||
null # So we don't return weird timeouts
|
||||
|
||||
clear: ->
|
||||
@statusMessage.text = ''
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
angular.module("admin.variantOverrides").controller "AdminVariantOverridesCtrl", ($scope, $http, $timeout, Indexer, Columns, SpreeApiAuth, PagedFetcher, StatusMessage, hubs, producers, hubPermissions, VariantOverrides, DirtyVariantOverrides) ->
|
||||
$scope.hubs = Indexer.index hubs
|
||||
$scope.hub = null
|
||||
$scope.products = []
|
||||
$scope.producers = producers
|
||||
$scope.producersByID = Indexer.index producers
|
||||
$scope.hubPermissions = hubPermissions
|
||||
$scope.variantOverrides = VariantOverrides.variantOverrides
|
||||
$scope.StatusMessage = StatusMessage
|
||||
|
||||
$scope.columns = Columns.setColumns
|
||||
producer: { name: "Producer", visible: true }
|
||||
product: { name: "Product", visible: true }
|
||||
sku: { name: "SKU", visible: false }
|
||||
price: { name: "Price", visible: true }
|
||||
on_hand: { name: "On Hand", visible: true }
|
||||
on_demand: { name: "On Demand", visible: false }
|
||||
reset: { name: "Reset Stock Level", visible: false }
|
||||
inheritance: { name: "Inheritance", visible: false }
|
||||
|
||||
$scope.resetSelectFilters = ->
|
||||
$scope.producerFilter = 0
|
||||
$scope.query = ''
|
||||
|
||||
$scope.resetSelectFilters()
|
||||
|
||||
$scope.initialise = ->
|
||||
SpreeApiAuth.authorise()
|
||||
.then ->
|
||||
$scope.spree_api_key_ok = true
|
||||
$scope.fetchProducts()
|
||||
.catch (message) ->
|
||||
$scope.api_error_msg = message
|
||||
|
||||
|
||||
$scope.fetchProducts = ->
|
||||
url = "/api/products/overridable?page=::page::;per_page=100"
|
||||
PagedFetcher.fetch url, (data) => $scope.addProducts data.products
|
||||
|
||||
|
||||
$scope.addProducts = (products) ->
|
||||
$scope.products = $scope.products.concat products
|
||||
VariantOverrides.ensureDataFor hubs, products
|
||||
|
||||
|
||||
$scope.selectHub = ->
|
||||
$scope.hub = $scope.hubs[$scope.hub_id]
|
||||
|
||||
$scope.displayDirty = ->
|
||||
if DirtyVariantOverrides.count() > 0
|
||||
num = if DirtyVariantOverrides.count() == 1 then "one override" else "#{DirtyVariantOverrides.count()} overrides"
|
||||
StatusMessage.display 'notice', "Changes to #{num} remain unsaved."
|
||||
else
|
||||
StatusMessage.clear()
|
||||
|
||||
$scope.update = ->
|
||||
if DirtyVariantOverrides.count() == 0
|
||||
StatusMessage.display 'alert', 'No changes to save.'
|
||||
else
|
||||
StatusMessage.display 'progress', 'Saving...'
|
||||
DirtyVariantOverrides.save()
|
||||
.success (updatedVos) ->
|
||||
DirtyVariantOverrides.clear()
|
||||
VariantOverrides.updateIds updatedVos
|
||||
$scope.variant_overrides_form.$setPristine()
|
||||
StatusMessage.display 'success', 'Changes saved.'
|
||||
VariantOverrides.updateData updatedVos # Refresh page data
|
||||
.error (data, status) ->
|
||||
StatusMessage.display 'failure', $scope.updateError(data, status)
|
||||
|
||||
|
||||
$scope.updateError = (data, status) ->
|
||||
if status == 401
|
||||
"I couldn't get authorisation to save those changes, so they remain unsaved."
|
||||
|
||||
else if status == 400 && data.errors?
|
||||
errors = []
|
||||
for field, field_errors of data.errors
|
||||
errors = errors.concat field_errors
|
||||
errors = errors.join ', '
|
||||
"I had some trouble saving: #{errors}"
|
||||
else
|
||||
"Oh no! I was unable to save your changes."
|
||||
|
||||
$scope.resetStock = ->
|
||||
if DirtyVariantOverrides.count() > 0
|
||||
StatusMessage.display 'alert', 'Save changes first.'
|
||||
$timeout ->
|
||||
$scope.displayDirty()
|
||||
, 3000 # 3 second delay
|
||||
else
|
||||
return unless $scope.hub_id?
|
||||
StatusMessage.display 'progress', 'Changing on hand stock levels...'
|
||||
$http
|
||||
method: "POST"
|
||||
url: "/admin/variant_overrides/bulk_reset"
|
||||
data: { hub_id: $scope.hub_id }
|
||||
.success (updatedVos) ->
|
||||
VariantOverrides.updateData updatedVos
|
||||
StatusMessage.display 'success', 'Stocks reset to defaults.'
|
||||
.error (data, status) ->
|
||||
$timeout -> StatusMessage.display 'failure', $scope.updateError(data, status)
|
||||
@@ -0,0 +1,12 @@
|
||||
angular.module("admin.variantOverrides").directive "trackInheritance", (VariantOverrides, DirtyVariantOverrides) ->
|
||||
require: "ngModel"
|
||||
link: (scope, element, attrs, ngModel) ->
|
||||
# This is a bit hacky, but it allows us to load the inherit property on the VO, but then not submit it
|
||||
scope.inherit = angular.equals scope.variantOverrides[scope.hub.id][scope.variant.id], VariantOverrides.newFor scope.hub.id, scope.variant.id
|
||||
|
||||
ngModel.$parsers.push (viewValue) ->
|
||||
if ngModel.$dirty && viewValue
|
||||
variantOverride = VariantOverrides.inherit(scope.hub.id, scope.variant.id)
|
||||
DirtyVariantOverrides.add variantOverride
|
||||
scope.displayDirty()
|
||||
viewValue
|
||||
@@ -1,9 +1,10 @@
|
||||
angular.module("ofn.admin").directive "ofnTrackVariantOverride", (DirtyVariantOverrides) ->
|
||||
angular.module("admin.variantOverrides").directive "ofnTrackVariantOverride", (DirtyVariantOverrides) ->
|
||||
require: "ngModel"
|
||||
link: (scope, element, attrs, ngModel) ->
|
||||
ngModel.$parsers.push (viewValue) ->
|
||||
if ngModel.$dirty
|
||||
variantOverride = scope.variantOverrides[scope.hub.id][scope.variant.id]
|
||||
scope.inherit = false
|
||||
DirtyVariantOverrides.add variantOverride
|
||||
scope.displayDirty()
|
||||
viewValue
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("ofn.admin").filter "hubPermissions", ($filter) ->
|
||||
angular.module("admin.variantOverrides").filter "hubPermissions", ($filter) ->
|
||||
return (products, hubPermissions, hub_id) ->
|
||||
return [] if !hub_id
|
||||
return $filter('filter')(products, ((product) -> hubPermissions[hub_id].indexOf(product.producer_id) > -1), true)
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("ofn.admin").factory "DirtyVariantOverrides", ($http) ->
|
||||
angular.module("admin.variantOverrides").factory "DirtyVariantOverrides", ($http) ->
|
||||
new class DirtyVariantOverrides
|
||||
dirtyVariantOverrides: {}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
angular.module("admin.variantOverrides").factory "VariantOverrides", (variantOverrides) ->
|
||||
new class VariantOverrides
|
||||
variantOverrides: {}
|
||||
|
||||
constructor: ->
|
||||
for vo in variantOverrides
|
||||
@variantOverrides[vo.hub_id] ||= {}
|
||||
@variantOverrides[vo.hub_id][vo.variant_id] = vo
|
||||
|
||||
ensureDataFor: (hubs, products) ->
|
||||
for hub_id, hub of hubs
|
||||
@variantOverrides[hub.id] ||= {}
|
||||
for product in products
|
||||
for variant in product.variants
|
||||
@inherit(hub.id, variant.id) unless @variantOverrides[hub.id][variant.id]
|
||||
|
||||
inherit: (hub_id, variant_id) ->
|
||||
# This method is called from the trackInheritance directive, to reinstate inheritance
|
||||
@variantOverrides[hub_id][variant_id] ||= {}
|
||||
angular.extend @variantOverrides[hub_id][variant_id], @newFor hub_id, variant_id
|
||||
|
||||
newFor: (hub_id, variant_id) ->
|
||||
# These properties need to match those checked in VariantOverrideSet.deletable?
|
||||
hub_id: hub_id
|
||||
variant_id: variant_id
|
||||
sku: null
|
||||
price: null
|
||||
count_on_hand: null
|
||||
on_demand: null
|
||||
default_stock: null
|
||||
resettable: false
|
||||
|
||||
updateIds: (updatedVos) ->
|
||||
for vo in updatedVos
|
||||
@variantOverrides[vo.hub_id][vo.variant_id].id = vo.id
|
||||
|
||||
updateData: (updatedVos) ->
|
||||
for vo in updatedVos
|
||||
@variantOverrides[vo.hub_id][vo.variant_id] = vo
|
||||
@@ -0,0 +1 @@
|
||||
angular.module("admin.variantOverrides", ["pasvaz.bindonce", "admin.indexUtils", "admin.utils", "admin.dropdown"])
|
||||
@@ -2,8 +2,11 @@ Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http, storage)->
|
||||
# Handles syncing of current cart/order state to server
|
||||
new class Cart
|
||||
dirty: false
|
||||
update_running: false
|
||||
update_enqueued: false
|
||||
order: CurrentOrder.order
|
||||
line_items: CurrentOrder.order?.line_items || []
|
||||
|
||||
constructor: ->
|
||||
for line_item in @line_items
|
||||
line_item.variant.line_item = line_item
|
||||
@@ -12,15 +15,31 @@ Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http, storage)->
|
||||
|
||||
orderChanged: =>
|
||||
@unsaved()
|
||||
|
||||
if !@update_running
|
||||
@scheduleUpdate()
|
||||
else
|
||||
@update_enqueued = true
|
||||
|
||||
scheduleUpdate: =>
|
||||
if @promise
|
||||
$timeout.cancel(@promise)
|
||||
@promise = $timeout @update, 1000
|
||||
|
||||
update: =>
|
||||
@update_running = true
|
||||
$http.post('/orders/populate', @data()).success (data, status)=>
|
||||
@saved()
|
||||
@update_running = false
|
||||
@popQueue() if @update_enqueued
|
||||
|
||||
.error (response, status)=>
|
||||
@scheduleRetry()
|
||||
@scheduleRetry(status)
|
||||
@update_running = false
|
||||
|
||||
popQueue: =>
|
||||
@update_enqueued = false
|
||||
@scheduleUpdate()
|
||||
|
||||
data: =>
|
||||
variants = {}
|
||||
@@ -30,7 +49,7 @@ Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http, storage)->
|
||||
max_quantity: li.max_quantity
|
||||
{variants: variants}
|
||||
|
||||
scheduleRetry: =>
|
||||
scheduleRetry: (status) =>
|
||||
console.log "Error updating cart: #{status}. Retrying in 3 seconds..."
|
||||
$timeout =>
|
||||
console.log "Retrying cart update"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.ofn_drop_down{ "ofn-drop-down" => true }
|
||||
.ofn-drop-down
|
||||
%span
|
||||
%i.icon-check
|
||||
Actions
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
#save-bar.animate-show{ ng: { show: 'dirty()' } }
|
||||
#save-bar.animate-show{ ng: { show: 'form.$dirty || StatusMessage.active()' } }
|
||||
.twelve.columns.alpha
|
||||
%h5{ ng: { show: "dirty() && !saving()" } }
|
||||
You have unsaved changes
|
||||
%h5{ ng: { hide: "dirty() || saving()" } }
|
||||
All changes saved
|
||||
%h5{ ng: { show: "saving()" } }
|
||||
Saving...
|
||||
%h5#status-message{ ng: { style: 'StatusMessage.statusMessage.style' } }
|
||||
{{ StatusMessage.statusMessage.text || " " }}
|
||||
.four.columns.omega.text-right
|
||||
%input.red{type: "button", value: "Save Changes", ng: { click: "save()" } }
|
||||
%input.red{type: "button", value: "Save Changes", ng: { disabled: '!form.$dirty', click: "save()" } }
|
||||
|
||||
13
app/assets/stylesheets/admin/disabled.css.scss
Normal file
13
app/assets/stylesheets/admin/disabled.css.scss
Normal file
@@ -0,0 +1,13 @@
|
||||
label.disabled {
|
||||
color: #c3c3c3;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
input[type='button']:disabled {
|
||||
background-color: #c3c3c3;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.select2-container-disabled {
|
||||
pointer-events: none;
|
||||
}
|
||||
70
app/assets/stylesheets/admin/dropdown.css.scss
Normal file
70
app/assets/stylesheets/admin/dropdown.css.scss
Normal file
@@ -0,0 +1,70 @@
|
||||
#content-header .ofn-drop-down {
|
||||
border: none;
|
||||
background-color: #5498da;
|
||||
color: #fff;
|
||||
float: none;
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.ofn-drop-down:hover, .ofn-drop-down.expanded {
|
||||
border: 1px solid #adadad;
|
||||
color: #575757;
|
||||
}
|
||||
|
||||
.ofn-drop-down {
|
||||
padding: 7px 15px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #d4d4d4;
|
||||
background-color: #f5f5f5;
|
||||
position: relative;
|
||||
display: block;
|
||||
float: left;
|
||||
color: #828282;
|
||||
cursor: pointer;
|
||||
-moz-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
text-align: center;
|
||||
|
||||
&.right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
&:hover, &.expanded {
|
||||
border: 1px solid #adadad;
|
||||
color: #575757;
|
||||
}
|
||||
|
||||
> span {
|
||||
width: auto;
|
||||
text-transform: uppercase;
|
||||
font-size: 85%;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.menu {
|
||||
margin-top: 1px;
|
||||
position: absolute;
|
||||
float: none;
|
||||
top:100%;
|
||||
left: 0px;
|
||||
padding: 5px 0px;
|
||||
border: 1px solid #adadad;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 1px 3px 10px #888888;
|
||||
z-index: 100;
|
||||
|
||||
.menu_item {
|
||||
margin: 0px;
|
||||
padding: 2px 0px;
|
||||
color: #454545;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.menu_item:hover {
|
||||
background-color: #ededed;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
.filters, .controls, .divider {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
@@ -184,68 +184,6 @@ table#listing_enterprise_groups {
|
||||
}
|
||||
}
|
||||
|
||||
#content-header .ofn_drop_down {
|
||||
border: none;
|
||||
background-color: #5498da;
|
||||
color: #fff;
|
||||
float: none;
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.ofn_drop_down {
|
||||
padding: 6px 15px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #d4d4d4;
|
||||
background-color: #f5f5f5;
|
||||
position: relative;
|
||||
display: block;
|
||||
float: left;
|
||||
color: #828282;
|
||||
cursor: pointer;
|
||||
-moz-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
text-align: center;
|
||||
|
||||
> span {
|
||||
width: auto;
|
||||
text-transform: uppercase;
|
||||
font-size: 85%;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.menu {
|
||||
margin-top: 1px;
|
||||
position: absolute;
|
||||
float: none;
|
||||
top:100%;
|
||||
left: 0px;
|
||||
padding: 5px 0px;
|
||||
border: 1px solid #adadad;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 1px 3px 10px #888888;
|
||||
z-index: 100;
|
||||
|
||||
.menu_item {
|
||||
margin: 0px;
|
||||
padding: 2px 0px;
|
||||
color: #454545;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.menu_item:hover {
|
||||
background-color: #ededed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ofn_drop_down:hover, .ofn_drop_down.expanded {
|
||||
border: 1px solid #adadad;
|
||||
color: #575757;
|
||||
}
|
||||
|
||||
.field_with_errors > input {
|
||||
border-color: red;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
.filter_select, .date_filter {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
input, div {
|
||||
&.update-pending {
|
||||
border: solid 1px orange;
|
||||
|
||||
@@ -13,6 +13,11 @@
|
||||
right: 10px
|
||||
top: 55px
|
||||
width: 480px
|
||||
|
||||
@media screen and (min-width: 641px)
|
||||
overflow-y: auto
|
||||
max-height: calc(95vh - 55px)
|
||||
|
||||
@media screen and (max-width: 640px)
|
||||
width: 96%
|
||||
|
||||
@@ -48,7 +53,7 @@
|
||||
.cart-item-delete
|
||||
a.delete
|
||||
font-size: 1.125em
|
||||
|
||||
|
||||
.item-thumb-image
|
||||
display: none
|
||||
@media screen and (min-width: 640px)
|
||||
|
||||
@@ -89,7 +89,7 @@ module Admin
|
||||
end
|
||||
|
||||
def collection_actions
|
||||
[:index, :for_order_cycle]
|
||||
[:index, :for_order_cycle, :bulk_update]
|
||||
end
|
||||
|
||||
def current_enterprise
|
||||
|
||||
@@ -175,5 +175,9 @@ module Admin
|
||||
def ams_prefix_whitelist
|
||||
[:basic]
|
||||
end
|
||||
|
||||
def collection_actions
|
||||
[:index, :bulk_update]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,32 +4,43 @@ module Admin
|
||||
class VariantOverridesController < ResourceController
|
||||
include OpenFoodNetwork::SpreeApiKeyLoader
|
||||
|
||||
prepend_before_filter :load_data
|
||||
before_filter :load_collection, only: [:bulk_update]
|
||||
before_filter :load_spree_api_key, only: :index
|
||||
before_filter :load_data
|
||||
|
||||
|
||||
def index
|
||||
end
|
||||
|
||||
|
||||
def bulk_update
|
||||
collection_hash = Hash[params[:variant_overrides].each_with_index.map { |vo, i| [i, vo] }]
|
||||
vo_set = VariantOverrideSet.new @variant_overrides, collection_attributes: collection_hash
|
||||
|
||||
# Ensure we're authorised to update all variant overrides
|
||||
vo_set.collection.each { |vo| authorize! :update, vo }
|
||||
@vo_set.collection.each { |vo| authorize! :update, vo }
|
||||
|
||||
if vo_set.save
|
||||
if @vo_set.save
|
||||
# Return saved VOs with IDs
|
||||
render json: vo_set.collection, each_serializer: Api::Admin::VariantOverrideSerializer
|
||||
render json: @vo_set.collection, each_serializer: Api::Admin::VariantOverrideSerializer
|
||||
else
|
||||
if vo_set.errors.present?
|
||||
render json: { errors: vo_set.errors }, status: 400
|
||||
if @vo_set.errors.present?
|
||||
render json: { errors: @vo_set.errors }, status: 400
|
||||
else
|
||||
render nothing: true, status: 500
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def bulk_reset
|
||||
# Ensure we're authorised to update all variant overrides.
|
||||
@collection.each { |vo| authorize! :bulk_reset, vo }
|
||||
@collection.each(&:reset_stock!)
|
||||
|
||||
if collection_errors.present?
|
||||
render json: { errors: collection_errors }, status: 400
|
||||
else
|
||||
render json: @collection, each_serializer: Api::Admin::VariantOverrideSerializer
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
@@ -43,10 +54,28 @@ module Admin
|
||||
|
||||
@hub_permissions = OpenFoodNetwork::Permissions.new(spree_current_user).
|
||||
variant_override_enterprises_per_hub
|
||||
@variant_overrides = VariantOverride.for_hubs(@hubs)
|
||||
end
|
||||
|
||||
def load_collection
|
||||
collection_hash = Hash[params[:variant_overrides].each_with_index.map { |vo, i| [i, vo] }]
|
||||
@vo_set = VariantOverrideSet.new @variant_overrides, collection_attributes: collection_hash
|
||||
end
|
||||
|
||||
def collection
|
||||
@variant_overrides = VariantOverride.for_hubs(params[:hub_id] || @hubs)
|
||||
end
|
||||
|
||||
def collection_actions
|
||||
[:index, :bulk_update, :bulk_reset]
|
||||
end
|
||||
|
||||
# This has been pulled from ModelSet as it is useful for compiling a list of errors on any generic collection (not necessarily a ModelSet)
|
||||
# Could be pulled down into a lower level controller if it is useful in other high level controllers
|
||||
def collection_errors
|
||||
errors = ActiveModel::Errors.new self
|
||||
full_messages = @collection.map { |element| element.errors.full_messages }.flatten
|
||||
full_messages.each { |fm| errors.add(:base, fm) }
|
||||
errors
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -23,13 +23,23 @@ Spree::OrdersController.class_eval do
|
||||
end
|
||||
|
||||
def populate
|
||||
populator = Spree::OrderPopulator.new(current_order(true), current_currency)
|
||||
if populator.populate(params.slice(:products, :variants, :quantity), true)
|
||||
fire_event('spree.cart.add')
|
||||
fire_event('spree.order.contents_changed')
|
||||
render json: true, status: 200
|
||||
else
|
||||
render json: false, status: 402
|
||||
# Without intervention, the Spree::Adjustment#update_adjustable callback is called many times
|
||||
# during cart population, for both taxation and enterprise fees. This operation triggers a
|
||||
# costly Spree::Order#update!, which only needs to be run once. We avoid this by disabling
|
||||
# callbacks on Spree::Adjustment and then manually invoke Spree::Order#update! on success.
|
||||
|
||||
Spree::Adjustment.without_callbacks do
|
||||
populator = Spree::OrderPopulator.new(current_order(true), current_currency)
|
||||
if populator.populate(params.slice(:products, :variants, :quantity), true)
|
||||
fire_event('spree.cart.add')
|
||||
fire_event('spree.order.contents_changed')
|
||||
|
||||
current_order.update!
|
||||
|
||||
render json: true, status: 200
|
||||
else
|
||||
render json: false, status: 402
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -31,12 +31,12 @@ module Admin
|
||||
admin_inject_json_ams_array ngModule, "shops", @shops, Api::Admin::IdNameSerializer
|
||||
end
|
||||
|
||||
def admin_inject_hubs
|
||||
admin_inject_json_ams_array "ofn.admin", "hubs", @hubs, Api::Admin::IdNameSerializer
|
||||
def admin_inject_hubs(opts={module: 'ofn.admin'})
|
||||
admin_inject_json_ams_array opts[:module], "hubs", @hubs, Api::Admin::IdNameSerializer
|
||||
end
|
||||
|
||||
def admin_inject_producers
|
||||
admin_inject_json_ams_array "ofn.admin", "producers", @producers, Api::Admin::IdNameSerializer
|
||||
def admin_inject_producers(opts={module: 'ofn.admin'})
|
||||
admin_inject_json_ams_array opts[:module], "producers", @producers, Api::Admin::IdNameSerializer
|
||||
end
|
||||
|
||||
def admin_inject_enterprise_permissions
|
||||
@@ -49,7 +49,7 @@ module Admin
|
||||
end
|
||||
|
||||
def admin_inject_hub_permissions
|
||||
render partial: "admin/json/injection_ams", locals: {ngModule: "ofn.admin", name: "hubPermissions", json: @hub_permissions.to_json}
|
||||
render partial: "admin/json/injection_ams", locals: {ngModule: "admin.variantOverrides", name: "hubPermissions", json: @hub_permissions.to_json}
|
||||
end
|
||||
|
||||
def admin_inject_products
|
||||
@@ -69,7 +69,7 @@ module Admin
|
||||
end
|
||||
|
||||
def admin_inject_variant_overrides
|
||||
admin_inject_json_ams_array "ofn.admin", "variantOverrides", @variant_overrides, Api::Admin::VariantOverrideSerializer
|
||||
admin_inject_json_ams_array "admin.variantOverrides", "variantOverrides", @variant_overrides, Api::Admin::VariantOverrideSerializer
|
||||
end
|
||||
|
||||
def admin_inject_order_cycle_instance
|
||||
@@ -85,7 +85,7 @@ module Admin
|
||||
end
|
||||
|
||||
def admin_inject_spree_api_key
|
||||
render partial: "admin/json/injection_ams", locals: {ngModule: 'ofn.admin', name: 'SpreeApiKey', json: "'#{@spree_api_key.to_s}'"}
|
||||
render partial: "admin/json/injection_ams", locals: {ngModule: 'admin.indexUtils', name: 'SpreeApiKey', json: "'#{@spree_api_key.to_s}'"}
|
||||
end
|
||||
|
||||
def admin_inject_json_ams(ngModule, name, data, serializer, opts = {})
|
||||
|
||||
@@ -10,4 +10,4 @@ Spree::BaseMailer.class_eval do
|
||||
# This lets us specify assets using relative paths in email templates
|
||||
super.merge(url_options: {host: URI(spree.root_url).host })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -16,8 +16,8 @@ class ModelSet
|
||||
end
|
||||
end
|
||||
|
||||
def collection_attributes=(attributes)
|
||||
attributes.each do |k, attributes|
|
||||
def collection_attributes=(collection_attributes)
|
||||
collection_attributes.each do |k, attributes|
|
||||
# attributes == {:id => 123, :next_collection_at => '...'}
|
||||
e = @collection.detect { |e| e.id.to_s == attributes[:id].to_s && !e.id.nil? }
|
||||
if e.nil?
|
||||
@@ -41,7 +41,11 @@ class ModelSet
|
||||
end
|
||||
|
||||
def collection_to_delete
|
||||
collection.select { |e| @delete_if.andand.call(e.attributes) }
|
||||
# Remove all elements to be deleted from collection and return them
|
||||
# Allows us to render @model_set.collection without deleted elements
|
||||
deleted = []
|
||||
collection.delete_if { |e| deleted << e if @delete_if.andand.call(e.attributes) }
|
||||
deleted
|
||||
end
|
||||
|
||||
def collection_to_keep
|
||||
@@ -51,5 +55,4 @@ class ModelSet
|
||||
def persisted?
|
||||
false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -66,7 +66,7 @@ class AbilityDecorator
|
||||
def add_enterprise_management_abilities(user)
|
||||
# Spree performs authorize! on (:create, nil) when creating a new order from admin, and also (:search, nil)
|
||||
# when searching for variants to add to the order
|
||||
can [:create, :search, :bulk_update], nil
|
||||
can [:create, :search], nil
|
||||
|
||||
can [:admin, :index], :overview
|
||||
|
||||
@@ -111,7 +111,9 @@ class AbilityDecorator
|
||||
OpenFoodNetwork::Permissions.new(user).managed_product_enterprises.include? variant.product.supplier
|
||||
end
|
||||
|
||||
can [:admin, :index, :read, :update, :bulk_update], VariantOverride do |vo|
|
||||
can [:admin, :index, :read, :update, :bulk_update, :bulk_reset], VariantOverride do |vo|
|
||||
next false unless vo.hub.present? && vo.variant.andand.product.andand.supplier.present?
|
||||
|
||||
hub_auth = OpenFoodNetwork::Permissions.new(user).
|
||||
variant_override_hubs.
|
||||
include? vo.hub
|
||||
|
||||
@@ -35,5 +35,19 @@ module Spree
|
||||
def display_included_tax
|
||||
Spree::Money.new(included_tax, { :currency => currency })
|
||||
end
|
||||
|
||||
def self.without_callbacks
|
||||
skip_callback :save, :after, :update_adjustable
|
||||
skip_callback :destroy, :after, :update_adjustable
|
||||
|
||||
result = yield
|
||||
|
||||
ensure
|
||||
set_callback :save, :after, :update_adjustable
|
||||
set_callback :destroy, :after, :update_adjustable
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,6 +3,8 @@ class VariantOverride < ActiveRecord::Base
|
||||
belongs_to :variant, class_name: 'Spree::Variant'
|
||||
|
||||
validates_presence_of :hub_id, :variant_id
|
||||
# Default stock can be nil, indicating stock should not be reset or zero, meaning reset to zero. Need to ensure this can be set by the user.
|
||||
validates :default_stock, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
|
||||
|
||||
scope :for_hubs, lambda { |hubs|
|
||||
where(hub_id: hubs)
|
||||
@@ -49,6 +51,21 @@ class VariantOverride < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def default_stock?
|
||||
default_stock.present?
|
||||
end
|
||||
|
||||
def reset_stock!
|
||||
if resettable
|
||||
if default_stock?
|
||||
self.attributes = { count_on_hand: default_stock }
|
||||
self.save
|
||||
else
|
||||
Bugsnag.notify RuntimeError.new "Attempting to reset stock level for a variant with no default stock level."
|
||||
end
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
class VariantOverrideSet < ModelSet
|
||||
def initialize(collection, attributes={})
|
||||
super(VariantOverride, collection, attributes, nil,
|
||||
proc { |attrs| attrs['price'].blank? && attrs['count_on_hand'].blank? } )
|
||||
super(VariantOverride, collection, attributes, nil, proc { |attrs| deletable?(attrs) } )
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def deletable?(attrs)
|
||||
attrs['price'].blank? &&
|
||||
attrs['count_on_hand'].blank? &&
|
||||
attrs['default_stock'].blank? &&
|
||||
attrs['resettable'].blank? &&
|
||||
attrs['sku'].nil? &&
|
||||
attrs['on_demand'].nil?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Api::Admin::ExchangeSerializer < ActiveModel::Serializer
|
||||
attributes :id, :sender_id, :receiver_id, :incoming, :variants, :pickup_time, :pickup_instructions
|
||||
attributes :id, :sender_id, :receiver_id, :incoming, :variants, :receival_instructions, :pickup_time, :pickup_instructions
|
||||
|
||||
has_many :enterprise_fees, serializer: Api::Admin::BasicEnterpriseFeeSerializer
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
class Api::Admin::VariantOverrideSerializer < ActiveModel::Serializer
|
||||
attributes :id, :hub_id, :variant_id, :price, :count_on_hand
|
||||
attributes :id, :hub_id, :variant_id, :sku, :price, :count_on_hand, :on_demand, :default_stock, :resettable
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Api::Admin::VariantSerializer < ActiveModel::Serializer
|
||||
attributes :id, :options_text, :unit_value, :unit_description, :unit_to_display, :on_demand, :display_as, :display_name, :name_to_display
|
||||
attributes :id, :options_text, :unit_value, :unit_description, :unit_to_display, :on_demand, :display_as, :display_name, :name_to_display, :sku
|
||||
attributes :on_hand, :price
|
||||
has_many :variant_overrides
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Api::LineItemSerializer < ActiveModel::Serializer
|
||||
attributes :id, :quantity, :price
|
||||
attributes :id, :quantity, :max_quantity, :price
|
||||
|
||||
has_one :variant, serializer: Api::VariantSerializer
|
||||
end
|
||||
|
||||
@@ -14,25 +14,13 @@
|
||||
.seven.columns.omega
|
||||
|
||||
.row{ 'ng-hide' => '!loaded() || filteredCustomers.length == 0' }
|
||||
.controls{ :class => "sixteen columns alpha", :style => "margin-bottom: 15px;" }
|
||||
.controls.sixteen.columns.alpha.omega
|
||||
.five.columns.alpha
|
||||
%input{ :class => "fullwidth", :type => "text", :id => 'quick_search', 'ng-model' => 'quickSearch', :placeholder => 'Quick Search' }
|
||||
%input.fullwidth{ :type => "text", :id => 'quick_search', 'ng-model' => 'quickSearch', :placeholder => 'Quick Search' }
|
||||
.five.columns
|
||||
-# %div.ofn_drop_down{ 'ng-controller' => "DropDownCtrl", :id => "bulk_actions_dropdown", 'ofn-drop-down' => true }
|
||||
-# %span{ :class => 'icon-check' } Actions
|
||||
-# %span{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" }
|
||||
-# %div.menu{ 'ng-show' => "expanded" }
|
||||
-# %div.menu_item{ :class => "three columns alpha", 'ng-repeat' => "action in bulkActions", 'ng-click' => "selectedBulkAction.callback(filteredCustomers)", 'ofn-close-on-click' => true }
|
||||
-# %span{ :class => 'three columns omega' } {{action.name }}
|
||||
-# =render 'admin/shared/bulk_actions_dropdown'
|
||||
.three.columns
|
||||
.three.columns.omega
|
||||
%div.ofn_drop_down{ 'ng-controller' => "DropDownCtrl", :id => "columns_dropdown", 'ofn-drop-down' => true, :style => 'float:right;' }
|
||||
%span{ :class => 'icon-reorder' } Columns
|
||||
%span{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" }
|
||||
%div.menu{ 'ng-show' => "expanded" }
|
||||
%div.menu_item{ :class => "three columns alpha", 'ng-repeat' => "column in columns", 'ofn-toggle-column' => true }
|
||||
%span{ :class => 'one column alpha', :style => 'text-align: center'} {{ column.visible && "✓" || !column.visible && " " }}
|
||||
%span{ :class => 'two columns omega' } {{column.name }}
|
||||
= render 'admin/shared/columns_dropdown'
|
||||
.row{ 'ng-if' => 'shop && !loaded()' }
|
||||
.sixteen.columns.alpha#loading
|
||||
%img.spinner{ src: "/assets/spinning-circles.svg" }
|
||||
|
||||
@@ -4,21 +4,9 @@
|
||||
.four.columns.alpha
|
||||
%input{ :class => "fullwidth", :type => "text", :id => 'quick_search', 'ng-model' => 'quickSearch', :placeholder => 'Search By Name' }
|
||||
.six.columns
|
||||
-# %div.ofn_drop_down{ 'ng-controller' => "DropDownCtrl", :id => "bulk_actions_dropdown", 'ofn-drop-down' => true }
|
||||
-# %span{ :class => 'icon-check' } Actions
|
||||
-# %span{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" }
|
||||
-# %div.menu{ 'ng-show' => "expanded" }
|
||||
-# %div.menu_item{ :class => "three columns alpha", 'ng-repeat' => "action in bulkActions", 'ng-click' => "selectedBulkAction.callback(filteredEnterprises)", 'ofn-close-on-click' => true }
|
||||
-# %span{ :class => 'three columns omega' } {{action.name }}
|
||||
-# = render 'admin/shared/bulk_actions_dropdown'
|
||||
.three.columns
|
||||
.three.columns.omega
|
||||
%div.ofn_drop_down{ 'ng-controller' => "DropDownCtrl", :id => "columns_dropdown", 'ofn-drop-down' => true, :style => 'float:right;' }
|
||||
%span{ :class => 'icon-reorder' } Columns
|
||||
%span{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" }
|
||||
%div.menu{ 'ng-show' => "expanded" }
|
||||
%div.menu_item{ :class => "three columns alpha", 'ng-repeat' => "column in columns", 'ofn-toggle-column' => true }
|
||||
%span{ :class => 'one column alpha', :style => 'text-align: center'} {{ column.visible && "✓" || !column.visible && " " }}
|
||||
%span{ :class => 'two columns omega' } {{column.name }}
|
||||
= render 'admin/shared/columns_dropdown'
|
||||
.row{ 'ng-if' => '!loaded' }
|
||||
.sixteen.columns.alpha#loading
|
||||
%img.spinner{ src: "/assets/spinning-circles.svg" }
|
||||
|
||||
7
app/views/admin/shared/_bulk_actions_dropdown.html.haml
Normal file
7
app/views/admin/shared/_bulk_actions_dropdown.html.haml
Normal file
@@ -0,0 +1,7 @@
|
||||
.three.columns
|
||||
.ofn-drop-down#bulk-actions-dropdown{ 'ng-controller' => "DropDownCtrl" }
|
||||
%span.icon-check Actions
|
||||
%span{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" }
|
||||
%div.menu{ 'ng-show' => "expanded" }
|
||||
.three.columns.alpha.menu_item{ 'ng-repeat' => "action in bulkActions", 'ng-click' => "$eval(action.callback)(filteredLineItems)", 'ofn-close-on-click' => true }
|
||||
%span.three.columns.omega {{action.name }}
|
||||
8
app/views/admin/shared/_columns_dropdown.html.haml
Normal file
8
app/views/admin/shared/_columns_dropdown.html.haml
Normal file
@@ -0,0 +1,8 @@
|
||||
%div.three.columns.omega
|
||||
%div.ofn-drop-down.right#columns-dropdown{ 'ng-controller' => "DropDownCtrl" }
|
||||
%span{ :class => 'icon-reorder' } Columns
|
||||
%span{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" }
|
||||
%div.menu{ 'ng-show' => "expanded" }
|
||||
%div.menu_item.three.columns.alpha.omega{ 'ng-repeat' => "column in columns", 'ofn-toggle-column' => true }
|
||||
%span.one.column.alpha.text-center {{ column.visible && "✓" || !column.visible && " " }}
|
||||
%span.two.columns.omega {{column.name }}
|
||||
@@ -1,4 +0,0 @@
|
||||
.row
|
||||
%input.four.columns.alpha{type: 'button', value: t(:save_changes), 'ng-click' => 'update()'}
|
||||
.twelve.columns.omega
|
||||
= render 'spree/admin/shared/status_message'
|
||||
@@ -1,5 +1,5 @@
|
||||
= admin_inject_spree_api_key
|
||||
= admin_inject_hubs
|
||||
= admin_inject_hubs module: 'admin.variantOverrides'
|
||||
= admin_inject_hub_permissions
|
||||
= admin_inject_producers
|
||||
= admin_inject_producers module: 'admin.variantOverrides'
|
||||
= admin_inject_variant_overrides
|
||||
|
||||
26
app/views/admin/variant_overrides/_filters.html.haml
Normal file
26
app/views/admin/variant_overrides/_filters.html.haml
Normal file
@@ -0,0 +1,26 @@
|
||||
.filters.sixteen.columns.alpha
|
||||
.filter.four.columns.alpha
|
||||
%label{ :for => 'query', ng: {class: '{disabled: !hub.id}'} }Quick Search
|
||||
%br
|
||||
%input.fullwidth{ :type => "text", :id => 'query', ng: { model: 'query', disabled: '!hub.id'} }
|
||||
.two.columns
|
||||
.filter_select.four.columns
|
||||
%label{ :for => 'hub_id', ng: { bind: 'hub_id ? "Shop" : "Select a shop"' } }
|
||||
%br
|
||||
%select.select2.fullwidth#hub_id{ 'ng-model' => 'hub_id', name: 'hub_id', ng: { options: 'hub.id as hub.name for (id, hub) in hubs', change: 'selectHub()' } }
|
||||
.filter_select.four.columns
|
||||
%label{ :for => 'producer_filter', ng: {class: '{disabled: !hub.id}'} }Producer
|
||||
%br
|
||||
%input.ofn-select2.fullwidth{ :id => 'producer_filter', type: 'number', style: 'display:none', data: 'producers', blank: "{id: 0, name: 'All'}", ng: { model: 'producerFilter', disabled: '!hub.id' } }
|
||||
-# .filter_select{ :class => "three columns" }
|
||||
-# %label{ :for => 'distributor_filter' }Hub
|
||||
-# %br
|
||||
-# %select{ :class => "three columns alpha", :id => 'distributor_filter', 'select2-min-search' => 5, 'ng-model' => 'distributorFilter', 'ng-options' => 'd.id as d.name for d in distributors'}
|
||||
-# .filter_select{ :class => "three columns" }
|
||||
-# %label{ :for => 'order_cycle_filter' }Order Cycle
|
||||
-# %br
|
||||
-# %select{ :class => "three columns alpha", :id => 'order_cycle_filter', 'select2-min-search' => 5, 'ng-model' => 'orderCycleFilter', 'ng-options' => 'oc.id as oc.name for oc in orderCycles', 'confirm-change' => "confirmRefresh()", 'ng-change' => 'refreshData()'}
|
||||
.filter_clear.two.columns.omega
|
||||
%label{ :for => 'clear_all_filters' }
|
||||
%br
|
||||
%input.red.fullwidth{ :type => 'button', :id => 'clear_all_filters', :value => "Clear All", ng: { click: "resetSelectFilters()", disabled: '!hub.id'} }
|
||||
@@ -1,7 +0,0 @@
|
||||
.row
|
||||
.two.columns.alpha
|
||||
=t :hub
|
||||
.four.columns
|
||||
%select.select2.fullwidth#hub_id{ 'ng-model' => 'hub_id', name: 'hub_id', 'ng-options' => 'hub.id as hub.name for hub in hubs' }
|
||||
.ten.columns.omega
|
||||
%input{ type: 'button', value: t(:go), 'ng-click' => 'selectHub()' }
|
||||
@@ -1,14 +1,23 @@
|
||||
%table.index.bulk{ng: {show: 'hub'}}
|
||||
%table.index.bulk{ ng: {show: 'hub'}}
|
||||
%col.producer{ width: "20%", ng: { show: 'columns.producer.visible' } }
|
||||
%col.product{ width: "20%", ng: { show: 'columns.product.visible' } }
|
||||
%col.sku{ width: "20%", ng: { show: 'columns.sku.visible' } }
|
||||
%col.price{ width: "10%", ng: { show: 'columns.price.visible' } }
|
||||
%col.on_hand{ width: "10%", ng: { show: 'columns.on_hand.visible' } }
|
||||
%col.on_demand{ width: "10%", ng: { show: 'columns.on_demand.visible' } }
|
||||
%col.reset{ width: "1%", ng: { show: 'columns.reset.visible' } }
|
||||
%col.reset{ width: "15%", ng: { show: 'columns.reset.visible' } }
|
||||
%col.inheritance{ width: "5%", ng: { show: 'columns.inheritance.visible' } }
|
||||
%thead
|
||||
%tr
|
||||
%th
|
||||
= t(:producer)
|
||||
%th
|
||||
= t(:product)
|
||||
%th
|
||||
= t(:price)
|
||||
%th
|
||||
= t(:on_hand)
|
||||
%tbody{ng: {repeat: 'product in products | hubPermissions:hubPermissions:hub.id'}}
|
||||
%tr{ ng: { controller: "ColumnsCtrl" } }
|
||||
%th.producer{ ng: { show: 'columns.producer.visible' } } = t(:producer)
|
||||
%th.product{ ng: { show: 'columns.product.visible' } } = t(:product)
|
||||
%th.sku{ ng: { show: 'columns.sku.visible' } } SKU
|
||||
%th.price{ ng: { show: 'columns.price.visible' } } = t(:price)
|
||||
%th.on_hand{ ng: { show: 'columns.on_hand.visible' } } = t(:on_hand)
|
||||
%th.on_demand{ ng: { show: 'columns.on_demand.visible' } } On Demand?
|
||||
%th.reset{ colspan: 2, ng: { show: 'columns.reset.visible' } } Enable Stock Level Reset?
|
||||
%th.inheritance{ ng: { show: 'columns.inheritance.visible' } } Inherit?
|
||||
%tbody{bindonce: true, ng: {repeat: 'product in products | hubPermissions:hubPermissions:hub.id | attrFilter:{producer_id:producerFilter} | filter:query' } }
|
||||
= render 'admin/variant_overrides/products_product'
|
||||
= render 'admin/variant_overrides/products_variants'
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
%tr.product.even
|
||||
%td {{ producers[product.producer_id].name }}
|
||||
%td {{ product.name }}
|
||||
%td
|
||||
%td
|
||||
%td.producer{ ng: { show: 'columns.producer.visible' }, bo: { bind: 'producersByID[product.producer_id].name'} }
|
||||
%td.product{ ng: { show: 'columns.product.visible' }, bo: { bind: 'product.name'} }
|
||||
%td.sku{ ng: { show: 'columns.sku.visible' } }
|
||||
%td.price{ ng: { show: 'columns.price.visible' } }
|
||||
%td.on_hand{ ng: { show: 'columns.on_hand.visible' } }
|
||||
%td.on_demand{ ng: { show: 'columns.on_demand.visible' } }
|
||||
%td.reset{ colspan: 2, ng: { show: 'columns.reset.visible' } }
|
||||
%td.inheritance{ ng: { show: 'columns.inheritance.visible' } }
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
%tr.variant{ng: {repeat: 'variant in product.variants'}}
|
||||
%td
|
||||
%td
|
||||
{{ variant.display_name }}
|
||||
.variant-override-unit {{ variant.unit_to_display }}
|
||||
%td
|
||||
%tr.variant{ id: "v_{{variant.id}}", ng: {repeat: 'variant in product.variants'}}
|
||||
%td.producer{ ng: { show: 'columns.producer.visible' } }
|
||||
%td.product{ ng: { show: 'columns.product.visible' } }
|
||||
%span{ bo: { bind: 'variant.display_name || ""'} }
|
||||
.variant-override-unit{ bo: { bind: 'variant.unit_to_display'} }
|
||||
%td.sku{ ng: { show: 'columns.sku.visible' } }
|
||||
%input{name: 'variant-overrides-{{ variant.id }}-sku', type: 'text', ng: {model: 'variantOverrides[hub.id][variant.id].sku'}, placeholder: '{{ variant.sku }}', 'ofn-track-variant-override' => 'sku'}
|
||||
%td.price{ ng: { show: 'columns.price.visible' } }
|
||||
%input{name: 'variant-overrides-{{ variant.id }}-price', type: 'text', ng: {model: 'variantOverrides[hub.id][variant.id].price'}, placeholder: '{{ variant.price }}', 'ofn-track-variant-override' => 'price'}
|
||||
|
||||
%td
|
||||
%input{name: 'variant-overrides-{{ variant.id }}-count-on-hand', type: 'text', ng: {model: 'variantOverrides[hub.id][variant.id].count_on_hand'}, placeholder: '{{ variant.on_hand }}', 'ofn-track-variant-override' => 'price'}
|
||||
%td.on_hand{ ng: { show: 'columns.on_hand.visible' } }
|
||||
%input{name: 'variant-overrides-{{ variant.id }}-count_on_hand', type: 'text', ng: {model: 'variantOverrides[hub.id][variant.id].count_on_hand'}, placeholder: '{{ variant.on_hand }}', 'ofn-track-variant-override' => 'count_on_hand'}
|
||||
%td.on_demand{ ng: { show: 'columns.on_demand.visible' } }
|
||||
%input.field{ :type => 'checkbox', name: 'variant-overrides-{{ variant.id }}-on_demand', ng: { model: 'variantOverrides[hub.id][variant.id].on_demand' }, 'ofn-track-variant-override' => 'on_demand' }
|
||||
%td.reset{ ng: { show: 'columns.reset.visible' } }
|
||||
%input{name: 'variant-overrides-{{ variant.id }}-resettable', type: 'checkbox', ng: {model: 'variantOverrides[hub.id][variant.id].resettable'}, placeholder: '{{ variant.resettable }}', 'ofn-track-variant-override' => 'resettable'}
|
||||
%td.reset{ ng: { show: 'columns.reset.visible' } }
|
||||
%input{name: 'variant-overrides-{{ variant.id }}-default_stock', type: 'text', ng: {model: 'variantOverrides[hub.id][variant.id].default_stock'}, placeholder: '{{ variant.default_stock ? variant.default_stock : "Default stock"}}', 'ofn-track-variant-override' => 'default_stock'}
|
||||
%td.inheritance{ ng: { show: 'columns.inheritance.visible' } }
|
||||
%input.field{ :type => 'checkbox', name: 'variant-overrides-{{ variant.id }}-inherit', ng: { model: 'inherit' }, 'track-inheritance' => true }
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
= render 'admin/variant_overrides/header'
|
||||
= render 'admin/variant_overrides/data'
|
||||
|
||||
%div{ ng: { app: 'ofn.admin', controller: 'AdminVariantOverridesCtrl', init: 'initialise()' } }
|
||||
= render 'admin/variant_overrides/hub_choice'
|
||||
%div{ ng: { app: 'admin.variantOverrides', controller: 'AdminVariantOverridesCtrl', init: 'initialise()' } }
|
||||
= render 'admin/variant_overrides/filters'
|
||||
%hr.divider.sixteen.columns.alpha.omega{ ng: { show: 'hub' } }
|
||||
.controls.sixteen.columns.alpha.omega{ ng: { show: 'hub' } }
|
||||
%input.four.columns.alpha{ type: 'button', value: 'Reset Stock to Defaults', 'ng-click' => 'resetStock()' }
|
||||
%div.nine.columns.alpha
|
||||
= render 'admin/shared/columns_dropdown'
|
||||
|
||||
%div{ng: {show: 'hub'}}
|
||||
%h2 {{ hub.name }}
|
||||
= render 'admin/variant_overrides/actions'
|
||||
|
||||
= render 'admin/variant_overrides/products'
|
||||
%form{ name: 'variant_overrides_form' }
|
||||
%save-bar{ save: "update()", form: "variant_overrides_form" }
|
||||
= render 'admin/variant_overrides/products'
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
- content_for(:title) do
|
||||
= current_distributor.name
|
||||
- content_for(:description) do
|
||||
= current_distributor.description
|
||||
- content_for(:image) do
|
||||
= current_distributor.logo.url
|
||||
|
||||
= inject_enterprises
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
- content_for(:title) do
|
||||
= @group.name
|
||||
- content_for(:description) do
|
||||
= @group.description
|
||||
- content_for(:image) do
|
||||
= @group.logo.url
|
||||
|
||||
-# inject all enterprises as "enterprises"
|
||||
-# it could be more efficient to inject only the enterprises that are related to the group
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
%head
|
||||
%meta{charset: 'utf-8'}/
|
||||
%meta{name: 'viewport', content: "width=device-width,initial-scale=1.0"}/
|
||||
|
||||
%meta{property: "og:title", content: content_for?(:title) ? yield(:title) : t(:title)}
|
||||
%meta{property: "og:description", content: content_for?(:description) ? yield(:description) : t(:description)}
|
||||
%meta{property: "og:image", content: content_for?(:image) ? yield(:image) : ContentConfig.logo.url}
|
||||
%title= content_for?(:title) ? "#{yield(:title)} - #{t(:title)}".html_safe : "#{t(:welcome_to)} #{t(:title)}"
|
||||
- if Rails.env.production?
|
||||
= favicon_link_tag
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
= render :partial => 'spree/admin/shared/order_sub_menu'
|
||||
|
||||
%div{ ng: { app: 'admin.lineItems', controller: 'LineItemsCtrl' } }
|
||||
%save-bar{ save: "submit()", saving: 'saving', dirty: "bulk_order_form.$dirty" }
|
||||
%save-bar{ save: "submit()", form: "bulk_order_form" }
|
||||
.filters{ :class => "sixteen columns alpha" }
|
||||
.date_filter{ :class => "two columns alpha" }
|
||||
%label{ :for => 'start_date_filter' }
|
||||
@@ -38,8 +38,10 @@
|
||||
%label{ :for => 'clear_all_filters' }
|
||||
%br
|
||||
%input.red.fullwidth{ :type => 'button', :id => 'clear_all_filters', :value => "Clear All", 'ng-click' => "resetSelectFilters()" }
|
||||
%hr{ :class => "sixteen columns alpha", 'ng-show' => 'unitsVariantSelected()' }
|
||||
%div#group_buy_calculation{ :class => "sixteen columns alpha", 'ng-show' => 'unitsVariantSelected()' }
|
||||
|
||||
%hr.divider.sixteen.columns.alpha.omega{ ng: { show: 'unitsVariantSelected()' } }
|
||||
|
||||
%div.sixteen.columns.alpha.omega#group_buy_calculation{ ng: { show: 'unitsVariantSelected()' } }
|
||||
%div.shared_resource{ :class => "four columns alpha" }
|
||||
%span{ :class => 'three columns alpha' }
|
||||
%input{ type: 'checkbox', :id => 'shared_resource', 'ng-model' => 'sharedResource'}
|
||||
@@ -106,9 +108,10 @@
|
||||
%div.sixteen.columns.alpha#loading{ 'ng-if' => 'RequestMonitor.loading' }
|
||||
%img.spinner{ src: "/assets/spinning-circles.svg" }
|
||||
%h1 LOADING ORDERS
|
||||
|
||||
%div{ :class => "sixteen columns alpha", 'ng-show' => '!RequestMonitor.loading && filteredLineItems.length == 0'}
|
||||
%h1#no_results
|
||||
= t "no_orders_found"
|
||||
%h1#no_results No orders found.
|
||||
|
||||
%div{ 'ng-hide' => 'RequestMonitor.loading || filteredLineItems.length == 0' }
|
||||
%form{ name: 'bulk_order_form' }
|
||||
%table.index#listing_orders.bulk{ :class => "sixteen columns alpha" }
|
||||
@@ -150,6 +153,7 @@
|
||||
%th.actions
|
||||
= t "ask"
|
||||
%input{ :type => 'checkbox', 'ng-model' => "confirmDelete" }
|
||||
|
||||
%tr.line_item{ 'ng-repeat' => "line_item in filteredLineItems = ( lineItems | filter:quickSearch | selectFilter:supplierFilter:distributorFilter:orderCycleFilter | variantFilter:selectedUnitsProduct:selectedUnitsVariant:sharedResource | orderBy:predicate:reverse )", 'ng-class-even' => "'even'", 'ng-class-odd' => "'odd'", :id => "li_{{line_item.id}}" }
|
||||
%td.bulk
|
||||
%input{ :type => "checkbox", :name => 'bulk', 'ng-model' => 'line_item.checked', 'ignore-dirty' => true }
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
%div{ ng: { app: 'ofn.admin', controller: 'AdminProductEditCtrl', init: 'initialise()' } }
|
||||
|
||||
= render 'spree/admin/products/bulk_edit/filters'
|
||||
%hr.sixteen.columns.alpha
|
||||
%hr.divider.sixteen.columns.alpha.omega
|
||||
= render 'spree/admin/products/bulk_edit/actions'
|
||||
= render 'spree/admin/products/bulk_edit/indicators'
|
||||
= render 'spree/admin/products/bulk_edit/products'
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
%div.sixteen.columns.alpha{ 'ng-hide' => 'loading || products.length == 0', style: "margin-bottom: 10px" }
|
||||
%div.four.columns.alpha
|
||||
.controls.sixteen.columns.alpha{ 'ng-hide' => 'loading || products.length == 0' }
|
||||
.four.columns.alpha
|
||||
%input.four.columns.alpha{ :type => 'button', :value => 'Save Changes', 'ng-click' => 'submitProducts()'}
|
||||
%div.nine.columns
|
||||
.nine.columns
|
||||
= render 'spree/admin/shared/status_message'
|
||||
%div.three.columns.omega
|
||||
%div.ofn_drop_down.three.columns.omega{ 'ng-controller' => "DropDownCtrl", :id => "columns_dropdown", 'ofn-drop-down' => true, :style => 'float:right;' }
|
||||
%span{ :class => 'icon-reorder' } Columns
|
||||
%span{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" }
|
||||
%div.menu{ 'ng-show' => "expanded" }
|
||||
%div.menu_item{ :class => "three columns alpha", 'ng-repeat' => "column in columns", 'ofn-toggle-column' => true }
|
||||
%span{ :class => 'one column alpha', :style => 'text-align: center'} {{ column.visible && "✓" || !column.visible && " " }}
|
||||
%span{ :class => 'two columns omega' } {{column.name }}
|
||||
= render 'admin/shared/columns_dropdown'
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
%div.sixteen.columns.alpha
|
||||
%div.quick_search{ :class => "four columns alpha" }
|
||||
.filters.sixteen.columns.alpha.omega
|
||||
.quick_search.four.columns.alpha
|
||||
%label{ :for => 'quick_filter' }
|
||||
%br
|
||||
%input.search{ :class => "four columns alpha", 'ng-model' => 'query', :name => "quick_filter", :type => 'text', 'placeholder' => 'Quick Search' }
|
||||
.filter_select{ :class => "four columns" }
|
||||
%label{ :for => 'producer_filter' }
|
||||
= t 'producer'
|
||||
%input.quick-search.fullwidth{ 'ng-model' => 'query', :name => "quick_filter", :type => 'text', 'placeholder' => 'Quick Search' }
|
||||
.filter_select.four.columns
|
||||
%label{ :for => 'producer_filter' }= t 'producer'
|
||||
%br
|
||||
%select{ :class => "four columns alpha", :id => 'producer_filter', 'ofn-select2-min-search' => 5, 'ng-model' => 'producerFilter', 'ng-options' => 'producer.id as producer.name for producer in filterProducers' }
|
||||
.filter_select{ :class => "four columns" }
|
||||
%label{ :for => 'category_filter' }
|
||||
= t 'category'
|
||||
%select.fullwidth{ :id => 'producer_filter', 'ofn-select2-min-search' => 5, 'ng-model' => 'producerFilter', 'ng-options' => 'producer.id as producer.name for producer in filterProducers' }
|
||||
.filter_select.four.columns
|
||||
%label{ :for => 'category_filter' }= t 'category'
|
||||
%br
|
||||
%select{ :class => "four columns alpha", :id => 'category_filter', 'ofn-select2-min-search' => 5, 'ng-model' => 'categoryFilter', 'ng-options' => 'taxon.id as taxon.name for taxon in filterTaxons'}
|
||||
%select.fullwidth{ :id => 'category_filter', 'ofn-select2-min-search' => 5, 'ng-model' => 'categoryFilter', 'ng-options' => 'taxon.id as taxon.name for taxon in filterTaxons'}
|
||||
%div{ :class => "one column" }
|
||||
.filter_clear{ :class => "three columns omega" }
|
||||
.filter_clear.three.columns.omega
|
||||
%label{ :for => 'clear_all_filters' }
|
||||
%br
|
||||
%input.fullwidth.red{ :type => 'button', :id => 'clear_all_filters', :value => "Clear Filters", 'ng-click' => "resetSelectFilters()" }
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
%a{ :class => "add-variant icon-plus-sign", 'ng-click' => "addVariant(product)", 'ng-show' => "$last" }
|
||||
%td{ 'ng-show' => 'columns.producer.visible' }
|
||||
%td{ 'ng-show' => 'columns.sku.visible' }
|
||||
%input{ 'ng-model' => "variant.sku", :name => 'variant_sku', 'ofn-track-variant' => 'sku', :type => 'text' }
|
||||
%td{ 'ng-show' => 'columns.name.visible' }
|
||||
%input{ 'ng-model' => 'variant.display_name', :name => 'variant_display_name', 'ofn-track-variant' => 'display_name', :type => 'text', placeholder: "{{ product.name }}" }
|
||||
%td.unit_value{ 'ng-show' => 'columns.unit.visible' }
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
%strong= order.shipping_method.name
|
||||
.pad
|
||||
.text-big
|
||||
Ready for collection
|
||||
= t :order_pickup_time
|
||||
%strong #{order.order_cycle.pickup_time_for(order.distributor)}
|
||||
%p.text-small.text-skinny.pre-line
|
||||
%em= order.shipping_method.description.andand.html_safe || ""
|
||||
@@ -140,7 +140,7 @@
|
||||
%tr.total
|
||||
%td.text-right{colspan: "3"}
|
||||
%h5
|
||||
= t :order_produce
|
||||
= t :order_total_price
|
||||
%td.text-right.total
|
||||
%h5#order_total= order.display_total.to_html
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ module Openfoodnetwork
|
||||
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
||||
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
||||
config.i18n.default_locale = ENV["LOCALE"]
|
||||
I18n.locale = config.i18n.locale = config.i18n.default_locale
|
||||
|
||||
# Setting this to true causes a performance regression in Rails 3.2.17
|
||||
# When we're on a version with the fix below, we can set it to true
|
||||
|
||||
@@ -29,6 +29,7 @@ en:
|
||||
home: "OFN"
|
||||
title: Open Food Network
|
||||
welcome_to: 'Welcome to '
|
||||
description: "We begin from the ground up. With farmers and growers ready to tell their stories proudly and truly. With distributors ready to connect people with products fairly and honestly. With buyers who believe that better weekly shopping decisions can…"
|
||||
search_by_name: Search by name or suburb...
|
||||
producers: Aussie Producers #FIXME
|
||||
producers_join: Australian producers are now welcome to join the Open Food Network. #FIXME
|
||||
@@ -52,6 +53,8 @@ en:
|
||||
free: "free"
|
||||
plus_tax: "plus GST"
|
||||
total_monthly_bill_incl_tax: "Total Monthly Bill (Incl. Tax)"
|
||||
say_no: "No"
|
||||
say_yes: "Yes"
|
||||
|
||||
sort_order_cycles_on_shopfront_by: "Sort Order Cycles On Shopfront By"
|
||||
|
||||
@@ -227,6 +230,7 @@ en:
|
||||
order_delivery_on: Delivery on
|
||||
order_delivery_address: Delivery address
|
||||
order_special_instructions: "Your notes:"
|
||||
order_pickup_time: Ready for collection
|
||||
order_pickup_instructions: Collection Instructions
|
||||
order_produce: Produce
|
||||
order_total_price: Total
|
||||
|
||||
@@ -166,6 +166,7 @@ fr:
|
||||
order_delivery_on: Livraison prévue
|
||||
order_delivery_address: Adresse de livraison
|
||||
order_special_instructions: "Vos commentaires:"
|
||||
order_pickup_time: Disponible pour retrait
|
||||
order_pickup_instructions: Instructions de retrait
|
||||
order_produce: Produit
|
||||
order_total_price: Total
|
||||
|
||||
@@ -103,6 +103,7 @@ Openfoodnetwork::Application.routes.draw do
|
||||
|
||||
resources :variant_overrides do
|
||||
post :bulk_update, on: :collection
|
||||
post :bulk_reset, on: :collection
|
||||
end
|
||||
|
||||
resources :customers, only: [:index, :update]
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
class AddDefaultStockToVariantOverrides < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :variant_overrides, :default_stock, :integer
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
class AddEnableResetToVariantOverrides < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :variant_overrides, :enable_reset, :boolean
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,6 @@
|
||||
class AddOnDemandAndSkuToVariantOverrides < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :variant_overrides, :sku, :string, :default => nil, :after => :hub_id
|
||||
add_column :variant_overrides, :on_demand, :boolean, :default => nil, :after => :count_on_hand
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,3 @@
|
||||
class RenameEnableResetToResettable < ActiveRecord::Migration
|
||||
rename_column :variant_overrides, :enable_reset, :resettable
|
||||
end
|
||||
@@ -11,7 +11,7 @@
|
||||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20151125051510) do
|
||||
ActiveRecord::Schema.define(:version => 20151128185900) do
|
||||
|
||||
create_table "account_invoices", :force => true do |t|
|
||||
t.integer "user_id", :null => false
|
||||
@@ -1159,6 +1159,10 @@ ActiveRecord::Schema.define(:version => 20151125051510) do
|
||||
t.integer "hub_id", :null => false
|
||||
t.decimal "price", :precision => 8, :scale => 2
|
||||
t.integer "count_on_hand"
|
||||
t.integer "default_stock"
|
||||
t.boolean "resettable"
|
||||
t.string "sku"
|
||||
t.boolean "on_demand"
|
||||
end
|
||||
|
||||
add_index "variant_overrides", ["variant_id", "hub_id"], :name => "index_variant_overrides_on_variant_id_and_hub_id"
|
||||
|
||||
173
knapsack_rspec_report.json
Normal file
173
knapsack_rspec_report.json
Normal file
@@ -0,0 +1,173 @@
|
||||
{
|
||||
"spec/controllers/admin/accounts_and_billing_settings_controller_spec.rb": 5.547292709350586,
|
||||
"spec/controllers/admin/business_model_configuration_controller_spec.rb": 0.3683593273162842,
|
||||
"spec/controllers/admin/customers_controller_spec.rb": 0.8933048248291016,
|
||||
"spec/controllers/admin/enterprises_controller_spec.rb": 5.984264850616455,
|
||||
"spec/controllers/admin/order_cycles_controller_spec.rb": 2.839667558670044,
|
||||
"spec/controllers/api/enterprises_controller_spec.rb": 0.2780017852783203,
|
||||
"spec/controllers/api/order_cycles_controller_spec.rb": 1.8730568885803223,
|
||||
"spec/controllers/base_controller_spec.rb": 0.02932429313659668,
|
||||
"spec/controllers/cart_controller_spec.rb": 1.062530517578125,
|
||||
"spec/controllers/checkout_controller_spec.rb": 1.6658811569213867,
|
||||
"spec/controllers/enterprise_confirmations_controller_spec.rb": 1.1228001117706299,
|
||||
"spec/controllers/enterprises_controller_spec.rb": 2.2625372409820557,
|
||||
"spec/controllers/groups_controller_spec.rb": 0.40616846084594727,
|
||||
"spec/controllers/registration_controller_spec.rb": 0.2145981788635254,
|
||||
"spec/controllers/shop_controller_spec.rb": 5.298644304275513,
|
||||
"spec/controllers/shops_controller_spec.rb": 0.2002561092376709,
|
||||
"spec/controllers/spree/admin/adjustments_controller_spec.rb": 1.023233413696289,
|
||||
"spec/controllers/spree/admin/base_controller_spec.rb": 0.28871917724609375,
|
||||
"spec/controllers/spree/admin/line_items_controller_spec.rb": 14.042466402053833,
|
||||
"spec/controllers/spree/admin/orders_controller_spec.rb": 12.639750480651855,
|
||||
"spec/controllers/spree/admin/overview_controller_spec.rb": 0.691641092300415,
|
||||
"spec/controllers/spree/admin/payment_methods_controller_spec.rb": 0.7098217010498047,
|
||||
"spec/controllers/spree/admin/products_controller_spec.rb": 1.4383087158203125,
|
||||
"spec/controllers/spree/admin/reports_controller_spec.rb": 47.79633665084839,
|
||||
"spec/controllers/spree/admin/search_controller_spec.rb": 0.9386723041534424,
|
||||
"spec/controllers/spree/admin/variants_controller_spec.rb": 2.0663084983825684,
|
||||
"spec/controllers/spree/api/line_items_controller_spec.rb": 0.4743325710296631,
|
||||
"spec/controllers/spree/api/products_controller_spec.rb": 8.339523792266846,
|
||||
"spec/controllers/spree/api/variants_controller_spec.rb": 4.835069179534912,
|
||||
"spec/controllers/spree/checkout_controller_spec.rb": 0.687798023223877,
|
||||
"spec/controllers/spree/orders_controller_spec.rb": 1.7623963356018066,
|
||||
"spec/controllers/spree/paypal_controller_spec.rb": 0.437147855758667,
|
||||
"spec/controllers/spree/store_controller_spec.rb": 0.03699040412902832,
|
||||
"spec/controllers/spree/user_sessions_controller_spec.rb": 0.09967947006225586,
|
||||
"spec/controllers/user_passwords_controller_spec.rb": 0.31070899963378906,
|
||||
"spec/controllers/user_registrations_controller_spec.rb": 0.36581993103027344,
|
||||
"spec/features/admin/account_spec.rb": 0.32449865341186523,
|
||||
"spec/features/admin/accounts_and_billing_settings_spec.rb": 15.864763259887695,
|
||||
"spec/features/admin/adjustments_spec.rb": 6.825028896331787,
|
||||
"spec/features/admin/authentication_spec.rb": 22.29801869392395,
|
||||
"spec/features/admin/bulk_order_management_spec.rb": 112.38913011550903,
|
||||
"spec/features/admin/bulk_product_update_spec.rb": 59.00568914413452,
|
||||
"spec/features/admin/business_model_configuration_spec.rb": 2.5152199268341064,
|
||||
"spec/features/admin/cms_spec.rb": 2.5085999965667725,
|
||||
"spec/features/admin/content_spec.rb": 1.2907540798187256,
|
||||
"spec/features/admin/customers_spec.rb": 33.99929761886597,
|
||||
"spec/features/admin/enterprise_fees_spec.rb": 13.33712100982666,
|
||||
"spec/features/admin/enterprise_groups_spec.rb": 8.689672231674194,
|
||||
"spec/features/admin/enterprise_relationships_spec.rb": 7.257282733917236,
|
||||
"spec/features/admin/enterprise_roles_spec.rb": 5.535412788391113,
|
||||
"spec/features/admin/enterprise_user_spec.rb": 2.5493221282958984,
|
||||
"spec/features/admin/enterprises/index_spec.rb": 5.77092719078064,
|
||||
"spec/features/admin/enterprises_spec.rb": 34.78606820106506,
|
||||
"spec/features/admin/image_settings_spec.rb": 0.4501008987426758,
|
||||
"spec/features/admin/order_cycles_spec.rb": 64.186044216156,
|
||||
"spec/features/admin/orders_spec.rb": 49.190918922424316,
|
||||
"spec/features/admin/overview_spec.rb": 5.788672208786011,
|
||||
"spec/features/admin/payment_method_spec.rb": 15.959310531616211,
|
||||
"spec/features/admin/products_spec.rb": 21.46337914466858,
|
||||
"spec/features/admin/reports_spec.rb": 150.51152086257935,
|
||||
"spec/features/admin/shipping_methods_spec.rb": 8.671862363815308,
|
||||
"spec/features/admin/tax_settings_spec.rb": 0.7941949367523193,
|
||||
"spec/features/admin/variant_overrides_spec.rb": 29.70982050895691,
|
||||
"spec/features/admin/variants_spec.rb": 5.565031290054321,
|
||||
"spec/features/consumer/authentication_spec.rb": 12.449390649795532,
|
||||
"spec/features/consumer/groups_spec.rb": 1.545715093612671,
|
||||
"spec/features/consumer/producers_spec.rb": 3.3242862224578857,
|
||||
"spec/features/consumer/registration_spec.rb": 2.421873092651367,
|
||||
"spec/features/consumer/shopping/cart_spec.rb": 1.6924467086791992,
|
||||
"spec/features/consumer/shopping/checkout_auth_spec.rb": 8.496914863586426,
|
||||
"spec/features/consumer/shopping/checkout_spec.rb": 39.204933881759644,
|
||||
"spec/features/consumer/shopping/shopping_spec.rb": 23.358332633972168,
|
||||
"spec/features/consumer/shopping/variant_overrides_spec.rb": 58.16736888885498,
|
||||
"spec/features/consumer/shops_spec.rb": 6.636866092681885,
|
||||
"spec/helpers/admin/business_model_configuration_helper_spec.rb": 0.2595028877258301,
|
||||
"spec/helpers/checkout_helper_spec.rb": 0.10617446899414062,
|
||||
"spec/helpers/groups_helper_spec.rb": 0.007729053497314453,
|
||||
"spec/helpers/html_helper_spec.rb": 0.05157279968261719,
|
||||
"spec/helpers/injection_helper_spec.rb": 0.6142556667327881,
|
||||
"spec/helpers/navigation_helper_spec.rb": 0.02951979637145996,
|
||||
"spec/helpers/order_cycles_helper_spec.rb": 0.5953588485717773,
|
||||
"spec/helpers/products_helper_spec.rb": 0.009511232376098633,
|
||||
"spec/helpers/shared_helper_spec.rb": 0.017564058303833008,
|
||||
"spec/helpers/shop_helper_spec.rb": 0.05760025978088379,
|
||||
"spec/jobs/confirm_order_job_spec.rb": 0.0458524227142334,
|
||||
"spec/jobs/confirm_signup_job_spec.rb": 0.021564006805419922,
|
||||
"spec/jobs/finalize_account_invoices_spec.rb": 4.505181312561035,
|
||||
"spec/jobs/order_cycle_notification_job_spec.rb": 2.0606272220611572,
|
||||
"spec/jobs/update_account_invoices_spec.rb": 18.434475898742676,
|
||||
"spec/jobs/update_billable_periods_spec.rb": 4.850176572799683,
|
||||
"spec/jobs/welcome_enterprise_job_spec.rb": 0.07065534591674805,
|
||||
"spec/lib/open_food_network/bulk_coop_report_spec.rb": 4.789663553237915,
|
||||
"spec/lib/open_food_network/customers_report_spec.rb": 2.419727325439453,
|
||||
"spec/lib/open_food_network/distribution_change_validator_spec.rb": 0.10607743263244629,
|
||||
"spec/lib/open_food_network/enterprise_fee_applicator_spec.rb": 0.7333858013153076,
|
||||
"spec/lib/open_food_network/enterprise_fee_calculator_spec.rb": 7.406745195388794,
|
||||
"spec/lib/open_food_network/enterprise_injection_data_spec.rb": 0.291548490524292,
|
||||
"spec/lib/open_food_network/enterprise_issue_validator_spec.rb": 0.09764814376831055,
|
||||
"spec/lib/open_food_network/feature_toggle_spec.rb": 0.010193109512329102,
|
||||
"spec/lib/open_food_network/group_buy_report_spec.rb": 3.708569049835205,
|
||||
"spec/lib/open_food_network/last_used_address_spec.rb": 0.0254666805267334,
|
||||
"spec/lib/open_food_network/lettuce_share_report_spec.rb": 2.3206725120544434,
|
||||
"spec/lib/open_food_network/option_value_namer_spec.rb": 0.06185555458068848,
|
||||
"spec/lib/open_food_network/order_and_distributor_report_spec.rb": 1.0406858921051025,
|
||||
"spec/lib/open_food_network/order_cycle_form_applicator_spec.rb": 4.533008337020874,
|
||||
"spec/lib/open_food_network/order_cycle_management_report_spec.rb": 2.036308526992798,
|
||||
"spec/lib/open_food_network/order_cycle_permissions_spec.rb": 23.74185061454773,
|
||||
"spec/lib/open_food_network/order_grouper_spec.rb": 0.029039621353149414,
|
||||
"spec/lib/open_food_network/orders_and_fulfillments_report_spec.rb": 5.135573148727417,
|
||||
"spec/lib/open_food_network/packing_report_spec.rb": 5.088447093963623,
|
||||
"spec/lib/open_food_network/permissions_spec.rb": 8.881855249404907,
|
||||
"spec/lib/open_food_network/products_and_inventory_report_spec.rb": 3.55375337600708,
|
||||
"spec/lib/open_food_network/referer_parser_spec.rb": 0.014271259307861328,
|
||||
"spec/lib/open_food_network/reports/report_spec.rb": 0.02238297462463379,
|
||||
"spec/lib/open_food_network/reports/row_spec.rb": 0.0031762123107910156,
|
||||
"spec/lib/open_food_network/reports/rule_spec.rb": 0.013959169387817383,
|
||||
"spec/lib/open_food_network/sales_tax_report_spec.rb": 0.10717129707336426,
|
||||
"spec/lib/open_food_network/scope_variant_to_hub_spec.rb": 2.4846229553222656,
|
||||
"spec/lib/open_food_network/user_balance_calculator_spec.rb": 3.4277901649475098,
|
||||
"spec/lib/open_food_network/users_and_enterprises_report_spec.rb": 0.40532779693603516,
|
||||
"spec/lib/open_food_network/xero_invoices_report_spec.rb": 1.1586685180664062,
|
||||
"spec/lib/spree/product_filters_spec.rb": 0.13163042068481445,
|
||||
"spec/mailers/enterprise_mailer_spec.rb": 0.4537942409515381,
|
||||
"spec/mailers/order_mailer_spec.rb": 1.452355146408081,
|
||||
"spec/mailers/producer_mailer_spec.rb": 8.775528192520142,
|
||||
"spec/mailers/user_mailer_spec.rb": 0.057527780532836914,
|
||||
"spec/models/adjustment_metadata_spec.rb": 0.22016620635986328,
|
||||
"spec/models/billable_period_spec.rb": 2.06524658203125,
|
||||
"spec/models/calculator/weight_spec.rb": 0.009344100952148438,
|
||||
"spec/models/cart_spec.rb": 4.099429130554199,
|
||||
"spec/models/customer_spec.rb": 0.07328605651855469,
|
||||
"spec/models/enterprise_caching_spec.rb": 0.8475983142852783,
|
||||
"spec/models/enterprise_fee_spec.rb": 3.1999905109405518,
|
||||
"spec/models/enterprise_group_spec.rb": 0.30861926078796387,
|
||||
"spec/models/enterprise_relationship_spec.rb": 2.1849746704101562,
|
||||
"spec/models/enterprise_spec.rb": 17.679611682891846,
|
||||
"spec/models/exchange_spec.rb": 13.899227857589722,
|
||||
"spec/models/model_set_spec.rb": 0.22760748863220215,
|
||||
"spec/models/order_cycle_spec.rb": 10.680967569351196,
|
||||
"spec/models/product_distribution_spec.rb": 2.227938413619995,
|
||||
"spec/models/spree/ability_spec.rb": 15.278357028961182,
|
||||
"spec/models/spree/addresses_spec.rb": 0.055602312088012695,
|
||||
"spec/models/spree/adjustment_spec.rb": 9.196375846862793,
|
||||
"spec/models/spree/classification_spec.rb": 0.161299467086792,
|
||||
"spec/models/spree/image_spec.rb": 0.007464408874511719,
|
||||
"spec/models/spree/line_item_spec.rb": 13.545411586761475,
|
||||
"spec/models/spree/order_populator_spec.rb": 1.635932207107544,
|
||||
"spec/models/spree/order_spec.rb": 10.645411968231201,
|
||||
"spec/models/spree/payment_method_spec.rb": 0.0733034610748291,
|
||||
"spec/models/spree/payment_spec.rb": 1.691227912902832,
|
||||
"spec/models/spree/preferences/file_configuration_spec.rb": 0.03429675102233887,
|
||||
"spec/models/spree/product_spec.rb": 17.406191110610962,
|
||||
"spec/models/spree/shipping_method_spec.rb": 3.0447566509246826,
|
||||
"spec/models/spree/tax_rate_spec.rb": 0.44750261306762695,
|
||||
"spec/models/spree/taxon_spec.rb": 0.553098201751709,
|
||||
"spec/models/spree/user_spec.rb": 1.2693369388580322,
|
||||
"spec/models/spree/variant_spec.rb": 13.75825023651123,
|
||||
"spec/models/variant_override_spec.rb": 4.086935520172119,
|
||||
"spec/performance/injection_helper_spec.rb": 6.890667676925659,
|
||||
"spec/performance/orders_controller_spec.rb": 0.031180143356323242,
|
||||
"spec/performance/shop_controller_spec.rb": 18.19426918029785,
|
||||
"spec/requests/large_request_spec.rb": 0.02229022979736328,
|
||||
"spec/requests/shop_spec.rb": 1.0012562274932861,
|
||||
"spec/serializers/admin/enterprise_serializer_spec.rb": 0.10484433174133301,
|
||||
"spec/serializers/admin/exchange_serializer_spec.rb": 0.7569985389709473,
|
||||
"spec/serializers/admin/for_order_cycle/enterprise_serializer_spec.rb": 0.4293792247772217,
|
||||
"spec/serializers/admin/index_enterprise_serializer_spec.rb": 1.2506742477416992,
|
||||
"spec/serializers/admin/variant_override_serializer_spec.rb": 0.38981151580810547,
|
||||
"spec/serializers/enterprise_serializer_spec.rb": 0.3511006832122803,
|
||||
"spec/serializers/spree/product_serializer_spec.rb": 0.26622653007507324,
|
||||
"spec/serializers/spree/variant_serializer_spec.rb": 0.30304574966430664
|
||||
}
|
||||
@@ -26,12 +26,16 @@ module OpenFoodNetwork
|
||||
end
|
||||
|
||||
def on_demand
|
||||
if @variant_override.andand.count_on_hand.present?
|
||||
# If we're overriding the stock level of an on_demand variant, show it as not
|
||||
# on_demand, so our stock control can take effect.
|
||||
false
|
||||
if @variant_override.andand.on_demand.nil?
|
||||
if @variant_override.andand.count_on_hand.present?
|
||||
# If we're overriding the stock level of an on_demand variant, show it as not
|
||||
# on_demand, so our stock control can take effect.
|
||||
false
|
||||
else
|
||||
super
|
||||
end
|
||||
else
|
||||
super
|
||||
@variant_override.andand.on_demand
|
||||
end
|
||||
end
|
||||
|
||||
@@ -42,7 +46,10 @@ module OpenFoodNetwork
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def sku
|
||||
@variant_override.andand.sku || super
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,12 +10,20 @@ else
|
||||
RAILS_RUN='bundle exec rails runner'
|
||||
fi
|
||||
|
||||
if [[ $1 != 'ofn-no' ]]; then
|
||||
DB_USER='openfoodweb'
|
||||
DB_DATABASE='openfoodweb_production'
|
||||
else
|
||||
DB_USER='ofn_user'
|
||||
DB_DATABASE='openfoodnetwork'
|
||||
fi
|
||||
|
||||
|
||||
# -- Mirror database
|
||||
echo "Mirroring database..."
|
||||
echo "drop database open_food_network_dev" | psql -h localhost -U ofn open_food_network_test
|
||||
echo "create database open_food_network_dev" | psql -h localhost -U ofn open_food_network_test
|
||||
ssh $1 "pg_dump -h localhost -U openfoodweb openfoodweb_production |gzip" |gunzip |psql -h localhost -U ofn open_food_network_dev
|
||||
ssh $1 "pg_dump -h localhost -U $DB_USER $DB_DATABASE |gzip" |gunzip |psql -h localhost -U ofn open_food_network_dev
|
||||
|
||||
|
||||
# -- Disable S3
|
||||
|
||||
135
spec/controllers/admin/variant_overrides_controller_spec.rb
Normal file
135
spec/controllers/admin/variant_overrides_controller_spec.rb
Normal file
@@ -0,0 +1,135 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Admin::VariantOverridesController, type: :controller do
|
||||
# include AuthenticationWorkflow
|
||||
|
||||
describe "bulk_update" do
|
||||
context "json" do
|
||||
let(:format) { :json }
|
||||
|
||||
let(:hub) { create(:distributor_enterprise) }
|
||||
let(:variant) { create(:variant) }
|
||||
let!(:variant_override) { create(:variant_override, hub: hub, variant: variant) }
|
||||
let(:variant_override_params) { [ { id: variant_override.id, price: 123.45, count_on_hand: 321, sku: "MySKU", on_demand: false } ] }
|
||||
|
||||
context "where I don't manage the variant override hub" do
|
||||
before do
|
||||
user = create(:user)
|
||||
user.owned_enterprises << create(:enterprise)
|
||||
allow(controller).to receive(:spree_current_user) { user }
|
||||
end
|
||||
|
||||
it "redirects to unauthorized" do
|
||||
spree_put :bulk_update, format: format, variant_overrides: variant_override_params
|
||||
expect(response).to redirect_to spree.unauthorized_path
|
||||
end
|
||||
end
|
||||
|
||||
context "where I manage the variant override hub" do
|
||||
before do
|
||||
allow(controller).to receive(:spree_current_user) { hub.owner }
|
||||
end
|
||||
|
||||
context "but the producer has not granted VO permission" do
|
||||
it "redirects to unauthorized" do
|
||||
spree_put :bulk_update, format: format, variant_overrides: variant_override_params
|
||||
expect(response).to redirect_to spree.unauthorized_path
|
||||
end
|
||||
end
|
||||
|
||||
context "and the producer has granted VO permission" do
|
||||
before do
|
||||
create(:enterprise_relationship, parent: variant.product.supplier, child: hub, permissions_list: [:create_variant_overrides])
|
||||
end
|
||||
|
||||
it "allows me to update the variant override" do
|
||||
spree_put :bulk_update, format: format, variant_overrides: variant_override_params
|
||||
variant_override.reload
|
||||
expect(variant_override.price).to eq 123.45
|
||||
expect(variant_override.count_on_hand).to eq 321
|
||||
expect(variant_override.sku).to eq "MySKU"
|
||||
expect(variant_override.on_demand).to eq false
|
||||
end
|
||||
|
||||
context "where params for a variant override are blank" do
|
||||
let(:variant_override_params) { [ { id: variant_override.id, price: "", count_on_hand: "", default_stock: nil, resettable: nil, sku: nil, on_demand: nil } ] }
|
||||
|
||||
it "destroys the variant override" do
|
||||
spree_put :bulk_update, format: format, variant_overrides: variant_override_params
|
||||
expect(VariantOverride.find_by_id(variant_override.id)).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "bulk_reset" do
|
||||
context "json" do
|
||||
let(:format) { :json }
|
||||
|
||||
let(:hub) { create(:distributor_enterprise) }
|
||||
let(:producer) { create(:supplier_enterprise) }
|
||||
let(:product) { create(:product, supplier: producer) }
|
||||
let(:variant1) { create(:variant, product: product) }
|
||||
let(:variant2) { create(:variant, product: product) }
|
||||
let!(:variant_override1) { create(:variant_override, hub: hub, variant: variant1, count_on_hand: 5, default_stock: 7, resettable: true) }
|
||||
let!(:variant_override2) { create(:variant_override, hub: hub, variant: variant2, count_on_hand: 2, default_stock: 1, resettable: false) }
|
||||
|
||||
let(:params) { { format: format, hub_id: hub.id } }
|
||||
|
||||
context "where I don't manage the variant override hub" do
|
||||
before do
|
||||
user = create(:user)
|
||||
user.owned_enterprises << create(:enterprise)
|
||||
allow(controller).to receive(:spree_current_user) { user }
|
||||
end
|
||||
|
||||
it "redirects to unauthorized" do
|
||||
spree_put :bulk_reset, params
|
||||
expect(response).to redirect_to spree.unauthorized_path
|
||||
end
|
||||
end
|
||||
|
||||
context "where I manage the variant override hub" do
|
||||
before do
|
||||
allow(controller).to receive(:spree_current_user) { hub.owner }
|
||||
end
|
||||
|
||||
context "where the producer has not granted create_variant_overrides permission to the hub" do
|
||||
it "restricts access" do
|
||||
spree_put :bulk_reset, params
|
||||
expect(response).to redirect_to spree.unauthorized_path
|
||||
end
|
||||
end
|
||||
|
||||
context "where the producer has granted create_variant_overrides permission to the hub" do
|
||||
let!(:er1) { create(:enterprise_relationship, parent: producer, child: hub, permissions_list: [:create_variant_overrides]) }
|
||||
|
||||
it "updates stock to default values where reset is enabled" do
|
||||
expect(variant_override1.reload.count_on_hand).to eq 5 # reset enabled
|
||||
expect(variant_override2.reload.count_on_hand).to eq 2 # reset disabled
|
||||
spree_put :bulk_reset, params
|
||||
expect(variant_override1.reload.count_on_hand).to eq 7 # reset enabled
|
||||
expect(variant_override2.reload.count_on_hand).to eq 2 # reset disabled
|
||||
end
|
||||
|
||||
context "and the producer has granted create_variant_overrides permission to another hub I manage" do
|
||||
before { hub.owner.update_attribute(:enterprise_limit, 2) }
|
||||
let(:hub2) { create(:distributor_enterprise, owner: hub.owner) }
|
||||
let(:product) { create(:product, supplier: producer) }
|
||||
let(:variant3) { create(:variant, product: product) }
|
||||
let!(:variant_override3) { create(:variant_override, hub: hub2, variant: variant3, count_on_hand: 1, default_stock: 13, resettable: true) }
|
||||
let!(:er2) { create(:enterprise_relationship, parent: producer, child: hub2, permissions_list: [:create_variant_overrides]) }
|
||||
|
||||
it "does not reset count_on_hand for variant_overrides not in params" do
|
||||
expect {
|
||||
spree_put :bulk_reset, params
|
||||
}.to_not change{variant_override3.reload.count_on_hand}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,7 +1,7 @@
|
||||
require 'spec_helper'
|
||||
|
||||
module Api
|
||||
describe EnterprisesController do
|
||||
describe EnterprisesController, :type => :controller do
|
||||
include AuthenticationWorkflow
|
||||
render_views
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ require 'spec_helper'
|
||||
require 'spree/api/testing_support/helpers'
|
||||
|
||||
module Api
|
||||
describe OrderCyclesController do
|
||||
describe OrderCyclesController, :type => :controller do
|
||||
include Spree::Api::TestingSupport::Helpers
|
||||
include AuthenticationWorkflow
|
||||
render_views
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe BaseController do
|
||||
describe BaseController, :type => :controller do
|
||||
let(:oc) { mock_model(OrderCycle) }
|
||||
let(:hub) { mock_model(Enterprise, ready_for_checkout?: true) }
|
||||
let(:order) { mock_model(Spree::Order, distributor: hub) }
|
||||
|
||||
@@ -58,21 +58,21 @@ describe Spree::OrdersController do
|
||||
end
|
||||
|
||||
it "returns HTTP success when successful" do
|
||||
Spree::OrderPopulator.stub(:new).and_return(populator = mock())
|
||||
Spree::OrderPopulator.stub(:new).and_return(populator = double())
|
||||
populator.stub(:populate).and_return true
|
||||
xhr :post, :populate, use_route: :spree, format: :json
|
||||
response.status.should == 200
|
||||
end
|
||||
|
||||
it "returns failure when unsuccessful" do
|
||||
Spree::OrderPopulator.stub(:new).and_return(populator = mock())
|
||||
Spree::OrderPopulator.stub(:new).and_return(populator = double())
|
||||
populator.stub(:populate).and_return false
|
||||
xhr :post, :populate, use_route: :spree, format: :json
|
||||
response.status.should == 402
|
||||
end
|
||||
|
||||
it "tells populator to overwrite" do
|
||||
Spree::OrderPopulator.stub(:new).and_return(populator = mock())
|
||||
Spree::OrderPopulator.stub(:new).and_return(populator = double())
|
||||
populator.should_receive(:populate).with({}, true)
|
||||
xhr :post, :populate, use_route: :spree, format: :json
|
||||
end
|
||||
|
||||
@@ -94,6 +94,8 @@ FactoryGirl.define do
|
||||
factory :variant_override, :class => VariantOverride do
|
||||
price 77.77
|
||||
count_on_hand 11111
|
||||
default_stock 2000
|
||||
resettable false
|
||||
end
|
||||
|
||||
factory :enterprise, :class => Enterprise do
|
||||
|
||||
@@ -119,10 +119,9 @@ feature %q{
|
||||
expect(page).to_not have_selector "#save-bar"
|
||||
fill_in "quantity", :with => 2
|
||||
expect(page).to have_selector "input[name='quantity'].ng-dirty"
|
||||
expect(page).to have_selector "#save-bar"
|
||||
expect(page).to have_button "Save Changes"
|
||||
expect(page).to have_selector "#save-bar", text: "You have unsaved changes"
|
||||
click_button "Save Changes"
|
||||
expect(page).to_not have_selector "#save-bar"
|
||||
expect(page).to have_selector "#save-bar", text: "All changes saved"
|
||||
expect(page).to_not have_selector "input[name='quantity'].ng-dirty"
|
||||
end
|
||||
end
|
||||
@@ -132,10 +131,9 @@ feature %q{
|
||||
expect(page).to_not have_selector "#save-bar"
|
||||
fill_in "quantity", :with => li1.variant.on_hand + li1.quantity + 10
|
||||
expect(page).to have_selector "input[name='quantity'].ng-dirty"
|
||||
expect(page).to have_selector "#save-bar"
|
||||
expect(page).to have_button "Save Changes"
|
||||
expect(page).to have_selector "#save-bar", text: "You have unsaved changes"
|
||||
click_button "Save Changes"
|
||||
expect(page).to have_selector "#save-bar"
|
||||
expect(page).to have_selector "#save-bar", text: "Fields with red borders contain errors."
|
||||
expect(page).to have_selector "input[name='quantity'].ng-dirty.update-error"
|
||||
expect(page).to have_content "exceeds available stock. Please ensure line items have a valid quantity."
|
||||
end
|
||||
@@ -158,9 +156,9 @@ feature %q{
|
||||
context "modifying the weight/volume of a line item" do
|
||||
it "price is altered" do
|
||||
visit '/admin/orders/bulk_management'
|
||||
first("div#columns_dropdown", :text => "COLUMNS").click
|
||||
first("div#columns_dropdown div.menu div.menu_item", text: "Weight/Volume").click
|
||||
first("div#columns_dropdown div.menu div.menu_item", text: "Price").click
|
||||
first("div#columns-dropdown", :text => "COLUMNS").click
|
||||
first("div#columns-dropdown div.menu div.menu_item", text: "Weight/Volume").click
|
||||
first("div#columns-dropdown div.menu div.menu_item", text: "Price").click
|
||||
within "tr#li_#{li1.id}" do
|
||||
expect(page).to have_field "price", with: "$50.00"
|
||||
fill_in "final_weight_volume", :with => 2000
|
||||
@@ -177,8 +175,8 @@ feature %q{
|
||||
context "modifying the quantity of a line item" do
|
||||
it "price is altered" do
|
||||
visit '/admin/orders/bulk_management'
|
||||
first("div#columns_dropdown", :text => "COLUMNS").click
|
||||
first("div#columns_dropdown div.menu div.menu_item", text: "Price").click
|
||||
first("div#columns-dropdown", :text => "COLUMNS").click
|
||||
first("div#columns-dropdown div.menu div.menu_item", text: "Price").click
|
||||
within "tr#li_#{li1.id}" do
|
||||
expect(page).to have_field "price", with: "$#{format("%.2f",li1.price * 5)}"
|
||||
fill_in "quantity", :with => 6
|
||||
@@ -190,8 +188,8 @@ feature %q{
|
||||
context "modifying the quantity of a line item" do
|
||||
it "weight/volume is altered" do
|
||||
visit '/admin/orders/bulk_management'
|
||||
first("div#columns_dropdown", :text => "COLUMNS").click
|
||||
first("div#columns_dropdown div.menu div.menu_item", text: "Weight/Volume").click
|
||||
first("div#columns-dropdown", :text => "COLUMNS").click
|
||||
first("div#columns-dropdown div.menu div.menu_item", text: "Weight/Volume").click
|
||||
within "tr#li_#{li1.id}" do
|
||||
expect(page).to have_field "final_weight_volume", with: "#{li1.final_weight_volume.round}"
|
||||
fill_in "quantity", :with => 6
|
||||
@@ -211,8 +209,8 @@ feature %q{
|
||||
expect(page).to have_selector "th", :text => "QUANTITY"
|
||||
expect(page).to have_selector "th", :text => "MAX"
|
||||
|
||||
first("div#columns_dropdown", :text => "COLUMNS").click
|
||||
first("div#columns_dropdown div.menu div.menu_item", text: "Producer").click
|
||||
first("div#columns-dropdown", :text => "COLUMNS").click
|
||||
first("div#columns-dropdown div.menu div.menu_item", text: "Producer").click
|
||||
|
||||
expect(page).to_not have_selector "th", :text => "PRODUCER"
|
||||
expect(page).to have_selector "th", :text => "NAME"
|
||||
@@ -501,8 +499,8 @@ feature %q{
|
||||
|
||||
it "displays a bulk action select box with a list of actions" do
|
||||
list_of_actions = ['Delete Selected']
|
||||
find("div#bulk_actions_dropdown").click
|
||||
within("div#bulk_actions_dropdown") do
|
||||
find("div#bulk-actions-dropdown").click
|
||||
within("div#bulk-actions-dropdown") do
|
||||
list_of_actions.each { |action_name| expect(page).to have_selector "div.menu_item", text: action_name }
|
||||
end
|
||||
end
|
||||
@@ -514,8 +512,8 @@ feature %q{
|
||||
within("tr#li_#{li2.id} td.bulk") do
|
||||
check "bulk"
|
||||
end
|
||||
find("div#bulk_actions_dropdown").click
|
||||
find("div#bulk_actions_dropdown div.menu_item", :text => "Delete Selected" ).click
|
||||
find("div#bulk-actions-dropdown").click
|
||||
find("div#bulk-actions-dropdown div.menu_item", :text => "Delete Selected" ).click
|
||||
expect(page).to have_selector "tr#li_#{li1.id}", visible: true
|
||||
expect(page).to_not have_selector "tr#li_#{li2.id}", visible: true
|
||||
end
|
||||
@@ -534,8 +532,8 @@ feature %q{
|
||||
it "only applies the delete action to filteredLineItems" do
|
||||
check "toggle_bulk"
|
||||
fill_in "quick_search", with: o1.number
|
||||
find("div#bulk_actions_dropdown").click
|
||||
find("div#bulk_actions_dropdown div.menu_item", :text => "Delete Selected" ).click
|
||||
find("div#bulk-actions-dropdown").click
|
||||
find("div#bulk-actions-dropdown div.menu_item", :text => "Delete Selected" ).click
|
||||
fill_in "quick_search", with: ''
|
||||
expect(page).to_not have_selector "tr#li_#{li1.id}", visible: true
|
||||
expect(page).to have_selector "tr#li_#{li2.id}", visible: true
|
||||
|
||||
@@ -46,8 +46,8 @@ feature %q{
|
||||
p2 = FactoryGirl.create(:product, available_on: Date.current-1)
|
||||
|
||||
visit '/admin/products/bulk_edit'
|
||||
first("div#columns_dropdown", :text => "COLUMNS").click
|
||||
first("div#columns_dropdown div.menu div.menu_item", text: "Available On").click
|
||||
first("div#columns-dropdown", :text => "COLUMNS").click
|
||||
first("div#columns-dropdown div.menu div.menu_item", text: "Available On").click
|
||||
|
||||
expect(page).to have_field "available_on", with: p1.available_on.strftime("%F %T")
|
||||
expect(page).to have_field "available_on", with: p2.available_on.strftime("%F %T")
|
||||
@@ -243,11 +243,11 @@ feature %q{
|
||||
|
||||
visit '/admin/products/bulk_edit'
|
||||
|
||||
first("div#columns_dropdown", :text => "COLUMNS").click
|
||||
first("div#columns_dropdown div.menu div.menu_item", text: "Available On").click
|
||||
first("div#columns_dropdown div.menu div.menu_item", text: "Category").click
|
||||
first("div#columns_dropdown div.menu div.menu_item", text: "Inherits Properties?").click
|
||||
first("div#columns_dropdown div.menu div.menu_item", text: "SKU").click
|
||||
first("div#columns-dropdown", :text => "COLUMNS").click
|
||||
first("div#columns-dropdown div.menu div.menu_item", text: "Available On").click
|
||||
first("div#columns-dropdown div.menu div.menu_item", text: "Category").click
|
||||
first("div#columns-dropdown div.menu div.menu_item", text: "Inherits Properties?").click
|
||||
first("div#columns-dropdown div.menu div.menu_item", text: "SKU").click
|
||||
|
||||
within "tr#p_#{p.id}" do
|
||||
expect(page).to have_field "product_name", with: p.name
|
||||
@@ -308,6 +308,7 @@ feature %q{
|
||||
p = FactoryGirl.create(:product, supplier: s1, available_on: Date.current, variant_unit: 'volume', variant_unit_scale: 0.001,
|
||||
price: 3.0, on_hand: 9, unit_value: 0.25, unit_description: '(bottle)' )
|
||||
v = p.variants.first
|
||||
v.update_column(:sku, "VARIANTSKU")
|
||||
|
||||
login_to_admin_section
|
||||
|
||||
@@ -315,12 +316,18 @@ feature %q{
|
||||
expect(page).to have_selector "a.view-variants"
|
||||
first("a.view-variants").trigger('click')
|
||||
|
||||
first("div#columns-dropdown", :text => "COLUMNS").click
|
||||
first("div#columns-dropdown div.menu div.menu_item", text: "SKU").click
|
||||
first("div#columns-dropdown", :text => "COLUMNS").click
|
||||
|
||||
expect(page).to have_field "variant_sku", with: "VARIANTSKU"
|
||||
expect(page).to have_field "variant_price", with: "3.0"
|
||||
expect(page).to have_field "variant_unit_value_with_description", with: "250 (bottle)"
|
||||
expect(page).to have_field "variant_on_hand", with: "9"
|
||||
expect(page).to have_selector "span[name='on_hand']", "9"
|
||||
|
||||
select "Volume (L)", from: "variant_unit_with_scale"
|
||||
fill_in "variant_sku", with: "NEWSKU"
|
||||
fill_in "variant_price", with: "4.0"
|
||||
fill_in "variant_on_hand", with: "10"
|
||||
fill_in "variant_unit_value_with_description", with: "2 (8x250 mL bottles)"
|
||||
@@ -331,6 +338,7 @@ feature %q{
|
||||
expect(page.find("#status-message")).to have_content "Changes saved."
|
||||
|
||||
v.reload
|
||||
expect(v.sku).to eq "NEWSKU"
|
||||
expect(v.price).to eq 4.0
|
||||
expect(v.on_hand).to eq 10
|
||||
expect(v.unit_value).to eq 2 # 2L in L
|
||||
@@ -556,8 +564,8 @@ feature %q{
|
||||
|
||||
visit '/admin/products/bulk_edit'
|
||||
|
||||
first("div#columns_dropdown", :text => "COLUMNS").click
|
||||
first("div#columns_dropdown div.menu div.menu_item", text: "Available On").click
|
||||
first("div#columns-dropdown", :text => "COLUMNS").click
|
||||
first("div#columns-dropdown div.menu div.menu_item", text: "Available On").click
|
||||
|
||||
expect(page).to have_selector "th", :text => "NAME"
|
||||
expect(page).to have_selector "th", :text => "PRODUCER"
|
||||
@@ -565,7 +573,7 @@ feature %q{
|
||||
expect(page).to have_selector "th", :text => "ON HAND"
|
||||
expect(page).to have_selector "th", :text => "AV. ON"
|
||||
|
||||
first("div#columns_dropdown div.menu div.menu_item", text: /^.{0,1}Producer$/).click
|
||||
first("div#columns-dropdown div.menu div.menu_item", text: /^.{0,1}Producer$/).click
|
||||
|
||||
expect(page).to have_no_selector "th", :text => "PRODUCER"
|
||||
expect(page).to have_selector "th", :text => "NAME"
|
||||
@@ -688,8 +696,8 @@ feature %q{
|
||||
v = p.variants.first
|
||||
|
||||
visit '/admin/products/bulk_edit'
|
||||
first("div#columns_dropdown", :text => "COLUMNS").click
|
||||
first("div#columns_dropdown div.menu div.menu_item", text: "Available On").click
|
||||
first("div#columns-dropdown", :text => "COLUMNS").click
|
||||
first("div#columns-dropdown div.menu div.menu_item", text: "Available On").click
|
||||
|
||||
within "tr#p_#{p.id}" do
|
||||
expect(page).to have_field "product_name", with: p.name
|
||||
|
||||
@@ -39,8 +39,8 @@ feature 'Customers' do
|
||||
# Toggling columns
|
||||
expect(page).to have_selector "th.email"
|
||||
expect(page).to have_content customer1.email
|
||||
first("div#columns_dropdown", :text => "COLUMNS").click
|
||||
first("div#columns_dropdown div.menu div.menu_item", text: "Email").click
|
||||
first("div#columns-dropdown", :text => "COLUMNS").click
|
||||
first("div#columns-dropdown div.menu div.menu_item", text: "Email").click
|
||||
expect(page).to_not have_selector "th.email"
|
||||
expect(page).to_not have_content customer1.email
|
||||
end
|
||||
|
||||
@@ -102,6 +102,7 @@ feature %q{
|
||||
# And I add a supplier and some products
|
||||
select 'My supplier', from: 'new_supplier_id'
|
||||
click_button 'Add supplier'
|
||||
fill_in 'order_cycle_incoming_exchange_0_receival_instructions', with: 'receival instructions'
|
||||
page.find('table.exchanges tr.supplier td.products input').click
|
||||
check "order_cycle_incoming_exchange_0_variants_#{v1.id}"
|
||||
check "order_cycle_incoming_exchange_0_variants_#{v2.id}"
|
||||
@@ -157,8 +158,11 @@ feature %q{
|
||||
oc.exchanges.first.variants.count.should == 2
|
||||
oc.exchanges.last.variants.count.should == 2
|
||||
|
||||
# And my pickup time and instructions should have been saved
|
||||
exchange = oc.exchanges.where(:sender_id => oc.coordinator_id).first
|
||||
# And my receival and pickup time and instructions should have been saved
|
||||
exchange = oc.exchanges.incoming.first
|
||||
exchange.receival_instructions.should == 'receival instructions'
|
||||
|
||||
exchange = oc.exchanges.outgoing.first
|
||||
exchange.pickup_time.should == 'pickup time'
|
||||
exchange.pickup_instructions.should == 'pickup instructions'
|
||||
end
|
||||
@@ -188,6 +192,9 @@ feature %q{
|
||||
page.should have_selector 'td.supplier_name', :text => oc.suppliers.first.name
|
||||
page.should have_selector 'td.supplier_name', :text => oc.suppliers.last.name
|
||||
|
||||
page.should have_field 'order_cycle_incoming_exchange_0_receival_instructions', with: 'instructions 0'
|
||||
page.should have_field 'order_cycle_incoming_exchange_1_receival_instructions', with: 'instructions 1'
|
||||
|
||||
# And the suppliers should have products
|
||||
page.all('table.exchanges tbody tr.supplier').each do |row|
|
||||
row.find('td.products input').click
|
||||
|
||||
@@ -192,7 +192,7 @@ feature %q{
|
||||
order = create(:completed_order_with_totals, distributor: distributor1)
|
||||
visit spree.admin_order_path(order)
|
||||
|
||||
find("#links-dropdown .ofn_drop_down").click
|
||||
find("#links-dropdown .ofn-drop-down").click
|
||||
within "#links-dropdown" do
|
||||
expect(page).to have_link "Edit", href: spree.edit_admin_order_path(order)
|
||||
expect(page).to have_link "Resend Confirmation", href: spree.resend_admin_order_path(order)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user