Compare commits

...

58 Commits
v1.13 ... v1.14

Author SHA1 Message Date
Pau Pérez Fabregat
1abfe2ab8c Merge pull request #2199 from coopdevs/auto-correct-cops
Auto correct cops
2018-04-16 14:58:28 +02:00
Pau Pérez Fabregat
b1fc15f242 Merge pull request #2223 from openfoodfoundation/transifex
Transifex
2018-04-16 13:43:40 +02:00
Pau Pérez Fabregat
fc7dd5d081 Merge pull request #2222 from coopdevs/upgrade-skylight
Upgrade to latest Skylight from 1.6.0 to 1.6.1
2018-04-16 11:38:23 +02:00
Pau Perez
2aea612f10 Upgrade to latest Skylight from 1.6.0 to 1.6.1 2018-04-16 10:52:15 +02:00
Pau Perez
147a74f005 Fix Rubocop violations reported by Code Climate 2018-04-16 10:27:44 +02:00
Pau Pérez Fabregat
514ad5d898 Merge pull request #2208 from coopdevs/performance-monitoring-badge
Add Skylight's performance monitoring badge
2018-04-13 08:45:30 +02:00
Pau Perez
5822e60a66 Add Skylight's performance monitoring badge
Adding the badge, which points now to Katuma's performance monitoring
information, is required for Skylight to showcase OFN on their website.
2018-04-12 09:29:40 +02:00
Transifex-Openfoodnetwork
ce2a7a510f Updating translations for config/locales/en_US.yml 2018-04-11 00:06:55 +10:00
Pau Perez
394fb91dd5 Auto correct Rubocop's Layout/MultilineArrayBraceLayout cop 2018-04-09 18:47:18 +02:00
Pau Perez
1640d5ad0b Auto correct Rubocop's Layout/IndentHeredoc cop 2018-04-09 18:47:18 +02:00
Pau Perez
76fe1c7ee9 Auto correct Rubocop's Layout/IndentAssignment cop 2018-04-09 18:47:18 +02:00
Pau Perez
33ea2c0b07 Auto correct Rubocop's Layout/FirstParameterIndentation cop 2018-04-09 18:47:18 +02:00
Pau Perez
f5a5d735fd Auto correct Rubocop's Layout/EmptyLinesAroundModuleBody cop 2018-04-09 18:47:18 +02:00
Pau Perez
6593dea4f6 Auto correct Rubocop's Layout/EmptyLinesAroundMethodBody cop 2018-04-09 18:47:17 +02:00
Pau Perez
3161fa3801 Auto correct Rubocop's Layout/EmptyLinesAroundExceptionHandlingKeywords cop 2018-04-09 18:47:17 +02:00
Pau Perez
746fcd5802 Auto correct Rubocop's Layout/EmptyLinesAroundAccessModifier cop 2018-04-09 18:47:17 +02:00
Pau Perez
9da33b4e82 Auto correct Rubocop's Layout/EmptyLinesAroundAccessModifier cop
This also `script/rubocop_autocorrect` to automate the process of fixing
a cop and comitting the changes.
2018-04-09 18:46:11 +02:00
Pau Perez
e876ef7df1 Auto correct Rubocop's Layout/ClosingParenthesisIndentation cop 2018-04-09 17:22:52 +02:00
Pau Perez
e4c86df7b2 Auto correct Rubocop's Layout/CaseIndentation cop 2018-04-09 17:19:47 +02:00
Transifex-Openfoodnetwork
15945fa1e0 Updating translations for config/locales/fr.yml 2018-04-05 04:48:54 +10:00
Transifex-Openfoodnetwork
ad898848f8 Updating translations for config/locales/pt.yml 2018-04-05 04:29:49 +10:00
Rob Harrington
236ba9328d Order cycles in specs comply with new date validations 2018-04-04 17:18:33 +10:00
Rob Harrington
ce56e667a4 Use union operator instead of concatenate to load order cycle collection 2018-04-04 17:18:33 +10:00
Rob Harrington
b17d8c2fe3 Add validation of open and close dates for order cycles 2018-04-04 17:18:32 +10:00
Rob Harrington
b14f27f956 Return an error if no order_cycle_set params are submitted to #bulk_update action 2018-04-04 17:17:36 +10:00
Rob Harrington
18f7ec992d Refactor loading of OrderCycleSet in OrderCyclesController
This should result in a significant speed bump in saving order cycles in bulk, because only referenced OCs are loaded into the set, rather than OrderCycle.all
2018-04-04 17:17:36 +10:00
stveep
46d2d6cb8a Include option text in dropdown cart even if the variant and product have the same name 2018-04-04 16:40:18 +10:00
Maikel Linke
a2e4c33922 Remove old and useless sentence from welcome email
The sentence made assumptions of the availability of FAQs and support
forums without linking to them. So it didn't really help. It also
promised that someone would monitor the support page in the forum which
nobody seems to do.
2018-04-04 16:21:39 +10:00
Matt-Yorkley
101269a487 Adjust wording on manager invite email 2018-04-04 15:49:04 +10:00
Maikel
61fbdfcefc Merge pull request #2178 from HugsDaniel/2172_flexi_rate_miscalculated
Fixing flexible rate miscalculation
2018-04-04 15:47:33 +10:00
Hugo Daniel
2a942da160 Use rspec context 2018-04-04 14:58:48 +10:00
Hugo Daniel
bd97d08653 Remove stub after test and create two distinct calculators 2018-04-04 14:58:47 +10:00
Hugo Daniel
68ca352510 Use rspec expect syntax 2018-04-04 14:58:47 +10:00
Hugo Daniel
a71b650f89 Added tests 2018-04-04 14:58:47 +10:00
Hugo Daniel
f40bd9cfcb Fixing wrong incrementation 2018-04-04 14:58:47 +10:00
Hugo Daniel
843bca9ea3 Updated calculation for flexible rate 2018-04-04 14:58:46 +10:00
Maikel Linke
80da0d5330 Set enterprise form dirty on any change
Commit 4953c69123 introduced a bug that
the save button is not activated when changing enterprise fields.
https://github.com/openfoodfoundation/openfoodnetwork/issues/2195

This is reverting the change and fixes #2195.
Sadly, it re-opens
https://github.com/openfoodfoundation/openfoodnetwork/issues/1216.
But that one is not as severe as the current bug.
2018-04-04 13:36:03 +10:00
Hugo Daniel
5ec89dde42 Update test sentences to fit new PriceSack behavior 2018-04-04 11:25:26 +10:00
Hugo Daniel
213456f4d9 Moved PriceSack tests from per item list to per order 2018-04-04 11:25:26 +10:00
Hugo Daniel
14ea591c7d Removed redundant self 2018-04-04 11:25:25 +10:00
Hugo Daniel
28009afbea Calculate price sack fees and tests 2018-04-04 11:25:25 +10:00
Matt-Yorkley
357ff5fb7d Improve associating customer specs 2018-04-04 10:14:55 +10:00
Matt-Yorkley
5f2e72e3d4 Private shop spec 2018-04-04 10:14:55 +10:00
Em-AK
3b5c3f41a2 Ensure created users are associated with customers
When a user is created with the same email as existing customers
Then the user is associated with these customers

So that the user can access the private shops where he has been invited
to before signup
2018-04-04 10:14:55 +10:00
Rob Harrington
a83bdf16c9 Add error message for case when schedule cannot be deleted 2018-04-04 09:21:52 +10:00
Maikel
f9dbf61afc Merge pull request #2176 from HugsDaniel/2002_calculator_options_not_translated
Overwrites spree_i18n translations for calculator's options
2018-04-04 08:17:18 +10:00
Pau Pérez Fabregat
15bd0de971 Merge pull request #2194 from wrycoder/spec-deprecation-fix
Replacing deprecated #ignore with #transient
2018-04-03 18:53:04 +02:00
Pau Pérez Fabregat
87329ad729 Merge pull request #2092 from ltrls/fix-tax-admin-order-show
Fix incorrect tax on Admin Order Show
2018-04-03 08:36:10 +02:00
Hugo Daniel
6731dd0b64 Overwrites spree_i18n translations for entreprise fees calculator's options 2018-04-03 08:38:00 +10:00
Michael Toulouse
0519269a53 Replacing deprecated #ignore with #transient 2018-04-02 06:40:12 -04:00
Pau Pérez Fabregat
1357c7c3b5 Merge pull request #2185 from coopdevs/remove-in-stock-dead-scope
Remove in_stock dead scope
2018-03-28 13:16:02 +02:00
Pau Perez
0cbd967007 Remove in_stock dead scope
This makes the upgrade to Spree 2.0 a bit easier.
`spree_variants.count_on_hand` is removed in that version and this
column was used in the `in_stock` scope that we no longer use.
2018-03-28 12:13:34 +02:00
Pau Pérez Fabregat
7fbaff71c7 Merge pull request #2179 from coopdevs/ignore-vendor-bundle
Ignore Bundler's vendor/bundle
2018-03-28 11:29:56 +02:00
Pau Perez
e8d8d5b0e6 Ignore Bundler's vendor/bundle 2018-03-27 16:56:58 +02:00
Pierre de Lacroix
28bb15f4a9 Fix old rspec syntax 2018-03-20 12:21:27 +01:00
Pierre de Lacroix
e0b12b1332 Remove dependency on model method in feature test 2018-03-20 12:18:54 +01:00
Pierre de Lacroix
2ceecc3d6e Test Order#tax_adjustment_totals with taxed adjustment on order 2018-03-20 12:18:51 +01:00
Pierre de Lacroix
03de6c690c Fix incorrect tax amount on Admin Order #show
by calling Order#tax_adjustment_totals from
Order#price_adjustment_totals
2018-03-20 12:18:09 +01:00
84 changed files with 822 additions and 342 deletions

1
.gitignore vendored
View File

@@ -41,3 +41,4 @@ coverage
libpeerconnection.log
/config/application.yml
node_modules
vendor/bundle/

View File

@@ -84,22 +84,6 @@ Layout/AlignParameters:
- 'spec/lib/open_food_network/user_balance_calculator_spec.rb'
- 'spec/support/request/authentication_workflow.rb'
# Offense count: 8
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentOneStep, IndentationWidth.
# SupportedStyles: case, end
Layout/CaseIndentation:
Exclude:
- 'app/models/enterprise.rb'
- 'app/models/product_importer.rb'
# Offense count: 3
# Cop supports --auto-correct.
Layout/ClosingParenthesisIndentation:
Exclude:
- 'app/overrides/add_capture_order_shortcut.rb'
- 'spec/serializers/variant_serializer_spec.rb'
# Offense count: 8
# Cop supports --auto-correct.
Layout/CommentIndentation:
@@ -261,16 +245,6 @@ Layout/EmptyLines:
- 'spec/support/delayed_job_helper.rb'
- 'spec/support/matchers/table_matchers.rb'
# Offense count: 6
# Cop supports --auto-correct.
Layout/EmptyLinesAroundAccessModifier:
Exclude:
- 'app/controllers/admin/order_cycles_controller.rb'
- 'app/controllers/spree/admin/shipping_methods_controller_decorator.rb'
- 'app/helpers/angular_form_builder.rb'
- 'spec/helpers/products_helper_spec.rb'
- 'spec/support/request/web_helper.rb'
# Offense count: 66
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
@@ -362,44 +336,6 @@ Layout/EmptyLinesAroundClassBody:
- 'lib/open_food_network/rack_request_blocker.rb'
- 'lib/open_food_network/reports/bulk_coop_report.rb'
# Offense count: 7
# Cop supports --auto-correct.
Layout/EmptyLinesAroundExceptionHandlingKeywords:
Exclude:
- 'app/controllers/checkout_controller.rb'
- 'app/controllers/enterprises_controller.rb'
- 'app/controllers/shop_controller.rb'
- 'app/models/spree/adjustment_decorator.rb'
- 'app/models/spree/tax_rate_decorator.rb'
- 'lib/tasks/users.rake'
- 'spec/features/admin/overview_spec.rb'
# Offense count: 4
# Cop supports --auto-correct.
Layout/EmptyLinesAroundMethodBody:
Exclude:
- 'app/controllers/checkout_controller.rb'
- 'app/controllers/spree/admin/reports_controller_decorator.rb'
- 'app/serializers/api/product_serializer.rb'
- 'lib/open_food_network/orders_and_fulfillments_report.rb'
# Offense count: 11
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines
Layout/EmptyLinesAroundModuleBody:
Exclude:
- 'app/helpers/add_to_cart_helper.rb'
- 'app/helpers/groups_helper.rb'
- 'lib/open_food_network/column_preference_defaults.rb'
- 'lib/open_food_network/group_buy_report.rb'
- 'lib/open_food_network/order_cycle_form_applicator.rb'
- 'lib/open_food_network/order_grouper.rb'
- 'lib/open_food_network/variant_and_line_item_naming.rb'
- 'spec/models/spree/ability_spec.rb'
- 'spec/support/request/distribution_helper.rb'
- 'spec/support/request/ui_component_helper.rb'
# Offense count: 55
# Cop supports --auto-correct.
# Configuration parameters: AllowForAlignment, ForceEqualSignAlignment.
@@ -443,15 +379,6 @@ Layout/ExtraSpacing:
- 'spec/spec_helper.rb'
- 'spec/support/request/web_helper.rb'
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
# SupportedStyles: consistent, special_for_inner_method_call, special_for_inner_method_call_in_parentheses
Layout/FirstParameterIndentation:
Exclude:
- 'lib/open_food_network/permissions.rb'
- 'spec/serializers/variant_serializer_spec.rb'
# Offense count: 3
# Cop supports --auto-correct.
# Configuration parameters: SupportedStyles, IndentationWidth.
@@ -459,13 +386,6 @@ Layout/FirstParameterIndentation:
Layout/IndentArray:
EnforcedStyle: consistent
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: IndentationWidth.
Layout/IndentAssignment:
Exclude:
- 'app/controllers/spree/admin/reports_controller_decorator.rb'
# Offense count: 52
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
@@ -489,14 +409,6 @@ Layout/IndentHash:
- 'spec/lib/open_food_network/order_cycle_form_applicator_spec.rb'
- 'spec/support/request/authentication_workflow.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: auto_detection, squiggly, active_support, powerpack, unindent
Layout/IndentHeredoc:
Exclude:
- 'app/models/content_configuration.rb'
# Offense count: 21
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
@@ -566,19 +478,6 @@ Layout/LeadingCommentSpace:
- 'spec/support/matchers/select2_matchers.rb'
- 'spec/support/request/authentication_workflow.rb'
# Offense count: 10
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: symmetrical, new_line, same_line
Layout/MultilineArrayBraceLayout:
Exclude:
- 'lib/open_food_network/customers_report.rb'
- 'lib/open_food_network/order_cycle_management_report.rb'
- 'lib/open_food_network/orders_and_fulfillments_report.rb'
- 'lib/open_food_network/packing_report.rb'
- 'lib/open_food_network/xero_invoices_report.rb'
- 'spec/archive/features/consumer/checkout_spec.rb'
# Offense count: 44
# Cop supports --auto-correct.
Layout/MultilineBlockLayout:

View File

@@ -640,7 +640,7 @@ GEM
shellany (0.0.1)
shoulda-matchers (2.8.0)
activesupport (>= 3.0.0)
skylight (1.6.0)
skylight (1.6.1)
activesupport (>= 3.0.0)
spinjs-rails (1.3)
rails (>= 3.1)

View File

@@ -1,5 +1,6 @@
[![Build Status](https://travis-ci.org/openfoodfoundation/openfoodnetwork.svg?branch=master)](https://travis-ci.org/openfoodfoundation/openfoodnetwork)
[![Code Climate](https://codeclimate.com/github/openfoodfoundation/openfoodnetwork.png)](https://codeclimate.com/github/openfoodfoundation/openfoodnetwork)
[![View performance data on Skylight](https://badges.skylight.io/status/EiXQ6sSKij8y.svg)](https://oss.skylight.io/app/applications/EiXQ6sSKij8y)
# Open Food Network

View File

@@ -31,6 +31,13 @@ angular.module("admin.orderCycles").directive 'scheduleDialog', ($window, $compi
if confirm(t('are_you_sure'))
Schedules.remove(scope.schedule).$promise.then (data) ->
scope.close()
, (response) ->
errors = response.data.errors
if errors?
scope.errors.push errors[0]
else
scope.errors.push "Could not delete schedule: #{scope.schedule.name}"
scope.loadMore = ->
scope.showMore().then ->

View File

@@ -151,23 +151,28 @@ angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, S
return unless @confirmNoDistributors()
oc = new OrderCycleResource({order_cycle: this.dataForSubmit()})
oc.$create (data) ->
if data['success']
$window.location = destination
$window.location = destination
, (response) ->
if response.data.errors?
StatusMessage.display('failure', response.data.errors[0])
else
console.log('Failed to create order cycle')
StatusMessage.display('failure', 'Failed to create order cycle')
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) =>
if data['success']
form.$setPristine() if form
if destination?
$window.location = destination
else
StatusMessage.display 'success', t('js.order_cycles.update_success')
form.$setPristine() if form
if destination?
$window.location = destination
else
console.log('Failed to update order cycle')
StatusMessage.display 'success', t('js.order_cycles.update_success')
, (response) ->
if response.data.errors?
StatusMessage.display('failure', response.data.errors[0])
else
StatusMessage.display('failure', 'Failed to create order cycle')
confirmNoDistributors: ->
if @order_cycle.outgoing_exchanges.length == 0

View File

@@ -45,7 +45,10 @@ angular.module("admin.resources").factory 'OrderCycles', ($q, $injector, OrderCy
form.$setPristine() if form?
StatusMessage.display('success', "Order cycles have been updated.")
, (response) =>
StatusMessage.display('failure', "Oh no! I was unable to save your changes.")
if response.data.errors?
StatusMessage.display('failure', response.data.errors[0])
else
StatusMessage.display('failure', "Oh no! I was unable to save your changes.")
saved: (order_cycle) ->
@diff(order_cycle).length == 0

View File

@@ -39,12 +39,6 @@ angular.module("admin.resources").factory "Schedules", ($q, $injector, RequestMo
orderCycle.schedules.splice(i, 1) for s, i in orderCycle.schedules by -1 when s.id == schedule.id
delete @byID[schedule.id]
StatusMessage.display 'success', "#{t('admin.order_cycles.index.deleted_schedule')}: '#{schedule.name}'"
, (response) =>
errors = response.data.errors
if errors?
InfoDialog.open 'error', errors[0]
else
InfoDialog.open 'error', "Could not delete schedule: #{schedule.name}"
index: ->
request = ScheduleResource.index (data) => @load(data)

View File

@@ -17,11 +17,11 @@ Darkswarm.factory 'Variants', ->
extendedVariantName: (variant) =>
if variant.product_name == variant.name_to_display
variant.product_name
name = variant.product_name
else
name = "#{variant.product_name} - #{variant.name_to_display}"
name += " (#{variant.options_text})" if variant.options_text
name
name += " (#{variant.options_text})" if variant.options_text
name
lineItemFor: (variant) ->
variant: variant

View File

@@ -9,8 +9,8 @@ module Admin
prepend_before_filter :load_data_for_index, :only => :index
before_filter :require_coordinator, only: :new
before_filter :remove_protected_attrs, only: [:update]
before_filter :remove_unauthorized_bulk_attrs, only: [:bulk_update]
before_filter :check_editable_schedule_ids, only: [:create, :update]
before_filter :require_order_cycle_set_params, only: [:bulk_update]
around_filter :protect_invalid_destroy, only: :destroy
create.after :sync_subscriptions
update.after :sync_subscriptions
@@ -51,10 +51,10 @@ module Admin
invoke_callbacks(:create, :after)
flash[:notice] = I18n.t(:order_cycles_create_notice)
format.html { redirect_to admin_order_cycles_path }
format.json { render :json => {:success => true} }
format.json { render :json => { success: true } }
else
format.html
format.json { render :json => {:success => false} }
format.json { render :json => { errors: @order_cycle.errors.full_messages }, status: :unprocessable_entity }
end
end
end
@@ -71,23 +71,22 @@ module Admin
invoke_callbacks(:update, :after)
flash[:notice] = I18n.t(:order_cycles_update_notice) if params[:reloading] == '1'
format.html { redirect_to main_app.edit_admin_order_cycle_path(@order_cycle) }
format.json { render :json => {:success => true} }
format.json { render :json => { :success => true } }
else
format.json { render :json => {:success => false} }
format.json { render :json => { errors: @order_cycle.errors.full_messages }, status: :unprocessable_entity }
end
end
end
def bulk_update
@order_cycle_set = params[:order_cycle_set] && OrderCycleSet.new(params[:order_cycle_set])
if @order_cycle_set.andand.save
if order_cycle_set.andand.save
respond_to do |format|
order_cycles = OrderCycle.where(id: params[:order_cycle_set][:collection_attributes].map{ |k,v| v[:id] })
format.json { render_as_json order_cycles, ams_prefix: 'index', current_user: spree_current_user }
format.json { render_as_json @order_cycles, ams_prefix: 'index', current_user: spree_current_user }
end
else
respond_to do |format|
format.json { render :json => {:success => false} }
order_cycle = order_cycle_set.collection.find{ |oc| oc.errors.present? }
format.json { render :json => { errors: order_cycle.errors.full_messages }, status: :unprocessable_entity }
end
end
end
@@ -107,8 +106,10 @@ module Admin
protected
def collection
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')
@@ -119,9 +120,9 @@ module Admin
OrderCycle.preload(:schedules).ransack(params[:q]).result.accessible_by(spree_current_user)
end
ocs.undated +
ocs.soonest_closing +
ocs.soonest_opening +
ocs.undated |
ocs.soonest_closing |
ocs.soonest_opening |
ocs.closed
end
@@ -130,6 +131,7 @@ module Admin
end
private
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
@@ -183,12 +185,10 @@ module Admin
end
def remove_unauthorized_bulk_attrs
if params.key? :order_cycle_set
params[:order_cycle_set][:collection_attributes].each do |i, hash|
order_cycle = OrderCycle.find(hash[:id])
unless Enterprise.managed_by(spree_current_user).include?(order_cycle.andand.coordinator)
params[:order_cycle_set][:collection_attributes].delete i
end
params[:order_cycle_set][:collection_attributes].each do |i, hash|
order_cycle = OrderCycle.find(hash[:id])
unless Enterprise.managed_by(spree_current_user).include?(order_cycle.andand.coordinator)
params[:order_cycle_set][:collection_attributes].delete i
end
end
end
@@ -216,6 +216,20 @@ module Admin
end
end
def order_cycles_from_set
remove_unauthorized_bulk_attrs
OrderCycle.where(id: params[:order_cycle_set][:collection_attributes].map{ |k,v| v[:id] })
end
def order_cycle_set
@order_cycle_set ||= OrderCycleSet.new(@order_cycles, params[:order_cycle_set])
end
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
end
def ams_prefix_whitelist
[:basic, :index]
end

View File

@@ -4,6 +4,7 @@ require 'open_food_network/proxy_order_syncer'
module Admin
class SchedulesController < ResourceController
before_filter :check_editable_order_cycle_ids, only: [:create, :update]
before_filter :check_dependent_subscriptions, only: [:destroy]
create.after :sync_subscriptions
update.after :sync_subscriptions
@@ -49,6 +50,11 @@ module Admin
@object.order_cycle_ids = result
end
def check_dependent_subscriptions
return if Subscription.where(schedule_id: @schedule).empty?
render json: { errors: [t('admin.schedules.destroy.associated_subscriptions_error')] }, status: :conflict
end
def permissions
return @permissions unless @permission.nil?
@permissions = OpenFoodNetwork::Permissions.new(spree_current_user)

View File

@@ -84,7 +84,6 @@ class CheckoutController < Spree::CheckoutController
customer_bill_address_id = @order.customer.bill_address.andand.id
@order.customer.update_attributes(bill_address_attributes: new_bill_address.merge('id' => customer_bill_address_id))
end
end
def set_default_ship_address
@@ -133,7 +132,6 @@ class CheckoutController < Spree::CheckoutController
def advance_order_state(order)
tries ||= 3
order.next
rescue ActiveRecord::StaleObjectError
retry unless (tries -= 1).zero?
false

View File

@@ -33,7 +33,6 @@ class EnterprisesController < BaseController
begin
Rails.application.routes.recognize_path( "/#{ params[:permalink].to_s }" )
render text: params[:permalink], status: 409
rescue ActionController::RoutingError
render text: params[:permalink], status: 200
end

View File

@@ -18,7 +18,6 @@ class ShopController < BaseController
products_json = filter(renderer.products_json)
render json: products_json
rescue OpenFoodNetwork::CachedProductsRenderer::NoProducts
render status: 404, json: ''
end

View File

@@ -222,7 +222,6 @@ Spree::Admin::ReportsController.class_eval do
csv_file_name = "#{params[:report_type]}_#{timestamp}.csv"
render_report(@report.header, @table, params[:csv], csv_file_name)
end
def products_and_inventory
@@ -320,9 +319,9 @@ Spree::Admin::ReportsController.class_eval do
reports[:order_cycle_management][:description] =
render_to_string(partial: 'order_cycle_management_description', layout: false, locals: {report_types: report_types[:order_cycle_management]}).html_safe
reports[:packing][:description] =
render_to_string(partial: 'packing_description', layout: false, locals: {report_types: report_types[:packing]}).html_safe
render_to_string(partial: 'packing_description', layout: false, locals: {report_types: report_types[:packing]}).html_safe
reports[:sales_tax][:description] =
render_to_string(partial: 'sales_tax_description', layout: false, locals: {report_types: report_types[:sales_tax]}).html_safe
render_to_string(partial: 'sales_tax_description', layout: false, locals: {report_types: report_types[:sales_tax]}).html_safe
# Return only reports the user is authorized to view.
reports.select { |action| can? action, :report }

View File

@@ -44,6 +44,7 @@ module Spree
end
private
def load_hubs
@hubs = Enterprise.managed_by(spree_current_user).is_distributor.sort_by!{ |d| [(@shipping_method.has_distributor? d) ? 0 : 1, d.name] }
end

View File

@@ -18,5 +18,4 @@ module AddToCartHelper
def available_order_cycles_for(order, product)
DistributionChangeValidator.new(order).available_order_cycles_for(product)
end
end

View File

@@ -36,6 +36,7 @@ class AngularFormBuilder < ActionView::Helpers::FormBuilder
end
private
def angular_name(method)
"#{@object_name}[#{@fields_for_record_name}_attributes][{{ $index }}][#{method}]"
end

View File

@@ -45,7 +45,7 @@ module CheckoutHelper
def display_checkout_taxes_hash(order)
order.tax_adjustment_totals.each_with_object(Hash.new) do |(tax_rate, tax_amount), hash|
hash[number_to_percentage(tax_rate * 100, :precision => 1)] = Spree::Money.new tax_amount, currency: order.currency
hash[number_to_percentage(tax_rate.amount * 100, :precision => 1)] = Spree::Money.new tax_amount, currency: order.currency
end
end

View File

@@ -1,5 +1,4 @@
module GroupsHelper
def link_to_service(baseurl, name, html_options = {})
return if name.blank?
html_options = html_options.merge target: '_blank'
@@ -19,5 +18,4 @@ module GroupsHelper
def strip_url(url)
url.andand.sub(/^https?:\/\//i, '')
end
end

View File

@@ -44,12 +44,12 @@ class ContentConfiguration < Spree::Preferences::FileConfiguration
preference :footer_pinterest_url, :string, default: ""
preference :footer_email, :string, default: "hello@openfoodnetwork.org"
preference :community_forum_url, :string, default: "http://community.openfoodnetwork.org"
preference :footer_links_md, :text, default: <<-EOS
[Newsletter sign-up](/)
preference :footer_links_md, :text, default: <<-EOS.strip_heredoc
[Newsletter sign-up](/)
[News](/)
[News](/)
[Calendar](/)
[Calendar](/)
EOS
preference :footer_about_url, :string, default: "http://www.openfoodnetwork.org/ofn-local/open-food-network-australia/"

View File

@@ -289,18 +289,18 @@ class Enterprise < ActiveRecord::Base
# Map backend cases to front end cases.
case cat
when "producer_sells_any"
:producer_hub # Producer hub who sells own and others produce and supplies other hubs.
when "producer_sells_own"
:producer_shop # Producer with shopfront and supplies other hubs.
when "producer_sells_none"
:producer # Producer only supplies through others.
when "non_producer_sells_any"
:hub # Hub selling others products in order cycles.
when "non_producer_sells_own"
:hub # Wholesaler selling through own shopfront? Does this need a separate name? Should it exist?
when "non_producer_sells_none"
:hub_profile # Hub selling outside the system.
when "producer_sells_any"
:producer_hub # Producer hub who sells own and others produce and supplies other hubs.
when "producer_sells_own"
:producer_shop # Producer with shopfront and supplies other hubs.
when "producer_sells_none"
:producer # Producer only supplies through others.
when "non_producer_sells_any"
:hub # Hub selling others products in order cycles.
when "non_producer_sells_own"
:hub # Wholesaler selling through own shopfront? Does this need a separate name? Should it exist?
when "non_producer_sells_none"
:hub_profile # Hub selling outside the system.
end
end

View File

@@ -19,7 +19,7 @@ class EnterpriseFee < ActiveRecord::Base
attr_accessible :enterprise_id, :fee_type, :name, :tax_category_id, :calculator_type, :inherits_tax_category
FEE_TYPES = %w(packing transport admin sales fundraising)
PER_ORDER_CALCULATORS = ['Spree::Calculator::FlatRate', 'Spree::Calculator::FlexiRate']
PER_ORDER_CALCULATORS = ['Spree::Calculator::FlatRate', 'Spree::Calculator::FlexiRate', 'Spree::Calculator::PriceSack']
validates_inclusion_of :fee_type, :in => FEE_TYPES

View File

@@ -14,6 +14,7 @@ class OrderCycle < ActiveRecord::Base
attr_accessor :incoming_exchanges, :outgoing_exchanges
validates_presence_of :name, :coordinator_id
validate :orders_close_at_after_orders_open_at?
after_save :refresh_products_cache
@@ -272,4 +273,10 @@ class OrderCycle < ActiveRecord::Base
distributed_variants.include?(product.master) &&
(product.variants & distributed_variants).empty?
end
def orders_close_at_after_orders_open_at?
return if orders_open_at.blank? || orders_close_at.blank?
return if orders_close_at > orders_open_at
errors.add(:orders_close_at, :after_orders_open_at)
end
end

View File

@@ -1,5 +1,5 @@
class OrderCycleSet < ModelSet
def initialize(attributes={})
super(OrderCycle, OrderCycle.all, attributes)
def initialize(collection, attributes={})
super(OrderCycle, collection, attributes)
end
end

View File

@@ -364,12 +364,12 @@ class ProductImporter
def assign_defaults(object, entry)
@import_settings[entry['supplier_id'].to_s]['defaults'].each do |attribute, setting|
case setting['mode']
when 'overwrite_all'
when 'overwrite_all'
object.assign_attributes(attribute => setting['value'])
when 'overwrite_empty'
if object.send(attribute).blank? or (attribute == 'on_hand' and entry['on_hand_nil'])
object.assign_attributes(attribute => setting['value'])
when 'overwrite_empty'
if object.send(attribute).blank? or (attribute == 'on_hand' and entry['on_hand_nil'])
object.assign_attributes(attribute => setting['value'])
end
end
end
end
end

View File

@@ -72,7 +72,6 @@ module Spree
skip_callback :destroy, :after, :update_adjustable
result = yield
ensure
set_callback :save, :after, :update_adjustable
set_callback :destroy, :after, :update_adjustable

View File

@@ -5,5 +5,9 @@ module Spree
extend Spree::LocalizedNumber
localize_number :preferred_amount
def self.description
I18n.t(:flat_rate_per_order)
end
end
end

View File

@@ -7,16 +7,20 @@ module Spree
localize_number :preferred_first_item,
:preferred_additional_item
def self.description
I18n.t(:flexible_rate)
end
def compute(object)
sum = 0
max = self.preferred_max_items.to_i
items_count = line_items_for(object).map(&:quantity).sum
items_count.times do |i|
# check max value to avoid divide by 0 errors
if (max == 0 && i == 0) || (max > 0) && (i % max == 0)
sum += self.preferred_first_item.to_f
else
sum += self.preferred_additional_item.to_f
# check max value to avoid divide by 0 errors
unless max == 0
if items_count > max
sum += (max - 1) * self.preferred_additional_item.to_f + self.preferred_first_item.to_f
elsif items_count <= max
sum += (items_count - 1) * self.preferred_additional_item.to_f + self.preferred_first_item.to_f
end
end

View File

@@ -6,6 +6,10 @@ module Spree
localize_number :preferred_amount
def self.description
I18n.t(:flat_rate_per_item)
end
def compute(object=nil)
return 0 if object.nil?
self.preferred_amount * line_items_for(object).reduce(0) do |sum, value|

View File

@@ -7,5 +7,22 @@ module Spree
localize_number :preferred_minimal_amount,
:preferred_normal_amount,
:preferred_discount_amount
def self.description
I18n.t(:price_sack)
end
def compute(object)
min = preferred_minimal_amount.to_i
order_amount = line_items_for(object).map { |x| x.price * x.quantity }.sum
if order_amount < min
cost = preferred_normal_amount.to_i
elsif order_amount >= min
cost = preferred_discount_amount.to_i
end
cost
end
end
end

View File

@@ -276,12 +276,19 @@ Spree::Order.class_eval do
tax_rates = adjustment.tax_rates
tax_rates_hash = Hash[tax_rates.collect do |tax_rate|
tax_amount = tax_rates.one? ? adjustment.included_tax : tax_rate.compute_tax(adjustment.amount)
[tax_rate.amount, tax_amount]
[tax_rate, tax_amount]
end]
hash.update(tax_rates_hash) { |_tax_rate, amount1, amount2| amount1 + amount2 }
end
end
def price_adjustment_totals
Hash[tax_adjustment_totals.map do |tax_rate, tax_amount|
[tax_rate.name,
Spree::Money.new(tax_amount, currency: currency)]
end]
end
def has_taxes_included
not line_items.with_tax.empty?
end

View File

@@ -51,7 +51,6 @@ module Spree
calculator.calculable.included_in_price = true
result = yield
ensure
self.included_in_price = old_included_in_price
calculator.calculable.included_in_price = old_included_in_price

View File

@@ -19,6 +19,7 @@ Spree.user_class.class_eval do
accepts_nested_attributes_for :ship_address
attr_accessible :enterprise_ids, :enterprise_roles_attributes, :enterprise_limit, :locale, :bill_address_attributes, :ship_address_attributes
after_create :associate_customers
validate :limit_owned_enterprises
@@ -64,6 +65,10 @@ Spree.user_class.class_eval do
Delayed::Job.enqueue ConfirmSignupJob.new(id)
end
def associate_customers
self.customers = Customer.where(email: email)
end
def can_own_more_enterprises?
owned_enterprises(:reload).size < enterprise_limit
end

View File

@@ -34,7 +34,6 @@ Spree::Variant.class_eval do
scope :with_order_cycles_inner, joins(exchanges: :order_cycle)
scope :not_deleted, where(deleted_at: nil)
scope :in_stock, where('spree_variants.count_on_hand > 0 OR spree_variants.on_demand=?', true)
scope :in_order_cycle, lambda { |order_cycle|
with_order_cycles_inner.
merge(Exchange.outgoing).

View File

@@ -2,10 +2,10 @@ Deface::Override.new(:virtual_path => "spree/admin/orders/index",
:name => "add_capture_order_shortcut",
:insert_bottom => "[data-hook='admin_orders_index_row_actions']",
:partial => 'spree/admin/orders/capture'
)
)
# And align actions column (not spree standard, but looks better IMO)
Deface::Override.new(:virtual_path => "spree/admin/orders/index",
:name => "add_capture_order_shortcut_align",
:set_attributes => "[data-hook='admin_orders_index_row_actions']",
:attributes => {:class => "actions", :style => "text-align:left;"} #removes 'align-center' class
)
)

View File

@@ -27,7 +27,6 @@ class Api::UncachedProductSerializer < ActiveModel::Serializer
else
object.master.price_with_fees(options[:current_distributor], options[:current_order_cycle])
end
end
end

View File

@@ -2,6 +2,7 @@
-# ng-change is only valid for inputs, not for a form.
-# So we use onchange and have to get the scope to access the ng controller
= form_for [main_app, :admin, @enterprise], html: { name: "enterprise_form",
onchange: "angular.element(enterprise_form).scope().setFormDirty()",
"ng-controller" => 'enterpriseCtrl',
"ng-cloak" => true } do |f|

View File

@@ -4,12 +4,9 @@
= t('invite_email.invited_to_manage', enterprise: @enterprise.name, instance: @instance)
%p
= t('invite_email.confirm_your_email')
= t('invite_email.confirm_your_email', enterprise: @enterprise.name)
%p
= t('invite_email.mistakenly_sent', owner_email: @enterprise.owner.email, instance: @instance, instance_email: @instance_email)
%p
= t :email_help
= t('invite_email.mistakenly_sent', owner_email: @enterprise.owner.email)
= render 'shared/mailers/signoff'

View File

@@ -14,9 +14,6 @@
%p
= t :email_community_html, link: link_to(t(:join_community), ContentConfig.community_forum_url)
%p
= t :email_help
= render 'shared/mailers/signoff'
= render 'shared/mailers/social_and_contact'

View File

@@ -66,6 +66,8 @@ en:
email: Customer E-Mail
spree/payment:
amount: Amount
order_cycle:
orders_close_at: Close date
errors:
models:
spree/user:
@@ -74,6 +76,10 @@ en:
taken: "There's already an account for this email. Please login or reset your password."
spree/order:
no_card: There are no valid credit cards available
order_cycle:
attributes:
orders_close_at:
after_orders_open_at: must be after open date
activemodel:
errors:
models:
@@ -811,6 +817,8 @@ en:
destroy_errors:
orders_present: That order cycle has been selected by a customer and cannot be deleted. To prevent customers from accessing it, please close it instead.
schedule_present: That order cycle is linked to a schedule and cannot be deleted. Please unlink or delete the schedule first.
bulk_update:
no_data: Hm, something went wrong. No order cycle data found.
producer_properties:
index:
title: Producer Properties
@@ -958,6 +966,10 @@ en:
why_dont_you_add_one: Why don't you add one? :)
no_matching_subscriptions: No matching subscriptions found
schedules:
destroy:
associated_subscriptions_error: This schedule cannot be deleted because it has associated subscriptions
stripe_connect_settings:
edit:
title: "Stripe Connect"
@@ -1268,7 +1280,6 @@ en:
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"
email_help: "If you have any difficulties, check out our FAQs, browse the forum or post a 'Support' topic and someone will help you out!"
email_confirmation_activate_account: "Before we can activate your new account, we need to confirm your email address."
email_confirmation_greeting: "Hi, %{contact}!"
email_confirmation_profile_created: "A profile for %{name} has been successfully created!
@@ -1337,9 +1348,9 @@ See the %{link} to find out more about %{sitename}'s features and to start using
invite_email:
greeting: "Hello!"
invited_to_manage: "You have been invited to manage %{enterprise} on %{instance}."
confirm_your_email: "You will receive an email shortly to confirm your registration."
confirm_your_email: "You should have received or will soon receive an email with a confirmation link. You wont be able to access %{enterprise}'s profile until you have confirmed your email."
set_a_password: "You will then be prompted to set a password before you are able to administer the enterprise."
mistakenly_sent: "Not sure why you have received this email? Please contact %{owner_email} for more information, or you can contact %{instance} at %{instance_email}."
mistakenly_sent: "Not sure why you have received this email? Please contact %{owner_email} for more information."
producer_mail_greeting: "Dear"
producer_mail_text_before: "We now have all the consumer orders for the next food drop."
@@ -1881,6 +1892,10 @@ See the %{link} to find out more about %{sitename}'s features and to start using
calculator: "Calculator"
calculator_values: "Calculator values"
flat_percent_per_item: "Flat Percent (per item)"
flat_rate_per_item: "Flat Rate (per item)"
flat_rate_per_order: "Flat Rate (per order)"
flexible_rate: "Flexible Rate"
price_sack: "Price Sack"
new_order_cycles: "New Order Cycles"
new_order_cycle: "New Order Cycle"
select_a_coordinator_for_your_order_cycle: "Select a coordinator for your order cycle"

View File

@@ -1,4 +1,5 @@
en_US:
language_name: "English"
activerecord:
attributes:
spree/order:
@@ -7,31 +8,110 @@ en_US:
completed_at: Completed At
number: Number
email: Customer E-mail
spree/payment:
amount: Amount
order_cycle:
orders_close_at: Close Date
errors:
models:
spree/user:
attributes:
email:
taken: "There's already an account registered for this email. Please login to reset your password."
spree/order:
no_card: There are no valid credit cards available
order_cycle:
attributes:
orders_close_at:
after_orders_open_at: must be after open date
activemodel:
errors:
models:
subscription_validator:
attributes:
subscription_line_items:
at_least_one_product: "^Please add at least one product"
not_available: "^%{name} is not available from the selected schedule"
ends_at:
after_begins_at: "must be after begins at"
customer:
does_not_belong_to_shop: "does not belong to %{shop}"
schedule:
not_coordinated_by_shop: "is not coordinated by %{shop}"
payment_method:
not_available_to_shop: "is not available to %{shop}"
invalid_type: "must be a Cash or Stripe method"
shipping_method:
not_available_to_shop: "is not available to %{shop}"
credit_card:
not_available: "is not available"
blank: "is required"
devise:
confirmations:
send_instructions: "You will receive an email with instructions about how to confirm your account in a few minutes."
failed_to_send: "An error occurred whilst sending your confirmation email."
resend_confirmation_email: "Resend confirmation email."
confirmed: "Thanks for confirming your email! You can now log in."
not_confirmed: "Your email address could not be confirmed. Perhaps you have already completed this step?"
user_registrations:
spree_user:
signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please open the link to activate your account."
failure:
invalid: |
Invalid email or password.
Were you a guest last time? Perhaps you need to create an account or reset your password.
unconfirmed: "You have to confirm your account before continuing."
enterprise_mailer:
confirmation_instructions:
subject: "Please confirm the email address for %{enterprise}"
welcome:
subject: "%{enterprise}is now on %{sitename}"
invite_manager:
subject: "%{enterprise} has invited you to be a manager"
producer_mailer:
order_cycle:
subject: "Order cycle report for %{producer}"
subscription_mailer:
placement_summary_email:
subject: A summary of recently placed subscription orders
greeting: "Hi %{name},"
intro: "Below is a summary of the subscription orders that have just been placed for %{shop}."
confirmation_summary_email:
subject: A summary of recently confirmed subscription orders
greeting: "Hi %{name},"
intro: "Below is a summary of the subscription orders that have just been finalised for %{shop}."
summary_overview:
total: A total of %{count} subscriptions were marked for automatic processing.
success_zero: Of these, none were processed successfully.
success_some: Of these, %{count} were processed successfully.
success_all: All were processed successfully.
issues: Details of the issues encountered are provided below.
summary_detail:
no_message_provided: No error message provided
changes:
title: Insufficient Stock (%{count} orders)
explainer: These orders were processed but insufficient stock was available for some requested items
empty:
title: No Stock (%{count} orders)
explainer: These orders were unable to be processed because no stock was available for any requested items
complete:
title: Already Processed (%{count} orders)
explainer: These orders were already marked as complete, and were therefore left untouched
processing:
title: Error Encountered (%{count} orders)
explainer: Automatic processing of these orders failed due to an error. The error has been listed where possible.
failed_payment:
title: Failed Payment (%{count} orders)
explainer: Automatic processing of payment for these orders failed due to an error. The error has been listed where possible.
other:
title: Other Failure (%{count} orders)
explainer: Automatic processing of these orders failed for an unknown reason. This should not occur, please contact us if you are seeing this.
home: "OFN"
title: US Food Coop - Open Food Network US
title: Open Food Network
welcome_to: 'Welcome to '
site_meta_description: "We begin from the ground up. With farmers and growers ready to tell their stories proudly and truly. With distributors ready to connect people with products fairly and honestly. With buyers who believe that better weekly shopping decisions can seriously change the world."
search_by_name: Search by name or city...
producers_join: US producers are now welcome to join US Food Coop - Open Food Network US.
producers_join: US producers are now welcome to join the Open Food Network.
charges_sales_tax: Charges Sales Tax?
print_invoice: "Invoice"
print_ticket: "Print invoice"
@@ -44,7 +124,7 @@ en_US:
cancel_order: "Cancel Order"
confirm_send_invoice: "An invoice for this order will be sent to the customer. Are you sure you want to continue?"
confirm_resend_order_confirmation: "Are you sure you want to resend the order confirmation email?"
must_have_valid_business_number: "Please enter your company number."
must_have_valid_business_number: " %{enterprise_name}must have a company registration # before invoices can be sent."
invoice: "Invoice"
percentage_of_sales: "%{percentage} of sales"
capped_at_cap: "capped at %{cap}"
@@ -56,6 +136,9 @@ en_US:
say_no: "No"
say_yes: "Yes"
then: then
ongoing: Ongoing
bill_address: Billing Address
ship_address: Shipping Address
sort_order_cycles_on_shopfront_by: "Sort Order Cycles On Storefront By"
required_fields: Required fields are marked with an asterisk
select_continue: Select and Continue
@@ -106,23 +189,36 @@ en_US:
filter_results: Filter Results
quantity: Quantity
pick_up: Pick up
copy: Copy
actions:
create_and_add_another: "Create and Add Another"
admin:
begins_at: Begins At
begins_on: Begins On
customer: Customer
date: Date
email: Email
ends_at: Ends At
ends_on: Ends On
name: Name
on_hand: On Hand
on_demand: On Demand
on_demand?: On Demand?
order_cycle: Order Cycle
payment: Payment
payment_method: Payment Method
phone: Phone
price: Price
producer: Producer
image: Image
product: Product
quantity: Quantity
schedule: Schedule
shipping: Shipping
shipping_method: Shipping Method
shop: Store
sku: SKU
status_state: State
tags: Tags
variant: Variant
weight: Weight
@@ -137,6 +233,10 @@ en_US:
form_invalid: "Form contains missing or invalid fields"
clear_filters: Clear Filters
clear: Clear
show_more: Show more
show_n_more: Show %{num} more
choose: "Choose..."
please_select: Please select...
columns: Columns
actions: Actions
viewing: "Viewing: %{current_view_name}"
@@ -264,11 +364,28 @@ en_US:
manages: manages
products:
unit_name_placeholder: 'eg. bunches'
bulk_edit:
unit: Unit
display_as: Display As
category: Category
tax_category: Tax Category
inherits_properties?: Inherits Properties?
available_on: Available On
av_on: "Av. On"
upload_an_image: Upload an image
product_search_keywords: Product Search Keywords
product_search_tip: Type words to help search your products in the shops. Use space to separate each keyword.
SEO_keywords: SEO Keywords
seo_tip: Type words to help search your products in the web. Use space to separate each keyword.
Search: Search
properties:
property_name: Property Name
inherited_property: Inherited Property
variants:
to_order_tip: "Items made to order do not have a set stock level, such as loaves of bread made fresh to order."
product_distributions: "Product Distributions"
group_buy_options: "Group Buy Options"
back_to_products_list: "Back to products list"
variant_overrides:
loading_flash:
loading_inventory: LOADING INVENTORY
@@ -319,6 +436,7 @@ en_US:
max_fulfilled_units: "Max Fulfilled Units"
order_error: "Some errors must be resolved before you can update orders.\nAny fields with red borders contain errors."
variants_without_unit_value: "WARNING: Some variants do not have a unit value"
select_variant: "Select a variant"
enterprise:
select_outgoing_oc_products_from: Select outgoing OC products from
enterprises:
@@ -345,6 +463,9 @@ en_US:
contact:
name: Name
name_placeholder: eg. Justin Jones
email_address: Public Email Address
email_address_placeholder: eg. inquiries@fresh-food.com
email_address_tip: "This email address will be displayed in your public profile"
phone: Phone
phone_placeholder: eg. (123)456-7891
website: Website
@@ -421,6 +542,10 @@ en_US:
allow_order_changes_tip: "Allow customers to change their order as long the order cycle is open."
allow_order_changes_false: "Placed orders cannot be changed / cancelled"
allow_order_changes_true: "Customers can change / cancel orders while order cycle is open"
enable_subscriptions: "Subscriptions"
enable_subscriptions_tip: "Enable subscriptions functionality?"
enable_subscriptions_false: "Disabled"
enable_subscriptions_true: "Enabled"
shopfront_message: Shopfront Message
shopfront_message_placeholder: >
An optional explanation for customers detailing how your shopfront works,
@@ -463,6 +588,7 @@ en_US:
resend: Resend
owner: 'Owner'
contact: "Contact"
contact_tip: "The manager who will receive enterprise emails for orders and notifications. Must have a confirmed email adress."
owner_tip: The primary user responsible for this enterprise.
notifications: Notifications
notifications_tip: Notifications about orders will be send to this email address.
@@ -470,6 +596,11 @@ en_US:
notifications_note: 'Note: A new email address may need to be confirmed prior to use'
managers: Managers
managers_tip: The other users with permission to manage this enterprise.
invite_manager: "Invite Manager"
invite_manager_tip: "Invite an unregistered user to sign up and become a manager of this enterprise."
add_unregistered_user: "Add an unregistered user"
email_confirmed: "Email confirmed"
email_not_confirmed: "Email not confirmed"
actions:
edit_profile: Edit Profile
properties: Properties
@@ -527,6 +658,9 @@ en_US:
welcome_text: You have successfully created a
next_step: Next step
choose_starting_point: 'Choose your starting point:'
invite_manager:
user_already_exists: "User already exists"
error: "Something went wrong"
order_cycles:
edit:
advanced_settings: Advanced Settings
@@ -563,6 +697,22 @@ en_US:
add_a_tag: Add a tag
delivery_details: Pickup / Delivery details
debug_info: Debug information
index:
involving: Involving
schedule: Schedule
schedules: Schedules
adding_a_new_schedule: Adding A New Schedule
updating_a_schedule: Updating A Schedule
new_schedule: New Schedule
create_schedule: Create Schedule
update_schedule: Update Schedule
delete_schedule: Delete Schedule
created_schedule: Created schedule
updated_schedule: Updated schedule
deleted_schedule: Deleted schedule
schedule_name_placeholder: Schedule Name
name_required_error: Please enter a name for this schedule
no_order_cycles_error: Please select at least one order cycle (drag and drop)
name_and_timing_form:
name: Name
orders_open: Orders open at
@@ -579,9 +729,19 @@ en_US:
customer_instructions_placeholder: Pick-up or delivery notes
products: Products
fees: Fees
destroy_errors:
orders_present: That order cycle has been selected by a customer and cannot be deleted. To prevent customers from accessing it, please close it instead.
schedule_present: That order cycle is linked to a schedule and cannot be deleted. Please unlink or delete the schedule first.
bulk_update:
no_data: Hm, something went wrong. No order cycle data found.
producer_properties:
index:
title: Producer Properties
proxy_orders:
cancel:
could_not_cancel_the_order: Could not cancel the order
resume:
could_not_resume_the_order: Could not resume the order
shared:
user_guide_link:
user_guide: User Guide
@@ -655,10 +815,66 @@ en_US:
packing:
name: Packing Reports
subscriptions:
subscriptions: Subscriptions
new: New Subscription
create: Create Subscription
index:
please_select_a_shop: Please select a shop
edit_subscription: Edit Subscription
pause_subscription: Pause Subscription
unpause_subscription: Unpause Subscription
cancel_subscription: Cancel Subscription
setup_explanation:
just_a_few_more_steps: 'Just a few more steps before you can begin:'
enable_subscriptions: "Enable subscriptions for at least one of your shops"
enable_subscriptions_step_1_html: 1. Go to the %{enterprises_link} page, find your shop, and click "Manage"
enable_subscriptions_step_2: 2. Under "Shop Preferences", enable the Subscriptions option
set_up_shipping_and_payment_methods_html: Set up %{shipping_link} and %{payment_link} methods
set_up_shipping_and_payment_methods_note_html: Note that only Cash and Stripe payment methods may<br />be used with subscriptions
ensure_at_least_one_customer_html: Ensure that at least one %{customer_link} exists
create_at_least_one_schedule: Create at least one Schedule
create_at_least_one_schedule_step_1_html: 1. Go to the on the %{order_cycles_link} page
create_at_least_one_schedule_step_2: 2. Create an order cycle if you have not already done so
create_at_least_one_schedule_step_3: 3. Click '+ New Schedule', and fill out the form
once_you_are_done_you_can_html: Once you are done, you can %{reload_this_page_link}
reload_this_page: reload this page
steps:
details: 1. Basic Details
address: 2. Address
products: 3. Add Products
review: 4. Review & Save
details:
details: Details
invalid_error: Oops! Please fill in all of the required fields...
allowed_payment_method_types_tip: Only Cash and Stripe payment methods may be used at the moment
credit_card: Credit Card
no_cards_available: No cards available
review:
details: Details
address: Address
products: Products
orders:
number: Number
confirm_edit: Are you sure you want to edit this order? Doing so may make it more difficult to automatically sync changes to the subscription in the future.
confirm_cancel_msg: Are you sure you want to cancel this subscription? This action cannot be undone.
cancel_failure_msg: 'Sorry, cancellation failed!'
confirm_pause_msg: Are you sure you want to pause this subscription?
pause_failure_msg: 'Sorry, pausing failed!'
confirm_unpause_msg: Are you sure you want to unpause this subscription?
unpause_failure_msg: 'Sorry, unpausing failed!'
confirm_cancel_open_orders_msg: "Some orders for this subscription are currently open. The customer has already been notified that the order will be placed. Would you like to cancel these order(s) or keep them?"
resume_canceled_orders_msg: "Some orders for this subscription can be resumed right now. You can resume them from the orders dropdown."
yes_cancel_them: Cancel them
no_keep_them: Keep them
yes_i_am_sure: Yes, I'm sure
order_update_issues_msg: Some orders could not be automatically updated, this is most likely because they have been manually edited. Please review the issues listed below and make any adjustments to individual orders if required.
no_results:
no_subscriptions: No subscriptions yet...
why_dont_you_add_one: Why don't you add one? :)
no_matching_subscriptions: No matching subscriptions found
schedules:
destroy:
associated_subscriptions_error: This schedule cannot be deleted because it has associated subscriptions
stripe_connect_settings:
edit:
title: "Stripe Connect"
@@ -773,8 +989,11 @@ en_US:
no_payment: no payment methods
no_shipping_or_payment: no shipping or payment methods
unconfirmed: unconfirmed
days: days
label_shop: "Shop"
label_shops: "Stores"
label_map: "Map"
label_producer: "Producer"
label_producers: "Producers"
label_groups: "Groups"
label_about: "About"
@@ -923,7 +1142,7 @@ en_US:
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."
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"
email_help: "If you have any difficulties, check out our FAQs, browse the forum or post a 'Support' topic and someone will help you out!"
email_confirmation_activate_account: "Before we can activate your new account, we need to confirm your email address."
email_confirmation_greeting: "Hi, %{contact}!"
email_confirmation_profile_created: "A profile for %{name} has been successfully created! To activate your Profile we need to confirm this email address."
email_confirmation_click_link: "Please click the link below to confirm your email and to continue setting up your profile."
@@ -951,6 +1170,23 @@ en_US:
email_payment_not_paid: NOT PAID
email_payment_summary: Payment summary
email_payment_method: "Paying via:"
email_so_placement_intro_html: "You have a new order with <strong>%{distributor}</strong>"
email_so_placement_details_html: "Here are the details of your order for <strong>%{distributor}</strong>:"
email_so_placement_changes: "Unfortunately, not all products that you requested were available. The original quantities that you requested appear crossed-out below."
email_so_payment_success_intro_html: "An automatic payment has been processed for your order from <strong>%{distributor}</strong>."
email_so_placement_explainer_html: "This order was automatically created for you."
email_so_edit_true_html: "You can <a href='%{order_url}'>make changes</a> until orders close on %{orders_close_at}."
email_so_edit_false_html: "You can <a href='%{order_url}'>view details of this order</a> at any time."
email_so_contact_distributor_html: "If you have any questions you can contact <strong>%{distributor}</strong> via %{email}."
email_so_confirmation_intro_html: "Your order with <strong>%{distributor}</strong> is now confirmed"
email_so_confirmation_explainer_html: "This order was automatically placed for you, and it has now been finalised."
email_so_confirmation_details_html: "Here's everything you need to know about your order from <strong>%{distributor}</strong>:"
email_so_empty_intro_html: "We tried to place a new order with <strong>%{distributor}</strong>, but had some problems..."
email_so_empty_explainer_html: "Unfortunately, none of products that you ordered were available, so no order has been placed. The original quantities that you requested appear crossed-out below."
email_so_empty_details_html: "Here are the details of the unplaced order for <strong>%{distributor}</strong>:"
email_so_failed_payment_intro_html: "We tried to process a payment, but had some problems..."
email_so_failed_payment_explainer_html: "The payment for your subscription with <strong>%{distributor}</strong> failed because of a problem with your credit card. <strong>%{distributor}</strong> has been notified of this failed payment."
email_so_failed_payment_details_html: "Here are the details of the failure provided by the payment gateway:"
email_shipping_delivery_details: Delivery details
email_shipping_delivery_time: "Delivery on:"
email_shipping_delivery_address: "Delivery address:"
@@ -960,8 +1196,16 @@ en_US:
email_special_instructions: "Your notes:"
email_signup_greeting: Hello!
email_signup_welcome: "Welcome to %{sitename}!"
email_signup_confirmed_email: "Thanks for confirming your email."
email_signup_shop_html: "You can now log in at %{link}."
email_signup_text: "Thanks for joining the network. If you are a customer, we look forward to introducing you to many fantastic farmers, wonderful food hubs and delicious food! If you are a producer or food enterprise, we are excited to have you as a part of the network."
email_signup_help_html: "We welcome all your questions and feedback; you can use the <em>Send Feedback</em> button on the site or email us at %{email}"
invite_email:
greeting: "Hello!"
invited_to_manage: "You have been invited to manage %{enterprise} on %{instance}."
confirm_your_email: "You should have received or will soon receive an email with a confirmation link. You wont be able to access %{enterprise}'s profile until you have confirmed your email."
set_a_password: "You will then be prompted to set a password before you are able to administer the enterprise."
mistakenly_sent: "Not sure why you have received this email? Please contact %{owner_email} for more information."
producer_mail_greeting: "Dear"
producer_mail_text_before: "We now have all the consumer orders for the next food drop."
producer_mail_order_text: "Here is a summary of the orders for your products:"
@@ -1121,6 +1365,7 @@ en_US:
shops_signup_help: We're ready to help.
shops_signup_help_text: You need a better return. You need new buyers and logistics partners. You need your story told across wholesale, retail, and the kitchen table.
shops_signup_detail: Here's the detail.
orders: Orders
orders_fees: Fees...
orders_edit_title: Shopping cart
orders_edit_headline: Your shopping cart
@@ -1217,6 +1462,7 @@ en_US:
password_reset_sent: "An email with instructions on resetting your password has been sent!"
reset_password: "Reset password"
who_is_managing_enterprise: "Who is responsible for managing %{enterprise}?"
update_and_recalculate_fees: "Update And Recalculate Fees"
enterprise:
registration:
modal:
@@ -1453,6 +1699,10 @@ en_US:
calculator: "Calculator"
calculator_values: "Calculator values"
flat_percent_per_item: "Flat Percent (per item)"
flat_rate_per_item: "Flat Rate (per item)"
flat_rate_per_order: "Flat Rate (per order)"
flexible_rate: "Flexible Rate"
price_sack: "Price Sack"
new_order_cycles: "New Order Cycles"
new_order_cycle: "New Order Cycle"
select_a_coordinator_for_your_order_cycle: "Select a coordinator for your order cycle"
@@ -1728,7 +1978,8 @@ en_US:
products_unsaved: "Changes to %{n} products remain unsaved."
is_already_manager: "is already a manager!"
no_change_to_save: "No change to save"
add_manager: "Add a manager"
user_invited: "%{email} has been invited to manage this enterprise"
add_manager: "Add an existing user"
users: "Users"
about: "About"
images: "Images"
@@ -1739,6 +1990,7 @@ en_US:
social: "Social"
business_details: "Business Details"
properties: "Properties"
shipping: "Shipping"
shipping_methods: "Shipping Methods"
payment_methods: "Payment Methods"
payment_method_fee: "Transaction fee"
@@ -1789,6 +2041,14 @@ en_US:
order_cycles_email_to_producers_notice: 'Emails to be sent to producers have been queued for sending.'
order_cycles_no_permission_to_coordinate_error: "None of your enterprises have permission to coordinate an order cycle"
order_cycles_no_permission_to_create_error: "You don't have permission to create an order cycle coordinated by that enterprise"
back_to_orders_list: "Back to order list"
order_information: "Order Information"
date_completed: "Date Completed"
amount: "Amount"
state_names:
ready: Ready
pending: Pending
shipped: Shipped
js:
saving: 'Saving...'
changes_saved: 'Changes saved.'
@@ -1807,8 +2067,12 @@ en_US:
resolve_errors: Please resolve the following errors
more_items: "+ %{count} More"
admin:
enterprise_limit_reached: "You have reached the standard limit of enterprises per account. Write to %{contact_email} if you need to increase it."
modals:
got_it: Got it
close: "Close"
invite: "Invite"
invite_title: "Invite an unregistered user"
tag_rule_help:
title: Tag Rules
overview: Overview
@@ -1972,6 +2236,10 @@ en_US:
customers:
select_shop: 'Please select a shop first'
could_not_create: Sorry! Could not create
subscriptions:
closes: closes
closed: closed
close_date_not_set: Close date not set
producers:
signup:
start_free_profile: "Start with a free profile, and expand when you're ready!"
@@ -1979,6 +2247,8 @@ en_US:
email: Email
account_updated: "Account updated!"
my_account: "My account"
date: "Date"
time: "Time"
admin:
orders:
invoice:
@@ -2085,14 +2355,22 @@ en_US:
address: address
adjustments: adjustments
awaiting_return: awaiting return
canceled: cancelled
cart: cart
complete: complete
confirm: confirm
delivery: delivery
paused: paused
payment: payment
pending: pending
resumed: resumed
returned: returned
skrill: skrill
subscription_state:
active: active
pending: pending
paused: paused
canceled: cancelled
payment_states:
balance_due: balance due
completed: completed
@@ -2120,6 +2398,8 @@ en_US:
issue_text: |
If the above URL does nor work, try to copy and paste it into your browser.
If you continue to have problems please feel free to contact us.
confirmation_instructions:
subject: Please confirm your OFN account
weight: Weight (per lb)
zipcode: Zipcode
users:
@@ -2131,6 +2411,7 @@ en_US:
cards: Credit Cards
transactions: Transactions
settings: Account Settings
unconfirmed_email: "Pending email confirmation for: %{unconfirmed_email}. Your email address will be updated once the new email is confirmed."
orders:
open_orders: Open Orders
past_orders: Past Orders

View File

@@ -367,6 +367,8 @@ fr:
available_on: Disponible via
av_on: "Disp. via"
upload_an_image: Importer une image
product_search_keywords: Mots-clés de recherche produits
Search: Rechercher
properties:
property_name: Nom du label
inherited_property: Label producteur appliqué par défaut
@@ -374,7 +376,6 @@ fr:
to_order_tip: "Les articles fabriqués sur commande n'ont pas un niveau de stock défini, comme des pains faits à la main."
product_distributions: "Lieux de distribution"
group_buy_options: "Options d'achat par lot"
seo: "Référencement"
back_to_products_list: "Retour à la liste produits"
variant_overrides:
loading_flash:
@@ -1131,7 +1132,6 @@ fr:
email_admin_html: "Vous pouvez gérer votre compte en vous connectant ici %{link} ou en cliquant sur la roue en haut à droite de la page d'accueil et en sélectionnant Administration."
email_community_html: "Nous avons aussi un forum de discussion en ligne (en anglais) pour échanger avec la communauté sur des questions liées au logiciel OFN et aux défis de la gestion d'un food hub. Nous vous invitons à y participer. Nous sommes en constante évolution et vos contributions à ce forum vont façonner les prochaines étapes. %{link}"
join_community: "Rejoindre la communauté"
email_help: "En cas de difficulté, consultez notre FAQ, parcourez le forum (en anglais) ou postez un message dans la section 'Support' et quelqu'un viendra vous aider!"
email_confirmation_activate_account: "Avant de pouvoir activer votre compte, nous devons nous assurer de la validité de votre adresse email."
email_confirmation_greeting: "Bonjour %{contact}!"
email_confirmation_profile_created: "Le profil pour %{name} a été créé avec succès! Pour activer votre Profil nous devons vérifier cette adresse email."
@@ -1193,9 +1193,7 @@ fr:
invite_email:
greeting: "Bonjour!"
invited_to_manage: "Vous avez été invité(e) à gérer %{enterprise} sur %{instance}."
confirm_your_email: "Vous avez reçu ou allez recevoir un email avec un lien de confirmation. Vous ne pourrez pas accéder au profil de l'entreprise avant d'avoir confirmé votre email."
set_a_password: "Vous serez ensuite invité(e) à choisir un mot de passe avant de pouvoir accéder et gérer le profil de l'entreprise."
mistakenly_sent: "Vous ne savez pas pourquoi vous recevez cet email? Veuillez contacter %{owner_email} pour toute question."
producer_mail_greeting: "Cher(ère)"
producer_mail_text_before: "Nous avons reçu toutes les commandes pour la prochaine livraison."
producer_mail_order_text: "Voilà la liste et les quantités des produits commandés vous concernant:"
@@ -2036,7 +2034,13 @@ fr:
order_cycles_no_permission_to_coordinate_error: "Aucune de vos entreprises n'a les droits requis pour coordonner un cycle de vente"
order_cycles_no_permission_to_create_error: "Vous n'avez pas les droits requis pour créer un cycle de vente coordonné par cette entreprise"
back_to_orders_list: "Retour à la liste des commandes"
order_information: "Info commande"
date_completed: "Date d'opération"
amount: "Montant"
state_names:
ready: Prêt
pending: En attente
shipped: Expédié
js:
saving: 'Enregistrement en cours...'
changes_saved: 'Modifications sauvegardées.'
@@ -2058,6 +2062,9 @@ fr:
enterprise_limit_reached: "Vous avez atteint le nombre limite d'entreprises autorisées par défaut. Ecrivez à %{contact_email}si vous avez besoin d'augmenter cette limite."
modals:
got_it: J'ai compris
close: "Fermer"
invite: "Inviter"
invite_title: "Inviter un nouvel utilisateur"
tag_rule_help:
title: Règles de tag
overview: Aperçu
@@ -2241,6 +2248,8 @@ fr:
email: Email
account_updated: "Compte mis à jour!"
my_account: "Mon compte"
date: "Date"
time: "Heure"
admin:
orders:
invoice:

View File

@@ -8,6 +8,8 @@ pt:
completed_at: Completado em
number: Número
email: Email do/a consumidor/a
spree/payment:
amount: Quantia
errors:
models:
spree/user:
@@ -58,6 +60,8 @@ pt:
subject: "Por favor confirme o endereço de email da %{enterprise}"
welcome:
subject: "%{enterprise} está agora em %{sitename}"
invite_manager:
subject: "%{enterprise} enviou-lhe um convite para ser gestora/a"
producer_mailer:
order_cycle:
subject: "Relatório de ciclo de encomendas de %{producer}"
@@ -200,6 +204,7 @@ pt:
phone: Telefone
price: Preço
producer: Produtor
image: Imagem
product: Produto
quantity: Quantidade
schedule: Horário
@@ -353,6 +358,20 @@ pt:
manages: gere
products:
unit_name_placeholder: 'ex: molho, ramo, etc.'
bulk_edit:
unit: Unidade
display_as: Mostrar como
category: Categoria
tax_category: Categoria de imposto
inherits_properties?: Herda Propriedades?
available_on: Disponível em
av_on: "Disp. em"
upload_an_image: Carregar uma imagem
product_search_keywords: Palavras-chave de Pesquisa de Produto
product_search_tip: Insira palavras que ajudem a encontrar os seus produtos nas lojas. Use um espaço para separar cada palavra-chave
SEO_keywords: Palavras-chave SEO
seo_tip: Insira palavras que ajudem a encontrar os seus produtos na web. Use um espaço para separar cada palavra-chave
Search: Procurar
properties:
property_name: Nome da propriedade
inherited_property: Propriedade herdada
@@ -360,7 +379,6 @@ pt:
to_order_tip: "Os itens feitos por encomenda não têm um nível de stock definido, como pão fresco, por exemplo."
product_distributions: "Distribuições de Produto"
group_buy_options: "Opções de Compra Colectiva"
seo: "SEO"
back_to_products_list: "Voltar à lista de produtos"
variant_overrides:
loading_flash:
@@ -412,6 +430,7 @@ pt:
max_fulfilled_units: "Máximo de Unidades Completas "
order_error: "Alguns erros devem ser corrigidos antes de actualizar os pedidos.\nOs campos com bordas vermelhas contêm erros."
variants_without_unit_value: "AVISO: Algumas variantes não possuem unidade de valor"
select_variant: "Selecionar uma variante"
enterprise:
select_outgoing_oc_products_from: 'Selecione a saída do ciclo de pedidos '
enterprises:
@@ -571,6 +590,9 @@ pt:
notifications_note: 'Nota: um novo endereço de e-mail pode precisar ser confirmado antes do uso'
managers: Administradores
managers_tip: Os outros utilizadores com permissão para gerir esta organização.
invite_manager: "Convidar Gestor/a"
invite_manager_tip: "Convidar um utilizador não-registado a inscrever-se e tornar-se gestor desta organização."
add_unregistered_user: "Adicionar um utilizador não-registado"
email_confirmed: "Email confirmado"
email_not_confirmed: "Email não confirmado"
actions:
@@ -630,6 +652,9 @@ pt:
welcome_text: Você criou com sucesso uma
next_step: Próximo passo
choose_starting_point: 'Escolha o seu ponto de partida:'
invite_manager:
user_already_exists: "O utilizador já existe"
error: "Algo correu mal"
order_cycles:
edit:
advanced_settings: Configurações avançadas
@@ -842,6 +867,9 @@ pt:
no_subscriptions: Ainda não existem subscrições....
why_dont_you_add_one: Porque não acrescentar uma? :)
no_matching_subscriptions: Não foram encontradas subscrições a condizer
schedules:
destroy:
associated_subscriptions_error: Este horário não pode ser eliminado porque tem subscrições associadas
stripe_connect_settings:
edit:
title: "Ligar ao Stripe"
@@ -1109,7 +1137,6 @@ pt:
email_admin_html: "Você pode gerenciar sua conta entrando no %{link} ou clicando na engrenagem no canto superior direito da página, e selecionando Administração."
email_community_html: "Também temos um fórum online para discussão sobre a plataforma e os desafios de se manter uma iniciativa de produção e consumo local. Está convidado/a a participar! Estamos constantemente a evoluir e as suas ideias vão ajudar-nos a melhorar.\n%{link}"
join_community: "Faça parte da comunidade"
email_help: "Se tiver quaisquer dificuldades, leia nosso FAQs, navegue no fórum ou crie um post no tópico 'Support' e alguém irá te ajudar!"
email_confirmation_activate_account: "Antes de podermos activar a sua conta, precisamos de confirmar o seu endereço de email."
email_confirmation_greeting: "Olá, %{contact}!"
email_confirmation_profile_created: "Um perfil para %{name} foi criado com sucesso!\nPara ativar seu Perfil precisamos que você confirme seu endereço de email."
@@ -1168,6 +1195,12 @@ pt:
email_signup_shop_html: "Já pode fazer log in em %{link}."
email_signup_text: "Obrigada por juntar-se à rede. Se é consumidor/a, vai ficar a conhecer vários produtores fantásticos, pontos de venda incríveis e comidas deliciosas! Se é produtor/a ou uma organização de consumo local, estamos felizes por tê-lo na nossa rede"
email_signup_help_html: "Dúvidas e comentários são sempre benvindos; você pode usar o botão <em>Enviar Comentário</em> no site, ou enviar um e-mail para %{email}"
invite_email:
greeting: "Olá!"
invited_to_manage: "Foste convidado/a para gerir %{enterprise} em %{instance}."
confirm_your_email: "Deves ter recebido, ou receberás em breve, um email com um link de confirmação. Não vais conseguir aceder ao perfil de %{enterprise} enquanto não tiveres confirmado o teu email. "
set_a_password: "Depois ser-te-á pedido que definas uma palavra-passe antes de poderes administrar a organização."
mistakenly_sent: "Não tens a certeza porque é que recebeste este email? Por favor contacta %{owner_email}para mais informação. "
producer_mail_greeting: "Querido"
producer_mail_text_before: "Agora temos todos os pedidos do cliente para a próxima entrega."
producer_mail_order_text: "Aqui está um resumo de pedidos para seus produtos:"
@@ -1430,6 +1463,7 @@ pt:
password_reset_sent: "Um email foi enviado com instruções para resetar sua senha!"
reset_password: "Resetar password"
who_is_managing_enterprise: "Quem é responsável por gerir %{enterprise}? "
update_and_recalculate_fees: "Actualizar e Recalcular Taxas"
enterprise:
registration:
modal:
@@ -1941,7 +1975,6 @@ pt:
products_unsaved: "Modificações para %{n} produtos permanecem não salvas."
is_already_manager: "já é um gestor!"
no_change_to_save: "Nenhuma modificação a ser salva"
add_manager: "Adicionar um gestor"
users: "Usuários"
about: "Sobre"
images: "Imagens"
@@ -1952,6 +1985,7 @@ pt:
social: "Social"
business_details: "Detalhes do negócio"
properties: "Propriedades"
shipping: "Envio"
shipping_methods: "Métodos de Entrega"
payment_methods: "Métodos de Pagamento"
payment_method_fee: "Taxa de transação"
@@ -2002,6 +2036,13 @@ pt:
order_cycles_email_to_producers_notice: 'Os email a enviar aos produtores foram postos na fila de espera para envio.'
order_cycles_no_permission_to_coordinate_error: "Nenhuma das suas organizações tem permissão para coordenar um ciclo de encomendas."
order_cycles_no_permission_to_create_error: "Não tem permissão para criar um ciclo de encomendas coordenado por essa organização."
back_to_orders_list: "Voltar à lista de encomendas"
order_information: "Informação da Encomenda"
date_completed: "Data Conclusão"
amount: "Quantia"
state_names:
ready: Pronto
pending: Pendente
js:
saving: 'A guardar....'
changes_saved: 'Alterações guardadas.'
@@ -2198,6 +2239,8 @@ pt:
email: Email
account_updated: "Conta actualizada!"
my_account: "A minha conta"
date: "Data"
time: "Hora"
admin:
orders:
invoice:

View File

@@ -1,6 +1,5 @@
module OpenFoodNetwork
module ColumnPreferenceDefaults
private
# NOTE: These methods define valid column names (via hash keys)

View File

@@ -41,8 +41,7 @@ module OpenFoodNetwork
ba.phone,
order.distributor.andand.name,
[da.andand.address1, da.andand.address2, da.andand.city].join(" "),
order.shipping_method.andand.name
]
order.shipping_method.andand.name]
end
end
end

View File

@@ -1,5 +1,4 @@
module OpenFoodNetwork
GroupBuyVariantRow = Struct.new(:variant, :sum_quantities, :sum_max_quantities) do
def to_row
[variant.product.supplier.name, variant.product.name, I18n.t('admin.reports.unitsize'), variant.options_text, variant.weight, sum_quantities, sum_max_quantities]

View File

@@ -1,7 +1,6 @@
require 'open_food_network/order_cycle_permissions'
module OpenFoodNetwork
# There are two translator classes on the boundary between Angular and Rails: On the Angular side,
# there is the OrderCycle#dataForSubmit method, and on the Rails side is this class. I think data
# translation is more a responsibility of Angular, so I'd be inclined to refactor this class to move

View File

@@ -74,8 +74,7 @@ module OpenFoodNetwork
order.shipping_method.andand.name,
order.payments.first.andand.payment_method.andand.name,
order.payments.first.amount,
OpenFoodNetwork::UserBalanceCalculator.new(order.email, order.distributor).balance
]
OpenFoodNetwork::UserBalanceCalculator.new(order.email, order.distributor).balance]
end
def delivery_row(order)
@@ -92,8 +91,7 @@ module OpenFoodNetwork
order.payments.first.amount,
OpenFoodNetwork::UserBalanceCalculator.new(order.email, order.distributor).balance,
has_temperature_controlled_items?(order),
order.special_instructions
]
order.special_instructions]
end
def filter_to_payment_method(orders)

View File

@@ -1,5 +1,4 @@
module OpenFoodNetwork
class OrderGrouper
def initialize(rules, column_constructors)
@rules = rules

View File

@@ -36,14 +36,12 @@ module OpenFoodNetwork
I18n.t(:report_header_ship_street), I18n.t(:report_header_ship_street_2), I18n.t(:report_header_ship_city), I18n.t(:report_header_ship_postcode), I18n.t(:report_header_ship_state),
I18n.t(:report_header_comments), I18n.t(:report_header_sku),
I18n.t(:report_header_order_cycle), I18n.t(:report_header_payment_method), I18n.t(:report_header_customer_code), I18n.t(:report_header_tags),
I18n.t(:report_header_billing_street), I18n.t(:report_header_billing_street_2), I18n.t(:report_header_billing_city), I18n.t(:report_header_billing_postcode), I18n.t(:report_header_billing_state),
]
I18n.t(:report_header_billing_street), I18n.t(:report_header_billing_street_2), I18n.t(:report_header_billing_city), I18n.t(:report_header_billing_postcode), I18n.t(:report_header_billing_state),]
else
[I18n.t(:report_header_producer), I18n.t(:report_header_product), I18n.t(:report_header_variant),
I18n.t(:report_header_amount), I18n.t(:report_header_curr_cost_per_unit), I18n.t(:report_header_total_cost),
I18n.t(:report_header_status), I18n.t(:report_header_incoming_transport)]
end
end
def search
@@ -247,7 +245,8 @@ module OpenFoodNetwork
proc { |line_items| line_items.first.order.bill_address.andand.address2 },
proc { |line_items| line_items.first.order.bill_address.andand.city },
proc { |line_items| line_items.first.order.bill_address.andand.zipcode },
proc { |line_items| line_items.first.order.bill_address.andand.state } ]
proc { |line_items| line_items.first.order.bill_address.andand.state }
]
else
[ proc { |line_items| line_items.first.product.supplier.name },
proc { |line_items| line_items.first.product.name },

View File

@@ -81,7 +81,8 @@ module OpenFoodNetwork
{ group_by: proc { |line_item| line_item.product },
sort_by: proc { |product| product.name } },
{ group_by: proc { |line_item| line_item.full_name },
sort_by: proc { |full_name| full_name } } ]
sort_by: proc { |full_name| full_name } }
]
else
# supplier_rows orders
# table_items = supplier_rows orders
@@ -118,8 +119,7 @@ module OpenFoodNetwork
proc { |line_items| line_items.first.product.name },
proc { |line_items| line_items.first.full_name },
proc { |line_items| line_items.sum { |li| li.quantity } },
proc { |line_items| is_temperature_controlled?(line_items.first) }
]
proc { |line_items| is_temperature_controlled?(line_items.first) }]
else
[
proc { |line_items| line_items.first.order.distributor.name },

View File

@@ -69,9 +69,9 @@ module OpenFoodNetwork
granted_distributors = related_enterprises_granted(:add_to_order_cycle, by: managed_enterprises.is_primary_producer)
produced = Spree::Order.with_line_items_variants_and_products_outer.
where(
"spree_orders.distributor_id IN (?) AND spree_products.supplier_id IN (?)",
granted_distributors,
related_enterprises_granting(:add_to_order_cycle, to: granted_distributors).merge(managed_enterprises.is_primary_producer)
"spree_orders.distributor_id IN (?) AND spree_products.supplier_id IN (?)",
granted_distributors,
related_enterprises_granting(:add_to_order_cycle, to: granted_distributors).merge(managed_enterprises.is_primary_producer)
).pluck(:id)
Spree::Order.where(id: editable | produced)

View File

@@ -13,7 +13,7 @@ module OpenFoodNetwork
when "tax_rates"
[I18n.t(:report_header_order_number),
I18n.t(:report_header_total_excl_vat, currency_symbol: currency_symbol)] +
relevant_rates.map { |rate| "%.1f%% (%s)" % [rate.to_f * 100, currency_symbol] } +
relevant_rates.map { |rate| "%.1f%% (%s)" % [rate.amount.to_f * 100, currency_symbol] } +
[I18n.t(:report_header_total_tax, currency_symbol: currency_symbol),
I18n.t(:report_header_total_incl_vat, currency_symbol: currency_symbol)]
else
@@ -66,7 +66,7 @@ module OpenFoodNetwork
def relevant_rates
return @relevant_rates unless @relevant_rates.nil?
@relevant_rates = Spree::TaxRate.pluck(:amount).uniq
@relevant_rates = Spree::TaxRate.uniq
end
def totals_of(line_items)

View File

@@ -6,7 +6,6 @@ require 'open_food_network/option_value_namer'
module OpenFoodNetwork
module VariantAndLineItemNaming
# Copied and modified from Spree::Variant
def options_text
values = self.option_values.joins(:option_type).order("#{Spree::OptionType.table_name}.position asc")

View File

@@ -152,8 +152,7 @@ module OpenFoodNetwork
'',
Spree::Config.currency,
'',
order.paid? ? I18n.t(:y) : I18n.t(:n)
]
order.paid? ? I18n.t(:y) : I18n.t(:n)]
end
def adjustments(order)

View File

@@ -75,7 +75,6 @@ namespace :openfoodnetwork do
ba_country = Spree::Country.find_by_name row[43]
ba = Spree::Address.create!({firstname: row[35], lastname: row[36], address1: row[37], address2: row[38], city: row[39], zipcode: row[40], phone: row[41], state: ba_state, country: ba_country, created_at: row[44], updated_at: row[45], company: row[46]}, without_protection: true)
user.update_column :bill_address_id, ba.id
rescue ActiveRecord::RecordInvalid => e
puts "#{row[2]} - #{e.message}"
end

9
script/rubocop_autocorrect Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/sh
set -e
COP="$1"
bundle exec rubocop -a --only "$COP"
git add -A
git commit -m "Auto correct Rubocop's ${COP} cop"

View File

@@ -306,8 +306,7 @@ feature %q{
within('fieldset#shipping') do
[@distributor.name,
@distributor.distributor_info,
@distributor.next_collection_at
].each do |value|
@distributor.next_collection_at].each do |value|
page.should have_content value
end
@@ -375,8 +374,7 @@ feature %q{
within('fieldset#shipping') do
[@distributor_oc.name,
@distributor_oc.distributor_info,
@distributor_oc.next_collection_at
].each do |value|
@distributor_oc.next_collection_at].each do |value|
page.should have_content value
end

View File

@@ -13,10 +13,10 @@ module Admin
describe "#index" do
describe "when the user manages a coordinator" do
let!(:coordinator) { create(:distributor_enterprise, owner: distributor_owner) }
let!(:oc1) { create(:simple_order_cycle, orders_close_at: 60.days.ago ) }
let!(:oc2) { create(:simple_order_cycle, orders_close_at: 40.days.ago ) }
let!(:oc3) { create(:simple_order_cycle, orders_close_at: 20.days.ago ) }
let!(:oc4) { create(:simple_order_cycle, orders_close_at: nil ) }
let!(:oc1) { create(:simple_order_cycle, orders_open_at: 70.days.ago, orders_close_at: 60.days.ago ) }
let!(:oc2) { create(:simple_order_cycle, orders_open_at: 70.days.ago, orders_close_at: 40.days.ago ) }
let!(:oc3) { create(:simple_order_cycle, orders_open_at: 70.days.ago, orders_close_at: 20.days.ago ) }
let!(:oc4) { create(:simple_order_cycle, orders_open_at: 70.days.ago, orders_close_at: nil ) }
context "html" do
it "doesn't load any data" do
@@ -125,18 +125,34 @@ module Admin
allow(form_applicator_mock).to receive(:go!) { nil }
end
it "does not run the OrderCycleFormApplicator" do
expect(order_cycle.exchanges.incoming).to eq [incoming_exchange]
expect(order_cycle.exchanges.outgoing).to eq [outgoing_exchange]
expect(order_cycle.prefers_product_selection_from_coordinator_inventory_only?).to be false
spree_put :update, id: order_cycle.id, order_cycle: { name: 'Some new name', preferred_product_selection_from_coordinator_inventory_only: true }
expect(form_applicator_mock).to_not have_received(:go!)
order_cycle.reload
expect(order_cycle.exchanges.incoming).to eq [incoming_exchange]
expect(order_cycle.exchanges.outgoing).to eq [outgoing_exchange]
expect(order_cycle.name).to eq 'Some new name'
expect(order_cycle.prefers_product_selection_from_coordinator_inventory_only?).to be true
end
it "does not run the OrderCycleFormApplicator" do
expect(order_cycle.exchanges.incoming).to eq [incoming_exchange]
expect(order_cycle.exchanges.outgoing).to eq [outgoing_exchange]
expect(order_cycle.prefers_product_selection_from_coordinator_inventory_only?).to be false
spree_put :update, id: order_cycle.id, order_cycle: { name: 'Some new name', preferred_product_selection_from_coordinator_inventory_only: true }
expect(form_applicator_mock).to_not have_received(:go!)
order_cycle.reload
expect(order_cycle.exchanges.incoming).to eq [incoming_exchange]
expect(order_cycle.exchanges.outgoing).to eq [outgoing_exchange]
expect(order_cycle.name).to eq 'Some new name'
expect(order_cycle.prefers_product_selection_from_coordinator_inventory_only?).to be true
end
end
context "when a validation error occurs" do
let(:params) {
{
format: :json,
id: order_cycle.id,
order_cycle: { orders_open_at: order_cycle.orders_close_at + 1.day }
}
}
it "returns an error message" do
spree_put :update, params
json_response = JSON.parse(response.body)
expect(json_response['errors']).to be_present
end
end
end
@@ -206,15 +222,18 @@ module Admin
let!(:coordinator) { oc.coordinator }
context "when I manage the coordinator of an order cycle" do
before { create(:enterprise_role, user: distributor_owner, enterprise: coordinator) }
it "updates order cycle properties" do
spree_put :bulk_update, order_cycle_set: { collection_attributes: { '0' => {
let(:params) do
{ format: :json, order_cycle_set: { collection_attributes: { '0' => {
id: oc.id,
orders_open_at: Date.current - 21.days,
orders_close_at: Date.current + 21.days,
} } }
} } } }
end
before { create(:enterprise_role, user: distributor_owner, enterprise: coordinator) }
it "updates order cycle properties" do
spree_put :bulk_update, params
oc.reload
expect(oc.orders_open_at.to_date).to eq Date.current - 21.days
expect(oc.orders_close_at.to_date).to eq Date.current + 21.days
@@ -222,8 +241,22 @@ module Admin
it "does nothing when no data is supplied" do
expect do
spree_put :bulk_update
spree_put :bulk_update, format: :json
end.to change(oc, :orders_open_at).by(0)
json_response = JSON.parse(response.body)
expect(json_response['errors']).to eq I18n.t('admin.order_cycles.bulk_update.no_data')
end
context "when a validation error occurs" do
before do
params[:order_cycle_set][:collection_attributes]['0'][:orders_open_at] = Date.current + 25.days
end
it "returns an error message" do
spree_put :bulk_update, params
json_response = JSON.parse(response.body)
expect(json_response['errors']).to be_present
end
end
end
@@ -232,7 +265,7 @@ module Admin
let!(:another_distributor) { create(:distributor_enterprise, users: [distributor_owner]) }
it "doesn't update order cycle properties" do
spree_put :bulk_update, order_cycle_set: { collection_attributes: { '0' => {
spree_put :bulk_update, format: :json, order_cycle_set: { collection_attributes: { '0' => {
id: oc.id,
orders_open_at: Date.current - 21.days,
orders_close_at: Date.current + 21.days,

View File

@@ -200,8 +200,20 @@ describe Admin::SchedulesController, type: :controller do
context "where I manage at least one of the schedule's coordinators" do
before { params.merge!(id: coordinated_schedule.id) }
it "allows me to destroy the schedule" do
expect { spree_delete :destroy, params }.to change(Schedule, :count).by(-1)
context "when no dependent subscriptions are present" do
it "allows me to destroy the schedule" do
expect { spree_delete :destroy, params }.to change(Schedule, :count).by(-1)
end
end
context "when a dependent subscription is present" do
let!(:subscription) { create(:subscription, schedule: coordinated_schedule) }
it "returns an error message and prevents me from deleting the schedule" do
expect { spree_delete :destroy, params }.to_not change(Schedule, :count)
json_response = JSON.parse(response.body)
expect(json_response["errors"]).to include I18n.t('admin.schedules.destroy.associated_subscriptions_error')
end
end
end

View File

@@ -87,7 +87,7 @@ FactoryGirl.define do
coordinator { Enterprise.is_distributor.first || FactoryGirl.create(:distributor_enterprise) }
ignore do
transient do
suppliers []
distributors []
variants []
@@ -148,7 +148,7 @@ FactoryGirl.define do
shipping_method { create(:shipping_method, distributors: [shop]) }
begins_at { 1.month.ago }
ignore do
transient do
with_items false
with_proxy_orders false
end
@@ -218,7 +218,7 @@ FactoryGirl.define do
is_primary_producer false
sells "any"
ignore do
transient do
with_payment_and_shipping false
end
@@ -250,7 +250,7 @@ FactoryGirl.define do
end
factory :enterprise_fee, :class => EnterpriseFee do
ignore { amount nil }
transient { amount nil }
sequence(:name) { |n| "Enterprise fee #{n}" }
sequence(:fee_type) { |n| EnterpriseFee::FEE_TYPES[n % EnterpriseFee::FEE_TYPES.count] }
@@ -295,6 +295,26 @@ FactoryGirl.define do
distributor { create(:distributor_enterprise) }
end
factory :order_with_taxes, parent: :completed_order_with_totals do
ignore do
product_price 0
tax_rate_amount 0
tax_rate_name ""
end
distributor { create(:distributor_enterprise) }
order_cycle { create(:simple_order_cycle) }
after(:create) do |order, proxy|
order.distributor.update_attribute(:charges_sales_tax, true)
Spree::Zone.global.update_attribute(:default_tax, true)
p = FactoryGirl.create(:taxed_product, zone: Spree::Zone.global, price: proxy.product_price, tax_rate_amount: proxy.tax_rate_amount, tax_rate_name: proxy.tax_rate_name, distributors: [order.distributor])
FactoryGirl.create(:line_item, order: order, product: p, price: p.price)
order.reload
end
end
factory :order_with_credit_payment, parent: :completed_order_with_totals do
distributor { create(:distributor_enterprise)}
order_cycle { create(:simple_order_cycle) }
@@ -316,7 +336,7 @@ FactoryGirl.define do
end
factory :completed_order_with_fees, parent: :order_with_totals_and_distribution do
ignore do
transient do
shipping_fee 3
payment_fee 5
end
@@ -345,8 +365,9 @@ FactoryGirl.define do
end
factory :taxed_product, :parent => :product do
ignore do
transient do
tax_rate_amount 0
tax_rate_name ""
zone nil
end
@@ -354,7 +375,7 @@ FactoryGirl.define do
after(:create) do |product, proxy|
raise "taxed_product factory requires a zone" unless proxy.zone
create(:tax_rate, amount: proxy.tax_rate_amount, tax_category: product.tax_category, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, zone: proxy.zone)
create(:tax_rate, amount: proxy.tax_rate_amount, tax_category: product.tax_category, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, zone: proxy.zone, name: proxy.tax_rate_name)
end
end
@@ -473,7 +494,7 @@ FactoryGirl.modify do
end
factory :payment do
ignore do
transient do
distributor { order.distributor || Enterprise.is_distributor.first || FactoryGirl.create(:distributor_enterprise) }
end
payment_method { FactoryGirl.create(:payment_method, distributors: [distributor]) }

View File

@@ -516,7 +516,11 @@ feature %q{
# Given three order cycles
oc1 = create(:simple_order_cycle)
oc2 = create(:simple_order_cycle)
oc3 = create(:simple_order_cycle, orders_open_at: Time.zone.local(2040, 12, 12, 12, 12, 12))
oc3 = create(:simple_order_cycle,
orders_open_at: Time.zone.local(2040, 12, 12, 12, 12, 12),
orders_close_at: Time.zone.local(2041, 12, 12, 12, 12, 12)
)
# When I go to the order cycles page
login_to_admin_section

View File

@@ -1,4 +1,5 @@
require "spec_helper"
include ActionView::Helpers::NumberHelper
feature %q{
As an administrator
@@ -214,11 +215,56 @@ feature %q{
Spree::Config[:enable_receipt_printing?] = true
distributor1.update_attribute(:abn, '12345678')
@order = create(:completed_order_with_totals, distributor: distributor1)
@order = create(:order_with_taxes,
distributor: distributor1,
product_price: 110,
tax_rate_amount: 0.1,
tax_rate_name: "Tax 1")
Spree::TaxRate.adjust(@order)
visit spree.admin_order_path(@order)
end
scenario "shows a list of line_items" do
within('table.index tbody', match: :first) do
@order.line_items.each do |item|
expect(page).to have_selector "td", match: :first, text: item.full_name
expect(page).to have_selector "td.price", text: item.single_display_amount
expect(page).to have_selector "td.qty", text: item.quantity
expect(page).to have_selector "td.total", text: item.display_amount
end
end
end
scenario "shows the order subtotal" do
within('table.index tbody#subtotal') do
expect(page).to have_selector "td.total", text: @order.display_item_total
end
end
scenario "shows the order charges (non-tax adjustments)" do
within('table.index tbody#order-charges') do
@order.adjustments.eligible.each do |adjustment|
next if (adjustment.originator_type == 'Spree::TaxRate') && (adjustment.amount == 0)
expect(page).to have_selector "td", match: :first, text: adjustment.label
expect(page).to have_selector "td.total", text: adjustment.display_amount
end
end
end
scenario "shows the order total" do
within('table.index tbody#order-total') do
expect(page).to have_selector "td.total", text: @order.display_total
end
end
scenario "shows the order taxes" do
within('table.index tbody#price-adjustments') do
expect(page).to have_selector "td", match: :first, text: "Tax 1"
expect(page).to have_selector "td.total", text: Spree::Money.new(10)
end
end
scenario "shows the dropdown menu" do
find("#links-dropdown .ofn-drop-down").click
within "#links-dropdown" do

View File

@@ -132,7 +132,6 @@ feature %q{
expect(Spree::Dash::Config.configured?).to be true
block.call
ensure
Spree::Dash::Config.preferred_app_id = nil
Spree::Dash::Config.preferred_site_id = nil

View File

@@ -415,12 +415,12 @@ feature "As a consumer I want to shop with a distributor", js: true do
page.should have_content "Orders are closed"
end
it "shows the last order cycle" do
oc1 = create(:simple_order_cycle, distributors: [distributor], orders_close_at: 10.days.ago)
oc1 = create(:simple_order_cycle, distributors: [distributor], orders_open_at: 17.days.ago, orders_close_at: 10.days.ago)
visit shop_path
page.should have_content "The last cycle closed 10 days ago"
end
it "shows the next order cycle" do
oc1 = create(:simple_order_cycle, distributors: [distributor], orders_open_at: 10.days.from_now)
oc1 = create(:simple_order_cycle, distributors: [distributor], orders_open_at: 10.days.from_now, orders_close_at: 17.days.from_now)
visit shop_path
page.should have_content "The next cycle opens in 10 days"
end
@@ -430,6 +430,7 @@ feature "As a consumer I want to shop with a distributor", js: true do
let(:exchange) { Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id) }
let(:product) { create(:simple_product) }
let(:variant) { create(:variant, product: product) }
let(:unregistered_customer) { create(:customer, user: nil, enterprise: distributor) }
before do
add_variant_to_order_cycle(exchange, variant)
@@ -469,8 +470,7 @@ feature "As a consumer I want to shop with a distributor", js: true do
it "shows just products" do
visit shop_path
expect(page).to have_no_content "This shop is for customers only."
expect(page).to have_content product.name
shows_products_without_customer_warning
end
end
@@ -479,8 +479,7 @@ feature "As a consumer I want to shop with a distributor", js: true do
it "shows just products" do
visit shop_path
expect(page).to have_no_content "This shop is for customers only."
expect(page).to have_content product.name
shows_products_without_customer_warning
end
end
@@ -492,11 +491,28 @@ feature "As a consumer I want to shop with a distributor", js: true do
it "shows just products" do
visit shop_path
expect(page).to have_no_content "This shop is for customers only."
expect(page).to have_content product.name
shows_products_without_customer_warning
end
end
end
context "when previously unregistered customer registers" do
let!(:returning_user) { create(:user, email: unregistered_customer.email) }
before do
quick_login_as returning_user
end
it "shows the products without customer only message" do
visit shop_path
shows_products_without_customer_warning
end
end
end
end
def shows_products_without_customer_warning
expect(page).to have_no_content "This shop is for customers only."
expect(page).to have_content product.name
end
end

View File

@@ -14,6 +14,7 @@ module Spree
end
private
def make_variant_stub(product_price, variant_price)
product = double(:product, price: product_price)
variant = double(:variant, product: product, price: variant_price)

View File

@@ -49,6 +49,14 @@ describe 'Variants service', ->
variant = {product_name: 'product_name', name_to_display: 'product_name'}
expect(Variants.extendedVariantName(variant)).toEqual "product_name"
it "includes the options text even if variant name is same as product", ->
variant =
product_name: 'product_name'
name_to_display: 'product_name'
options_text: 'options_text'
expect(Variants.extendedVariantName(variant)).toEqual "product_name (options_text)"
describe "when the product name and the variant name differ", ->
it "returns a combined name when there is no options text", ->
variant =

View File

@@ -812,7 +812,7 @@ describe 'OrderCycle services', ->
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: false}
}).respond 400, { errors: [] }
OrderCycle.create('/destination/page')
$httpBackend.flush()
@@ -840,7 +840,7 @@ describe 'OrderCycle services', ->
spyOn(OrderCycle, 'dataForSubmit').and.returnValue('this is the submit data')
$httpBackend.expectPUT('/admin/order_cycles.json?reloading=1', {
order_cycle: 'this is the submit data'
}).respond {success: false}
}).respond 400, { errors: [] }
OrderCycle.update('/destination/page')
$httpBackend.flush()

View File

@@ -22,7 +22,7 @@ describe EnterpriseFee do
oc = create(:simple_order_cycle, coordinator_fees: [ef])
ef.destroy
oc.reload.coordinator_fee_ids.should be_empty
expect(oc.reload.coordinator_fee_ids).to be_empty
end
it "removes itself from order cycle exchange fees when destroyed" do
@@ -30,7 +30,7 @@ describe EnterpriseFee do
ex = create(:exchange, order_cycle: oc, enterprise_fees: [ef])
ef.destroy
ex.reload.exchange_fee_ids.should be_empty
expect(ex.reload.exchange_fee_ids).to be_empty
end
describe "for tax_category" do
@@ -66,38 +66,38 @@ describe EnterpriseFee do
describe "scopes" do
describe "finding per-item enterprise fees" do
it "does not return fees with FlatRate and FlexiRate calculators" do
it "does not return fees with FlatRate, FlexiRate and PriceSack calculators" do
create(:enterprise_fee, calculator: Spree::Calculator::FlatRate.new)
create(:enterprise_fee, calculator: Spree::Calculator::FlexiRate.new)
create(:enterprise_fee, calculator: Spree::Calculator::PriceSack.new)
EnterpriseFee.per_item.should be_empty
expect(EnterpriseFee.per_item).to be_empty
end
it "returns fees with any other calculator" do
ef1 = create(:enterprise_fee, calculator: Spree::Calculator::DefaultTax.new)
ef2 = create(:enterprise_fee, calculator: Calculator::FlatPercentPerItem.new)
ef3 = create(:enterprise_fee, calculator: Spree::Calculator::PerItem.new)
ef4 = create(:enterprise_fee, calculator: Spree::Calculator::PriceSack.new)
EnterpriseFee.per_item.should match_array [ef1, ef2, ef3, ef4]
expect(EnterpriseFee.per_item).to match_array [ef1, ef2, ef3]
end
end
describe "finding per-order enterprise fees" do
it "returns fees with FlatRate and FlexiRate calculators" do
it "returns fees with FlatRate, FlexiRate and PriceSack calculators" do
ef1 = create(:enterprise_fee, calculator: Spree::Calculator::FlatRate.new)
ef2 = create(:enterprise_fee, calculator: Spree::Calculator::FlexiRate.new)
ef3 = create(:enterprise_fee, calculator: Spree::Calculator::PriceSack.new)
EnterpriseFee.per_order.should match_array [ef1, ef2]
expect(EnterpriseFee.per_order).to match_array [ef1, ef2, ef3]
end
it "does not return fees with any other calculator" do
ef1 = create(:enterprise_fee, calculator: Spree::Calculator::DefaultTax.new)
ef2 = create(:enterprise_fee, calculator: Calculator::FlatPercentPerItem.new)
ef3 = create(:enterprise_fee, calculator: Spree::Calculator::PerItem.new)
ef4 = create(:enterprise_fee, calculator: Spree::Calculator::PriceSack.new)
EnterpriseFee.per_order.should be_empty
expect(EnterpriseFee.per_order).to be_empty
end
end
end

View File

@@ -318,7 +318,7 @@ describe Enterprise do
s = create(:supplier_enterprise)
d = create(:distributor_enterprise)
p = create(:product)
create(:simple_order_cycle, :orders_open_at => 10.days.from_now, suppliers: [s], distributors: [d], variants: [p.master])
create(:simple_order_cycle, :orders_open_at => 10.days.from_now, orders_close_at: 17.days.from_now, suppliers: [s], distributors: [d], variants: [p.master])
Enterprise.distributors_with_active_order_cycles.should_not include d
end
end

View File

@@ -11,6 +11,11 @@ describe OrderCycle do
oc.should_not be_valid
end
it 'should not be valid when open date is after close date' do
oc = build(:simple_order_cycle, orders_open_at: Time.zone.now, orders_close_at: 1.minute.ago)
expect(oc).to_not be_valid
end
it "has a coordinator and associated fees" do
oc = create(:simple_order_cycle)
@@ -196,13 +201,13 @@ describe OrderCycle do
let(:d1) { create(:enterprise) }
let(:d2) { create(:enterprise) }
let!(:e0) { create(:exchange, incoming: true,
order_cycle: oc, sender: create(:enterprise), receiver: oc.coordinator)
order_cycle: oc, sender: create(:enterprise), receiver: oc.coordinator)
}
let!(:e1) { create(:exchange, incoming: false,
order_cycle: oc, sender: oc.coordinator, receiver: d1)
order_cycle: oc, sender: oc.coordinator, receiver: d1)
}
let!(:e2) { create(:exchange, incoming: false,
order_cycle: oc, sender: oc.coordinator, receiver: d2)
order_cycle: oc, sender: oc.coordinator, receiver: d2)
}
let!(:p0) { create(:simple_product) }
let!(:p1) { create(:simple_product) }

View File

@@ -49,7 +49,7 @@ describe ProducerProperty do
describe "with a producer property for a product in a closed order cycle" do
before do
oc.update_attributes! orders_close_at: 1.week.ago
oc.update_attributes! orders_open_at: 2.weeks.ago, orders_close_at: 1.week.ago
end
it "doesn't return the producer property for .currently_sold_by" do

View File

@@ -3,7 +3,6 @@ require "cancan/matchers"
require 'support/cancan_helper'
module Spree
describe User do
describe "broad permissions" do

View File

@@ -1,14 +1,29 @@
require 'spec_helper'
describe Spree::Calculator::FlexiRate do
let(:calculator) { Spree::Calculator::FlexiRate.new }
let(:line_item) { instance_double(Spree::LineItem, amount: 10, quantity: 4) }
let(:line_item) { instance_double(Spree::LineItem, amount: 10, quantity: quantity) }
let(:calculator) do
Spree::Calculator::FlexiRate.new(
preferred_first_item: 2,
preferred_additional_item: 1,
preferred_max_items: 3
)
end
describe "computing for a single line item" do
it "returns the first item rate" do
calculator.stub preferred_first_item: 1.0
calculator.compute(line_item).round(2).should == 1.0
end
context 'when nb of items ordered is above preferred max' do
let(:quantity) { 4.0 }
it "returns the first item rate" do
expect(calculator.compute(line_item).round(2)).to eq(4.0)
end
end
context 'when nb of items ordered is below preferred max' do
let(:quantity) { 2.0 }
it "returns the first item rate" do
expect(calculator.compute(line_item).round(2)).to eq(3.0)
end
end
it "allows creation of new object with all the attributes" do

View File

@@ -9,10 +9,20 @@ describe Spree::Calculator::PriceSack do
calculator
end
let(:line_item) { build(:line_item, price: 1, quantity: 2) }
let(:line_item) { build(:line_item, price: price, quantity: 2) }
it "computes with a line item object" do
calculator.compute(line_item)
context 'when the order amount is below preferred minimal' do
let(:price) { 2 }
it "uses the preferred normal amount" do
expect(calculator.compute(line_item)).to eq(10)
end
end
context 'when the order amount is above preferred minimal' do
let(:price) { 6 }
it "uses the preferred discount amount" do
expect(calculator.compute(line_item)).to eq(1)
end
end
context "extends LocalizedNumber" do

View File

@@ -283,16 +283,19 @@ describe Spree::Order do
let(:tax_rate10) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.1, zone: zone) }
let(:tax_rate15) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.15, zone: zone) }
let(:tax_rate20) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.2, zone: zone) }
let(:tax_rate25) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.25, zone: zone) }
let(:tax_category10) { create(:tax_category, tax_rates: [tax_rate10]) }
let(:tax_category15) { create(:tax_category, tax_rates: [tax_rate15]) }
let(:tax_category20) { create(:tax_category, tax_rates: [tax_rate20]) }
let(:tax_category25) { create(:tax_category, tax_rates: [tax_rate25]) }
let(:variant) { create(:variant, product: create(:product, tax_category: tax_category10)) }
let(:shipping_method) { create(:shipping_method, calculator: Spree::Calculator::FlatRate.new(preferred_amount: 46.0)) }
let(:enterprise_fee) { create(:enterprise_fee, enterprise: coordinator, tax_category: tax_category20, calculator: Spree::Calculator::FlatRate.new(preferred_amount: 48.0)) }
let(:additional_adjustment) { create(:adjustment, amount: 50.0, included_tax: tax_rate25.compute_tax(50.0)) }
let(:order_cycle) { create(:simple_order_cycle, coordinator: coordinator, coordinator_fees: [enterprise_fee], distributors: [coordinator], variants: [variant]) }
let!(:order) { create(:order, shipping_method: shipping_method, bill_address: create(:address), order_cycle: order_cycle, distributor: coordinator) }
let!(:order) { create(:order, shipping_method: shipping_method, bill_address: create(:address), order_cycle: order_cycle, distributor: coordinator, adjustments: [additional_adjustment]) }
let!(:line_item) { create(:line_item, order: order, variant: variant, price: 44.0) }
before do
@@ -304,19 +307,23 @@ describe Spree::Order do
end
it "returns a hash with all 3 taxes" do
expect(order.tax_adjustment_totals.size).to eq(3)
expect(order.tax_adjustment_totals.size).to eq(4)
end
it "contains tax on line_item" do
expect(order.tax_adjustment_totals[tax_rate10.amount]).to eq(4.0)
expect(order.tax_adjustment_totals[tax_rate10]).to eq(4.0)
end
it "contains tax on shipping_fee" do
expect(order.tax_adjustment_totals[tax_rate15.amount]).to eq(6.0)
expect(order.tax_adjustment_totals[tax_rate15]).to eq(6.0)
end
it "contains tax on enterprise_fee" do
expect(order.tax_adjustment_totals[tax_rate20.amount]).to eq(8.0)
expect(order.tax_adjustment_totals[tax_rate20]).to eq(8.0)
end
it "contains tax on order adjustment" do
expect(order.tax_adjustment_totals[tax_rate25]).to eq(10.0)
end
end

View File

@@ -339,7 +339,7 @@ module Spree
p1 = create(:product)
p2 = create(:product)
p3 = create(:product)
oc2 = create(:simple_order_cycle, suppliers: [s], distributors: [d2], variants: [p2.master], orders_close_at: 1.day.ago)
oc2 = create(:simple_order_cycle, suppliers: [s], distributors: [d2], variants: [p2.master], orders_open_at: 8.days.ago, orders_close_at: 1.day.ago)
oc2 = create(:simple_order_cycle, suppliers: [s], distributors: [d3], variants: [p3.master], orders_close_at: Date.tomorrow)
Product.in_an_active_order_cycle.should == [p3]
end
@@ -532,7 +532,7 @@ module Spree
let!(:p) { create(:simple_product,
variant_unit: 'weight',
variant_unit_scale: 1,
variant_unit_name: nil)
variant_unit_name: nil)
}
let!(:ot_volume) { create(:option_type, name: 'unit_volume', presentation: 'Volume') }

View File

@@ -77,6 +77,21 @@ describe Spree.user_class do
end.to enqueue_job Delayed::PerformableMethod
expect(Delayed::Job.last.payload_object.method_name).to eq(:send_on_create_confirmation_instructions_without_delay)
end
context "with the the same email as existing customers" do
let(:email) { Faker::Internet.email }
let(:enterprise1) { create(:enterprise) }
let(:enterprise2) { create(:enterprise) }
let!(:customer1) { create(:customer, user: nil, email: email, enterprise: enterprise1) }
let!(:customer2) { create(:customer, user: nil, email: email, enterprise: enterprise2) }
let!(:user) { create(:user, email: email) }
it "should associate these customers with the created user" do
expect(user.customers.reload).to include customer1, customer2
expect(user.customer_of(enterprise1)).to be_truthy
expect(user.customer_of(enterprise2)).to be_truthy
end
end
end
context "confirming email" do

View File

@@ -21,23 +21,6 @@ module Spree
Spree::Variant.not_deleted.should_not include v_deleted
end
describe "finding variants in stock" do
before do
p = create(:product, on_hand: 0)
@v_in_stock = create(:variant, product: p)
@v_on_demand = create(:variant, product: p, on_demand: true)
@v_no_stock = create(:variant, product: p)
@v_in_stock.update_attribute(:count_on_hand, 1)
@v_on_demand.update_attribute(:count_on_hand, 0)
@v_no_stock.update_attribute(:count_on_hand, 0)
end
it "returns variants in stock or on demand, but not those that are neither" do
Variant.where(is_master: false).in_stock.should match_array [@v_in_stock, @v_on_demand]
end
end
describe "finding variants in a distributor" do
let!(:d1) { create(:distributor_enterprise) }
let!(:d2) { create(:distributor_enterprise) }

View File

@@ -7,7 +7,7 @@ describe Api::VariantSerializer do
it "includes the expected attributes" do
expect(subject.attributes.keys).
to include(
:id,
:id,
:name_to_display,
:is_master,
:count_on_hand,
@@ -21,6 +21,6 @@ describe Api::VariantSerializer do
:price_with_fees,
:product_name,
:tag_list # Used to apply tag rules
)
)
end
end

View File

@@ -1,6 +1,5 @@
module OpenFoodNetwork
module DistributionHelper
def select_distribution(distributor, order_cycle=nil)
create_enterprise_group_for distributor
visit root_path

View File

@@ -1,5 +1,4 @@
module UIComponentHelper
def browse_as_medium
page.driver.resize(1024, 768)
end

View File

@@ -199,6 +199,7 @@ module WebHelper
end
private
def wait_for_ajax
wait_until { page.evaluate_script("$.active") == 0 }
end