Compare commits

...

81 Commits

Author SHA1 Message Date
Matt-Yorkley
165f4f9201 Merge pull request #4485 from openfoodfoundation/transifex
Transifex
2019-11-23 12:48:27 +01:00
Matt-Yorkley
0d1740ba4a Merge pull request #4430 from Matt-Yorkley/variant_option_types
Variant option_values
2019-11-23 12:37:34 +01:00
Matt-Yorkley
cbb3f202ca Eager-load option_values in OpenFoodNetwork::ScopeVariantsForSearch 2019-11-23 10:58:18 +01:00
Matt-Yorkley
ff076fd7be Eager-load option_values in Api::ProductsController 2019-11-23 10:58:18 +01:00
Matt-Yorkley
d30192207b Eager-load option_values in ProducerMailer 2019-11-23 10:58:18 +01:00
Matt-Yorkley
19afc1a6da Eager-load option_values in Api::VariantsController 2019-11-23 10:58:18 +01:00
Matt-Yorkley
4ef682915c Eager-load option_values in Admin::EnterprisesController 2019-11-23 10:58:18 +01:00
Matt-Yorkley
e693e8ac37 Eager-load option_values in Admin::BulkLineItemsController 2019-11-23 10:58:18 +01:00
Matt-Yorkley
07fe8e8390 Eager-load option_values in various reports 2019-11-23 10:58:18 +01:00
Matt-Yorkley
6e58ffa927 Enable variant option_values to be successfully eager-loaded 2019-11-23 10:58:18 +01:00
Transifex-Openfoodnetwork
8a8e612fd3 Updating translations for config/locales/fr.yml 2019-11-23 06:03:21 +11:00
Transifex-Openfoodnetwork
1e8ad4748a Updating translations for config/locales/fr.yml 2019-11-23 06:00:16 +11:00
Transifex-Openfoodnetwork
4c346549f5 Updating translations for config/locales/en_FR.yml 2019-11-23 05:58:47 +11:00
Transifex-Openfoodnetwork
427e44aee9 Updating translations for config/locales/fr.yml 2019-11-23 05:57:03 +11:00
Transifex-Openfoodnetwork
8dfc62b206 Updating translations for config/locales/ar.yml 2019-11-23 02:57:34 +11:00
Transifex-Openfoodnetwork
ef4a99eadc Updating translations for config/locales/ar.yml 2019-11-23 02:54:27 +11:00
Transifex-Openfoodnetwork
8337e43e64 Updating translations for config/locales/ar.yml 2019-11-23 02:51:17 +11:00
Luis Ramos
689eb88332 Merge pull request #4450 from luisramos0/return_auth
Move return authorizations from spree_backend to OFN
2019-11-22 14:33:45 +00:00
Matt-Yorkley
698210c849 Create release-template.md 2019-11-22 14:48:50 +01:00
luisramos0
e2087bcc8c Bring return authorizations view from spree_backend 2019-11-22 13:39:36 +00:00
luisramos0
b066b87141 Bring return authorizations controller from spree_backend 2019-11-22 13:39:04 +00:00
Matt-Yorkley
d88a766de4 Merge pull request #4461 from openfoodfoundation/dependabot/bundler/i18n-js-3.5.0
Bump i18n-js from 3.4.2 to 3.5.0
2019-11-22 14:37:10 +01:00
Matt-Yorkley
6c7910c8fa Merge pull request #4477 from openfoodfoundation/transifex
Transifex
2019-11-22 14:30:05 +01:00
Transifex-Openfoodnetwork
f83d469833 Updating translations for config/locales/en_CA.yml 2019-11-22 08:25:52 +11:00
Transifex-Openfoodnetwork
1cea5327e9 Updating translations for config/locales/en_CA.yml 2019-11-22 08:13:47 +11:00
Transifex-Openfoodnetwork
26c854df5b Updating translations for config/locales/en_FR.yml 2019-11-21 21:18:34 +11:00
Transifex-Openfoodnetwork
a43ef174f6 Updating translations for config/locales/nb.yml 2019-11-21 21:13:56 +11:00
Transifex-Openfoodnetwork
99f8bf039a Updating translations for config/locales/fr.yml 2019-11-21 21:12:07 +11:00
Transifex-Openfoodnetwork
bdb2c6efb3 Updating translations for config/locales/nb.yml 2019-11-21 21:10:49 +11:00
Transifex-Openfoodnetwork
21512e9722 Updating translations for config/locales/fr.yml 2019-11-21 21:09:00 +11:00
Luis Ramos
008921c201 Merge pull request #4447 from luisramos0/clickable_steps
Clickable steps on the OC edit page
2019-11-20 21:16:07 +00:00
Luis Ramos
0882887abe Merge pull request #4452 from luisramos0/ready_for
Make "Ready for" field show a red border when added to the list of outgoing exchanges
2019-11-20 21:14:25 +00:00
Luis Ramos
0eb4574b37 Merge pull request #4422 from luisramos0/the_poc
New Order Cycles edit page with steps
2019-11-20 21:11:23 +00:00
Maikel
b54edff4cc Merge pull request #4470 from luisramos0/oc_perms
Improve readability of OC permissions...
2019-11-20 11:38:38 +11:00
Maikel
0d6911f41c Merge pull request #4467 from openfoodfoundation/transifex
Transifex
2019-11-20 08:04:54 +11:00
Luis Ramos
498acaefbc Merge pull request #4469 from Matt-Yorkley/shipping_selection
Fix shipping_rate fetching in customer_totals_report
2019-11-19 09:39:13 +00:00
Matt-Yorkley
585135d27e Fix shipping_method querying in customer totals reports 2019-11-18 15:14:10 +00:00
Matt-Yorkley
06fabe491d Add failing shipping_methods spec 2019-11-18 15:06:54 +00:00
luisramos0
052cc2848f Make visible_variants_for_incoming_exchanges_from and editable_variants_for_incoming_exchanges_from a bit easier to read 2019-11-18 13:25:38 +00:00
Transifex-Openfoodnetwork
b5b9d42764 Updating translations for config/locales/nb.yml 2019-11-18 19:04:54 +11:00
Transifex-Openfoodnetwork
d8e2239438 Updating translations for config/locales/nb.yml 2019-11-18 19:01:46 +11:00
Transifex-Openfoodnetwork
403ca3e538 Updating translations for config/locales/nb.yml 2019-11-18 18:58:37 +11:00
Transifex-Openfoodnetwork
ed65c80869 Updating translations for config/locales/ar.yml 2019-11-17 02:51:01 +11:00
Transifex-Openfoodnetwork
ca6ec9ee68 Updating translations for config/locales/ar.yml 2019-11-17 02:47:54 +11:00
Transifex-Openfoodnetwork
04fa4d3587 Updating translations for config/locales/fr.yml 2019-11-16 22:49:18 +11:00
Transifex-Openfoodnetwork
eedbcb6f1e Updating translations for config/locales/fr.yml 2019-11-16 22:46:21 +11:00
Transifex-Openfoodnetwork
61e3798533 Updating translations for config/locales/en_FR.yml 2019-11-16 22:44:43 +11:00
Transifex-Openfoodnetwork
bca978aacc Updating translations for config/locales/en_CA.yml 2019-11-16 15:06:46 +11:00
Transifex-Openfoodnetwork
190cb1dede Updating translations for config/locales/en_NZ.yml 2019-11-16 07:30:50 +11:00
Luis Ramos
9c8c71bd08 Merge pull request #4443 from openfoodfoundation/dependabot/bundler/roadie-rails-1.3.0
Bump roadie-rails from 1.1.1 to 1.3.0
2019-11-15 16:48:23 +00:00
Luis Ramos
2b37592280 Merge pull request #4449 from luisramos0/properties
Move properties and product properties from spree_backend to OFN
2019-11-15 08:57:32 +00:00
dependabot-preview[bot]
179ec6a3e9 Bump i18n-js from 3.4.2 to 3.5.0
Bumps [i18n-js](https://github.com/fnando/i18n-js) from 3.4.2 to 3.5.0.
- [Release notes](https://github.com/fnando/i18n-js/releases)
- [Changelog](https://github.com/fnando/i18n-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/fnando/i18n-js/compare/v3.4.2...v3.5.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-12 19:34:42 +00:00
luisramos0
f1c055805f Use $timeout instead of setTimeout which makes it possible to remove apply() 2019-11-12 12:06:44 +00:00
luisramos0
5cadb0d16f Make ready for field show with red borders immediatly after exchange is added to the list 2019-11-12 12:06:44 +00:00
luisramos0
6875e9a41e Make view a bit simpler by removing unnecessary string interpolation 2019-11-12 12:05:40 +00:00
luisramos0
b6f1d6e395 Make OC edit page steps clickable when editing an OC 2019-11-12 12:05:40 +00:00
luisramos0
14433e7764 Fix some rubocop issues in admin/order_cycles_controller 2019-11-12 12:02:36 +00:00
luisramos0
5fdb86ae43 Make simple create redirect to OC list but normal create to jump to incoming settings 2019-11-12 12:00:48 +00:00
luisramos0
6615469f8b Fix 3 more specs in OC edit pages 2019-11-12 12:00:48 +00:00
luisramos0
d281837dd9 Remove useless spec now that we have 3 steps in OC edit process 2019-11-12 12:00:48 +00:00
luisramos0
7c63e59ae9 Add OC imcoming and outgoing abilities to managers, this fixes a few OC feature specs 2019-11-12 12:00:48 +00:00
luisramos0
7c19fe418e Adapt OC specs to new page flow with 3 steps (these specs are not green yet) 2019-11-12 12:00:48 +00:00
luisramos0
46d0023018 Adapt OC spec to new page flow with 3 steps 2019-11-12 12:00:48 +00:00
luisramos0
43cf249184 Make NoDistributors warning only appear on simple_create and simple_edit and outgoing settings 2019-11-12 12:00:48 +00:00
luisramos0
537dbd3dc0 Fix angular specs by moving specs to the same place as the code was moved previously
Quite a few copy pasted specs were also removed
2019-11-12 12:00:48 +00:00
luisramos0
7c54781d90 Restructure OC page controllers so that methods related to exchanges are only loaded on the incoming and outgoing settings pages 2019-11-12 12:00:48 +00:00
luisramos0
3b4241c70d Remove more copy pasted code by adding new AdminOrderCycleCtrl with common code from create and edit OC controllers 2019-11-12 12:00:48 +00:00
luisramos0
a290e83501 Move more copy pasted code to basic OC controller 2019-11-12 12:00:48 +00:00
luisramos0
6e0019227b Remove some serious copy/paste party of the past... by extending from new AdminOrderCycleBasicCtrl where we put all the basic methods for the OC create/edit/simple_create/simple_edit controllers 2019-11-12 12:00:48 +00:00
luisramos0
7845b6c6fb Use only AdminOrderCycleIncomingCtrl in incoming view and make AdminOrderCycleIncomingCtrl extend AdminEditOrderCycleCtrl
Same for AdminOrderCycleOutgoingCtrl
2019-11-12 12:00:48 +00:00
luisramos0
e03e3ae50a Fix the simple edit OC and the new OC page flows 2019-11-12 12:00:48 +00:00
luisramos0
305d7b1125 Adapted navigation between OC edit pages by adding new previous and next buttons 2019-11-12 12:00:48 +00:00
luisramos0
5ef751d409 Add wizard to OC new and edit pages 2019-11-12 12:00:48 +00:00
luisramos0
683232dd10 Improve page titles and fix broken translation 2019-11-12 12:00:48 +00:00
luisramos0
5f1360e226 Move incoming and outgoing parts of the (not simple) OC new and edit pages to separate routes and views to make this page a multi step page 2019-11-12 12:00:48 +00:00
luisramos0
de1d7f2877 Remove references to prototype (inexistent in OFN) in model properties 2019-11-08 17:49:35 +00:00
luisramos0
215f2897f3 Bring Property model from spree core 2019-11-08 17:48:49 +00:00
luisramos0
2d240f23a8 Converted erb properties views to haml and added lazy lookups for translations 2019-11-08 17:31:43 +00:00
luisramos0
f8b0ad29df Bring properties views from spree_backend 2019-11-08 17:18:26 +00:00
luisramos0
af1eff9427 Bring properties and product_properties controllers from spree_backend 2019-11-08 17:18:04 +00:00
dependabot-preview[bot]
5def2f6f5f Bump roadie-rails from 1.1.1 to 1.3.0
Bumps [roadie-rails](https://github.com/Mange/roadie-rails) from 1.1.1 to 1.3.0.
- [Release notes](https://github.com/Mange/roadie-rails/releases)
- [Changelog](https://github.com/Mange/roadie-rails/blob/master/Changelog.md)
- [Commits](https://github.com/Mange/roadie-rails/compare/v1.1.1...v1.3.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-07 19:18:56 +00:00
70 changed files with 1504 additions and 737 deletions

View File

@@ -0,0 +1,10 @@
Draft: x
Target commit: x
Build: x
- [ ] Draft
- [ ] Test
- [ ] Publish
- [ ] Deploy

View File

@@ -32,7 +32,6 @@ Metrics/LineLength:
- app/controllers/admin/enterprises_controller.rb
- app/controllers/admin/inventory_items_controller.rb
- app/controllers/admin/manager_invitations_controller.rb
- app/controllers/admin/order_cycles_controller.rb
- app/controllers/admin/product_import_controller.rb
- app/controllers/admin/proxy_orders_controller.rb
- app/controllers/admin/schedules_controller.rb

View File

@@ -3,7 +3,7 @@ ruby "2.2.10"
git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" }
gem 'i18n', '~> 0.6.11'
gem 'i18n-js', '~> 3.4.2'
gem 'i18n-js', '~> 3.5.0'
gem 'rails', '~> 3.2.22'
gem 'rails-i18n', '~> 3.0.0'
gem 'rails_safe_tasks', '~> 1.0'
@@ -84,7 +84,7 @@ gem 'paper_trail', '~> 5.2.3'
gem 'paperclip', '~> 3.4.1'
gem 'rack-rewrite'
gem 'rack-ssl', require: 'rack/ssl'
gem 'roadie-rails', '~> 1.1.1'
gem 'roadie-rails', '~> 1.3.0'
gem 'spinjs-rails'
gem 'combine_pdf'

View File

@@ -216,7 +216,7 @@ GEM
connection_pool (2.2.2)
crack (0.4.3)
safe_yaml (~> 1.0.0)
css_parser (1.6.0)
css_parser (1.7.0)
addressable
daemons (1.3.1)
dalli (2.7.10)
@@ -439,7 +439,7 @@ GEM
httparty (0.16.2)
multi_xml (>= 0.5.2)
i18n (0.6.11)
i18n-js (3.4.2)
i18n-js (3.5.0)
i18n (>= 0.6.6)
immigrant (0.3.6)
activerecord (>= 3.0)
@@ -482,7 +482,7 @@ GEM
money (5.1.1)
i18n (~> 0.6.0)
msgpack (1.3.1)
multi_json (1.13.1)
multi_json (1.14.1)
multi_xml (0.6.0)
multipart-post (2.1.1)
net-http-persistent (3.1.0)
@@ -564,7 +564,7 @@ GEM
thor (>= 0.14.6, < 2.0)
rainbow (3.0.0)
raindrops (0.19.0)
rake (12.3.3)
rake (13.0.0)
ransack (0.7.2)
actionpack (~> 3.0)
activerecord (~> 3.0)
@@ -585,8 +585,8 @@ GEM
roadie (3.4.0)
css_parser (~> 1.4)
nokogiri (~> 1.5)
roadie-rails (1.1.1)
railties (>= 3.0, < 5.1)
roadie-rails (1.3.0)
railties (>= 3.0, < 5.3)
roadie (~> 3.1)
roo (2.7.1)
nokogiri (~> 1)
@@ -763,7 +763,7 @@ DEPENDENCIES
gmaps4rails
haml
i18n (~> 0.6.11)
i18n-js (~> 3.4.2)
i18n-js (~> 3.5.0)
immigrant
jquery-migrate-rails
jquery-rails (= 3.0.4)
@@ -793,7 +793,7 @@ DEPENDENCIES
rails-i18n (~> 3.0.0)
rails_safe_tasks (~> 1.0)
redcarpet
roadie-rails (~> 1.1.1)
roadie-rails (~> 1.3.0)
roo (~> 2.7.0)
roo-xls (~> 1.1.0)
rspec-rails (>= 3.5.2)

View File

@@ -1,92 +1,12 @@
angular.module('admin.orderCycles')
.controller 'AdminCreateOrderCycleCtrl', ($scope, $filter, $window, OrderCycle, Enterprise, EnterpriseFee, Schedules, RequestMonitor, 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.schedules = Schedules.index({enterprise_id: ocInstance.coordinator_id})
.controller 'AdminCreateOrderCycleCtrl', ($scope, $controller, $filter, $window, OrderCycle, Enterprise, EnterpriseFee, Schedules, RequestMonitor, ocInstance, StatusMessage) ->
$controller('AdminOrderCycleBasicCtrl', {$scope: $scope, ocInstance: ocInstance})
$scope.OrderCycle = OrderCycle
$scope.order_cycle = OrderCycle.new({ coordinator_id: ocInstance.coordinator_id})
$scope.StatusMessage = StatusMessage
$scope.$watch 'order_cycle_form.$dirty', (newValue) ->
StatusMessage.display 'notice', t("admin.unsaved_changes") if newValue
$scope.$watch 'order_cycle_form.$valid', (isValid) ->
StatusMessage.setValidation(isValid)
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded && !RequestMonitor.loading
$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.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.order_cycle_form.$dirty = true
$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.enterprises = Enterprise.index(coordinator_id: ocInstance.coordinator_id)
$scope.enterprise_fees = EnterpriseFee.index(coordinator_id: ocInstance.coordinator_id)
$scope.submit = ($event, destination) ->
$event.preventDefault()
StatusMessage.display 'progress', t('js.saving')
OrderCycle.create(destination)
$scope.cancel = (destination) ->
$window.location = destination

View File

@@ -1,91 +1,17 @@
angular.module('admin.orderCycles')
.controller 'AdminEditOrderCycleCtrl', ($scope, $filter, $location, $window, OrderCycle, Enterprise, EnterpriseFee, StatusMessage, Schedules, RequestMonitor, ocInstance) ->
.controller 'AdminEditOrderCycleCtrl', ($scope, $controller, $filter, $location, $window, OrderCycle, Enterprise, EnterpriseFee, StatusMessage, Schedules, RequestMonitor, ocInstance) ->
$controller('AdminOrderCycleBasicCtrl', {$scope: $scope, ocInstance: ocInstance})
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.schedules = Schedules.index({enterprise_id: ocInstance.coordinator_id})
$scope.OrderCycle = OrderCycle
$scope.order_cycle = OrderCycle.load(order_cycle_id)
$scope.StatusMessage = StatusMessage
$scope.$watch 'order_cycle_form.$dirty', (newValue) ->
StatusMessage.display 'notice', t("admin.unsaved_changes") if newValue
$scope.$watch 'order_cycle_form.$valid', (isValid) ->
StatusMessage.setValidation(isValid)
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded && !RequestMonitor.loading
$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.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.order_cycle_form.$dirty = true
$scope.addCoordinatorFee = ($event) ->
$event.preventDefault()
OrderCycle.addCoordinatorFee()
$scope.enterprises = Enterprise.index(order_cycle_id: order_cycle_id)
$scope.enterprise_fees = EnterpriseFee.index(order_cycle_id: order_cycle_id)
$scope.removeCoordinatorFee = ($event, index) ->
$event.preventDefault()
OrderCycle.removeCoordinatorFee(index)
$scope.order_cycle_form.$dirty = true
$scope.addExchangeFee = ($event, exchange) ->
$event.preventDefault()
OrderCycle.addExchangeFee(exchange)
$scope.removeExchangeFee = ($event, exchange, index) ->
$event.preventDefault()
OrderCycle.removeExchangeFee(exchange, index)
$scope.order_cycle_form.$dirty = true
$scope.removeDistributionOfVariant = (variant_id) ->
OrderCycle.removeDistributionOfVariant(variant_id)
$scope.submit = (destination) ->
$event.preventDefault()
StatusMessage.display 'progress', t('js.saving')
@@ -94,6 +20,3 @@ angular.module('admin.orderCycles')
$event.preventDefault()
StatusMessage.display 'progress', t('js.saving')
OrderCycle.update(destination, $scope.order_cycle_form)
$scope.cancel = (destination) ->
$window.location = destination

View File

@@ -0,0 +1,5 @@
angular.module('admin.orderCycles').controller 'AdminOrderCycleIncomingCtrl', ($scope, $controller, $location, Enterprise, ocInstance) ->
$controller('AdminOrderCycleExchangesCtrl', {$scope: $scope, ocInstance: ocInstance, $location: $location})
$scope.enterpriseTotalVariants = (enterprise) ->
Enterprise.totalVariants(enterprise)

View File

@@ -0,0 +1,40 @@
angular.module('admin.orderCycles')
.controller 'AdminOrderCycleBasicCtrl', ($scope, $filter, $window, OrderCycle, Enterprise, EnterpriseFee, Schedules, RequestMonitor, ocInstance, StatusMessage) ->
$scope.StatusMessage = StatusMessage
$scope.OrderCycle = OrderCycle
$scope.$watch 'order_cycle_form.$dirty', (newValue) ->
StatusMessage.display 'notice', t("admin.unsaved_changes") if newValue
$scope.$watch 'order_cycle_form.$valid', (isValid) ->
StatusMessage.setValidation(isValid)
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded && !RequestMonitor.loading
$scope.enterpriseFeesForEnterprise = (enterprise_id) ->
EnterpriseFee.forEnterprise(parseInt(enterprise_id))
$scope.cancel = (destination) ->
$window.location = destination
# Used in panels/exchange_supplied_products.html
$scope.suppliedVariants = (enterprise_id) ->
Enterprise.suppliedVariants(enterprise_id)
# Used in panels/exchange_supplied_products.html and panels/exchange_distributed_products.html
$scope.setExchangeVariants = (exchange, variants, selected) ->
OrderCycle.setExchangeVariants(exchange, variants, selected)
# The following methods are specific to the general settings pages:
# - simple create, simple edit and general settings pages
$scope.schedules = Schedules.index({enterprise_id: ocInstance.coordinator_id})
$scope.addCoordinatorFee = ($event) ->
$event.preventDefault()
OrderCycle.addCoordinatorFee()
$scope.removeCoordinatorFee = ($event, index) ->
$event.preventDefault()
OrderCycle.removeCoordinatorFee(index)

View File

@@ -0,0 +1,46 @@
angular.module('admin.orderCycles')
.controller 'AdminOrderCycleExchangesCtrl', ($scope, $controller, $filter, $window, $location, $timeout, OrderCycle, Enterprise, EnterpriseFee, Schedules, RequestMonitor, ocInstance, StatusMessage) ->
$controller('AdminEditOrderCycleCtrl', {$scope: $scope, ocInstance: ocInstance, $location: $location})
$scope.supplier_enterprises = Enterprise.producer_enterprises
$scope.distributor_enterprises = Enterprise.hub_enterprises
$scope.supplied_products = Enterprise.supplied_products
$scope.exchangeSelectedVariants = (exchange) ->
OrderCycle.exchangeSelectedVariants(exchange)
$scope.exchangeDirection = (exchange) ->
OrderCycle.exchangeDirection(exchange)
$scope.enterprisesWithFees = ->
$scope.enterprises[id] for id in OrderCycle.participatingEnterpriseIds() when $scope.enterpriseFeesForEnterprise(id).length > 0
$scope.removeExchange = ($event, exchange) ->
$event.preventDefault()
OrderCycle.removeExchange(exchange)
$scope.order_cycle_form.$dirty = true
$scope.addExchangeFee = ($event, exchange) ->
$event.preventDefault()
OrderCycle.addExchangeFee(exchange)
$scope.removeExchangeFee = ($event, exchange, index) ->
$event.preventDefault()
OrderCycle.removeExchangeFee(exchange, index)
$scope.order_cycle_form.$dirty = true
$scope.addSupplier = ($event) ->
$event.preventDefault()
OrderCycle.addSupplier($scope.new_supplier_id)
$scope.addDistributor = ($event) ->
$event.preventDefault()
OrderCycle.addDistributor($scope.new_distributor_id)
$scope.setPickupTimeFieldDirty = (index) ->
$timeout ->
pickup_time_field_name = "order_cycle_outgoing_exchange_" + index + "_pickup_time"
$scope.order_cycle_form[pickup_time_field_name].$setDirty()
$scope.removeDistributionOfVariant = (variant_id) ->
OrderCycle.removeDistributionOfVariant(variant_id)

View File

@@ -0,0 +1,16 @@
angular.module('admin.orderCycles').controller 'AdminOrderCycleOutgoingCtrl', ($scope, $controller, $filter, $location, OrderCycle, ocInstance, StatusMessage) ->
$controller('AdminOrderCycleExchangesCtrl', {$scope: $scope, ocInstance: ocInstance, $location: $location})
$scope.productSuppliedToOrderCycle = (product) ->
OrderCycle.productSuppliedToOrderCycle(product)
$scope.variantSuppliedToOrderCycle = (variant) ->
OrderCycle.variantSuppliedToOrderCycle(variant)
$scope.incomingExchangeVariantsFor = (enterprise_id) ->
$filter('filterExchangeVariants')(OrderCycle.incomingExchangesVariants(), $scope.order_cycle.visible_variants_for_outgoing_exchanges[enterprise_id])
$scope.submit = ($event, destination) ->
$event.preventDefault()
StatusMessage.display 'progress', t('js.saving')
OrderCycle.update(destination, $scope.order_cycle_form) if OrderCycle.confirmNoDistributors()

View File

@@ -1,19 +1,12 @@
angular.module('admin.orderCycles').controller "AdminSimpleCreateOrderCycleCtrl", ($scope, $window, OrderCycle, Enterprise, EnterpriseFee, StatusMessage, Schedules, RequestMonitor, ocInstance) ->
$scope.StatusMessage = StatusMessage
$scope.OrderCycle = OrderCycle
$scope.schedules = Schedules.index({enterprise_id: ocInstance.coordinator_id})
angular.module('admin.orderCycles').controller "AdminSimpleCreateOrderCycleCtrl", ($scope, $controller, $window, OrderCycle, Enterprise, EnterpriseFee, StatusMessage, Schedules, RequestMonitor, ocInstance) ->
$controller('AdminOrderCycleBasicCtrl', {$scope: $scope, ocInstance: ocInstance})
$scope.order_cycle = OrderCycle.new {coordinator_id: ocInstance.coordinator_id}, =>
# TODO: make this a get method, which only fetches one enterprise
$scope.enterprises = Enterprise.index {coordinator_id: ocInstance.coordinator_id}, (enterprises) =>
$scope.init(enterprises)
$scope.enterprise_fees = EnterpriseFee.index(coordinator_id: ocInstance.coordinator_id)
$scope.$watch 'order_cycle_form.$dirty', (newValue) ->
StatusMessage.display 'notice', t("admin.unsaved_changes") if newValue
$scope.$watch 'order_cycle_form.$valid', (isValid) ->
StatusMessage.setValidation(isValid)
$scope.init = (enterprises) ->
enterprise = enterprises[Object.keys(enterprises)[0]]
OrderCycle.addSupplier enterprise.id
@@ -26,33 +19,10 @@ angular.module('admin.orderCycles').controller "AdminSimpleCreateOrderCycleCtrl"
OrderCycle.order_cycle.coordinator_id = enterprise.id
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded && !RequestMonitor.loading
$scope.removeDistributionOfVariant = angular.noop
$scope.setExchangeVariants = (exchange, variants, selected) ->
OrderCycle.setExchangeVariants(exchange, variants, selected)
$scope.suppliedVariants = (enterprise_id) ->
Enterprise.suppliedVariants(enterprise_id)
$scope.addCoordinatorFee = ($event) ->
$event.preventDefault()
OrderCycle.addCoordinatorFee()
$scope.removeCoordinatorFee = ($event, index) ->
$event.preventDefault()
OrderCycle.removeCoordinatorFee(index)
$scope.enterpriseFeesForEnterprise = (enterprise_id) ->
EnterpriseFee.forEnterprise(parseInt(enterprise_id))
$scope.submit = ($event, destination) ->
$event.preventDefault()
StatusMessage.display 'progress', t('js.saving')
OrderCycle.mirrorIncomingToOutgoingProducts()
OrderCycle.create(destination)
$scope.cancel = (destination) ->
$window.location = destination
OrderCycle.create(destination) if OrderCycle.confirmNoDistributors()

View File

@@ -1,51 +1,21 @@
angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl", ($scope, $location, $window, OrderCycle, Enterprise, EnterpriseFee, Schedules, RequestMonitor, StatusMessage, ocInstance) ->
angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl", ($scope, $controller, $location, $window, OrderCycle, Enterprise, EnterpriseFee, Schedules, RequestMonitor, StatusMessage, ocInstance) ->
$controller('AdminOrderCycleBasicCtrl', {$scope: $scope, ocInstance: ocInstance})
$scope.orderCycleId = ->
$location.absUrl().match(/\/admin\/order_cycles\/(\d+)/)[1]
$scope.StatusMessage = StatusMessage
$scope.enterprises = Enterprise.index(order_cycle_id: $scope.orderCycleId())
$scope.enterprise_fees = EnterpriseFee.index(order_cycle_id: $scope.orderCycleId())
$scope.schedules = Schedules.index({enterprise_id: ocInstance.coordinator_id})
$scope.OrderCycle = OrderCycle
$scope.order_cycle = OrderCycle.load $scope.orderCycleId(), (order_cycle) =>
$scope.init()
$scope.$watch 'order_cycle_form.$dirty', (newValue) ->
StatusMessage.display 'notice', t("admin.unsaved_changes") if newValue
$scope.$watch 'order_cycle_form.$valid', (isValid) ->
StatusMessage.setValidation(isValid)
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded && !RequestMonitor.loading
$scope.init = ->
$scope.outgoing_exchange = OrderCycle.order_cycle.outgoing_exchanges[0]
$scope.enterpriseFeesForEnterprise = (enterprise_id) ->
EnterpriseFee.forEnterprise(parseInt(enterprise_id))
$scope.removeDistributionOfVariant = angular.noop
$scope.setExchangeVariants = (exchange, variants, selected) ->
OrderCycle.setExchangeVariants(exchange, variants, selected)
$scope.suppliedVariants = (enterprise_id) ->
Enterprise.suppliedVariants(enterprise_id)
$scope.addCoordinatorFee = ($event) ->
$event.preventDefault()
OrderCycle.addCoordinatorFee()
$scope.removeCoordinatorFee = ($event, index) ->
$event.preventDefault()
OrderCycle.removeCoordinatorFee(index)
$scope.submit = ($event, destination) ->
$event.preventDefault()
StatusMessage.display 'progress', t('js.saving')
OrderCycle.mirrorIncomingToOutgoingProducts()
OrderCycle.update(destination, $scope.order_cycle_form)
$scope.cancel = (destination) ->
$window.location = destination
OrderCycle.update(destination, $scope.order_cycle_form) if OrderCycle.confirmNoDistributors()

View File

@@ -148,10 +148,12 @@ angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, S
this.order_cycle
create: (destination) ->
return unless @confirmNoDistributors()
oc = new OrderCycleResource({order_cycle: this.dataForSubmit()})
oc.$create (data) ->
$window.location = destination
if destination? && destination.length != 0
$window.location = destination
else if data.edit_path?
$window.location = data.edit_path
, (response) ->
if response.data.errors?
StatusMessage.display('failure', response.data.errors[0])
@@ -159,7 +161,6 @@ angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, S
StatusMessage.display('failure', t('js.order_cycles.create_failure'))
update: (destination, form) ->
return unless @confirmNoDistributors()
oc = new OrderCycleResource({order_cycle: this.dataForSubmit()})
oc.$update {order_cycle_id: this.order_cycle.id, reloading: (if destination? then 1 else 0)}, (data) =>
form.$setPristine() if form
@@ -173,7 +174,6 @@ angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, S
else
StatusMessage.display('failure', t('js.order_cycles.update_failure'))
confirmNoDistributors: ->
if @order_cycle.outgoing_exchanges.length == 0
confirm t('js.order_cycles.no_distributors')

View File

@@ -19,6 +19,9 @@ ul.wizard-progress {
line-height: 30px;
padding: 0 25px 0 40px;
position: relative;
a {
color: #494949;
}
&:first-child {
padding-left: 25px;
border-top-left-radius: 3px;
@@ -62,6 +65,9 @@ ul.wizard-progress {
&.current {
background-color: $color_selected;
color: #fff;
a {
color: #fff;
}
&:after {
background-color: $color_selected;
}

View File

@@ -4,9 +4,17 @@ module Admin
#
def index
order_params = params[:q].andand.delete :order
orders = OpenFoodNetwork::Permissions.new(spree_current_user).editable_orders.ransack(order_params).result
line_items = OpenFoodNetwork::Permissions.new(spree_current_user).editable_line_items.where(order_id: orders).ransack(params[:q])
render_as_json line_items.result.reorder('order_id ASC, id ASC')
orders = OpenFoodNetwork::Permissions.new(spree_current_user).
editable_orders.ransack(order_params).result
line_items = OpenFoodNetwork::Permissions.new(spree_current_user).
editable_line_items.where(order_id: orders).
includes(variant: { option_values: :option_type }).
ransack(params[:q]).result.
reorder('spree_line_items.order_id ASC, spree_line_items.id ASC')
render_as_json line_items
end
# PUT /admin/bulk_line_items/:id.json

View File

@@ -148,7 +148,8 @@ module Admin
unless enterprises.empty?
enterprises.includes(
supplied_products: [:supplier, :variants, master: [:images]]
supplied_products:
[:supplier, master: [:images], variants: { option_values: :option_type }]
)
end
when :index

View File

@@ -2,6 +2,7 @@ module Admin
class OrderCyclesController < ResourceController
include OrderCyclesHelper
prepend_before_filter :set_order_cycle_id, only: [:incoming, :outgoing]
before_filter :load_data_for_index, only: :index
before_filter :require_coordinator, only: :new
before_filter :remove_protected_attrs, only: [:update]
@@ -12,9 +13,10 @@ module Admin
respond_to do |format|
format.html
format.json do
render_as_json @collection, ams_prefix: params[:ams_prefix],
current_user: spree_current_user,
subscriptions_count: SubscriptionsCount.new(@collection)
render_as_json @collection,
ams_prefix: params[:ams_prefix],
current_user: spree_current_user,
subscriptions_count: SubscriptionsCount.new(@collection)
end
end
end
@@ -42,12 +44,17 @@ module Admin
if @order_cycle_form.save
flash[:notice] = I18n.t(:order_cycles_create_notice)
render json: { success: true }
render json: { success: true,
edit_path: main_app.admin_order_cycle_incoming_path(@order_cycle) }
else
render json: { errors: @order_cycle.errors.full_messages }, status: :unprocessable_entity
end
end
def set_order_cycle_id
params[:id] = params[:order_cycle_id]
end
def update
@order_cycle_form = OrderCycleForm.new(@order_cycle, params, spree_current_user)
@@ -64,9 +71,10 @@ module Admin
def bulk_update
if order_cycle_set.andand.save
render_as_json @order_cycles, ams_prefix: 'index',
current_user: spree_current_user,
subscriptions_count: SubscriptionsCount.new(@collection)
render_as_json @order_cycles,
ams_prefix: 'index',
current_user: spree_current_user,
subscriptions_count: SubscriptionsCount.new(@collection)
else
order_cycle = order_cycle_set.collection.find{ |oc| oc.errors.present? }
render json: { errors: order_cycle.errors.full_messages }, status: :unprocessable_entity
@@ -94,20 +102,8 @@ module Admin
return Enterprise.where("1=0") unless json_request?
return order_cycles_from_set if params[:order_cycle_set]
ocs = if params[:as] == "distributor"
OrderCycle.preload(:schedules).ransack(params[:q]).result.
involving_managed_distributors_of(spree_current_user).order('updated_at DESC')
elsif params[:as] == "producer"
OrderCycle.preload(:schedules).ransack(params[:q]).result.
involving_managed_producers_of(spree_current_user).order('updated_at DESC')
else
OrderCycle.preload(:schedules).ransack(params[:q]).result.accessible_by(spree_current_user)
end
ocs.undated |
ocs.soonest_closing |
ocs.soonest_opening |
ocs.closed
ocs = order_cycles
ocs.undated | ocs.soonest_closing | ocs.soonest_opening | ocs.closed
end
def collection_actions
@@ -116,21 +112,60 @@ module Admin
private
def order_cycles
if params[:as] == "distributor"
order_cycles_as_distributor
elsif params[:as] == "producer"
order_cycles_as_producer
else
order_cycles_as_both
end
end
def order_cycles_as_distributor
OrderCycle.
preload(:schedules).
ransack(params[:q]).
result.
involving_managed_distributors_of(spree_current_user).
order('updated_at DESC')
end
def order_cycles_as_producer
OrderCycle.
preload(:schedules).
ransack(params[:q]).
result.
involving_managed_producers_of(spree_current_user).
order('updated_at DESC')
end
def order_cycles_as_both
OrderCycle.
preload(:schedules).
ransack(params[:q]).
result.
accessible_by(spree_current_user)
end
def load_data_for_index
if json_request?
# Split ransack params into all those that currently exist and new ones to limit returned ocs to recent or undated
# Split ransack params into all those that currently exist and new ones
# to limit returned ocs to recent or undated
orders_close_at_gt = params[:q].andand.delete(:orders_close_at_gt) || 31.days.ago
params[:q] = {
g: [params.delete(:q) || {}, { m: 'or', orders_close_at_gt: orders_close_at_gt, orders_close_at_null: true }]
g: [params.delete(:q) || {}, { m: 'or',
orders_close_at_gt: orders_close_at_gt,
orders_close_at_null: true }]
}
@collection = collection
end
end
def require_coordinator
if params[:coordinator_id] && @order_cycle.coordinator = permitted_coordinating_enterprises_for(@order_cycle).find_by_id(params[:coordinator_id])
return
end
@order_cycle.coordinator =
permitted_coordinating_enterprises_for(@order_cycle).find_by_id(params[:coordinator_id])
return if params[:coordinator_id] && @order_cycle.coordinator
available_coordinators = permitted_coordinating_enterprises_for(@order_cycle)
case available_coordinators.count
@@ -140,7 +175,9 @@ module Admin
when 1
@order_cycle.coordinator = available_coordinators.first
else
flash[:error] = I18n.t(:order_cycles_no_permission_to_create_error) if params[:coordinator_id]
if params[:coordinator_id]
flash[:error] = I18n.t(:order_cycles_no_permission_to_create_error)
end
render :set_coordinator
end
end
@@ -164,7 +201,9 @@ module Admin
params[:order_cycle].delete :coordinator_id
unless Enterprise.managed_by(spree_current_user).include?(@order_cycle.coordinator)
params[:order_cycle].delete_if{ |k, _v| [:name, :orders_open_at, :orders_close_at].include? k.to_sym }
params[:order_cycle].delete_if do |k, _v|
[:name, :orders_open_at, :orders_close_at].include? k.to_sym
end
end
end
@@ -189,7 +228,8 @@ module Admin
def require_order_cycle_set_params
return if params[:order_cycle_set]
render json: { errors: t('admin.order_cycles.bulk_update.no_data') }, status: :unprocessable_entity
render json: { errors: t('admin.order_cycles.bulk_update.no_data') },
status: :unprocessable_entity
end
def ams_prefix_whitelist

View File

@@ -115,7 +115,8 @@ module Api
def product_query_includes
[
master: [:images],
variants: [:default_price, :stock_locations, :stock_items, :variant_overrides]
variants: [:default_price, :stock_locations, :stock_items, :variant_overrides,
{ option_values: :option_type }]
]
end

View File

@@ -6,12 +6,12 @@ module Api
before_filter :product
def index
@variants = scope.includes(:option_values).ransack(params[:q]).result
@variants = scope.includes(option_values: :option_type).ransack(params[:q]).result
render json: @variants, each_serializer: Api::VariantSerializer
end
def show
@variant = scope.includes(:option_values).find(params[:id])
@variant = scope.includes(option_values: :option_type).find(params[:id])
render json: @variant, serializer: Api::VariantSerializer
end

View File

@@ -0,0 +1,19 @@
module Spree
module Admin
class ProductPropertiesController < ResourceController
belongs_to 'spree/product', find_by: :permalink
before_filter :find_properties
before_filter :setup_property, only: [:index]
private
def find_properties
@properties = Spree::Property.pluck(:name)
end
def setup_property
@product.product_properties.build
end
end
end
end

View File

@@ -0,0 +1,6 @@
module Spree
module Admin
class PropertiesController < ResourceController
end
end
end

View File

@@ -0,0 +1,24 @@
module Spree
module Admin
class ReturnAuthorizationsController < ResourceController
belongs_to 'spree/order', find_by: :number
update.after :associate_inventory_units
create.after :associate_inventory_units
def fire
@return_authorization.public_send("#{params[:e]}!")
flash[:success] = Spree.t(:return_authorization_updated)
redirect_to :back
end
protected
def associate_inventory_units
(params[:return_quantity] || []).each do |variant_id, qty|
@return_authorization.add_variant(variant_id.to_i, qty.to_i)
end
end
end
end
end

View File

@@ -35,6 +35,7 @@ class ProducerMailer < Spree::BaseMailer
def line_items_from(order_cycle, producer)
Spree::LineItem.
includes(variant: { option_values: :option_type }).
from_order_cycle(order_cycle).
sorted_by_name_and_unit_value.
merge(Spree::Product.in_supplier(producer)).

View File

@@ -192,7 +192,7 @@ class AbilityDecorator
end
def add_order_cycle_management_abilities(user)
can [:admin, :index, :read, :edit, :update], OrderCycle do |order_cycle|
can [:admin, :index, :read, :edit, :update, :incoming, :outgoing], OrderCycle do |order_cycle|
OrderCycle.accessible_by(user).include? order_cycle
end
can [:admin, :index, :create], Schedule

View File

@@ -0,0 +1,12 @@
module Spree
class Property < ActiveRecord::Base
has_many :product_properties, dependent: :destroy
has_many :products, through: :product_properties
attr_accessible :name, :presentation
validates :name, :presentation, presence: true
scope :sorted, -> { order(:name) }
end
end

View File

@@ -14,7 +14,7 @@
%td.tags.panel-toggle.text-center{ name: "tags", ng: { if: 'enterprises[exchange.enterprise_id].managed || order_cycle.viewing_as_coordinator' } }
{{ exchange.tags.length }}
%td.collection-details
= text_field_tag 'order_cycle_outgoing_exchange_{{ $index }}_pickup_time', '', 'id' => 'order_cycle_outgoing_exchange_{{ $index }}_pickup_time', 'required' => 'required', 'placeholder' => t('.pickup_time_placeholder'), 'ng-model' => 'exchange.pickup_time', 'ng-disabled' => '!enterprises[exchange.enterprise_id].managed && !order_cycle.viewing_as_coordinator', 'maxlength' => 35
= text_field_tag 'order_cycle_outgoing_exchange_{{ $index }}_pickup_time', '', 'ng-init' => 'setPickupTimeFieldDirty($index)', 'id' => 'order_cycle_outgoing_exchange_{{ $index }}_pickup_time', 'required' => 'required', 'placeholder' => t('.pickup_time_placeholder'), 'ng-model' => 'exchange.pickup_time', 'ng-disabled' => '!enterprises[exchange.enterprise_id].managed && !order_cycle.viewing_as_coordinator', 'maxlength' => 35
%span.icon-question-sign{'ofn-with-tip' => t('.pickup_time_tip')}
%br/
= text_field_tag 'order_cycle_outgoing_exchange_{{ $index }}_pickup_instructions', '', 'id' => 'order_cycle_outgoing_exchange_{{ $index }}_pickup_instructions', 'placeholder' => t('.pickup_instructions_placeholder'), 'ng-model' => 'exchange.pickup_instructions', 'ng-disabled' => '!enterprises[exchange.enterprise_id].managed && !order_cycle.viewing_as_coordinator'

View File

@@ -1,49 +1,9 @@
= render 'wizard_progress'
%fieldset.no-border-bottom
%legend{ align: 'center'}= t('.general_settings')
= render 'name_and_timing_form', f: f
-if Enterprise.managed_by(spree_current_user).include? @order_cycle.coordinator
= render 'coordinator_fees', f: f
%h2= t('.incoming')
%table.exchanges
%thead
%tr
%th= t('.supplier')
%th
=t('.products')
= surround '(', ')' do
%a{href: '#', 'ng-click' => "OrderCycle.toggleAllProducts('incoming')"}
%span{'ng-show' => "OrderCycle.showProducts['incoming']"}= t(:collapse_all)
%span{'ng-hide' => "OrderCycle.showProducts['incoming']"}= t(:expand_all)
%th= t('.receival_details')
%th= t('.fees')
%th.actions
%tbody.panel-ctrl{ object: 'exchange', 'ng-repeat' => 'exchange in order_cycle.incoming_exchanges'}
= render 'exchange_form', f: f, type: 'supplier'
- if Enterprise.managed_by(spree_current_user).include? @order_cycle.coordinator
= render 'add_exchange_form', f: f, type: 'supplier'
%h2= t('.outgoing')
%table.exchanges
%thead
%tr
%th= t('.distributor')
%th
= t('.products')
= surround '(', ')' do
%a{href: '#', 'ng-click' => "OrderCycle.toggleAllProducts('outgoing')"}
%span{'ng-show' => "OrderCycle.showProducts['outgoing']"}= t(:collapse_all)
%span{'ng-hide' => "OrderCycle.showProducts['outgoing']"}= t(:expand_all)
%th{ ng: { if: 'enterprises[exchange.enterprise_id].managed || order_cycle.viewing_as_coordinator' } }
= t('.tags')
%th= t('.delivery_details')
%th= t('.fees')
%th.actions
%tbody.panel-ctrl{ object: 'exchange', 'ng-repeat' => 'exchange in order_cycle.outgoing_exchanges'}
= render 'exchange_form', f: f, type: 'distributor'
- if Enterprise.managed_by(spree_current_user).include? @order_cycle.coordinator
= render 'add_exchange_form', f: f, type: 'distributor'
.actions
%span{'ng-hide' => 'loaded()'}= t(:loading)

View File

@@ -0,0 +1,18 @@
%ul.wizard-progress
- if action_name == 'new'
%li{ class: "current" }
= t("admin.order_cycles.wizard_progress.edit")
%li
= t("admin.order_cycles.wizard_progress.incoming")
%li
= t("admin.order_cycles.wizard_progress.outgoing")
- else
%li{ class: "#{'current' if action_name == 'edit'}" }
%a{ href: main_app.edit_admin_order_cycle_path(@order_cycle) }
= t("admin.order_cycles.wizard_progress.edit")
%li{ class: "#{'current' if action_name == 'incoming'}" }
%a{ href: main_app.admin_order_cycle_incoming_path(@order_cycle) }
= t("admin.order_cycles.wizard_progress.incoming")
%li{ class: "#{'current' if action_name == 'outgoing'}" }
%a{ href: main_app.admin_order_cycle_outgoing_path(@order_cycle) }
= t("admin.order_cycles.wizard_progress.outgoing")

View File

@@ -21,7 +21,7 @@
#advanced_settings{ hidden: true }
= render partial: "/admin/order_cycles/advanced_settings"
%h1
- content_for :page_title do
= t :edit_order_cycle
- ng_controller = order_cycles_simple_form ? 'AdminSimpleEditOrderCycleCtrl' : 'AdminEditOrderCycleCtrl'
@@ -29,9 +29,13 @@
= form_for [main_app, :admin, @order_cycle], :url => '', :html => {:class => 'ng order_cycle', 'ng-app' => 'admin.orderCycles', 'ng-controller' => ng_controller, name: 'order_cycle_form'} do |f|
%save-bar{ dirty: "order_cycle_form.$dirty", persist: "true" }
%input.red{ type: "button", value: t(:update), ng: { click: "submit($event, null)", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } }
%input.red{ type: "button", value: t('.update_and_close'), ng: { click: "submit($event, '#{main_app.admin_order_cycles_path}')", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } }
%input{ type: "button", ng: { value: "order_cycle_form.$dirty ? '#{t(:cancel)}' : '#{t(:close)}'", click: "cancel('#{main_app.admin_order_cycles_path}')" } }
%input.red{ type: "button", value: t('.save'), ng: { click: "submit($event, null)", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } }
- if order_cycles_simple_form
%input.red{ type: "button", value: t('.save_and_back_to_list'), ng: { click: "submit($event, '#{main_app.admin_order_cycles_path}')", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } }
- else
%input.red{ type: "button", value: t('.save_and_next'), ng: { click: "submit($event, '#{main_app.admin_order_cycle_incoming_path(@order_cycle)}')", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } }
%input{ type: "button", value: t('.next'), ng: { click: "cancel('#{main_app.admin_order_cycle_incoming_path(@order_cycle)}')", disabled: "order_cycle_form.$dirty" } }
%input{ type: "button", ng: { value: "order_cycle_form.$dirty ? '#{t('.cancel')}' : '#{t('.back_to_list')}'", click: "cancel('#{main_app.admin_order_cycles_path}')" } }
- if order_cycles_simple_form
= render 'simple_form', f: f

View File

@@ -0,0 +1,39 @@
- content_for :page_title do
= t :edit_order_cycle
= admin_inject_order_cycle_instance
= form_for [main_app, :admin, @order_cycle], :url => '', :html => {:class => 'ng order_cycle', 'ng-app' => 'admin.orderCycles', 'ng-controller' => 'AdminOrderCycleIncomingCtrl', name: 'order_cycle_form'} do |f|
= render 'wizard_progress'
%save-bar{ dirty: "order_cycle_form.$dirty", persist: "true" }
%input{ type: "button", value: t('.previous'), ng: { click: "cancel('#{main_app.edit_admin_order_cycle_path(@order_cycle)}')", disabled: "order_cycle_form.$dirty" } }
%input.red{ type: "button", value: t('.save'), ng: { click: "submit($event, null)", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } }
%input.red{ type: "button", value: t('.save_and_next'), ng: { click: "submit($event, '#{main_app.admin_order_cycle_outgoing_path(@order_cycle)}')", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } }
%input{ type: "button", value: t('.next'), ng: { click: "cancel('#{main_app.admin_order_cycle_outgoing_path(@order_cycle)}')", disabled: "order_cycle_form.$dirty" } }
%input{ type: "button", ng: { value: "order_cycle_form.$dirty ? '#{t('.cancel')}' : '#{t('.back_to_list')}'", click: "cancel('#{main_app.admin_order_cycles_path}')" } }
%fieldset.no-border-bottom
%legend{ align: 'center'}= t('.incoming')
%table.exchanges
%thead
%tr
%th= t('.supplier')
%th
= t('.products')
= surround '(', ')' do
%a{href: '#', 'ng-click' => "OrderCycle.toggleAllProducts('incoming')"}
%span{'ng-show' => "OrderCycle.showProducts['incoming']"}= t(:collapse_all)
%span{'ng-hide' => "OrderCycle.showProducts['incoming']"}= t(:expand_all)
%th= t('.receival_details')
%th= t('.fees')
%th.actions
%tbody.panel-ctrl{ object: 'exchange', 'ng-repeat' => 'exchange in order_cycle.incoming_exchanges'}
= render 'exchange_form', f: f, type: 'supplier'
- if Enterprise.managed_by(spree_current_user).include? @order_cycle.coordinator
= render 'add_exchange_form', f: f, type: 'supplier'
.actions
%span{'ng-hide' => 'loaded()'}= t(:loading)

View File

@@ -7,8 +7,10 @@
= form_for [main_app, :admin, @order_cycle], :url => '', :html => {:class => 'ng order_cycle', 'ng-app' => 'admin.orderCycles', 'ng-controller' => ng_controller, name: 'order_cycle_form'} do |f|
%save-bar{ dirty: "order_cycle_form.$dirty", persist: "true" }
%input.red{ type: "button", value: t(:create), ng: { click: "submit($event, '#{main_app.admin_order_cycles_path}')", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } }
%input{ type: "button", ng: { value: "order_cycle_form.$dirty ? 'Cancel' : 'Close'", click: "cancel('#{main_app.admin_order_cycles_path}')" } }
- if order_cycles_simple_form
- custom_redirect_path = main_app.admin_order_cycles_path
%input.red{ type: "button", value: t('.create'), ng: { click: "submit($event, '#{custom_redirect_path}')", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } }
%input{ type: "button", ng: { value: "order_cycle_form.$dirty ? '#{t('.cancel')}' : '#{t('.back_to_list')}'", click: "cancel('#{main_app.admin_order_cycles_path}')" } }
- if order_cycles_simple_form
= render 'simple_form', f: f

View File

@@ -0,0 +1,40 @@
- content_for :page_title do
= t :edit_order_cycle
= admin_inject_order_cycle_instance
= form_for [main_app, :admin, @order_cycle], :url => '', :html => {:class => 'ng order_cycle', 'ng-app' => 'admin.orderCycles', 'ng-controller' => 'AdminOrderCycleOutgoingCtrl', name: 'order_cycle_form'} do |f|
= render 'wizard_progress'
%save-bar{ dirty: "order_cycle_form.$dirty", persist: "true" }
%input{ type: "button", value: t('.previous'), ng: { click: "cancel('#{main_app.admin_order_cycle_incoming_path(@order_cycle)}')", disabled: "order_cycle_form.$dirty" } }
%input.red{ type: "button", value: t('.save'), ng: { click: "submit($event, null)", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } }
%input.red{ type: "button", value: t('.save_and_back_to_list'), ng: { click: "submit($event, '#{main_app.admin_order_cycles_path}')", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } }
%input{ type: "button", ng: { value: "order_cycle_form.$dirty ? '#{t('.cancel')}' : '#{t('.back_to_list')}'", click: "cancel('#{main_app.admin_order_cycles_path}')" } }
%fieldset.no-border-bottom
%legend{ align: 'center'}= t('.outgoing')
%table.exchanges
%thead
%tr
%th= t('.distributor')
%th
= t('.products')
= surround '(', ')' do
%a{href: '#', 'ng-click' => "OrderCycle.toggleAllProducts('outgoing')"}
%span{'ng-show' => "OrderCycle.showProducts['outgoing']"}= t(:collapse_all)
%span{'ng-hide' => "OrderCycle.showProducts['outgoing']"}= t(:expand_all)
%th{ ng: { if: 'enterprises[exchange.enterprise_id].managed || order_cycle.viewing_as_coordinator' } }
= t('.tags')
%th= t('.delivery_details')
%th= t('.fees')
%th.actions
%tbody.panel-ctrl{ object: 'exchange', 'ng-repeat' => 'exchange in order_cycle.outgoing_exchanges'}
= render 'exchange_form', f: f, type: 'distributor'
- if Enterprise.managed_by(spree_current_user).include? @order_cycle.coordinator
= render 'add_exchange_form', f: f, type: 'distributor'
.actions
%span{'ng-hide' => 'loaded()'}= t(:loading)

View File

@@ -0,0 +1,15 @@
.align-center.row
.alpha.eight.columns
= f.field_container :name do
= f.label :name, t('.name')
%span.required *
%br/
= f.text_field :name, class: 'fullwidth'
= f.error_message_on :name
.eight.columns.omega
= f.field_container :presentation do
= f.label :presentation, t('.presentation')
%span.required *
%br/
= f.text_field :presentation, class: 'fullwidth'
= f.error_message_on :presentation

View File

@@ -0,0 +1,14 @@
= render partial: 'spree/admin/shared/product_sub_menu'
- content_for :page_title do
= t('.editing_property')
- content_for :page_actions do
%li= button_link_to t('.back_to_properties_list'), admin_properties_url, icon: 'icon-arrow-left'
= render partial: 'spree/shared/error_messages', locals: { target: @property }
= form_for [:admin, @property] do |f|
%fieldset.no-border-top
= render partial: 'form', locals: { f: f }
= render partial: 'spree/admin/shared/edit_resource_links'

View File

@@ -0,0 +1,30 @@
- content_for :page_title do
= t('.properties')
- content_for :page_actions do
%li#new_property_link
= button_link_to t('.new_property'), new_admin_property_url, { remote: true, icon: 'icon-plus', 'data-update' => 'new_property', id: 'new_property_link' }
= render partial: 'spree/admin/shared/product_sub_menu'
#new_property
%table#listing_properties.index
%colgroup
%col{style: "width: 45%"}/
%col{style: "width: 45%"}/
%col{style: "width: 10%"}/
%thead
%tr
%th= t('.name')
%th= t('.presentation')
%th.actions
%tbody
- @properties.each do |property|
- tr_class = cycle('odd', 'even')
- tr_id = spree_dom_id(property)
%tr{class: tr_class, id: tr_id}
%td= property.name
%td= property.presentation
%td.actions
= link_to_edit(property, no_text: true)
= link_to_delete(property, no_text: true)

View File

@@ -0,0 +1,10 @@
= render partial: 'spree/admin/shared/product_sub_menu'
= render partial: 'spree/shared/error_messages', locals: { target: @property }
= form_for [:admin, @property] do |f|
%fieldset
%legend{align: "center"}= t('.new_property')
= render partial: 'form', locals: { f: f }
.filter-actions
= render partial: 'spree/admin/shared/new_resource_links'

View File

@@ -0,0 +1,2 @@
$("#new_property").html('<%= escape_javascript(render :template => "spree/admin/properties/new", :formats => [:html], :handlers => [:erb]) %>');
$("#new_property_link").parent().hide();

View File

@@ -0,0 +1,48 @@
%div
%table.index
%thead
%tr
%th= t('.product')
%th= t('.quantity_shipped')
%th= t('.quantity_returned')
%th= t('.return_quantity')
%tbody
- @return_authorization.order.shipments.shipped.collect{|s| s.inventory_units.all}.flatten.group_by(&:variant).each do | variant, units|
- tr_class = cycle('odd', 'even')
- tr_id = dom_id(variant)
%tr{class: tr_class, id: tr_id}
%td
.variant-name= variant.name
.variant-options= variant.options_text
%td.align-center= units.select(&:shipped?).size
%td.align-center= units.select(&:returned?).size
%td.return_quantity.align-center
- if @return_authorization.received?
= @return_authorization.inventory_units.group_by(&:variant)[variant].try(:size) || 0
- elsif units.select(&:shipped?).empty?
0
- else
= number_field_tag "return_quantity[#{variant.id}]", @return_authorization.inventory_units.group_by(&:variant)[variant].try(:size) || 0, { style: 'width:100px;', min: 0 }
= f.field_container :amount do
= f.label :amount, t('.amount')
%span.required *
%br/
- if @return_authorization.received?
= @return_authorization.display_amount
- else
= f.text_field :amount, { style: 'width:80px;' }
= t('.rma_value')
\:
%span#rma_value 0.00
= f.error_message_on :amount
= f.field_container :reason do
= f.label :reason, t('.reason')
= f.text_area :reason, { style: 'height:100px;', class: 'fullwidth' }
= f.error_message_on :reason
= f.field_container :stock_location do
= f.label :stock_location, t('.stock_location')
= f.select :stock_location_id, Spree::StockLocation.active.all.collect{ |l| [l.name, l.id] }, { style: 'height:100px;', class: 'fullwidth' }
= f.error_message_on :reason

View File

@@ -0,0 +1,25 @@
- content_for :page_actions do
%li
- if @return_authorization.can_receive?
= button_link_to t('.receive'), fire_admin_order_return_authorization_url(@order, @return_authorization, e: 'receive'), method: :put, data: { confirm: t('.are_you_sure') }, icon: 'icon-download-alt'
%li
- if @return_authorization.can_cancel?
= button_link_to t('actions.cancel'), fire_admin_order_return_authorization_url(@order, @return_authorization, e: 'cancel'), method: :put, data: { confirm: t('.are_you_sure') }, icon: 'icon-remove'
= render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Return Authorizations' }
- content_for :page_title do
%i.icon-arrow-right
= t('.return_authorization')
= @return_authorization.number
(#{t("spree.admin.return_authorizations.states." + @return_authorization.state.downcase)})
= render partial: 'spree/shared/error_messages', locals: { target: @return_authorization }
= form_for [:admin, @order, @return_authorization] do |f|
%fieldset.no-border-top
= render partial: 'form', locals: { f: f }
.form-buttons.filter-actions.actions
= button t('actions.update'), 'icon-repeat'
%span.or= t(:or)
= button_link_to t('actions.cancel'), admin_order_return_authorizations_url(@order), icon: 'icon-remove'

View File

@@ -0,0 +1,39 @@
= render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Return Authorizations' }
- content_for :page_actions do
- if @order.shipments.any? &:shipped?
%li
= button_link_to t('.new_return_authorization'), new_admin_order_return_authorization_url(@order), icon: 'icon-plus'
%li= button_link_to t('.back_to_orders_list'), spree.admin_orders_path, icon: 'icon-arrow-left'
- content_for :page_title do
%i.icon-arrow-right
= t('.return_authorizations')
- if @order.shipments.any?(&:shipped?) || @order.return_authorizations.any?
%table.index
%thead
%tr
%th= t('.rma_number')
%th= t('.status')
%th= t('.amount')
%th= "#{t('spree.date')}/#{t('spree.time')}"
%th.actions
%tbody
- @return_authorizations.each do |return_authorization|
- tr_class = cycle('odd', 'even')
- tr_id = spree_dom_id(return_authorization)
%tr{class: tr_class, id: tr_id}
%td= return_authorization.number
%td= Spree.t('spree.admin.return_authorizations.states.' + return_authorization.state.downcase)
%td= return_authorization.display_amount.to_html
%td= pretty_time(return_authorization.created_at)
%td.actions
= link_to_edit return_authorization, no_text: true, class: 'edit'
- unless return_authorization.received?
&nbsp;
= link_to_delete return_authorization, no_text: true
- else
.no-objects-found
= t('.cannot_create_returns')
= button_link_to t('.continue'), admin_orders_url, icon: 'icon-arrow-right'

View File

@@ -0,0 +1,18 @@
= render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Return Authorizations' }
- content_for :page_title do
%i.icon-arrow-right
= t('.new_return_authorization')
- content_for :page_actions do
%li= button_link_to t('.back_to_return_authorizations_list'), spree.admin_order_return_authorizations_url, icon: 'icon-arrow-left'
= render partial: 'spree/shared/error_messages', locals: { target: @return_authorization }
= form_for [:admin, @order, @return_authorization] do |f|
%fieldset.no-border-top
= render partial: 'form', locals: { f: f }
.form-buttons.filter-actions.actions
= button t('.continue'), 'icon-arrow-right'
%span.or= t(:or)
= button_link_to t('actions.cancel'), admin_order_return_authorizations_url(@order), icon: 'icon-remove'

View File

@@ -832,10 +832,36 @@ ar:
loading_flash:
loading_order_cycles: تحميل دورات الطلب
loading: جار التحميل...
new:
create: "انشاء"
cancel: "إلغاء"
back_to_list: "العودة للقائمة"
edit:
advanced_settings: إعدادات متقدمة
update_and_close: تحديث وإغلاق
choose_products_from: 'اختر المنتجات من:'
advanced_settings: "إعدادات متقدمة"
save: "حفظ"
save_and_next: "حفظ والتالي"
next: "التالى"
cancel: "إلغاء"
back_to_list: "العودة للقائمة"
save_and_back_to_list: "حفظ والعودة إلى القائمة"
choose_products_from: "اختر المنتجات من:"
incoming:
previous: "السابق"
save: "حفظ"
save_and_next: "حفظ والتالي"
next: "التالى"
cancel: "إلغاء"
back_to_list: "العودة للقائمة"
outgoing:
previous: "السابق"
save: "حفظ"
save_and_back_to_list: "حفظ والعودة إلى القائمة"
cancel: "إلغاء"
back_to_list: "العودة للقائمة"
wizard_progress:
edit: "1. الإعدادات العامة"
incoming: "2. المنتجات الواردة"
outgoing: "3. المنتجات الصادرة"
exchange_form:
pickup_time_tip: عندما تكون الطلبات من OC جاهزة للعميل
pickup_instructions_placeholder: "تعليمات التحميل"
@@ -862,6 +888,7 @@ ar:
any_enterprise: "أي شركة"
any_schedule: "أي جدول"
form:
general_settings: "الاعدادات العامة"
incoming: الوارد
supplier: المورد
receival_details: تفاصيل الاستلام
@@ -2831,6 +2858,20 @@ ar:
inherits_properties_checkbox_hint: "وراثة الخصائص من %{supplier}؟ (ما لم يتم تجاوزه أعلاه)"
add_product_properties: "إضافة خصائص المنتج"
select_from_prototype: "حدد من النموذج الأولي"
properties:
index:
properties: "الخصائص"
new_property: "خصائص جديدة"
name: "الاسم"
presentation: "عرض"
new:
new_property: "خصائص جديدة"
edit:
editing_property: "تحرير الخصائص"
back_to_properties_list: "العودة إلى قائمة الخصائص"
form:
name: "الاسم"
presentation: "عرض"
orders:
index:
listing_orders: "لائحة الطلبات"

View File

@@ -295,6 +295,7 @@ en:
cancel: "Cancel"
save: "Save"
edit: "Edit"
update: "Update"
delete: "Delete"
admin:
@@ -888,10 +889,36 @@ en:
loading_flash:
loading_order_cycles: LOADING ORDER CYCLES
loading: LOADING...
new:
create: "Create"
cancel: "Cancel"
back_to_list: "Back To List"
edit:
advanced_settings: Advanced Settings
update_and_close: Update and Close
choose_products_from: 'Choose Products From:'
advanced_settings: "Advanced Settings"
save: "Save"
save_and_next: "Save and Next"
next: "Next"
cancel: "Cancel"
back_to_list: "Back To List"
save_and_back_to_list: "Save and Back to List"
choose_products_from: "Choose Products From:"
incoming:
previous: "Previous"
save: "Save"
save_and_next: "Save and Next"
next: "Next"
cancel: "Cancel"
back_to_list: "Back To List"
outgoing:
previous: "Previous"
save: "Save"
save_and_back_to_list: "Save and Back to List"
cancel: "Cancel"
back_to_list: "Back To List"
wizard_progress:
edit: "1. General Settings"
incoming: "2. Incoming Products"
outgoing: "3. Outgoing Products"
exchange_form:
pickup_time_tip: When orders from this OC will be ready for the customer
pickup_instructions_placeholder: "Pick-up instructions"
@@ -918,6 +945,7 @@ en:
any_enterprise: "Any Enterprise"
any_schedule: "Any Schedule"
form:
general_settings: "General Settings"
incoming: Incoming
supplier: Supplier
products: Products
@@ -2992,6 +3020,51 @@ See the %{link} to find out more about %{sitename}'s features and to start using
inherits_properties_checkbox_hint: "Inherit properties from %{supplier}? (unless overridden above)"
add_product_properties: "Add Product Properties"
select_from_prototype: "Select From Prototype"
properties:
index:
properties: "Properties"
new_property: "New Property"
name: "Name"
presentation: "Presentation"
new:
new_property: "New Property"
edit:
editing_property: "Editing Property"
back_to_properties_list: "Back To Properties List"
form:
name: "Name"
presentation: "Presentation"
return_authorizations:
index:
new_return_authorization: "New Return Authorization"
return_authorizations: "Return Authorizations"
back_to_orders_list: "Back To Orders List"
rma_number: "RMA Number"
status: "Status"
amount: "Amount"
cannot_create_returns: "Cannot create returns as this order has no shipped units."
continue: "Continue"
new:
new_return_authorization: "New Return Authorization"
back_to_return_authorizations_list: "Back To Return Authorization List"
continue: "Continue"
edit:
receive: "receive"
are_you_sure: "Are you sure?"
return_authorization: "Return Authorization"
form:
product: "Product"
quantity_shipped: "Quantity Shipped"
quantity_returned: "Quantity Returned"
return_quantity: "Return Quantity"
amount: "Amount"
rma_value: "RMA Value"
reason: "Reason"
stock_location: "Stock Location"
states:
authorized: "Authorized"
received: "Received"
canceled: "Canceled"
orders:
index:
listing_orders: "Listing Orders"

View File

@@ -114,7 +114,9 @@ en_CA:
email_welcome: "Welcome"
email_registered: "is now part of"
email_userguide_html: "The User Guide with detailed support for setting up your Producer or Hub is here: %{link}"
userguide: "Open Food Network User Guide"
email_admin_html: "You can manage your account by logging into the %{link} or by clicking on the cog in the top right hand side of the homepage, and selecting Administration."
admin_panel: "Admin Panel"
email_community_html: "We also have an online forum for community discussion related to OFN software and the unique challenges of running a food enterprise. You are encouraged to join in. We are constantly evolving and your input into this forum will shape what happens next. %{link}"
join_community: "Join the community"
invite_manager:
@@ -389,7 +391,7 @@ en_CA:
user_guide: User Guide
enterprise_fees:
index:
title: "Enterprise Fees/Mark-Ups"
title: "Enterprise Fees"
enterprise: "Enterprise"
fee_type: "Fee Type"
name: "Name"
@@ -431,9 +433,12 @@ en_CA:
infinity: "Infinity"
to_order_tip: "Items made to order do not have a set stock level, such as loaves of bread made fresh to order."
back_to_products_list: "Back to products list"
editing_product: "Editing Product"
tabs:
product_details: "Product Details"
group_buy_options: "Group Buy Options"
images: "Images"
variants: "Variants"
product_properties: "Product Properties"
product_import:
title: Product Import
@@ -536,6 +541,7 @@ en_CA:
title: Inventory
description: Use this page to manage inventories for your enterprises. Any product details set here will override those set on the 'Products' page
enable_reset?: Enable Stock Reset?
default_stock: "Default Stock"
inherit?: Inherit?
add: Add
hide: Hide
@@ -827,10 +833,36 @@ en_CA:
loading_flash:
loading_order_cycles: LOADING ORDER CYCLES
loading: LOADING....
new:
create: "Create"
cancel: "Cancel"
back_to_list: "Back to List"
edit:
advanced_settings: Advanced Settings
update_and_close: Update and Close
choose_products_from: 'Choose Products From:'
advanced_settings: "Advanced Settings"
save: "Save"
save_and_next: "Save and Next"
next: "Next"
cancel: "Cancel"
back_to_list: "Back to List"
save_and_back_to_list: "Save and Back to List"
choose_products_from: "Choose Products From:"
incoming:
previous: "Previous"
save: "Save"
save_and_next: "Save and Next"
next: "Next"
cancel: "Cancel"
back_to_list: "Back to List"
outgoing:
previous: "Previous"
save: "Save"
save_and_back_to_list: "Save and Back to List"
cancel: "Cancel"
back_to_list: "Back to List"
wizard_progress:
edit: "1. General Settings"
incoming: "2. Incoming Products"
outgoing: "3. Outgoing Products"
exchange_form:
pickup_time_tip: When orders from this OC will be ready for the customer
pickup_instructions_placeholder: "Pick-up instructions"
@@ -857,6 +889,7 @@ en_CA:
any_enterprise: "Any Enterprise"
any_schedule: "Any Schedule"
form:
general_settings: "General Settings"
incoming: Incoming
supplier: Supplier
receival_details: Receival details
@@ -1163,7 +1196,7 @@ en_CA:
menu_4_title: "Groups"
menu_4_url: "/groups"
menu_5_title: "About"
menu_5_url: "https://about.openfoodnetwork.org.au/"
menu_5_url: "https://about.openfoodnetwork.ca"
menu_6_title: "Connect"
menu_6_url: "https://openfoodnetwork.org/au/connect/"
menu_7_title: "Learn"
@@ -1807,7 +1840,7 @@ en_CA:
enterprise_final_step: "Final step!"
enterprise_social_text: "How can people find %{enterprise} online?"
website: "Website"
website_placeholder: "eg. openfoodnetwork.org.au"
website_placeholder: "eg. openfoodnetwork.ca"
facebook: "Facebook"
facebook_placeholder: "eg. www.facebook.com/PageNameHere"
linkedin: "LinkedIn"
@@ -2774,6 +2807,12 @@ en_CA:
minimal_amount: "Minimal Amount"
normal_amount: "Normal Amount"
discount_amount: "Discount Amount"
no_images_found: "No Images Found"
new_image: "New Image"
filename: "Filename"
alt_text: "Alternative Text"
thumbnail: "Thumbnail"
back_to_images_list: "Back to Images List"
email: Email
account_updated: "Account updated!"
email_updated: "The account will be updated once the new email is confirmed."
@@ -2785,6 +2824,7 @@ en_CA:
zipcode: Postal Code
weight: Weight (per kg)
error_user_destroy_with_orders: "Users with completed orders may not be deleted"
options: "Options"
actions:
update: "Update"
errors:
@@ -2816,6 +2856,22 @@ en_CA:
product_properties:
index:
inherits_properties_checkbox_hint: "Inherit properties from %{supplier}? (unless overridden above)"
add_product_properties: "Add Product Properties"
select_from_prototype: "Select From Prototype"
properties:
index:
properties: "Properties"
new_property: "New Property"
name: "Name"
presentation: "Presentation"
new:
new_property: "New Property"
edit:
editing_property: "Editing Property"
back_to_properties_list: "Back to Properties List"
form:
name: "Name"
presentation: "Presentation"
orders:
index:
listing_orders: "Listing Orders"
@@ -3006,12 +3062,23 @@ en_CA:
index:
sku: "SKU"
price: "Price"
options: "Options"
no_results: "No results"
to_add_variants_you_must_first_define: "To add variants, you must first define"
option_types: "Option Types"
option_values: "Option Values"
and: "and"
new_variant: "New Variant"
show_active: "Show Active"
show_deleted: "Show Deleted"
new:
new_variant: "New Variant"
form:
cost_price: "Cost Price"
sku: "SKU"
price: "Price"
display_as: "Display As"
display_name: "Display Name"
autocomplete:
producer_name: "Producer"
unit: "Unit"
@@ -3151,3 +3218,19 @@ en_CA:
allow_charges?: "Allow Charges?"
localized_number:
invalid_format: has an invalid format. Please enter a number.
api:
invalid_api_key: "Invalid API key (%{key}) specified."
unauthorized: "You are not authorized to perform that action."
invalid_resource: "Invalid resource. Please fix errors and try again."
resource_not_found: "The resource you were looking for could not be found."
access: "API Access"
key: "Key"
clear_key: "Clear key"
regenerate_key: "Regenerate Key"
no_key: "No key"
generate_key: "Generate API key"
key_generated: "Key generated"
key_cleared: "Key cleared"
shipment:
cannot_ready: "Cannot ready shipment."
invalid_taxonomy_id: "Invalid taxonomy id."

View File

@@ -262,6 +262,7 @@ en_FR:
cancel: "Cancel"
save: "Save"
edit: "Edit"
update: "Update"
delete: "Delete"
admin:
begins_at: Begins At
@@ -833,10 +834,36 @@ en_FR:
loading_flash:
loading_order_cycles: LOADING ORDER CYCLES
loading: LOADING...
new:
create: "Create"
cancel: "Cancel"
back_to_list: "Back To List"
edit:
advanced_settings: Advanced Settings
update_and_close: Update and Close
choose_products_from: 'Choose Products From:'
advanced_settings: "Advanced Settings"
save: "Save"
save_and_next: "Save and Next"
next: "Next"
cancel: "Cancel"
back_to_list: "Back To List"
save_and_back_to_list: "Save and Back to List"
choose_products_from: "Choose Products From:"
incoming:
previous: "Previous"
save: "Save"
save_and_next: "Save and Next"
next: "Next"
cancel: "Cancel"
back_to_list: "Back To List"
outgoing:
previous: "Previous"
save: "Save"
save_and_back_to_list: "Save and Back to List"
cancel: "Cancel"
back_to_list: "Back To List"
wizard_progress:
edit: "1. General Settings"
incoming: "2. Incoming Products"
outgoing: "3. Outgoing Products"
exchange_form:
pickup_time_tip: When orders from this OC will be ready for the customer
pickup_instructions_placeholder: "Pick-up instructions"
@@ -863,6 +890,7 @@ en_FR:
any_enterprise: "Any Enterprise"
any_schedule: "Any Schedule"
form:
general_settings: "General Settings"
incoming: Incoming
supplier: Supplier
receival_details: Receival details
@@ -2831,6 +2859,51 @@ en_FR:
inherits_properties_checkbox_hint: "Inherit properties from %{supplier}? (unless overridden above)"
add_product_properties: "Add Product Properties"
select_from_prototype: "Select From Prototype"
properties:
index:
properties: "Properties"
new_property: "New Property"
name: "Name"
presentation: "Presentation"
new:
new_property: "New Property"
edit:
editing_property: "Editing Property"
back_to_properties_list: "Back To Properties List"
form:
name: "Name"
presentation: "Presentation"
return_authorizations:
index:
new_return_authorization: "New Return Authorization"
return_authorizations: "Return Authorizations"
back_to_orders_list: "Back To Orders List"
rma_number: "RMA Number"
status: "Status"
amount: "Amount"
cannot_create_returns: "Cannot create returns as this order has no shipped units."
continue: "Continue"
new:
new_return_authorization: "New Return Authorization"
back_to_return_authorizations_list: "Back To Return Authorization List"
continue: "Continue"
edit:
receive: "receive"
are_you_sure: "Are you sure?"
return_authorization: "Return Authorization"
form:
product: "Product"
quantity_shipped: "Quantity Shipped"
quantity_returned: "Quantity Returned"
return_quantity: "Return Quantity"
amount: "Amount"
rma_value: "RMA Value"
reason: "Reason"
stock_location: "Stock Location"
states:
authorized: "Authorized"
received: "Received"
canceled: "Canceled"
orders:
index:
listing_orders: "Listing Orders"

View File

@@ -433,9 +433,12 @@ en_NZ:
infinity: "Infinity"
to_order_tip: "Items made to order do not have a set stock level, such as loaves of bread made fresh to order."
back_to_products_list: "Back to products list"
editing_product: "Editing Product"
tabs:
product_details: "Product Details"
group_buy_options: "Group Buy Options"
images: "Images"
variants: "Variants"
product_properties: "Product Properties"
product_import:
title: Product Import
@@ -2777,6 +2780,12 @@ en_NZ:
minimal_amount: "Minimal Amount"
normal_amount: "Normal Amount"
discount_amount: "Discount Amount"
no_images_found: "No Images Found"
new_image: "New Image"
filename: "Filename"
alt_text: "Alternative Text"
thumbnail: "Thumbnail"
back_to_images_list: "Back To Images List"
email: Email
account_updated: "Account updated!"
email_updated: "The account will be updated once the new email is confirmed."
@@ -2788,6 +2797,7 @@ en_NZ:
zipcode: Postcode
weight: Weight (per kg)
error_user_destroy_with_orders: "Users with completed orders may not be deleted"
options: "Options"
actions:
update: "Update"
errors:
@@ -2819,6 +2829,22 @@ en_NZ:
product_properties:
index:
inherits_properties_checkbox_hint: "Inherit properties from %{supplier}? (unless overridden above)"
add_product_properties: "Add Product Properties"
select_from_prototype: "Select From Prototype"
properties:
index:
properties: "Properties"
new_property: "New Property"
name: "Name"
presentation: "Presentation"
new:
new_property: "New Property"
edit:
editing_property: "Editing Property"
back_to_properties_list: "Back To Properties List"
form:
name: "Name"
presentation: "Presentation"
orders:
index:
listing_orders: "Listing Orders"
@@ -3009,12 +3035,23 @@ en_NZ:
index:
sku: "SKU"
price: "Price"
options: "Options"
no_results: "No results"
to_add_variants_you_must_first_define: "To add variants, you must first define"
option_types: "Option Types"
option_values: "Option Values"
and: "and"
new_variant: "New Variant"
show_active: "Show Active"
show_deleted: "Show Deleted"
new:
new_variant: "New Variant"
form:
cost_price: "Cost Price"
sku: "SKU"
price: "Price"
display_as: "Display As"
display_name: "Display Name"
autocomplete:
producer_name: "Producer"
unit: "Unit"
@@ -3154,3 +3191,19 @@ en_NZ:
allow_charges?: "Allow Charges?"
localized_number:
invalid_format: has an invalid format. Please enter a number.
api:
invalid_api_key: "Invalid API key (%{key}) specified."
unauthorized: "You are not authorized to perform that action."
invalid_resource: "Invalid resource. Please fix errors and try again."
resource_not_found: "The resource you were looking for could not be found."
access: "API Access"
key: "Key"
clear_key: "Clear key"
regenerate_key: "Regenerate Key"
no_key: "No key"
generate_key: "Generate API key"
key_generated: "Key generated"
key_cleared: "Key cleared"
shipment:
cannot_ready: "Cannot ready shipment."
invalid_taxonomy_id: "Invalid taxonomy id."

View File

@@ -262,6 +262,7 @@ fr:
cancel: "Annuler"
save: "Sauvegarder"
edit: "Modifier"
update: "Mettre à jour"
delete: "Supprimer"
admin:
begins_at: Commence
@@ -834,10 +835,36 @@ fr:
loading_flash:
loading_order_cycles: Cycles de vente en cours de chargement
loading: Chargement...
new:
create: "Créer"
cancel: "Annuler"
back_to_list: "Retour à la liste"
edit:
advanced_settings: Paramétrages avancés
update_and_close: Mettre à jour et fermer
choose_products_from: 'Choisir produits depuis :'
advanced_settings: "Paramétrages avancés"
save: "Sauvegarder"
save_and_next: "Sauvegarder et suivant"
next: "Suivant"
cancel: "Annuler"
back_to_list: "Retour à la liste"
save_and_back_to_list: "Sauvegarder et revenir à la liste"
choose_products_from: "Choisir produits depuis :"
incoming:
previous: "Précédent"
save: "Sauvegarder"
save_and_next: "Sauvegarder et suivant"
next: "Suivant"
cancel: "Annuler"
back_to_list: "Retour à la liste"
outgoing:
previous: "Précédent"
save: "Sauvegarder"
save_and_back_to_list: "Sauvegarder et revenir à la liste"
cancel: "Annuler"
back_to_list: "Retour à la liste"
wizard_progress:
edit: "1. Informations générales"
incoming: "2. Produits entrants"
outgoing: "3. Produits vendus (sortants)"
exchange_form:
pickup_time_tip: Quand des commandes liées à ce cycle de vente seront prêtes à être soumises à l'acheteur
pickup_instructions_placeholder: "Modalités de retrait/livraison"
@@ -864,6 +891,7 @@ fr:
any_enterprise: "Toutes les entreprises"
any_schedule: "Tous"
form:
general_settings: "Configurations générales"
incoming: Produits entrants (pouvant être mis en vente par les hubs)
supplier: Fournisseur
receival_details: Détails livraison produits
@@ -1601,7 +1629,7 @@ fr:
sell_hubs_detail: "Créer un profil pour votre entreprise de distribution ou organisation sur OFFrance. A tout moment vous pourrez créer une boutique multi-fournisseurs."
sell_groups_detail: "Créer un répertoire sur mesure (regroupant différents producteurs et hubs de distribution) pour votre région ou votre organisation."
sell_user_guide: "En savoir plus en explorant le guide utilisateur."
sell_listing_price: "L'inscription sur OFFrance est gratuite. Ouvrir est gérer une boutique sur OFFrance ou créer un groupe sur OFFrance pour votre organisation ou réseau régional, n'est pas gratuit, mais le prix est libre: soit 2% du chiffre d'affaire (ou autre forme de contribution libre designée par votre hub), soit une contribution \"en compétences\" à Open Food France (développement de fonctionnalités, recherche de financement, support utilisateur, etc.), soit un mix des deux."
sell_listing_price: "L'inscription sur OFFrance est gratuite. Ouvrir et gérer une boutique sur OFFrance ou créer un groupe sur OFFrance pour votre organisation ou réseau régional, n'est pas gratuit, mais le prix est libre: soit 2% du chiffre d'affaire (ou autre forme de contribution libre designée par votre hub), soit une contribution \"en compétences\" à Open Food France (développement de fonctionnalités, recherche de financement, support utilisateur, etc.), soit un mix des deux."
sell_embed: "Nous pouvons aussi intégrer votre boutique OFFrance dans votre propre site web ou construire un site web d'alimentation locale sur mesure pour votre région."
sell_ask_services: "Nous consulter sur les services des partenaires OFFrance."
shops_title: Boutiques
@@ -2860,6 +2888,51 @@ fr:
inherits_properties_checkbox_hint: "Hériter des propriétés de %{supplier} ? (non applicable si information de remplacement déjà saisie)"
add_product_properties: "Ajouter des propriétés/labels"
select_from_prototype: "Sélectionnez depuis le prototype"
properties:
index:
properties: "Propriétés / labels"
new_property: "Nouvelle propriété"
name: "Produit/Variante"
presentation: "Présentation"
new:
new_property: "Nouvelle propriété"
edit:
editing_property: "Modifier la propriété"
back_to_properties_list: "Retour à la liste de propriétés"
form:
name: "Produit/Variante"
presentation: "Présentation"
return_authorizations:
index:
new_return_authorization: "Nouvelle autorisation de retour"
return_authorizations: "Autorisations de retours"
back_to_orders_list: "Retour à la liste des commandes"
rma_number: "Numéro RMA"
status: "Statut"
amount: "Montant"
cannot_create_returns: "Impossible de créer une autorisation de retour car aucun produit n'a été livré pour cette commande."
continue: "Suivant"
new:
new_return_authorization: "Nouvelle autorisation de retour"
back_to_return_authorizations_list: "Revenir à la liste des autorisations"
continue: "Suivant"
edit:
receive: "reçoit"
are_you_sure: "Confirmer?"
return_authorization: "Autorisation de retour"
form:
product: "Produit"
quantity_shipped: "Quantité envoyée"
quantity_returned: "Quantité retournée"
return_quantity: "Quantité à retourner"
amount: "Montant"
rma_value: "Valeur RMA"
reason: "Raison"
stock_location: "Localisation"
states:
authorized: "Autorisé"
received: "Reçu"
canceled: "Annulé"
orders:
index:
listing_orders: "Liste des commandes"

View File

@@ -833,10 +833,36 @@ nb:
loading_flash:
loading_order_cycles: LASTER BESTILLINGSRUNDER
loading: LASTER...
new:
create: "Opprett"
cancel: "Avbryt"
back_to_list: "Tilbake til Listen"
edit:
advanced_settings: Avanserte Innstillinger
update_and_close: Oppdater og Lukk
choose_products_from: 'Velg Produkter Fra:'
advanced_settings: "Avanserte Innstillinger"
save: "Lagre"
save_and_next: "Lagre og Neste"
next: "Neste"
cancel: "Avbryt"
back_to_list: "Tilbake til Listen"
save_and_back_to_list: "Lagre og Tilbake til Listen"
choose_products_from: "Velg Produkter Fra:"
incoming:
previous: "Tidligere"
save: "Lagre"
save_and_next: "Lagre og Neste"
next: "Neste"
cancel: "Avbryt"
back_to_list: "Tilbake til Listen"
outgoing:
previous: "Tidligere"
save: "Lagre"
save_and_back_to_list: "Lagre og Tilbake til Listen"
cancel: "Avbryt"
back_to_list: "Tilbake til Listen"
wizard_progress:
edit: "1. Generelle Innstillinger"
incoming: "2. Innkommende Produkter"
outgoing: "3. Utgående Produkter"
exchange_form:
pickup_time_tip: Når bestillinger fra denne runden vil være klar for kunden
pickup_instructions_placeholder: "Henteinstruksjoner"
@@ -863,6 +889,7 @@ nb:
any_enterprise: "Enhver Bedrift"
any_schedule: "Enhver Tidsplan"
form:
general_settings: "Generelle innstillinger"
incoming: Innkommende
supplier: Leverandør
receival_details: Mottaksdetaljer
@@ -2830,6 +2857,20 @@ nb:
inherits_properties_checkbox_hint: "Arve egenskaper fra %{supplier}? (med mindre overstyrt over)"
add_product_properties: "Legg til Produktegenskaper"
select_from_prototype: "Velg Fra Prototyp"
properties:
index:
properties: "Egenskaper"
new_property: "Ny Egenskap"
name: "Navn"
presentation: "Presentasjon"
new:
new_property: "Ny Egenskap"
edit:
editing_property: "Redigerer Egenskap"
back_to_properties_list: "Tilbake til listen over egenskaper"
form:
name: "Navn"
presentation: "Presentasjon"
orders:
index:
listing_orders: "Lister opp bestillinger"

View File

@@ -9,6 +9,8 @@ Openfoodnetwork::Application.routes.draw do
resources :order_cycles do
post :bulk_update, on: :collection, as: :bulk_update
get :incoming
get :outgoing
member do
get :clone

View File

@@ -51,8 +51,7 @@ module OpenFoodNetwork
def table_items
return [] unless @render_table
Reports::LineItems.list(permissions, params)
Reports::LineItems.list(permissions, report_options)
end
def rules
@@ -122,9 +121,17 @@ module OpenFoodNetwork
private
def report_options
@params.merge(line_item_includes: line_item_includes)
end
def line_item_includes
[{ order: [:bill_address],
variant: [{ option_values: :option_type }, { product: :supplier }] }]
end
def permissions
return @permissions unless @permissions.nil?
@permissions = OpenFoodNetwork::Permissions.new(@user)
end
end

View File

@@ -120,38 +120,40 @@ module OpenFoodNetwork
# Find the variants that a user can POTENTIALLY see within incoming exchanges
def visible_variants_for_incoming_exchanges_from(producer)
return Spree::Variant.where("1=0") unless @order_cycle
if user_manages_coordinator_or(producer)
# All variants belonging to the producer
Spree::Variant.joins(:product).where('spree_products.supplier_id = (?)', producer)
if @order_cycle &&
(user_manages_coordinator_or(producer) || user_is_permitted_add_to_oc_by(producer))
all_variants_supplied_by(producer)
else
# Producer variants if it has granted P-OC to any of my managed hubs that are in this OC
permitted = EnterpriseRelationship.
permitting(managed_participating_hubs.select("enterprises.id")).
permitted_by(producer.id).
with_permission(:add_to_order_cycle).
present?
if permitted
Spree::Variant.joins(:product).where('spree_products.supplier_id = (?)', producer)
else
Spree::Variant.where("1=0")
end
no_variants
end
end
# Producer has granted P-OC to any of my managed hubs that are in this OC
def user_is_permitted_add_to_oc_by(producer)
EnterpriseRelationship.
permitting(managed_participating_hubs.select("enterprises.id")).
permitted_by(producer.id).
with_permission(:add_to_order_cycle).
present?
end
# Find the variants that a user can edit within incoming exchanges
def editable_variants_for_incoming_exchanges_from(producer)
return Spree::Variant.where("1=0") unless @order_cycle
if user_manages_coordinator_or(producer)
# All variants belonging to the producer
Spree::Variant.joins(:product).where('spree_products.supplier_id = (?)', producer)
if @order_cycle && user_manages_coordinator_or(producer)
all_variants_supplied_by(producer)
else
Spree::Variant.where("1=0")
no_variants
end
end
def all_variants_supplied_by(producer)
Spree::Variant.joins(:product).where('spree_products.supplier_id = (?)', producer)
end
def no_variants
Spree::Variant.where("1=0")
end
def all_incoming_editable_variants
valid_suppliers = visible_enterprises.select do |enterprise|
user_manages_coordinator_or(enterprise)

View File

@@ -190,7 +190,7 @@ module OpenFoodNetwork
# rubocop:enable Metrics/PerceivedComplexity
def line_item_includes
[{ variant: { product: :supplier },
[{ variant: [{ option_values: :option_type }, { product: :supplier }],
order: [:bill_address, :ship_address, :order_cycle, :adjustments, :payments,
:user, :distributor, shipments: { shipping_rates: :shipping_method }] }]
end
@@ -198,8 +198,13 @@ module OpenFoodNetwork
private
def shipping_method(line_items)
line_items.first.order.shipments.first.
andand.shipping_rates.andand.first.andand.shipping_method
shipping_rates = line_items.first.order.shipments.first.
andand.shipping_rates
return unless shipping_rates
shipping_rate = shipping_rates.find(&:selected) || shipping_rates.first
shipping_rate.try(:shipping_method)
end
end
end

View File

@@ -69,7 +69,7 @@ module OpenFoodNetwork
def line_item_includes
[{ order: [:distributor, :adjustments, shipments: { shipping_rates: :shipping_method }],
variant: { product: :supplier } }]
variant: [{ option_values: :option_type }, { product: :supplier }] }]
end
end
end

View File

@@ -69,7 +69,8 @@ module OpenFoodNetwork
# rubocop:enable Metrics/AbcSize
def line_item_includes
[{ order: :distributor, variant: { product: :supplier } }]
[{ order: :distributor,
variant: [{ option_values: :option_type }, { product: :supplier }] }]
end
end
end

View File

@@ -55,7 +55,7 @@ module OpenFoodNetwork
# rubocop:enable Metrics/MethodLength
def line_item_includes
[{ variant: { product: :supplier } }]
[{ variant: [{ option_values: :option_type }, { product: :supplier }] }]
end
end
end

View File

@@ -43,8 +43,7 @@ module OpenFoodNetwork
def table_items
return [] unless @render_table
Reports::LineItems.list(permissions, params)
Reports::LineItems.list(permissions, report_options)
end
def rules
@@ -121,9 +120,17 @@ module OpenFoodNetwork
private
def report_options
@params.merge(line_item_includes: line_item_includes)
end
def line_item_includes
[{ order: [:bill_address, :distributor],
variant: [{ option_values: :option_type }, { product: :supplier }] }]
end
def permissions
return @permissions unless @permissions.nil?
@permissions = OpenFoodNetwork::Permissions.new(@user)
end

View File

@@ -25,6 +25,7 @@ module OpenFoodNetwork
def child_variants
Spree::Variant.
where(is_master: false).
includes(option_values: :option_type).
joins(:product).
merge(visible_products).
order('spree_products.name')

View File

@@ -30,7 +30,9 @@ module OpenFoodNetwork
end
def query_scope
Spree::Variant.where(is_master: false).ransack(search_params.merge(m: 'or')).result
Spree::Variant.where(is_master: false).
includes(option_values: :option_type).
ransack(search_params.merge(m: 'or')).result
end
def distributor

View File

@@ -8,11 +8,17 @@ module OpenFoodNetwork
module VariantAndLineItemNaming
# Copied and modified from Spree::Variant
def options_text
values = option_values.joins(:option_type).order("#{Spree::OptionType.table_name}.position asc")
values = if option_values_eager_loaded?
# Don't trigger N+1 queries if option_values are already eager-loaded.
# For best results, use: `Spree::Variant.includes(option_values: :option_type)`
# or: `Spree::Product.includes(variant: {option_values: :option_type})`
option_values.sort_by{ |o| o.option_type.position }
else
option_values.joins(:option_type).
order("#{Spree::OptionType.table_name}.position asc")
end
values.map!(&:presentation) # This line changed
values.to_sentence(words_connector: ", ", two_words_connector: ", ")
values.map(&:presentation).to_sentence(words_connector: ", ", two_words_connector: ", ")
end
def product_and_full_name
@@ -69,6 +75,10 @@ module OpenFoodNetwork
private
def option_values_eager_loaded?
option_values.loaded?
end
def option_value_name
if has_attribute?(:display_as) && display_as.present?
display_as

View File

@@ -43,6 +43,15 @@ module OpenFoodNetwork
private
def report_options
@opts.merge(line_item_includes: line_item_includes)
end
def line_item_includes
[:bill_address, :adjustments,
line_items: { variant: [{ option_values: :option_type }, { product: :supplier }] }]
end
def detail_rows_for_order(order, invoice_number, opts)
rows = []

View File

@@ -111,10 +111,20 @@ module Admin
context "when creation is successful" do
before { allow(form_mock).to receive(:save) { true } }
it "returns success: true" do
# mock build_resource so that we can control the edit_path
OrderCyclesController.class_eval do
def build_resource
order_cycle = OrderCycle.new
order_cycle.id = 1
order_cycle
end
end
it "returns success: true and a valid edit path" do
spree_post :create, params
json_response = JSON.parse(response.body)
expect(json_response['success']).to be true
expect(json_response['edit_path']).to eq "/admin/order_cycles/1/incoming"
end
end

View File

@@ -196,6 +196,9 @@ feature '
click_button 'Add coordinator fee'
select 'Coord fee', from: 'order_cycle_coordinator_fee_0_id'
click_button 'Create'
expect(page).to have_content 'Your order cycle has been created.'
# I should not be able to add a blank supplier
expect(page).to have_select 'new_supplier_id', selected: ''
expect(page).to have_button 'Add supplier', disabled: true
@@ -218,6 +221,8 @@ feature '
select 'My supplier', from: 'order_cycle_incoming_exchange_0_enterprise_fees_0_enterprise_id'
select 'Supplier fee', from: 'order_cycle_incoming_exchange_0_enterprise_fees_0_enterprise_fee_id'
click_button 'Save and Next'
# And I add a distributor with the same products
select 'My distributor', from: 'new_distributor_id'
click_button 'Add distributor'
@@ -239,14 +244,9 @@ feature '
select 'My distributor', from: 'order_cycle_outgoing_exchange_0_enterprise_fees_0_enterprise_id'
select 'Distributor fee', from: 'order_cycle_outgoing_exchange_0_enterprise_fees_0_enterprise_fee_id'
# And I click Create
click_button 'Create'
# Then my order cycle should have been created
expect(page).to have_content 'Your order cycle has been created.'
click_button 'Save and Back to List'
oc = OrderCycle.last
toggle_columns "Producers", "Shops"
expect(page).to have_input "oc#{oc.id}[name]", value: "Plums & Avos"
@@ -316,9 +316,6 @@ feature '
fill_in 'order_cycle_orders_open_at', with: order_cycle_opening_time
fill_in 'order_cycle_orders_close_at', with: order_cycle_closing_time
# CAN'T CHANGE COORDINATOR ANYMORE
# select 'My coordinator', from: 'order_cycle_coordinator_id'
# And I configure some coordinator fees
click_button 'Add coordinator fee'
select 'Coord fee 1', from: 'order_cycle_coordinator_fee_0_id'
@@ -327,6 +324,9 @@ feature '
click_link 'order_cycle_coordinator_fee_2_remove'
select 'Coord fee 2', from: 'order_cycle_coordinator_fee_1_id'
click_button 'Save and Next'
expect(page).to have_content 'Your order cycle has been updated.'
# And I add a supplier and some products
select 'My supplier', from: 'new_supplier_id'
click_button 'Add supplier'
@@ -347,6 +347,8 @@ feature '
select 'My supplier', from: 'order_cycle_incoming_exchange_2_enterprise_fees_0_enterprise_id'
select 'Supplier fee 2', from: 'order_cycle_incoming_exchange_2_enterprise_fees_0_enterprise_fee_id'
click_button 'Save and Next'
# And I add a distributor and some products
select 'My distributor', from: 'new_distributor_id'
click_button 'Add distributor'
@@ -378,15 +380,10 @@ feature '
select 'My distributor', from: 'order_cycle_outgoing_exchange_2_enterprise_fees_0_enterprise_id'
select 'Distributor fee 2', from: 'order_cycle_outgoing_exchange_2_enterprise_fees_0_enterprise_fee_id'
# And I click Update
expect(page).to have_selector "#save-bar"
click_button 'Update and Close'
# Then my order cycle should have been updated
expect(page).to have_content 'Your order cycle has been updated.'
click_button 'Save and Back to List'
oc = OrderCycle.last
toggle_columns "Producers", "Shops"
expect(page).to have_input "oc#{oc.id}[name]", value: "Plums & Avos"
@@ -439,6 +436,8 @@ feature '
expect(page.find('#order_cycle_orders_close_at').value).to eq(oc.orders_close_at.to_s)
expect(page).to have_content "COORDINATOR #{oc.coordinator.name}"
click_button 'Next'
# And I should see the suppliers
expect(page).to have_selector 'td.supplier_name', text: oc.suppliers.first.name
expect(page).to have_selector 'td.supplier_name', text: oc.suppliers.last.name
@@ -465,6 +464,8 @@ feature '
expect(page).to have_select 'order_cycle_incoming_exchange_1_enterprise_fees_0_enterprise_id', selected: supplier.name
expect(page).to have_select 'order_cycle_incoming_exchange_1_enterprise_fees_0_enterprise_fee_id', selected: supplier.enterprise_fees.first.name
click_button 'Next'
# And I should see the distributors
expect(page).to have_selector 'td.distributor_name', text: oc.distributors.first.name
expect(page).to have_selector 'td.distributor_name', text: oc.distributors.last.name
@@ -505,13 +506,15 @@ feature '
# When I edit the first order cycle, the exchange should appear as incoming
quick_login_as_admin
visit edit_admin_order_cycle_path(oc_incoming)
expect(page).to have_selector 'table.exchanges tr.supplier'
visit admin_order_cycle_incoming_path(oc_incoming)
expect(page).to have_selector 'table.exchanges tr.supplier'
visit admin_order_cycle_outgoing_path(oc_incoming)
expect(page).not_to have_selector 'table.exchanges tr.distributor'
# And when I edit the second order cycle, the exchange should appear as outgoing
visit edit_admin_order_cycle_path(oc_outgoing)
expect(page).to have_selector 'table.exchanges tr.distributor'
visit admin_order_cycle_outgoing_path(oc_outgoing)
expect(page).to have_selector 'table.exchanges tr.distributor'
visit admin_order_cycle_incoming_path(oc_outgoing)
expect(page).not_to have_selector 'table.exchanges tr.supplier'
end
@@ -689,6 +692,9 @@ feature '
visit admin_order_cycles_path
click_link 'New Order Cycle'
[distributor_unmanaged.name, supplier_managed.name, supplier_unmanaged.name].each do |enterprise_name|
expect(page).not_to have_select 'coordinator_id', with_options: [enterprise_name]
end
select2_select 'Managed distributor', from: 'coordinator_id'
click_button "Continue >"
@@ -698,6 +704,13 @@ feature '
expect(page).not_to have_select2 'schedule_ids', with_options: [schedule_of_other_managed_distributor.name]
multi_select2_select schedule.name, from: 'schedule_ids'
click_button 'Add coordinator fee'
select 'Managed distributor fee', from: 'order_cycle_coordinator_fee_0_id'
click_button 'Create'
expect(page).to have_select 'new_supplier_id'
expect(page).not_to have_select 'new_supplier_id', with_options: [supplier_unmanaged.name]
select 'Managed supplier', from: 'new_supplier_id'
click_button 'Add supplier'
select 'Permitted supplier', from: 'new_supplier_id'
@@ -706,9 +719,10 @@ feature '
select_incoming_variant supplier_managed, 0, variant_managed
select_incoming_variant supplier_permitted, 1, variant_permitted
click_button 'Add coordinator fee'
select 'Managed distributor fee', from: 'order_cycle_coordinator_fee_0_id'
click_button 'Save and Next'
expect(page).to have_select 'new_distributor_id'
expect(page).not_to have_select 'new_distributor_id', with_options: [distributor_unmanaged.name]
select 'Managed distributor', from: 'new_distributor_id'
click_button 'Add distributor'
select 'Permitted distributor', from: 'new_distributor_id'
@@ -719,24 +733,15 @@ feature '
fill_in 'order_cycle_outgoing_exchange_1_pickup_time', with: 'pickup time 2'
fill_in 'order_cycle_outgoing_exchange_1_pickup_instructions', with: 'pickup instructions'
# Should only have suppliers / distributors listed which the user is managing or
# has E2E permission to add products to order cycles
expect(page).not_to have_select 'new_supplier_id', with_options: [supplier_unmanaged.name]
expect(page).not_to have_select 'new_distributor_id', with_options: [distributor_unmanaged.name]
[distributor_unmanaged.name, supplier_managed.name, supplier_unmanaged.name].each do |enterprise_name|
expect(page).not_to have_select 'order_cycle_coordinator_id', with_options: [enterprise_name]
end
page.find("table.exchanges tr.distributor-#{distributor_managed.id} td.tags").click
within ".exchange-tags" do
find(:css, "tags-input .tags input").set "wholesale\n"
end
click_button 'Create'
expect(flash_message).to eq("Your order cycle has been created.")
click_button 'Save and Back to List'
order_cycle = OrderCycle.find_by_name('My order cycle')
expect(page).to have_input "oc#{order_cycle.id}[name]", value: order_cycle.name
expect(order_cycle.suppliers).to match_array [supplier_managed, supplier_permitted]
expect(order_cycle.coordinator).to eq(distributor_managed)
expect(order_cycle.distributors).to match_array [distributor_managed, distributor_permitted]
@@ -745,39 +750,6 @@ feature '
expect(exchange.tag_list).to eq(["wholesale"])
end
scenario "editing an order cycle we can see (and for now, edit) all exchanges in the order cycle" do
# TODO: when we add the editable scope to variant permissions, we should test that
# exchanges with enterprises who have not granted P-OC to the coordinator are not
# editable, but at this point we cannot distiguish between visible and editable
# variants.
oc = create(:simple_order_cycle, suppliers: [supplier_managed, supplier_permitted, supplier_unmanaged], coordinator: distributor_managed, distributors: [distributor_managed, distributor_permitted, distributor_unmanaged], name: 'Order Cycle 1' )
visit edit_admin_order_cycle_path(oc)
fill_in 'order_cycle_name', with: 'Coordinated'
# I should be able to see but not edit exchanges for supplier_unmanaged or distributor_unmanaged
expect(page).to have_selector "tr.supplier-#{supplier_managed.id}"
expect(page).to have_selector "tr.supplier-#{supplier_permitted.id}"
expect(page).to have_selector "tr.supplier-#{supplier_unmanaged.id}"
expect(page).to have_selector 'tr.supplier', count: 3
expect(page).to have_selector "tr.distributor-#{distributor_managed.id}"
expect(page).to have_selector "tr.distributor-#{distributor_permitted.id}"
expect(page).to have_selector "tr.distributor-#{distributor_unmanaged.id}"
expect(page).to have_selector 'tr.distributor', count: 3
# When I save, then those exchanges should remain
click_button 'Update'
expect(page).to have_content "Your order cycle has been updated."
oc.reload
expect(oc.suppliers).to match_array [supplier_managed, supplier_permitted, supplier_unmanaged]
expect(oc.coordinator).to eq(distributor_managed)
expect(oc.distributors).to match_array [distributor_managed, distributor_permitted, distributor_unmanaged]
end
scenario "editing an order cycle" do
oc = create(:simple_order_cycle, suppliers: [supplier_managed, supplier_permitted, supplier_unmanaged], coordinator: distributor_managed, distributors: [distributor_managed, distributor_permitted, distributor_unmanaged], name: 'Order Cycle 1' )
distributor_managed.update_attribute(:enable_subscriptions, true)
@@ -788,15 +760,18 @@ feature '
multi_select2_select schedule.name, from: 'schedule_ids'
expect(page).not_to have_select2 'schedule_ids', with_options: [schedule_of_other_managed_distributor.name]
# When I remove all the exchanges and save
click_button 'Save and Next'
# When I remove all incoming exchanges
page.find("tr.supplier-#{supplier_managed.id} a.remove-exchange").click
page.find("tr.supplier-#{supplier_permitted.id} a.remove-exchange").click
click_button 'Save and Next'
# And I remove all outgoing exchanges
page.find("tr.distributor-#{distributor_managed.id} a.remove-exchange").click
page.find("tr.distributor-#{distributor_permitted.id} a.remove-exchange").click
click_button 'Update'
# Then the exchanges should be removed
expect(page).to have_content "Your order cycle has been updated."
click_button 'Save and Back to List'
expect(page).to have_input "oc#{oc.id}[name]", value: oc.name
oc.reload
expect(oc.suppliers).to eq([supplier_unmanaged])
@@ -848,14 +823,14 @@ feature '
{ distributor_managed.id.to_s => [v1.id] }
end
visit edit_admin_order_cycle_path(oc)
# I should only see exchanges for supplier_managed AND
# distributor_managed and distributor_permitted (who I have given permission to) AND
# and distributor_unmanaged (who distributes my products)
visit admin_order_cycle_incoming_path(oc)
expect(page).to have_selector "tr.supplier-#{supplier_managed.id}"
expect(page).to have_selector 'tr.supplier', count: 1
visit admin_order_cycle_outgoing_path(oc)
expect(page).to have_selector "tr.distributor-#{distributor_managed.id}"
expect(page).to have_selector "tr.distributor-#{distributor_permitted.id}"
expect(page).to have_selector 'tr.distributor', count: 2
@@ -875,7 +850,7 @@ feature '
expect(page).not_to have_selector "table.exchanges tr.distributor-#{distributor_managed.id} td.tags"
# When I save, any exchanges that I can't manage remain
click_button 'Update'
click_button 'Save'
expect(page).to have_content "Your order cycle has been updated."
oc.reload
@@ -916,15 +891,15 @@ feature '
{ supplier_managed.id.to_s => [v1.id] }
end
visit edit_admin_order_cycle_path(oc)
# I should see exchanges for my_distributor, and the incoming exchanges supplying the variants in it
expect(page).to have_selector "tr.supplier-#{supplier_managed.id}"
expect(page).to have_selector 'tr.supplier', count: 1
visit admin_order_cycle_outgoing_path(oc)
expect(page).to have_selector "tr.distributor-#{my_distributor.id}"
expect(page).to have_selector 'tr.distributor', count: 1
visit admin_order_cycle_incoming_path(oc)
expect(page).to have_selector "tr.supplier-#{supplier_managed.id}"
expect(page).to have_selector 'tr.supplier', count: 1
# Open the products list for managed_supplier's incoming exchange
within "tr.supplier-#{supplier_managed.id}" do
page.find("td.products").click
@@ -937,12 +912,12 @@ feature '
# I should be able to see but not toggle v2, because I don't have permission
expect(page).to have_checked_field "order_cycle_incoming_exchange_0_variants_#{v2.id}", disabled: true
expect(page).to have_selector "table.exchanges tr.distributor-#{my_distributor.id} td.tags"
# When I save, any exchange that I can't manage remains
click_button 'Update'
click_button 'Save and Next'
expect(page).to have_content "Your order cycle has been updated."
expect(page).to have_selector "table.exchanges tr.distributor-#{my_distributor.id} td.tags"
oc.reload
expect(oc.suppliers).to match_array [supplier_managed, supplier_permitted, supplier_unmanaged]
expect(oc.coordinator).to eq(distributor_managed)
@@ -1099,11 +1074,11 @@ feature '
select 'that fee', from: 'order_cycle_coordinator_fee_0_id'
# When I update, or update and close, both work
click_button 'Update'
click_button 'Save'
expect(page).to have_content 'Your order cycle has been updated.'
fill_in 'order_cycle_outgoing_exchange_0_pickup_instructions', with: 'yyz'
click_button 'Update and Close'
click_button 'Save and Back to List'
# Then my order cycle should have been updated
expect(page).to have_content 'Your order cycle has been updated.'

View File

@@ -8,46 +8,23 @@ describe 'AdminCreateOrderCycleCtrl', ->
beforeEach ->
scope =
order_cycle_form: jasmine.createSpyObj('order_cycle_form', ['$dirty'])
$watch: jasmine.createSpy('$watch')
event =
preventDefault: jasmine.createSpy('preventDefault')
OrderCycle =
exchangeSelectedVariants: jasmine.createSpy('exchangeSelectedVariants').and.returnValue('variants selected')
productSuppliedToOrderCycle: jasmine.createSpy('productSuppliedToOrderCycle').and.returnValue('product supplied')
variantSuppliedToOrderCycle: jasmine.createSpy('variantSuppliedToOrderCycle').and.returnValue('variant supplied')
exchangeDirection: jasmine.createSpy('exchangeDirection').and.returnValue('exchange direction')
toggleProducts: jasmine.createSpy('toggleProducts')
setExchangeVariants: jasmine.createSpy('setExchangeVariants')
addSupplier: jasmine.createSpy('addSupplier')
addDistributor: jasmine.createSpy('addDistributor')
removeExchange: jasmine.createSpy('removeExchange')
addCoordinatorFee: jasmine.createSpy('addCoordinatorFee')
removeCoordinatorFee: jasmine.createSpy('removeCoordinatorFee')
addExchangeFee: jasmine.createSpy('addExchangeFee')
removeExchangeFee: jasmine.createSpy('removeExchangeFee')
removeDistributionOfVariant: jasmine.createSpy('removeDistributionOfVariant')
create: jasmine.createSpy('create')
new: jasmine.createSpy('new').and.returnValue "my order cycle"
Enterprise =
index: jasmine.createSpy('index').and.returnValue('enterprises list')
supplied_products: 'supplied products'
suppliedVariants: jasmine.createSpy('suppliedVariants').and.returnValue('supplied variants')
totalVariants: jasmine.createSpy('totalVariants').and.returnValue('variants total')
EnterpriseFee =
index: jasmine.createSpy('index').and.returnValue('enterprise fees list')
forEnterprise: jasmine.createSpy('forEnterprise').and.returnValue('enterprise fees for enterprise')
ocInstance = {}
module('admin.orderCycles')
inject ($controller) ->
ctrl = $controller 'AdminCreateOrderCycleCtrl', {$scope: scope, OrderCycle: OrderCycle, Enterprise: Enterprise, EnterpriseFee: EnterpriseFee, ocInstance: ocInstance}
it 'Loads enterprises and supplied products', ->
it 'Loads enterprises', ->
expect(Enterprise.index).toHaveBeenCalled()
expect(scope.enterprises).toEqual('enterprises list')
expect(scope.supplied_products).toEqual('supplied products')
it 'Loads enterprise fees', ->
expect(EnterpriseFee.index).toHaveBeenCalled()
@@ -56,104 +33,6 @@ describe 'AdminCreateOrderCycleCtrl', ->
it 'Loads order cycles', ->
expect(scope.order_cycle).toEqual('my order cycle')
describe 'Reporting when all resources are loaded', ->
beforeEach inject (RequestMonitor) ->
RequestMonitor.loading = false
Enterprise.loaded = true
EnterpriseFee.loaded = true
OrderCycle.loaded = true
it 'returns true when all resources are loaded', ->
expect(scope.loaded()).toBe(true)
it 'returns false otherwise', ->
EnterpriseFee.loaded = false
expect(scope.loaded()).toBe(false)
it "delegates suppliedVariants to Enterprise", ->
expect(scope.suppliedVariants('enterprise_id')).toEqual('supplied variants')
expect(Enterprise.suppliedVariants).toHaveBeenCalledWith('enterprise_id')
it 'Delegates exchangeSelectedVariants to OrderCycle', ->
expect(scope.exchangeSelectedVariants('exchange')).toEqual('variants selected')
expect(OrderCycle.exchangeSelectedVariants).toHaveBeenCalledWith('exchange')
it "delegates setExchangeVariants to OrderCycle", ->
scope.setExchangeVariants('exchange', 'variants', 'selected')
expect(OrderCycle.setExchangeVariants).toHaveBeenCalledWith('exchange', 'variants', 'selected')
it 'Delegates enterpriseTotalVariants to Enterprise', ->
expect(scope.enterpriseTotalVariants('enterprise')).toEqual('variants total')
expect(Enterprise.totalVariants).toHaveBeenCalledWith('enterprise')
it 'Delegates productSuppliedToOrderCycle to OrderCycle', ->
expect(scope.productSuppliedToOrderCycle('product')).toEqual('product supplied')
expect(OrderCycle.productSuppliedToOrderCycle).toHaveBeenCalledWith('product')
it 'Delegates variantSuppliedToOrderCycle to OrderCycle', ->
expect(scope.variantSuppliedToOrderCycle('variant')).toEqual('variant supplied')
expect(OrderCycle.variantSuppliedToOrderCycle).toHaveBeenCalledWith('variant')
it 'Delegates exchangeDirection to OrderCycle', ->
expect(scope.exchangeDirection('exchange')).toEqual('exchange direction')
expect(OrderCycle.exchangeDirection).toHaveBeenCalledWith('exchange')
it 'Finds enterprises participating in the order cycle that have fees', ->
scope.enterprises =
1: {id: 1, name: 'Eaterprises'}
2: {id: 2, name: 'Pepper Tree Place'}
3: {id: 3, name: 'South East'}
OrderCycle.participatingEnterpriseIds = jasmine.createSpy('participatingEnterpriseIds').and.returnValue([2])
EnterpriseFee.enterprise_fees = [ {enterprise_id: 2} ] # Pepper Tree Place has a fee
expect(scope.enterprisesWithFees()).toEqual([
{id: 2, name: 'Pepper Tree Place'}
])
it 'Delegates enterpriseFeesForEnterprise to EnterpriseFee', ->
scope.enterpriseFeesForEnterprise('123')
expect(EnterpriseFee.forEnterprise).toHaveBeenCalledWith(123)
it 'Adds order cycle suppliers', ->
scope.new_supplier_id = 'new supplier id'
scope.addSupplier(event)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.addSupplier).toHaveBeenCalledWith('new supplier id')
it 'Adds order cycle distributors', ->
scope.new_distributor_id = 'new distributor id'
scope.addDistributor(event)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.addDistributor).toHaveBeenCalledWith('new distributor id')
it 'Removes order cycle exchanges', ->
scope.removeExchange(event, 'exchange')
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.removeExchange).toHaveBeenCalledWith('exchange')
it 'Adds coordinator fees', ->
scope.addCoordinatorFee(event)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.addCoordinatorFee).toHaveBeenCalled()
it 'Removes coordinator fees', ->
scope.removeCoordinatorFee(event, 0)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.removeCoordinatorFee).toHaveBeenCalledWith(0)
it 'Adds exchange fees', ->
scope.addExchangeFee(event)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.addExchangeFee).toHaveBeenCalled()
it 'Removes exchange fees', ->
scope.removeExchangeFee(event, 'exchange', 0)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.removeExchangeFee).toHaveBeenCalledWith('exchange', 0)
it 'Removes distribution of a variant', ->
scope.removeDistributionOfVariant('variant')
expect(OrderCycle.removeDistributionOfVariant).toHaveBeenCalledWith('variant')
it 'Submits the order cycle via OrderCycle create', ->
eventMock = {preventDefault: jasmine.createSpy()}
scope.submit(eventMock,'/admin/order_cycles')

View File

@@ -18,29 +18,12 @@ describe 'AdminEditOrderCycleCtrl', ->
'example.com/admin/order_cycles/27/edit'
OrderCycle =
load: jasmine.createSpy('load')
exchangeSelectedVariants: jasmine.createSpy('exchangeSelectedVariants').and.returnValue('variants selected')
productSuppliedToOrderCycle: jasmine.createSpy('productSuppliedToOrderCycle').and.returnValue('product supplied')
variantSuppliedToOrderCycle: jasmine.createSpy('variantSuppliedToOrderCycle').and.returnValue('variant supplied')
exchangeDirection: jasmine.createSpy('exchangeDirection').and.returnValue('exchange direction')
toggleProducts: jasmine.createSpy('toggleProducts')
setExchangeVariants: jasmine.createSpy('setExchangeVariants')
addSupplier: jasmine.createSpy('addSupplier')
addDistributor: jasmine.createSpy('addDistributor')
removeExchange: jasmine.createSpy('removeExchange')
addCoordinatorFee: jasmine.createSpy('addCoordinatorFee')
removeCoordinatorFee: jasmine.createSpy('removeCoordinatorFee')
addExchangeFee: jasmine.createSpy('addExchangeFee')
removeExchangeFee: jasmine.createSpy('removeExchangeFee')
removeDistributionOfVariant: jasmine.createSpy('removeDistributionOfVariant')
update: jasmine.createSpy('update')
Enterprise =
index: jasmine.createSpy('index').and.returnValue('enterprises list')
supplied_products: 'supplied products'
suppliedVariants: jasmine.createSpy('suppliedVariants').and.returnValue('supplied variants')
totalVariants: jasmine.createSpy('totalVariants').and.returnValue('variants total')
EnterpriseFee =
index: jasmine.createSpy('index').and.returnValue('enterprise fees list')
forEnterprise: jasmine.createSpy('forEnterprise').and.returnValue('enterprise fees for enterprise')
ocInstance = {}
module('admin.orderCycles')
@@ -50,7 +33,6 @@ describe 'AdminEditOrderCycleCtrl', ->
it 'Loads enterprises and supplied products', ->
expect(Enterprise.index).toHaveBeenCalled()
expect(scope.enterprises).toEqual('enterprises list')
expect(scope.supplied_products).toEqual('supplied products')
it 'Loads enterprise fees', ->
expect(EnterpriseFee.index).toHaveBeenCalled()
@@ -59,107 +41,12 @@ describe 'AdminEditOrderCycleCtrl', ->
it 'Loads order cycles', ->
expect(OrderCycle.load).toHaveBeenCalledWith('27')
describe 'Reporting when all resources are loaded', ->
beforeEach inject (RequestMonitor) ->
RequestMonitor.loading = false
Enterprise.loaded = true
EnterpriseFee.loaded = true
OrderCycle.loaded = true
it 'returns true when all resources are loaded', ->
expect(scope.loaded()).toBe(true)
it 'returns false otherwise', ->
EnterpriseFee.loaded = false
expect(scope.loaded()).toBe(false)
it "delegates suppliedVariants to Enterprise", ->
expect(scope.suppliedVariants('enterprise_id')).toEqual('supplied variants')
expect(Enterprise.suppliedVariants).toHaveBeenCalledWith('enterprise_id')
it 'Delegates exchangeSelectedVariants to OrderCycle', ->
expect(scope.exchangeSelectedVariants('exchange')).toEqual('variants selected')
expect(OrderCycle.exchangeSelectedVariants).toHaveBeenCalledWith('exchange')
it "delegates setExchangeVariants to OrderCycle", ->
scope.setExchangeVariants('exchange', 'variants', 'selected')
expect(OrderCycle.setExchangeVariants).toHaveBeenCalledWith('exchange', 'variants', 'selected')
it 'Delegates totalVariants to Enterprise', ->
expect(scope.enterpriseTotalVariants('enterprise')).toEqual('variants total')
expect(Enterprise.totalVariants).toHaveBeenCalledWith('enterprise')
it 'Delegates productSuppliedToOrderCycle to OrderCycle', ->
expect(scope.productSuppliedToOrderCycle('product')).toEqual('product supplied')
expect(OrderCycle.productSuppliedToOrderCycle).toHaveBeenCalledWith('product')
it 'Delegates variantSuppliedToOrderCycle to OrderCycle', ->
expect(scope.variantSuppliedToOrderCycle('variant')).toEqual('variant supplied')
expect(OrderCycle.variantSuppliedToOrderCycle).toHaveBeenCalledWith('variant')
it 'Delegates exchangeDirection to OrderCycle', ->
expect(scope.exchangeDirection('exchange')).toEqual('exchange direction')
expect(OrderCycle.exchangeDirection).toHaveBeenCalledWith('exchange')
it 'Finds enterprises participating in the order cycle that have fees', ->
scope.enterprises =
1: {id: 1, name: 'Eaterprises'}
2: {id: 2, name: 'Pepper Tree Place'}
3: {id: 3, name: 'South East'}
OrderCycle.participatingEnterpriseIds = jasmine.createSpy('participatingEnterpriseIds').and.returnValue([2])
EnterpriseFee.enterprise_fees = [ {enterprise_id: 2} ] # Pepper Tree Place has a fee
expect(scope.enterprisesWithFees()).toEqual([
{id: 2, name: 'Pepper Tree Place'}
])
it 'Delegates enterpriseFeesForEnterprise to EnterpriseFee', ->
scope.enterpriseFeesForEnterprise('123')
expect(EnterpriseFee.forEnterprise).toHaveBeenCalledWith(123)
it 'Adds order cycle suppliers', ->
scope.new_supplier_id = 'new supplier id'
scope.addSupplier(event)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.addSupplier).toHaveBeenCalledWith('new supplier id')
it 'Adds order cycle distributors', ->
scope.new_distributor_id = 'new distributor id'
scope.addDistributor(event)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.addDistributor).toHaveBeenCalledWith('new distributor id')
it 'Removes order cycle exchanges', ->
scope.removeExchange(event, 'exchange')
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.removeExchange).toHaveBeenCalledWith('exchange')
expect(scope.order_cycle_form.$dirty).toEqual true
it 'Adds coordinator fees', ->
scope.addCoordinatorFee(event)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.addCoordinatorFee).toHaveBeenCalled()
it 'Removes coordinator fees', ->
scope.removeCoordinatorFee(event, 0)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.removeCoordinatorFee).toHaveBeenCalledWith(0)
expect(scope.order_cycle_form.$dirty).toEqual true
it 'Adds exchange fees', ->
scope.addExchangeFee(event)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.addExchangeFee).toHaveBeenCalled()
it 'Removes exchange fees', ->
scope.removeExchangeFee(event, 'exchange', 0)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.removeExchangeFee).toHaveBeenCalledWith('exchange', 0)
expect(scope.order_cycle_form.$dirty).toEqual true
it 'Removes distribution of a variant', ->
scope.removeDistributionOfVariant('variant')
expect(OrderCycle.removeDistributionOfVariant).toHaveBeenCalledWith('variant')
it 'Submits the order cycle via OrderCycle update', ->
eventMock = {preventDefault: jasmine.createSpy()}
scope.submit(eventMock,'/admin/order_cycles')

View File

@@ -0,0 +1,26 @@
describe 'AdminOrderCycleIncomingCtrl', ->
ctrl = null
scope = null
event = null
location = null
OrderCycle = null
Enterprise = null
EnterpriseFee = null
beforeEach ->
scope =
$watch: jasmine.createSpy('$watch')
location =
absUrl: ->
'example.com/admin/order_cycles/27/edit'
Enterprise =
totalVariants: jasmine.createSpy('totalVariants').and.returnValue('variants total')
ocInstance = {}
module('admin.orderCycles')
inject ($controller) ->
ctrl = $controller 'AdminOrderCycleIncomingCtrl', {$scope: scope, $location: location, OrderCycle: OrderCycle, Enterprise: Enterprise, EnterpriseFee: EnterpriseFee, ocInstance: ocInstance}
it 'Delegates totalVariants to Enterprise', ->
expect(scope.enterpriseTotalVariants('enterprise')).toEqual('variants total')
expect(Enterprise.totalVariants).toHaveBeenCalledWith('enterprise')

View File

@@ -0,0 +1,63 @@
describe 'AdminOrderCycleBasicCtrl', ->
ctrl = null
scope = null
event = null
location = null
OrderCycle = null
Enterprise = null
EnterpriseFee = null
beforeEach ->
scope =
$watch: jasmine.createSpy('$watch')
event =
preventDefault: jasmine.createSpy('preventDefault')
OrderCycle =
setExchangeVariants: jasmine.createSpy('setExchangeVariants')
addCoordinatorFee: jasmine.createSpy('addCoordinatorFee')
removeCoordinatorFee: jasmine.createSpy('removeCoordinatorFee')
Enterprise =
suppliedVariants: jasmine.createSpy('suppliedVariants').and.returnValue('supplied variants')
EnterpriseFee =
forEnterprise: jasmine.createSpy('forEnterprise').and.returnValue('enterprise fees for enterprise')
ocInstance = {}
module('admin.orderCycles')
inject ($controller) ->
ctrl = $controller 'AdminOrderCycleBasicCtrl', {$scope: scope, $location: location, OrderCycle: OrderCycle, Enterprise: Enterprise, EnterpriseFee: EnterpriseFee, ocInstance: ocInstance}
describe 'Reporting when all resources are loaded', ->
beforeEach inject (RequestMonitor) ->
RequestMonitor.loading = false
Enterprise.loaded = true
EnterpriseFee.loaded = true
OrderCycle.loaded = true
it 'returns true when all resources are loaded', ->
expect(scope.loaded()).toBe(true)
it 'returns false otherwise', ->
EnterpriseFee.loaded = false
expect(scope.loaded()).toBe(false)
it "delegates suppliedVariants to Enterprise", ->
expect(scope.suppliedVariants('enterprise_id')).toEqual('supplied variants')
expect(Enterprise.suppliedVariants).toHaveBeenCalledWith('enterprise_id')
it "delegates setExchangeVariants to OrderCycle", ->
scope.setExchangeVariants('exchange', 'variants', 'selected')
expect(OrderCycle.setExchangeVariants).toHaveBeenCalledWith('exchange', 'variants', 'selected')
it 'Delegates enterpriseFeesForEnterprise to EnterpriseFee', ->
scope.enterpriseFeesForEnterprise('123')
expect(EnterpriseFee.forEnterprise).toHaveBeenCalledWith(123)
it 'Adds coordinator fees', ->
scope.addCoordinatorFee(event)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.addCoordinatorFee).toHaveBeenCalled()
it 'Removes coordinator fees', ->
scope.removeCoordinatorFee(event, 0)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.removeCoordinatorFee).toHaveBeenCalledWith(0)

View File

@@ -0,0 +1,95 @@
describe 'AdminOrderCycleExchangesCtrl', ->
ctrl = null
scope = null
event = null
location = null
OrderCycle = null
Enterprise = null
EnterpriseFee = null
beforeEach ->
scope =
order_cycle_form: jasmine.createSpyObj('order_cycle_form', ['$dirty', '$setPristine'])
$watch: jasmine.createSpy('$watch')
event =
preventDefault: jasmine.createSpy('preventDefault')
location =
absUrl: ->
'example.com/admin/order_cycles/27/edit'
OrderCycle =
exchangeSelectedVariants: jasmine.createSpy('exchangeSelectedVariants').and.returnValue('variants selected')
exchangeDirection: jasmine.createSpy('exchangeDirection').and.returnValue('exchange direction')
addSupplier: jasmine.createSpy('addSupplier')
addDistributor: jasmine.createSpy('addDistributor')
removeExchange: jasmine.createSpy('removeExchange')
addExchangeFee: jasmine.createSpy('addExchangeFee')
removeExchangeFee: jasmine.createSpy('removeExchangeFee')
removeDistributionOfVariant: jasmine.createSpy('removeDistributionOfVariant')
Enterprise =
supplied_products: 'supplied products'
EnterpriseFee =
forEnterprise: jasmine.createSpy('forEnterprise').and.returnValue('enterprise fees for enterprise')
ocInstance = {}
module('admin.orderCycles')
inject ($controller) ->
ctrl = $controller 'AdminOrderCycleExchangesCtrl', {$scope: scope, $location: location, OrderCycle: OrderCycle, Enterprise: Enterprise, EnterpriseFee: EnterpriseFee, ocInstance: ocInstance}
it 'Loads supplied products', ->
expect(scope.supplied_products).toEqual('supplied products')
it 'Delegates exchangeSelectedVariants to OrderCycle', ->
expect(scope.exchangeSelectedVariants('exchange')).toEqual('variants selected')
expect(OrderCycle.exchangeSelectedVariants).toHaveBeenCalledWith('exchange')
it 'Delegates exchangeDirection to OrderCycle', ->
expect(scope.exchangeDirection('exchange')).toEqual('exchange direction')
expect(OrderCycle.exchangeDirection).toHaveBeenCalledWith('exchange')
it 'Finds enterprises participating in the order cycle that have fees', ->
# this is inhetited from order_cycle_basic_controller
scope.enterpriseFeesForEnterprise = (enterprise_id) ->
EnterpriseFee.forEnterprise(parseInt(enterprise_id))
scope.enterprises =
1: {id: 1, name: 'Eaterprises'}
2: {id: 2, name: 'Pepper Tree Place'}
3: {id: 3, name: 'South East'}
OrderCycle.participatingEnterpriseIds = jasmine.createSpy('participatingEnterpriseIds').and.returnValue([2])
EnterpriseFee.enterprise_fees = [ {enterprise_id: 2} ] # Pepper Tree Place has a fee
expect(scope.enterprisesWithFees()).toEqual([
{id: 2, name: 'Pepper Tree Place'}
])
it 'Removes order cycle exchanges', ->
scope.removeExchange(event, 'exchange')
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.removeExchange).toHaveBeenCalledWith('exchange')
expect(scope.order_cycle_form.$dirty).toEqual true
it 'Adds exchange fees', ->
scope.addExchangeFee(event)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.addExchangeFee).toHaveBeenCalled()
it 'Removes exchange fees', ->
scope.removeExchangeFee(event, 'exchange', 0)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.removeExchangeFee).toHaveBeenCalledWith('exchange', 0)
expect(scope.order_cycle_form.$dirty).toEqual true
it 'Adds order cycle suppliers', ->
scope.new_supplier_id = 'new supplier id'
scope.addSupplier(event)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.addSupplier).toHaveBeenCalledWith('new supplier id')
it 'Adds order cycle distributors', ->
scope.new_distributor_id = 'new distributor id'
scope.addDistributor(event)
expect(event.preventDefault).toHaveBeenCalled()
expect(OrderCycle.addDistributor).toHaveBeenCalledWith('new distributor id')
it 'Removes distribution of a variant', ->
scope.removeDistributionOfVariant('variant')
expect(OrderCycle.removeDistributionOfVariant).toHaveBeenCalledWith('variant')

View File

@@ -0,0 +1,31 @@
describe 'AdminOrderCycleOutgoingCtrl', ->
ctrl = null
scope = null
event = null
location = null
OrderCycle = null
Enterprise = null
EnterpriseFee = null
beforeEach ->
scope =
$watch: jasmine.createSpy('$watch')
location =
absUrl: ->
'example.com/admin/order_cycles/27/edit'
OrderCycle =
productSuppliedToOrderCycle: jasmine.createSpy('productSuppliedToOrderCycle').and.returnValue('product supplied')
variantSuppliedToOrderCycle: jasmine.createSpy('variantSuppliedToOrderCycle').and.returnValue('variant supplied')
ocInstance = {}
module('admin.orderCycles')
inject ($controller) ->
ctrl = $controller 'AdminOrderCycleOutgoingCtrl', {$scope: scope, $location: location, OrderCycle: OrderCycle, Enterprise: Enterprise, EnterpriseFee: EnterpriseFee, ocInstance: ocInstance}
it 'Delegates productSuppliedToOrderCycle to OrderCycle', ->
expect(scope.productSuppliedToOrderCycle('product')).toEqual('product supplied')
expect(OrderCycle.productSuppliedToOrderCycle).toHaveBeenCalledWith('product')
it 'Delegates variantSuppliedToOrderCycle to OrderCycle', ->
expect(scope.variantSuppliedToOrderCycle('variant')).toEqual('variant supplied')
expect(OrderCycle.variantSuppliedToOrderCycle).toHaveBeenCalledWith('variant')

View File

@@ -348,17 +348,28 @@ describe 'OrderCycle service', ->
beforeEach ->
spyOn(OrderCycle, 'confirmNoDistributors').and.returnValue true
it 'redirects to the destination page on success', ->
it 'redirects to the given destination on success', ->
OrderCycle.order_cycle = 'this is the order cycle'
spyOn(OrderCycle, 'dataForSubmit').and.returnValue('this is the submit data')
$httpBackend.expectPOST('/admin/order_cycles.json', {
order_cycle: 'this is the submit data'
}).respond {success: true}
}).respond {success: true, edit_path: "/edit/path"}
OrderCycle.create('/destination/page')
$httpBackend.flush()
expect($window.location).toEqual('/destination/page')
it 'redirects to the edit_path on success if no destination is given', ->
OrderCycle.order_cycle = 'this is the order cycle'
spyOn(OrderCycle, 'dataForSubmit').and.returnValue('this is the submit data')
$httpBackend.expectPOST('/admin/order_cycles.json', {
order_cycle: 'this is the submit data'
}).respond {success: true, edit_path: "/edit/path"}
OrderCycle.create()
$httpBackend.flush()
expect($window.location).toEqual('/edit/path')
it 'does not redirect on error', ->
OrderCycle.order_cycle = 'this is the order cycle'
spyOn(OrderCycle, 'dataForSubmit').and.returnValue('this is the submit data')

View File

@@ -2,14 +2,7 @@ require "spec_helper"
RSpec.describe OpenFoodNetwork::OrdersAndFulfillmentsReport::CustomerTotalsReport do
let!(:distributor) { create(:distributor_enterprise) }
let!(:customer) { create(:customer, enterprise: distributor) }
let!(:order) do
create(:completed_order_with_totals, line_items_count: 1, user: customer.user,
customer: customer, distributor: distributor)
end
let(:current_user) { distributor.owner }
let(:permissions) { OpenFoodNetwork::Permissions.new(current_user) }
@@ -22,18 +15,51 @@ RSpec.describe OpenFoodNetwork::OrdersAndFulfillmentsReport::CustomerTotalsRepor
OpenFoodNetwork::OrderGrouper.new(report.rules, report.columns).table(report.table_items)
end
it "generates the report" do
expect(report_table.length).to eq(2)
context "viewing the report" do
let!(:order) do
create(:completed_order_with_totals, line_items_count: 1, user: customer.user,
customer: customer, distributor: distributor)
end
it "generates the report" do
expect(report_table.length).to eq(2)
end
it "has a line item row" do
distributor_name_field = report_table.first[0]
expect(distributor_name_field).to eq distributor.name
customer_name_field = report_table.first[1]
expect(customer_name_field).to eq order.bill_address.full_name
total_field = report_table.last[5]
expect(total_field).to eq I18n.t("admin.reports.total")
end
end
it "has a line item row" do
distributor_name_field = report_table.first[0]
expect(distributor_name_field).to eq distributor.name
context "loading shipping methods" do
let!(:shipping_method1) {
create(:shipping_method, distributors: [distributor], name: "First")
}
let!(:shipping_method2) {
create(:shipping_method, distributors: [distributor], name: "Second")
}
let!(:shipping_method3) {
create(:shipping_method, distributors: [distributor], name: "Third")
}
let!(:order) do
create(:completed_order_with_totals, line_items_count: 1, user: customer.user,
customer: customer, distributor: distributor)
end
customer_name_field = report_table.first[1]
expect(customer_name_field).to eq order.bill_address.full_name
before do
order.shipments.each(&:refresh_rates)
order.select_shipping_method(shipping_method2.id)
end
total_field = report_table.last[5]
expect(total_field).to eq I18n.t("admin.reports.total")
it "displays the correct shipping_method" do
shipping_method_name_field = report_table.first[15]
expect(shipping_method_name_field).to eq shipping_method2.name
end
end
end