Compare commits

..

60 Commits

Author SHA1 Message Date
Kristina Lim
dd2f2b37d0 Specify API date format when converting date to string in JS 2019-08-30 09:13:48 +10:00
Maikel Linke
e876a25d59 Fix flaky proxy order spec 2019-08-28 10:48:57 +10:00
Maikel Linke
2a780151be Update all locales with the latest Transifex translations 2019-08-28 09:54:31 +10:00
Maikel
9d2009d2af Merge pull request #4188 from openfoodfoundation/transifex
Transifex
2019-08-28 09:43:02 +10:00
Maikel
f887533dda Merge pull request #4157 from mkllnk/4138-update-products
4138 Avoid infinite loop when updating products
2019-08-28 09:42:28 +10:00
Transifex-Openfoodnetwork
bef3f154d6 Updating translations for config/locales/fr_CA.yml 2019-08-28 09:12:59 +10:00
Transifex-Openfoodnetwork
6fb775d5ed Updating translations for config/locales/en_CA.yml 2019-08-28 09:05:39 +10:00
Transifex-Openfoodnetwork
b5a8563725 Updating translations for config/locales/en_GB.yml 2019-08-27 23:28:34 +10:00
Transifex-Openfoodnetwork
1a9ade6de9 Updating translations for config/locales/en_GB.yml 2019-08-27 23:25:26 +10:00
Maikel Linke
48df853ff5 Skip cascading callbacks when touching distributors 2019-08-27 10:44:19 +10:00
Maikel Linke
2137a2addb Add spec for current bug
https://github.com/openfoodfoundation/openfoodnetwork/issues/4138
2019-08-27 10:44:19 +10:00
Transifex-Openfoodnetwork
e6a7239716 Updating translations for config/locales/en_AU.yml 2019-08-27 10:09:05 +10:00
Transifex-Openfoodnetwork
25bed92f2e Updating translations for config/locales/en_AU.yml 2019-08-27 10:08:32 +10:00
Maikel
909cd407dd Merge pull request #4149 from openfoodfoundation/transifex
Transifex
2019-08-27 09:58:31 +10:00
Luis Ramos
f2d25748b1 Merge pull request #4078 from HugsDaniel/defacepocalypse-variants
[Defacepocalypse] De-deface variants
2019-08-25 22:51:15 +01:00
Luis Ramos
6396e6e970 Merge pull request #4152 from openfoodfoundation/dependabot/bundler/stripe-4.24.0
Bump stripe from 4.19.0 to 4.24.0
2019-08-25 22:49:47 +01:00
Luis Ramos
e52f813dae Merge pull request #4159 from luisramos0/fix_prod_set
Add bugsnag notifications to both product_set and products_controller when stock update fails
2019-08-25 22:49:06 +01:00
Luis Ramos
9ab2eec30c Merge pull request #4185 from kristinalim/fix/4176-fix_saving_of_shipping_method
4176 Fix saving of shipping method when automatically advancing subscription order state
2019-08-25 22:48:39 +01:00
Luis Ramos
f96b37dae3 Merge pull request #4162 from luisramos0/checkout_cache
Checkout is not refreshing products cache
2019-08-25 21:52:55 +01:00
Kristina Lim
5b68b2f707 Fix ship method when advancing subscription order 2019-08-22 21:32:41 +08:00
Kristina Lim
ff634bd870 Test ship method when advancing subscription order 2019-08-22 21:30:21 +08:00
Transifex-Openfoodnetwork
5e68604f11 Updating translations for config/locales/nb.yml 2019-08-20 17:42:09 +10:00
Transifex-Openfoodnetwork
c4edd3a683 Updating translations for config/locales/fr.yml 2019-08-20 17:41:25 +10:00
Transifex-Openfoodnetwork
574781e901 Updating translations for config/locales/nb.yml 2019-08-20 17:39:01 +10:00
Transifex-Openfoodnetwork
8ea4f933da Updating translations for config/locales/fr.yml 2019-08-20 17:38:12 +10:00
Transifex-Openfoodnetwork
1e9820f291 Updating translations for config/locales/fr.yml 2019-08-20 17:35:05 +10:00
Luis Ramos
34ed86cf2d Merge pull request #4132 from Matt-Yorkley/import_launch
Product Import beta
2019-08-19 17:17:16 +01:00
Kristina Lim
706168f2f0 Refresh variant cache when changing stock movements 2019-08-18 16:22:12 +08:00
Kristina Lim
3ecb5c0c75 Flush background jobs in failing spec 2019-08-18 18:16:28 +10:00
luisramos0
249a3c4e18 Make product set raise error and inform the user something went wrong and keep bugsnag notification so we can get more information about what's going on 2019-08-17 19:19:46 +01:00
luisramos0
2b8ebba233 Fix some rubocop issues in product_set and admin/products_controller 2019-08-17 19:15:32 +01:00
luisramos0
758394464b Add bugsnag notification to products_controller create and update when on_hand or on_demand update fails with exception 2019-08-17 19:15:32 +01:00
luisramos0
d3c624ae10 Add bugsnag notification to product_set create_variant when on_hand or on_demand update fails with exception 2019-08-17 19:15:31 +01:00
luisramos0
163c65849e Make product set a bit more robust by not failing to update on_hand when variant is not valid. This will make the overall set update work 2019-08-17 19:14:25 +01:00
luisramos0
99ff714913 Enable cache on checkout spec to test cache after checkout 2019-08-16 20:17:14 +01:00
luisramos0
c2f302450f Add spec to checkout to validate product is removed from shopfront just after all available quantity is checked out 2019-08-16 19:35:57 +01:00
luisramos0
9186bcd455 Dry out some code in checkout_spec 2019-08-16 19:35:08 +01:00
Transifex-Openfoodnetwork
3d074b530f Updating translations for config/locales/nb.yml 2019-08-15 19:16:43 +10:00
Transifex-Openfoodnetwork
20783db373 Updating translations for config/locales/en_GB.yml 2019-08-15 19:14:53 +10:00
Pau Pérez Fabregat
53496ff9eb Merge branch 'master' into transifex 2019-08-14 09:08:40 +02:00
Transifex-Openfoodnetwork
c1248857b8 Updating translations for config/locales/en_CA.yml 2019-08-14 09:15:20 +10:00
dependabot-preview[bot]
e2d61f5e89 Bump stripe from 4.19.0 to 4.24.0
Bumps [stripe](https://github.com/stripe/stripe-ruby) from 4.19.0 to 4.24.0.
- [Release notes](https://github.com/stripe/stripe-ruby/releases)
- [Changelog](https://github.com/stripe/stripe-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stripe/stripe-ruby/compare/v4.19.0...v4.24.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-13 19:18:17 +00:00
Transifex-Openfoodnetwork
5a1ef04c67 Updating translations for config/locales/en_ZA.yml 2019-08-14 04:57:27 +10:00
Transifex-Openfoodnetwork
e9e73ef0e4 Updating translations for config/locales/en_ZA.yml 2019-08-14 04:43:50 +10:00
Transifex-Openfoodnetwork
001e3688da Updating translations for config/locales/en_GB.yml 2019-08-14 03:28:13 +10:00
Transifex-Openfoodnetwork
e5a9606449 Updating translations for config/locales/en_GB.yml 2019-08-14 03:25:02 +10:00
Hugo Daniel
1217811402 Refactor and remove empty lines 2019-08-13 11:03:04 +02:00
Hugo Daniel
bf2c1a0c1d Add ng directive for setting on demand 2019-08-09 14:42:39 +02:00
Matt-Yorkley
5d83414e9b Disable rubocop for spree tabs helper 2019-08-08 20:09:35 +01:00
Matt-Yorkley
2f5b0a5afb Remove product import FeatureFlag 2019-08-07 09:59:55 +01:00
Matt-Yorkley
b3728568a8 Enable product import for non-superadmin users
This class_eval hack for premissions on the #tab method was really hard to find, and is obviously quite ugly, but refactoring it is maybe outside of the scope here...
2019-08-06 18:59:12 +01:00
Matt-Yorkley
6ba98b4b2c Add beta notice to Product Import 2019-08-06 17:02:38 +01:00
Hugo Daniel
60bdde6349 Convert variants/new from erb to haml and import new.js.erb 2019-08-01 11:23:44 +02:00
Hugo Daniel
5faf33fabe Import variants/new.html.erb from spree_backend 2019-08-01 10:50:13 +02:00
Hugo Daniel
f3b1a5dd35 Convert variants/edit from erb to haml 2019-08-01 10:45:04 +02:00
Hugo Daniel
07ccbf7f98 Import variants/edit.html.erb from spree_backend 2019-07-31 16:55:47 +02:00
Hugo Daniel
ec6f6056a8 Remove data-hooks 2019-07-25 14:34:06 +02:00
Hugo Daniel
a11562e4dd Fix incorrect indentation in variants table 2019-07-25 12:05:50 +02:00
Hugo Daniel
986837d601 Import variants/_form.html.erb from spree_backend to ofn and de-deface it 2019-07-25 11:07:35 +02:00
Hugo Daniel
353d6fbc5f Import variants/index from spree_backend to ofn and convert to Haml 2019-07-24 16:57:11 +02:00
41 changed files with 605 additions and 294 deletions

View File

@@ -49,7 +49,6 @@ Metrics/LineLength:
- app/controllers/spree/admin/orders_controller_decorator.rb
- app/controllers/spree/admin/payments_controller_decorator.rb
- app/controllers/spree/admin/payment_methods_controller_decorator.rb
- app/controllers/spree/admin/products_controller_decorator.rb
- app/controllers/spree/admin/reports_controller_decorator.rb
- app/controllers/spree/api/products_controller_decorator.rb
- app/controllers/spree/credit_cards_controller.rb
@@ -437,7 +436,6 @@ Metrics/AbcSize:
- app/models/spree/order_decorator.rb
- app/models/spree/payment_decorator.rb
- app/models/spree/product_decorator.rb
- app/models/spree/product_set.rb
- app/models/spree/taxon_decorator.rb
- app/serializers/api/admin/enterprise_serializer.rb
- app/serializers/api/product_serializer.rb
@@ -559,6 +557,7 @@ Metrics/CyclomaticComplexity:
- app/helpers/checkout_helper.rb
- app/helpers/i18n_helper.rb
- app/helpers/order_cycles_helper.rb
- app/helpers/spree/admin/navigation_helper_decorator.rb
- app/models/enterprise.rb
- app/models/enterprise_relationship.rb
- app/models/product_import/entry_processor.rb
@@ -566,7 +565,6 @@ Metrics/CyclomaticComplexity:
- app/models/spree/ability_decorator.rb
- app/models/spree/payment_decorator.rb
- app/models/spree/product_decorator.rb
- app/models/spree/product_set.rb
- app/models/variant_override_set.rb
- app/services/cart_service.rb
- lib/discourse/single_sign_on.rb
@@ -594,7 +592,6 @@ Metrics/PerceivedComplexity:
- app/models/spree/ability_decorator.rb
- app/models/spree/order_decorator.rb
- app/models/spree/product_decorator.rb
- app/models/spree/product_set.rb
- lib/discourse/single_sign_on.rb
- lib/open_food_network/bulk_coop_report.rb
- lib/open_food_network/enterprise_issue_validator.rb
@@ -650,7 +647,6 @@ Metrics/MethodLength:
- app/models/spree/payment_decorator.rb
- app/models/spree/payment_method_decorator.rb
- app/models/spree/product_decorator.rb
- app/models/spree/product_set.rb
- app/serializers/api/admin/order_cycle_serializer.rb
- app/serializers/api/cached_enterprise_serializer.rb
- app/services/order_cycle_form.rb

View File

@@ -512,7 +512,7 @@ GEM
multi_xml (0.6.0)
multipart-post (2.1.1)
nenv (0.3.0)
net-http-persistent (3.0.1)
net-http-persistent (3.1.0)
connection_pool (~> 2.2)
newrelic_rpm (3.18.1.330)
nokogiri (1.6.8.1)
@@ -701,7 +701,7 @@ GEM
tilt (~> 1.1, != 1.3.0)
state_machine (1.2.0)
stringex (1.5.1)
stripe (4.19.0)
stripe (4.24.0)
faraday (~> 0.13)
net-http-persistent (~> 3.0)
therubyracer (0.12.0)

View File

@@ -0,0 +1,19 @@
angular.module("admin.products").directive "setOnDemand", ->
link: (scope, element, attr) ->
onHand = element.context.querySelector("#variant_on_hand")
onDemand = element.context.querySelector("#variant_on_demand")
disableOnHandIfOnDemand = ->
if onDemand.checked
onHand.disabled = 'disabled'
onHand.dataStock = onHand.value
onHand.value = t('admin.products.variants.infinity')
disableOnHandIfOnDemand()
onDemand.addEventListener 'change', (event) ->
disableOnHandIfOnDemand()
if !onDemand.checked
onHand.removeAttribute('disabled')
onHand.value = onHand.dataStock

View File

@@ -1,10 +1,15 @@
@API_DATETIME_FORMAT = "YYYY-MM-DD HH:mm:SS Z"
Darkswarm.filter "date_in_words", ->
(date) ->
moment(date).fromNow()
(date, dateFormat) ->
dateFormat ?= @API_DATETIME_FORMAT
moment(date, dateFormat).fromNow()
Darkswarm.filter "sensible_timeframe", (date_in_wordsFilter)->
(date) ->
if moment().add(2, 'days') < moment(date)
(date, dateFormat) ->
dateFormat ?= @API_DATETIME_FORMAT
if moment().add(2, 'days') < moment(date, dateFormat)
t 'orders_open'
else
t('closing') + date_in_wordsFilter(date)

View File

@@ -48,19 +48,13 @@ Spree::Admin::ProductsController.class_eval do
end
def bulk_update
collection_hash = Hash[params[:products].each_with_index.map { |p, i| [i, p] }]
product_set = Spree::ProductSet.new(collection_attributes: collection_hash)
params[:filters] ||= {}
bulk_index_query = params[:filters].reduce("") do |string, filter|
"#{string}q[#{filter[:property][:db_column]}_#{filter[:predicate][:predicate]}]=#{filter[:value]};"
end
product_set = product_set_from_params(params)
# Ensure we're authorised to update all products
product_set.collection.each { |p| authorize! :update, p }
if product_set.save
redirect_to "/api/products/bulk_products?page=1;per_page=500;#{bulk_index_query}"
redirect_to "/api/products/bulk_products?page=1;per_page=500;#{bulk_index_query(params)}"
else
if product_set.errors.present?
render json: { errors: product_set.errors }, status: :bad_request
@@ -73,7 +67,8 @@ Spree::Admin::ProductsController.class_eval do
protected
def collection
# This method is copied directly from the spree product controller, except where we narrow the search below with the managed_by search to support
# This method is copied directly from the spree product controller
# except where we narrow the search below with the managed_by search to support
# enterprise users.
# TODO: There has to be a better way!!!
return @collection if @collection.present?
@@ -108,14 +103,38 @@ Spree::Admin::ProductsController.class_eval do
private
def product_set_from_params(params)
collection_hash = Hash[params[:products].each_with_index.map { |p, i| [i, p] }]
Spree::ProductSet.new(collection_attributes: collection_hash)
end
def bulk_index_query(params)
params[:filters] ||= {}
params[:filters].reduce("") do |string, filter|
filter_db_column = filter[:property][:db_column]
filter_predicate = filter[:predicate][:predicate]
filter_value = filter[:value]
"#{string}q[#{filter_db_column}_#{filter_predicate}]=#{filter_value};"
end
end
def load_form_data
@producers = OpenFoodNetwork::Permissions.new(spree_current_user).managed_product_enterprises.is_primary_producer.by_name
@producers = OpenFoodNetwork::Permissions.new(spree_current_user).
managed_product_enterprises.is_primary_producer.by_name
@taxons = Spree::Taxon.order(:name)
@import_dates = product_import_dates.uniq.to_json
end
def product_import_dates
import_dates = Spree::Variant.
options = [{ id: '0', name: '' }]
product_import_dates_query.collect(&:import_date).
map { |i| options.push(id: i.to_date, name: i.to_date.to_formatted_s(:long)) }
options
end
def product_import_dates_query
Spree::Variant.
select('DISTINCT spree_variants.import_date').
joins(:product).
where('spree_products.supplier_id IN (?)', editable_enterprises.collect(&:id)).
@@ -123,18 +142,14 @@ Spree::Admin::ProductsController.class_eval do
where(spree_variants: { is_master: false }).
where(spree_variants: { deleted_at: nil }).
order('spree_variants.import_date DESC')
options = [{ id: '0', name: '' }]
import_dates.collect(&:import_date).map { |i| options.push(id: i.to_date, name: i.to_date.to_formatted_s(:long)) }
options
end
def strip_new_properties
unless spree_current_user.admin? || params[:product][:product_properties_attributes].nil?
names = Spree::Property.pluck(:name)
params[:product][:product_properties_attributes].each do |key, property|
params[:product][:product_properties_attributes].delete key unless names.include? property[:property_name]
return if spree_current_user.admin? || params[:product][:product_properties_attributes].nil?
names = Spree::Property.pluck(:name)
params[:product][:product_properties_attributes].each do |key, property|
unless names.include? property[:property_name]
params[:product][:product_properties_attributes].delete key
end
end
end
@@ -149,12 +164,32 @@ Spree::Admin::ProductsController.class_eval do
end
def set_stock_levels(product, on_hand, on_demand)
variant = product.master
if product.variants.any?
variant = product.variants.first
variant = product_variant(product)
begin
variant.on_demand = on_demand if on_demand.present?
variant.on_hand = on_hand.to_i if on_hand.present?
rescue StandardError => error
notify_bugsnag(error, product, variant)
raise error
end
end
def notify_bugsnag(error, product, variant)
Bugsnag.notify(error) do |report|
report.add_tab(:product, product.attributes)
report.add_tab(:product_error, product.errors.first) unless product.valid?
report.add_tab(:variant, variant.attributes)
report.add_tab(:variant_error, variant.errors.first) unless variant.valid?
end
end
def product_variant(product)
if product.variants.any?
product.variants.first
else
product.master
end
variant.on_demand = on_demand if on_demand.present?
variant.on_hand = on_hand.to_i if on_hand.present?
end
def set_product_master_variant_price_to_zero

View File

@@ -18,6 +18,7 @@ module Spree
klass = Spree::Order if klass == :bulk_order_management
klass = EnterpriseGroup if klass == :group
klass = VariantOverride if klass == :Inventory
klass = ProductImport::ProductImporter if klass == :import
klass = Spree::Admin::ReportsController if klass == :report
klass
end

View File

@@ -59,7 +59,7 @@ class SubscriptionPlacementJob
end
def move_to_completion(order)
until order.completed? do order.next! end
AdvanceOrderService.new(order).call!
end
def unavailable_stock_lines_for(order)

View File

@@ -464,9 +464,11 @@ class Enterprise < ActiveRecord::Base
self.permalink = Enterprise.find_available_permalink(name)
end
# Touch distributors without them touching their distributors.
# We avoid an infinite loop and don't need to touch the whole distributor tree.
def touch_distributors
Enterprise.distributing_products(supplied_products.select(:id)).
where('enterprises.id != ?', id).
find_each(&:touch)
update_all(updated_at: Time.zone.now)
end
end

View File

@@ -1,20 +0,0 @@
# Tells whether a particular feature is enabled or not
class FeatureFlags
# Constructor
#
# @param user [User]
def initialize(user)
@user = user
end
# Checks whether product import is enabled for the specified user
#
# @return [Boolean]
def product_import_enabled?
user.superadmin?
end
private
attr_reader :user
end

View File

@@ -17,9 +17,7 @@ class Spree::ProductSet < ModelSet
# variant.update_attributes( { price: xx.x } )
#
def update_attributes(attributes)
if attributes[:taxon_ids].present?
attributes[:taxon_ids] = attributes[:taxon_ids].split(',')
end
split_taxon_ids!(attributes)
found_model = @collection.find do |model|
model.id.to_s == attributes[:id].to_s && model.persisted?
@@ -28,12 +26,20 @@ class Spree::ProductSet < ModelSet
if found_model.nil?
@klass.new(attributes).save unless @reject_if.andand.call(attributes)
else
update_product_only_attributes(found_model, attributes) &&
update_product_variants(found_model, attributes) &&
update_product_master(found_model, attributes)
update_product(found_model, attributes)
end
end
def split_taxon_ids!(attributes)
attributes[:taxon_ids] = attributes[:taxon_ids].split(',') if attributes[:taxon_ids].present?
end
def update_product(found_model, attributes)
update_product_only_attributes(found_model, attributes) &&
update_product_variants(found_model, attributes) &&
update_product_master(found_model, attributes)
end
def update_product_only_attributes(product, attributes)
variant_related_attrs = [:id, :variants_attributes, :master_attributes]
product_related_attrs = attributes.except(*variant_related_attrs)
@@ -90,8 +96,23 @@ class Spree::ProductSet < ModelSet
variant = product.variants.create(variant_attributes)
variant.on_demand = on_demand if on_demand.present?
variant.on_hand = on_hand.to_i if on_hand.present?
begin
variant.on_demand = on_demand if on_demand.present?
variant.on_hand = on_hand.to_i if on_hand.present?
rescue StandardError => error
notify_bugsnag(error, product, variant, variant_attributes)
raise error
end
end
def notify_bugsnag(error, product, variant, variant_attributes)
Bugsnag.notify(error) do |report|
report.add_tab(:product, product.attributes)
report.add_tab(:product_error, product.errors.first) unless product.valid?
report.add_tab(:variant_attributes, variant_attributes)
report.add_tab(:variant, variant.attributes)
report.add_tab(:variant_error, variant.errors.first) unless variant.valid?
end
end
def collection_attributes=(attributes)

View File

@@ -0,0 +1,10 @@
Spree::StockMovement.class_eval do
after_save :refresh_products_cache
private
def refresh_products_cache
return if stock_item.variant.blank?
OpenFoodNetwork::ProductsCache.variant_changed stock_item.variant
end
end

View File

@@ -1,2 +0,0 @@
add_to_attributes '[data-hook="admin_variant_form_fields"]'
attributes 'ng-app' => 'admin.products'

View File

@@ -1,25 +0,0 @@
/ insert_top "[data-hook='admin_variant_form_fields']"
.field
= f.label :display_name, t(:display_name)
= f.text_field :display_name, class: "fullwidth"
.field
= f.label :display_as, t(:display_as)
= f.text_field :display_as, class: "fullwidth"
- if product_has_variant_unit_option_type?(@product)
- if @product.variant_unit != 'items'
.field{"data-hook" => "unit_value", 'ng-controller' => 'variantUnitsCtrl'}
= f.label :unit_value, "#{t('admin.'+@product.variant_unit)} ({{unitName(#{@product.variant_unit_scale}, '#{@product.variant_unit}')}})"
= hidden_field_tag 'product_variant_unit_scale', @product.variant_unit_scale
= text_field_tag :unit_value_human, nil, {class: "fullwidth", 'ng-model' => 'unit_value_human', 'ng-change' => 'updateValue()'}
= f.text_field :unit_value, {hidden: true, 'ng-value' => 'unit_value'}
.field{"data-hook" => "unit_description"}
= f.label :unit_description, t(:spree_admin_unit_description)
= f.text_field :unit_description, class: "fullwidth", placeholder: t('admin.products.unit_name_placeholder')
:javascript
angular.element(document.getElementById("new_variant")).ready(function() {
angular.bootstrap(document.getElementById("new_variant"), ['admin.products']);
});

View File

@@ -1,11 +0,0 @@
/ insert_bottom "[data-hook='admin_variant_form_fields']"
- if Spree::Config[:track_inventory_levels]
.field.checkbox
%label
= f.check_box :on_demand
= t(:on_demand)
.field
= f.label :on_hand, t(:on_hand)
.fullwidth
= f.text_field :on_hand

View File

@@ -1,10 +0,0 @@
/ replace "[data-hook='presentation']"
- unless variant_unit_option_type?(option_type)
.field{"data-hook" => "presentation"}
= label :new_variant, option_type.presentation
- if @variant.new_record?
= select(:new_variant, option_type.presentation, option_type.option_values.collect {|ov| [ ov.presentation, ov.id ] }, {}, {:class => 'select2 fullwidth'})
- else
- if opt = @variant.option_values.detect {|o| o.option_type == option_type }.try(:presentation)
= text_field(:new_variant, option_type.presentation, :value => opt, :disabled => 'disabled', :class => 'fullwidth')

View File

@@ -1,33 +0,0 @@
/ insert_bottom "[data-hook='admin_variant_form_fields']"
:javascript
$(document).ready(function() {
var on_demand = $('input#variant_on_demand');
var on_hand = $('input#variant_on_hand');
disableOnHandIfOnDemand = function() {
on_demand_checked = on_demand.attr('checked')
if ( on_demand_checked == undefined )
on_demand_checked = false;
on_hand.attr('disabled', on_demand_checked);
if(on_demand_checked) {
on_hand.attr('data-stock', on_hand.val());
on_hand.val(t('admin.products.variants.infinity'));
}
}
disableOnHandIfOnDemand();
on_demand.change(function(){
disableOnHandIfOnDemand();
if(!this.checked) {
if(on_hand.attr('data-stock') !== undefined) {
on_hand.val(on_hand.attr('data-stock'));
} else {
on_hand.val("0");
}
}
});
});

View File

@@ -1,3 +0,0 @@
/ insert_bottom "[data-hook='on_demand']"
%div{'ofn-with-tip' => t('admin.products.variants.to_order_tip')}
%a= t('admin.whats_this')

View File

@@ -1,14 +0,0 @@
/ replace "[data-hook='admin_variant_form_additional_fields']"
.right.six.columns.omega.label-block{"data-hook" => "admin_variant_form_additional_fields"}
- if @product.variant_unit != 'weight'
.field{"data-hook" => 'weight'}
= f.label 'weight', t('weight')+' (kg)'
- value = number_with_precision(@variant.weight, :precision => 2)
= f.text_field 'weight', :value => value, :class => 'fullwidth'
- [:height, :width, :depth].each do |field|
.field{"data-hook" => field}
= f.label field, t(field)
- value = number_with_precision(@variant.send(field), :precision => 2)
= f.text_field field, :value => value, :class => 'fullwidth'

View File

@@ -1,3 +0,0 @@
/ replace "code[erb-loud]:contains('variant.options_text')"
= variant.full_name

View File

@@ -5,4 +5,11 @@
= render 'upload_sidebar'
%h5
= t('.notice')
%br
%p
= t('.beta_notice')
%br
= render 'upload_form'

View File

@@ -12,13 +12,12 @@
%label{ for: 'category_filter' }= t 'category'
%br
%select.fullwidth{ id: 'category_filter', 'ofn-select2-min-search' => 5, ng: {model: 'categoryFilter', options: 'taxon.id as taxon.name for taxon in filterTaxons'} }
- if FeatureFlags.new(@current_user).product_import_enabled?
.filter_select.three.columns
%label{ for: 'import_filter' } Import Date
%br
%select.fullwidth{ id: 'import_date_filter', 'ofn-select2-min-search' => 5, ng: {model: 'importDateFilter', init: "importDates = #{@import_dates}; showLatestImport = #{@show_latest_import}"}}
%option{value: "{{date.id}}", ng: {repeat: "date in importDates track by date.id" }}
{{date.name}}
.filter_select.three.columns
%label{ for: 'import_filter' } Import Date
%br
%select.fullwidth{ id: 'import_date_filter', 'ofn-select2-min-search' => 5, ng: {model: 'importDateFilter', init: "importDates = #{@import_dates}; showLatestImport = #{@show_latest_import}"}}
%option{value: "{{date.id}}", ng: {repeat: "date in importDates track by date.id" }}
{{date.name}}
.filter_clear.three.columns.omega
%label{ for: 'clear_all_filters' }

View File

@@ -0,0 +1,67 @@
.label-block.left.six.columns.alpha{'ng-app' => 'admin.products'}
.field
= f.label :display_name, t(:display_name)
= f.text_field :display_name, class: "fullwidth"
.field
= f.label :display_as, t(:display_as)
= f.text_field :display_as, class: "fullwidth"
- if product_has_variant_unit_option_type?(@product)
- if @product.variant_unit != 'items'
.field{'ng-controller' => 'variantUnitsCtrl'}
= f.label :unit_value, "#{t('admin.'+@product.variant_unit)} ({{unitName(#{@product.variant_unit_scale}, '#{@product.variant_unit}')}})"
= hidden_field_tag 'product_variant_unit_scale', @product.variant_unit_scale
= text_field_tag :unit_value_human, nil, {class: "fullwidth", 'ng-model' => 'unit_value_human', 'ng-change' => 'updateValue()'}
= f.text_field :unit_value, {hidden: true, 'ng-value' => 'unit_value'}
.field
= f.label :unit_description, t(:spree_admin_unit_description)
= f.text_field :unit_description, class: "fullwidth", placeholder: t('admin.products.unit_name_placeholder')
%div
- @product.option_types.each do |option_type|
- unless variant_unit_option_type?(option_type)
.field
= label :new_variant, option_type.presentation
- if @variant.new_record?
= select(:new_variant, option_type.presentation, option_type.option_values.collect {|ov| [ ov.presentation, ov.id ] }, {}, {class: 'select2 fullwidth'})
- else
- if opt = @variant.option_values.detect {|o| o.option_type == option_type }.try(:presentation)
= text_field(:new_variant, option_type.presentation, value: opt, disabled: 'disabled', class: 'fullwidth')
.field
= f.label :sku, Spree.t(:sku)
= f.text_field :sku, class: 'fullwidth'
.field
= f.label :price, Spree.t(:price)
= f.text_field :price, value: number_to_currency(@variant.price, unit: ''), class: 'fullwidth'
.field
= f.label :cost_price, Spree.t(:cost_price)
= f.text_field :cost_price, value: number_to_currency(@variant.cost_price, unit: ''), class: 'fullwidth'
- if Spree::Config[:track_inventory_levels]
%div{ 'set-on-demand' => '' }
.field.checkbox
%label
= f.check_box :on_demand
= t(:on_demand)
%div{'ofn-with-tip' => t('admin.products.variants.to_order_tip')}
%a= t('admin.whats_this')
.field
= f.label :on_hand, t(:on_hand)
.fullwidth
= f.text_field :on_hand
.right.six.columns.omega.label-block
- if @product.variant_unit != 'weight'
.field
= f.label 'weight', t('weight')+' (kg)'
- value = number_with_precision(@variant.weight, precision: 2)
= f.text_field 'weight', value: value, class: 'fullwidth'
- [:height, :width, :depth].each do |field|
.field
= f.label field, t(field)
- value = number_with_precision(@variant.send(field), precision: 2)
= f.text_field field, value: value, class: 'fullwidth'
.clear

View File

@@ -0,0 +1,11 @@
= render partial: 'spree/admin/shared/product_sub_menu'
= render partial: 'spree/admin/shared/product_tabs', locals: { current: 'Variants' }
= render partial: 'spree/shared/error_messages', locals: { target: @variant }
= form_for [:admin, @product, @variant] do |f|
%fieldset.no-border-top
%div
= render partial: 'form', locals: { f: f }
= render partial: 'spree/admin/shared/edit_resource_links'

View File

@@ -0,0 +1,54 @@
= render partial: 'spree/admin/shared/product_sub_menu'
= render partial: 'spree/admin/shared/product_tabs', locals: {current: 'Variants'}
#new_variant
- if @variants.any?
%table.index.sortable{"data-sortable-link" => update_positions_admin_product_variants_path(@product)}
%colgroup
%col{style: "width: 5%"}/
%col{style: "width: 25%"}/
%col{style: "width: 20%"}/
%col{style: "width: 20%"}/
%col{style: "width: 15%"}/
%col{style: "width: 15%"}/
%thead
%tr
%th{colspan: "2"}= Spree.t(:options)
%th= Spree.t(:price)
%th= Spree.t(:sku)
%th.actions
%tbody
- @variants.each do |variant|
%tr{id: spree_dom_id(variant), class: cycle('odd', 'even'), style: "#{"color:red;" if variant.deleted? }" }
%td.no-border
%span.handle
%td= variant.full_name
%td.align-center= variant.display_price.to_html
%td.align-center= variant.sku
%td.actions
= link_to_edit(variant, no_text: true) unless variant.deleted?
= link_to_delete(variant, no_text: true) unless variant.deleted?
- unless @product.has_variants?
%tr
%td{colspan: "5"}= Spree.t(:none)
- else
.alpha.twelve.columns.no-objects-found
= Spree.t(:no_results)
\.
- if @product.empty_option_values?
%p.first_add_option_types.no-objects-found
= Spree.t(:to_add_variants_you_must_first_define)
= link_to Spree.t(:option_types), admin_product_url(@product)
= Spree.t(:and)
= link_to Spree.t(:option_values), admin_option_types_url
- else
- content_for :page_actions do
%ul.inline-menu
%li#new_var_link
= link_to_with_icon('icon-plus', Spree.t(:new_variant), new_admin_product_variant_url(@product), remote: true, 'data-update' => 'new_variant', class: 'button')
%li= link_to_with_icon('icon-filter', @deleted.blank? ? Spree.t(:show_deleted) : Spree.t(:show_active), admin_product_variants_url(@product, deleted: @deleted.blank? ? "on" : "off"), class: 'button')

View File

@@ -0,0 +1,7 @@
= render partial: 'spree/shared/error_messages', locals: { target: @variant }
= form_for [:admin, @product, @variant] do |f|
%fieldset{'data-hook' => "admin_variant_new_form"}
%legend{align: "center"}= Spree.t(:new_variant)
= render partial: 'form', locals: { f: f }
= render partial: 'spree/admin/shared/new_resource_links'

View File

@@ -0,0 +1,3 @@
$("#new_variant").html('<%= escape_javascript(render template: 'spree/admin/variants/new', formats: [:html], handlers: [:erb]) %>');
$(".select2").select2();
$("#new_var_link").hide();

View File

@@ -507,6 +507,8 @@ en:
encoding_error: "Please check the language setting of your source file and ensure it is saved with UTF-8 encoding"
unexpected_error: "Product Import encountered an unexpected error whilst opening the file: %{error_message}"
index:
notice: "Notice"
beta_notice: "This feature is still in beta: you may experience some errors while using it. Please don't hesitate to contact support."
select_file: Select a spreadsheet to upload
spreadsheet: Spreadsheet
choose_import_type: Select import type

View File

@@ -94,6 +94,7 @@ en_AU:
user_passwords:
spree_user:
updated_not_active: "Your password has been reset, but your email has not been confirmed yet."
updated: "Your password was changed successfully. You are now signed in."
send_instructions: "You will receive an email with instructions about how to confirm your account in a few minutes."
models:
order_cycle:
@@ -243,6 +244,7 @@ en_AU:
reset_password_token: Reset password token
expired: has expired, please request a new one
back_to_payments_list: "Back to Payments List"
maestro_or_solo_cards: "Maestro/Solo cards"
actions:
create_and_add_another: "Create and Add Another"
create: "Create"
@@ -451,6 +453,8 @@ en_AU:
encoding_error: "Please check the language setting of your source file and ensure it is saved with UTF-8 encoding"
unexpected_error: "Product Import encountered an unexpected error whilst opening the file: %{error_message}"
index:
notice: "Notice"
beta_notice: "This feature is still in beta: you may experience some errors while using it. Please don't hesitate to contact support."
select_file: Select a spreadsheet to upload
spreadsheet: Spreadsheet
choose_import_type: Select import type
@@ -1027,6 +1031,7 @@ en_AU:
saved: "SAVED"
product_already_in_order: This product has already been added to the order. Please edit the quantity directly.
stock:
insufficient_stock: "Insufficient stock available"
out_of_stock: "Out of Stock"
orders:
number: Number
@@ -1035,6 +1040,7 @@ en_AU:
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: "If you have an open Order Cycle in this subscription's schedule, an order will be created for this customer. 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."
@@ -2779,6 +2785,7 @@ en_AU:
inventory: Inventory
zipcode: Postcode
weight: Weight (per kg)
error_user_destroy_with_orders: "Users with completed orders may not be deleted"
actions:
update: "Update"
errors:

View File

@@ -94,6 +94,7 @@ en_CA:
user_passwords:
spree_user:
updated_not_active: "Your password has been reset, but your email has not been confirmed yet."
updated: "Your password was changed successfully. You are now signed in."
send_instructions: "You will receive an email with instructions about how to confirm your account in a few minutes."
models:
order_cycle:
@@ -243,6 +244,7 @@ en_CA:
reset_password_token: Reset password token
expired: has expired, please request a new one
back_to_payments_list: "Back to Payments List"
maestro_or_solo_cards: "Maestro/Solo cards"
actions:
create_and_add_another: "Create and Add Another"
create: "Create"
@@ -451,6 +453,8 @@ en_CA:
encoding_error: "Please check the language setting of your source file and ensure it is saved with UTF-8 encoding"
unexpected_error: "Product Import encountered an unexpected error whilst opening the file: %{error_message}"
index:
notice: "Notice"
beta_notice: "This feature is still in beta: you may experience some errors while using it. Please don't hesitate to contact support."
select_file: Select a spreadsheet to upload
spreadsheet: Spreadsheet
choose_import_type: Select import type
@@ -1027,6 +1031,7 @@ en_CA:
saved: "SAVED"
product_already_in_order: This product has already been added to the order. Please edit the quantity directly.
stock:
insufficient_stock: "Insufficient stock available"
out_of_stock: "Out of Stock"
orders:
number: Number
@@ -1035,6 +1040,7 @@ en_CA:
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: "If you have an open Order Cycle in this subscription's schedule, an order will be created for this customer. 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."
@@ -2779,6 +2785,7 @@ en_CA:
inventory: Inventory
zipcode: Postal Code
weight: Weight (per kg)
error_user_destroy_with_orders: "Users with completed orders may not be deleted"
actions:
update: "Update"
errors:
@@ -2882,9 +2889,11 @@ en_CA:
new_shipping_method: "New Shipping Method"
back_to_shipping_methods_list: "Back to Shipping Methods List"
edit:
editing_shipping_method: "Editing Shipping Method"
new: "New"
back_to_shipping_methods_list: "Back to Shipping Methods List"
form:
categories: "Categories"
zones: "Zones"
both: "Both"
front_end: "Front End"
@@ -2915,6 +2924,7 @@ en_CA:
error_saving_payment: Error saving payment
submitting_payment: Submitting payment...
products:
image_upload_error: "The product image was not recognised. Please upload an image in PNG or JPG format."
new:
title: 'New Product'
unit_name_placeholder: 'eg. bunches'
@@ -3015,6 +3025,7 @@ en_CA:
line_item:
insufficient_stock: "Insufficient stock available, only %{on_hand} remaining"
out_of_stock: "Out of Stock"
unavailable_item: "Currently unavailable"
shipment_states:
backorder: backorder
partial: partial
@@ -3034,6 +3045,8 @@ en_CA:
invalid: invalid
order_mailer:
cancel_email:
customer_greeting: "Hi %{name}!"
instructions: "Your order has been CANCELED. Please retain this cancellation information for your records."
order_summary_canceled: "Order Summary [CANCELED]"
subject: "Cancellation of Order"
confirm_email:

View File

@@ -244,6 +244,7 @@ en_GB:
reset_password_token: Reset password
expired: has expired, please request a new one
back_to_payments_list: "Back to Payments List"
maestro_or_solo_cards: "Maestro/Solo cards"
actions:
create_and_add_another: "Create and Add Another"
create: "Create"
@@ -452,6 +453,8 @@ en_GB:
encoding_error: "Please check the language setting of your source file and ensure it is saved with UTF-8 encoding"
unexpected_error: "Product Import encountered an unexpected error whilst opening the file: %{error_message}"
index:
notice: "Notice"
beta_notice: "This feature is still in beta: you may experience some errors while using it. Please don't hesitate to contact support."
select_file: Select a spreadsheet to upload
spreadsheet: Spreadsheet
choose_import_type: Select import type
@@ -1028,6 +1031,7 @@ en_GB:
saved: "SAVED"
product_already_in_order: This product has already been added to the order. Please edit the quantity directly.
stock:
insufficient_stock: "Insufficient stock available"
out_of_stock: "Out of Stock"
orders:
number: Number
@@ -1036,6 +1040,7 @@ en_GB:
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: "If you have an open Order Cycle in this subscription's schedule, an order will be created for this customer. 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."
@@ -1374,7 +1379,7 @@ en_GB:
email_confirmed: "Thank you for confirming your email address."
email_registered: "is now part of"
email_userguide_html: "The User Guide with detailed support for setting up your Producer or Hub is here: %{link}"
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_admin_html: "You can manage your account by logging into the %{link} or by clicking on 'Profile' 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_confirmation_activate_account: "Before we can activate your new account, we need to confirm your email address."

View File

@@ -94,6 +94,7 @@ en_ZA:
user_passwords:
spree_user:
updated_not_active: "Your password has been reset, but your email has not been confirmed yet."
updated: "Your password was changed successfully. You are now signed in."
send_instructions: "You will receive an email with instructions about how to confirm your account in a few minutes."
models:
order_cycle:
@@ -1027,6 +1028,7 @@ en_ZA:
saved: "SAVED"
product_already_in_order: This product has already been added to the order. Please edit the quantity directly.
stock:
insufficient_stock: "Insufficient stock available"
out_of_stock: "Out of Stock"
orders:
number: Number
@@ -1035,6 +1037,7 @@ en_ZA:
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: "If you have an open Order Cycle in this subscription's schedule, an order will be created for this customer. 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."
@@ -2680,9 +2683,9 @@ en_ZA:
check_for_spree_alerts: "Check for Spree alerts"
currency_decimal_mark: "Currency decimal mark"
currency_settings: "Currency Settings"
currency_symbol_position: Put "currency symbol before or after pound amount?"
currency_symbol_position: Put "currency symbol before or after Rand amount?"
currency_thousands_separator: "Currency thousands separator"
hide_cents: "Hide pence"
hide_cents: "Hide cents"
display_currency: "Display currency"
choose_currency: "Choose Currency"
mail_method_settings: "Mail Method Settings"
@@ -2728,7 +2731,7 @@ en_ZA:
default_tax: "Default Tax"
default_tax_zone: "Default Tax Zone"
country_based: "Country Based"
state_based: "County Based"
state_based: "Province Based"
countries: "Countries"
listing_countries: "Listing Countries"
iso_name: "ISO Name"
@@ -2786,6 +2789,7 @@ en_ZA:
inventory: Inventory
zipcode: Postcode
weight: Weight (per kg)
error_user_destroy_with_orders: "Users with completed orders may not be deleted"
actions:
update: "Update"
errors:

View File

@@ -5,9 +5,9 @@ fr:
spree/order:
payment_state: Statut du paiement
shipment_state: Statut livraison
completed_at: 'Passée à '
completed_at: Date
number: N° commande
state: Etat
state: Statut
email: Email acheteur
spree/payment:
amount: Montant
@@ -216,7 +216,7 @@ fr:
unused: inutilisé
admin_and_handling: Frais si par commande
profile: Profil
supplier_only: Uniquement Producteur
supplier_only: ne gère pas de boutique
has_shopfront: gère une boutique
weight: Poids
volume: Volume
@@ -244,6 +244,7 @@ fr:
reset_password_token: La demande de réinitialisation du mot de passe
expired: a expiré, veuillez faire une nouvelle demande.
back_to_payments_list: "Retour à la liste des paiements"
maestro_or_solo_cards: "Cartes Maestro/Solo"
actions:
create_and_add_another: "Créer et ajouter nouveau"
create: "Créer"
@@ -277,7 +278,7 @@ fr:
shipping_method: Option d'expédition
shop: Boutique
sku: Référence produit
status_state: Etat
status_state: Statut
tags: Tags
variant: Variante
weight: Poids
@@ -452,6 +453,8 @@ fr:
encoding_error: "Veuillez vérifier le paramètre de langue de votre code source et vous assurer qu'il est encodé en UTF-8"
unexpected_error: "L'import de fichier produits à rencontré une erreur inconnue à l'ouverture du fichier : %{error_message}"
index:
notice: "Notice"
beta_notice: "Cette fonctionnalité est en mode bêta : il est possible que vous rencontriez des erreurs en l'utilisant. N'hésitez pas à contacter le support utilisateurs."
select_file: Sélectionner le fichier (tableur sous format csv) à importer
spreadsheet: Tableur csv
choose_import_type: Choisir le type d'import
@@ -555,7 +558,7 @@ fr:
tip: "Utilisez cette page pour changer les quantités d'un produit sur plusieurs commandes. Les produits peuvent aussi être supprimés de toutes les commandes, si nécessaire."
shared: "Ressource partagée?"
order_no: "N° commande"
order_date: "Passée le"
order_date: "Date"
max: "Max"
product_unit: "Produit: Unité"
weight_volume: "Poids/Volume"
@@ -725,7 +728,7 @@ fr:
no_rules_yet: Aucune règle ne concerne ce tag pour le moment
for_customers_tagged: 'Pour les acheteurs avec le tag:'
add_new_rule: '+ Ajouter une nouvelle règle'
add_new_tag: '+ Ajouter un nouveau tag'
add_new_tag: '+ Ajouter une règle pour un autre tag'
users:
email_confirmation_notice_html: "L'email de confirmation n'a pas encore été validé. Il a été envoyé à %{email}."
resend: Renvoyer
@@ -923,7 +926,7 @@ fr:
totals_by_supplier: Totaux Cycle de Vente par Hub Distributeur pour chaque Producteur
customer_totals: Totaux Cycle de Vente par Acheteur
all_products: Tous les produits
inventory: Catalogue boutique (en stock)
inventory: Produits disponibles (stock positif)
lettuce_share: LettuceShare
mailing_list: Liste de mails
addresses: Adresses
@@ -947,7 +950,7 @@ fr:
customers:
name: Acheteurs
products_and_inventory:
name: Produits et Catalogues
name: Listings produits
sales_total:
name: Total des Ventes
description: Total des Ventes pour toutes les Commandes
@@ -1032,7 +1035,7 @@ fr:
insufficient_stock: "Stock disponible insuffisant"
out_of_stock: "En rupture de stock"
orders:
number: Nombre
number: N° commande
confirm_edit: Voulez-vous vraiment modifier cette commande? Si vous poursuivez, la synchronisation automatique des modifications de l'abonnement pourrait être plus difficile à l'avenir.
confirm_cancel_msg: "Voulez-vous vraiment annuler cet abonnement? Cette action sera irréversible."
cancel_failure_msg: "Désolé, l'annulation a échoué!"
@@ -1855,7 +1858,7 @@ fr:
transaction_date: "Date"
payment_state: "Statut du paiement"
shipping_state: "Statut de la livraison"
value: "Nb unités"
value: "Montant"
balance_due: "Montant dû"
credit: "Créditer"
Paid: "Payé"
@@ -2405,13 +2408,13 @@ fr:
description: Description
resolve: Résoudre
tag_rules:
shipping_method_tagged_top: "Les méthodes de livraison taggées"
shipping_method_tagged_top: "Les méthodes de livraison taguées"
shipping_method_tagged_bottom: "sont:"
payment_method_tagged_top: "Les méthodes de payments taguées"
payment_method_tagged_bottom: "sont:"
order_cycle_tagged_top: "Les cycles de vente taggés"
order_cycle_tagged_top: "Les cycles de vente tagués"
order_cycle_tagged_bottom: "sont:"
inventory_tagged_top: "Les variantes du catalogue boutique taggées"
inventory_tagged_top: "Les variantes du catalogue boutique taguées"
inventory_tagged_bottom: "sont:"
new_tag_rule_dialog:
select_rule_type: "Choisir le type de règle:"
@@ -2430,7 +2433,7 @@ fr:
address: "adresse"
adjustments: "ajustements"
awaiting_return: "attente du retour"
canceled: "annulé"
canceled: "annulée"
cart: "panier"
complete: "finalisée"
confirm: "confirmer"
@@ -2520,8 +2523,8 @@ fr:
stock_reset: Les niveaux de stock ont été réinitiatlisés (valeurs par défaut)
tag_rules:
show_hide_variants: 'Afficher ou Masquer les variantes dans ma boutique'
show_hide_shipping: 'Afficher ou Montrer les méthodes de livraison lors de la finalisation de commande'
show_hide_payment: 'Afficher ou Montrer les méthodes de paiement lors de la finalisation de commande'
show_hide_shipping: 'Afficher ou Masquer les méthodes de livraison lors de la finalisation de commande'
show_hide_payment: 'Afficher ou Masquer les méthodes de paiement lors de la finalisation de commande'
show_hide_order_cycles: 'Afficher ou Masquer les cycles de vente de ma boutique'
visible: VISIBLE
not_visible: INVISIBLE
@@ -2556,7 +2559,7 @@ fr:
close_date_not_set: Date de fin non renseignée
spree:
users:
order: "Commandes à venir"
order: "Commande"
registration:
welcome_to_ofn: "Bienvenue sur Open Food France !"
signup_or_login: "Commencez par vous inscrire (ou connexion)"
@@ -2604,7 +2607,7 @@ fr:
tax_category_name: "TVA applicable"
total_amount: "€ total"
invalid_filter_parameters: "Les filtres sélectionnés pour ce rapport sont invalides."
order: "Commandes à venir"
order: "Commande"
distribution: "Distribution"
order_details: "Détails de la commande"
customer_details: "Informations acheteur"
@@ -2848,8 +2851,8 @@ fr:
payment_state: "Statut du Paiement"
shipment_state: "Statut livraison"
completed_at: "Date"
number: "Nombre"
state: "Etat"
number: "N° commande"
state: "Statut"
email: "Email acheteur"
invoice:
issued_on: "Editée le"
@@ -3067,7 +3070,7 @@ fr:
address: adresse
adjustments: ajustements
awaiting_return: attente du retour
canceled: annulé
canceled: annulée
cart: panier
complete: finalisée
confirm: confirmer
@@ -3123,7 +3126,7 @@ fr:
closed: Fermée
until: Jusqu'à
past_orders:
order: Commandes à venir
order: Commande
shop: Boutique
completed_at: Date
items: Produits
@@ -3134,7 +3137,7 @@ fr:
default?: Carte utilisée par défaut?
delete?: Supprimer?
cards:
authorised_shops: Boutiques autorisées.
authorised_shops: Boutiques autorisées
authorised_shops_popover: Voilà la liste des boutiques que vous avez autorisées à débiter votre carte de paiement par défaut dans le cadre de vos abonnements en cours (commandes récurrentes). Les informations concernant votre carte de paiement sont sécurisées et ne sont pas accessibles par le gérant de la boutique. Vous recevrez systématiquement une notification avant tout débit sur votre carte.
saved_cards_popover: Voilà la liste des cartes de paiement que vous avez enregistrées. Votre carte par défaut sera automatiquement sélectionnée au moment de la finalisation d'une commande, et pourra être débitée par les boutiques auxquelles vous avez donné cette autorisation (voir à droite).
authorised_shops:

View File

@@ -14,7 +14,9 @@ fr_CA:
spree/product:
primary_taxon: "Catégorie Produit"
supplier: "Fournisseur"
shipping_category_id: "Condition de transport"
variant_unit: "Unité"
variant_unit_name: "Unité de la variante"
order_cycle:
orders_close_at: Date de fermeture
errors:
@@ -75,6 +77,8 @@ fr_CA:
user_confirmations:
spree_user:
send_instructions: "Un email a été envoyé avec des instructions pour confirmer votre adresse email. Vérifiez votre boite mail!"
confirmation_sent: "L'email de confirmation a bien été envoyé"
confirmation_not_sent: "Une erreur est survenue lors de l'envoi de l'email de confirmation"
user_registrations:
spree_user:
signed_up_but_unconfirmed: "Un message avec un lien de confirmation a été envoyé à l'adresse email indiquée. Veuillez cliquer sur ce lien pour activer votre compte."
@@ -86,9 +90,12 @@ fr_CA:
Créez votre compte ou réinitialisez votre mot de passe.
unconfirmed: "Veuillez valider le lien envoyé par email pour pouvoir continuer."
already_registered: "Cet email existe déjà. Veuillez vous connecter ou utiliser une autre adresse email."
success:
logged_in_succesfully: "Vous êtes désormais connecté !"
user_passwords:
spree_user:
updated_not_active: "Votre mot de passe a été mis à jour, mais votre email n'a pas encore été confirmé."
updated: "Votre mot de passer a été changé avec succès. Vous êtes maintenant connecté(e)."
send_instructions: "Un email a été envoyé avec des instructions pour confirmer votre adresse email. Vérifiez votre boite mail!"
models:
order_cycle:
@@ -238,6 +245,7 @@ fr_CA:
reset_password_token: La demande de réinitialisation du mot de passe
expired: a expiré, veuillez faire une nouvelle demande.
back_to_payments_list: "Retour à la liste des paiements"
maestro_or_solo_cards: "Cartes Maestro/Solo"
actions:
create_and_add_another: "Créer et ajouter nouveau"
create: "Créer"
@@ -322,6 +330,7 @@ fr_CA:
invoice_settings:
edit:
title: "Paramètres de facturation"
enable_invoices?: "Autoriser l'émission de factures ?"
invoice_style2?: "Utiliser le modèle de facture alternatif qui détaille le montant de Taxe agrégé par taux et l'information du taux de taxe par produit (pas adapté pour les instances affichant les prix HT)"
enable_receipt_printing?: "Afficher les options d'impression de tickets de caisse dans le menu déroulant des commandes?"
stripe_connect_settings:
@@ -390,6 +399,7 @@ fr_CA:
calculator: "Calculateur"
calculator_values: "Valeurs applicables"
search: "Chercher"
name_placeholder: "ex.: marge de conditionnement"
enterprise_groups:
index:
new_button: Nouveau groupe d'entreprises
@@ -419,6 +429,7 @@ fr_CA:
property_name: Nom du label
inherited_property: Label producteur appliqué par défaut
variants:
infinity: "Infini"
to_order_tip: "Les articles fabriqués sur commande n'ont pas un niveau de stock défini, comme des pains faits à la main."
group_buy_options: "Options d'achat par lot"
back_to_products_list: "Retour à la liste produits"
@@ -443,6 +454,8 @@ fr_CA:
encoding_error: "Veuillez vérifier le paramètre de langue de votre code source et vous assurer qu'il est encodé en UTF-8"
unexpected_error: "L'import de fichier produits à rencontré une erreur inconnue à l'ouverture du fichier : %{error_message}"
index:
notice: "Notice"
beta_notice: "Cette fonctionnalité est en mode bêta : il est possible que vous rencontriez des erreurs en l'utilisant. N'hésitez pas à contacter le support utilisateurs."
select_file: Sélectionner une feuille de calcul à uploader
spreadsheet: Feuille de calcul
choose_import_type: Choisir le type d'import
@@ -648,6 +661,8 @@ fr_CA:
permalink_tip: "Ce nom permanent est utilisé pour créer l'url de votre boutique: %{link}ma-boutique/shop"
link_to_front: Lien URL de la boutique
link_to_front_tip: C'est le lien qui permet d'accéder en direct à votre boutique sur Open Food Network.
ofn_uid: ID OFN
ofn_uid_tip: L'identifiant unique pour les comptes entreprises sur Open Food Network.
shipping_methods:
name: Nom
applies: S'applique?
@@ -677,6 +692,8 @@ fr_CA:
shopfront_message_placeholder: >
Vous pouvez ici expliquer à vos acheteurs comment votre boutique fonctionne.
Ce texte s'affiche dans votre boutique, au-dessus de la liste de produits.
shopfront_message_link_tooltip: "Insérer / modifier un lien"
shopfront_message_link_prompt: "Veuillez entrer l'URL à insérer"
shopfront_closed_message: "Message d'accueil de la boutique fermée"
shopfront_closed_message_placeholder: >
Vous pouvez ici expliquer à vos acheteurs pourquoi votre boutique est
@@ -806,6 +823,9 @@ fr_CA:
user_already_exists: "Le compte existe déjà"
error: "Un problème est survenu"
order_cycles:
loading_flash:
loading_order_cycles: Cycles de vente en cours de chargement
loading: Chargement en cours...
edit:
advanced_settings: Paramétrages avancés
update_and_close: Mettre à jour et fermer
@@ -824,6 +844,7 @@ fr_CA:
add_distributor: 'Ajouter un distributeur'
advanced_settings:
title: Paramétrages avancés
choose_product_tip: Vous pouvez restreindre les produits entrants et sortants uniquement au catalogue boutique de %{inventory}
preferred_product_selection_from_coordinator_inventory_only_here: Uniquement le catalogue boutique du coordinateur
preferred_product_selection_from_coordinator_inventory_only_all: Tous les produits disponibles dans les catalogues producteurs
save_reload: Sauvegarder et rafraichir la page
@@ -959,6 +980,8 @@ fr_CA:
pause_subscription: Mettre en pause Abonnement
unpause_subscription: Reprendre Abonnement
cancel_subscription: Annuler Abonnement
filters:
query_placeholder: "Recherche par email"
setup_explanation:
just_a_few_more_steps: 'Encore quelques étapes avant de pouvoir commencer:'
enable_subscriptions: "Activez la fonction abonnements pour au moins une de vos boutiques"
@@ -994,6 +1017,8 @@ fr_CA:
charges_not_allowed: Le débit automatique sur carte de paiement n'a pas été autorisé par l'acheteur
no_default_card: L'acheteur n'a pas de carte de paiement disponible pour le débit
card_ok: L'acheteur a une carte de paiement disponible pour le débit
begins_at_placeholder: "Sélectionnez une date"
ends_at_placeholder: "Facultatif"
loading_flash:
loading: Abonnements en cours de chargement
review:
@@ -1007,6 +1032,7 @@ fr_CA:
saved: "Enregistré"
product_already_in_order: Ce produit a déjà été ajouté à la commande. Veuillez directement modifier la quantité.
stock:
insufficient_stock: "Stock disponible insuffisant"
out_of_stock: "En rupture de stock"
orders:
number: Nombre
@@ -1015,6 +1041,7 @@ fr_CA:
cancel_failure_msg: "Désolé, l'annulation a échoué!"
confirm_pause_msg: "Voulez-vous vraiment mettre en pause cet abonnement?"
pause_failure_msg: "Désolé, la mise en pause a échoué!"
confirm_unpause_msg: "Si vous avez un cycle de vente ouvert pour ce rythme d'abonnement, une commande sera créée pour cet acheteur. Êtes-vous sûr de vouloir relancer cet abonnement ?"
unpause_failure_msg: "Désolé, l'annulation de la mise en pause a échoué!"
confirm_cancel_open_orders_msg: "Cet abonnement a des commandes ouvertes. Les acheteurs ont été notifiés que leur commande allait être passée. Voulez-vous annulez ces commandes ou les conserver?"
resume_canceled_orders_msg: "Certaines commandes pour cet abonnement peuvent être réouvertes dès maintenant. Vous pouvez les réouvrir depuis la liste des commandes."
@@ -1052,8 +1079,12 @@ fr_CA:
show_on_map: "Tout afficher sur la carte"
shared:
menu:
cart:
cart: "Panier"
signed_in:
profile: "Profil"
mobile_menu:
cart: "Panier"
joyride:
checkout: "Passer la commande"
already_ordered_products: "Déjà commandé dans ce cycle de vente"
@@ -1090,7 +1121,11 @@ fr_CA:
shop:
messages:
login: "se connecter"
signup: "inscrivez-vous"
contact: "contact"
require_customer_login: "Seul les acheteurs autorisés peuvent accéder à cette boutique."
require_login_html: "Si vous êtes déjà autorisé à accéder à la boutique, %{login}ou %{signup} pour continuer. Si vous voulez demander à y accéder, veuillez %{contact} %{enterprise}. "
require_customer_html: "Si vous voulez demander à y accéder, veuillez %{contact} %{enterprise}."
card_could_not_be_updated: La carte n'a pu être mise à jour
card_could_not_be_saved: la carte n'a pas pu être sauvegardée
spree_gateway_error_flash_for_checkout: "Il y a eu un problème avec vos informations de paiement : %{error}"
@@ -1127,6 +1162,7 @@ fr_CA:
menu_4_title: "Groupes"
menu_4_url: "/groups"
menu_5_title: "A propos"
menu_5_url: "https://about.openfoodnetwork.org.au/"
menu_6_title: "Se connecter"
menu_6_url: "https://openfoodnetwork.org/au/connect/"
menu_7_title: "Apprendre"
@@ -1563,6 +1599,7 @@ fr_CA:
sell_hubs_detail: "Créer un profil pour votre entreprise de distribution ou organisation sur OFN. A tout moment vous pourrez créer une boutique multi-fournisseurs."
sell_groups_detail: "Créer un répertoire sur mesure (regroupant différents producteurs et hubs de distribution) pour votre région ou votre organisation."
sell_user_guide: "En savoir plus en explorant le guide utilisateur."
sell_listing_price: "L'inscription sur OFFrance est gratuite. Opening and running a shop on OFN is free up to $500 of monthly sales. If you sell more we will invoice you for 2% of sales to a maximum of $100/month. For more detail on pricing visit the Software Platform section via the About link in the top menu."
sell_embed: "Nous pouvons aussi intégrer votre boutique OFN dans votre propre site web ou construire un site web d'alimentation locale sur mesure pour votre région."
sell_ask_services: "Nous consulter sur les services de OFN."
shops_title: Boutiques
@@ -1599,7 +1636,7 @@ fr_CA:
orders_show_order_number: "Commande #%{number}"
orders_show_cancelled: Annulée
orders_show_confirmed: Confirmée
orders_your_order_has_been_cancelled: "Votre commande a été annulée"
orders_your_order_has_been_cancelled: "VotrVotre commande a été annuléee commande a été annulée"
orders_could_not_cancel: "Désolé, la commande n'a pas pu être annulée"
orders_cannot_remove_the_final_item: "Impossible de supprimer le dernier produit d'une commande, si vous souhaitez supprimer l'ensemble des produits, veuillez annuler la commande."
orders_bought_items_notice:
@@ -1678,6 +1715,7 @@ fr_CA:
introduction:
registration_greeting: "Bonjour!"
registration_intro: "Vous pouvez maintenant créer votre profil \"Producteur\" ou \"Hub\""
registration_checklist: "De quoi ai-je besoin ?"
registration_time: "5-10 minutes"
registration_enterprise_address: "L'adresse de l'entreprise"
registration_contact_details: "Les détails du contact référent"
@@ -1932,6 +1970,7 @@ fr_CA:
spree_admin_supplier: Fournisseur
spree_admin_product_category: Catégorie Produit
spree_admin_variant_unit_name: Nom de la pièce (si vendu à la pièce)
unit_name: "Unité"
change_package: "Changer de type de compte"
spree_admin_single_enterprise_hint: "Astuce: Pour permettre aux gens de vous trouver, activez votre visibilité "
spree_admin_eg_pickup_from_school: "ex : \"Retrait des produits à l'Ecole Marimati / Au Café du coin / chez Babette / ...\""
@@ -2167,6 +2206,7 @@ fr_CA:
payment_methods: "Méthodes de paiement"
payment_method_fee: "Frais de transaction"
payment_processing_failed: "Le paiement n'a pas pu être traité, veuillez vérifier les informations saisies"
payment_method_not_supported: "Cette méthode de paiement n'est pas maintenue. Veuillez en sélectionner une autre."
payment_updated: "Paiement mis à jour"
inventory_settings: "Paramètres catalogue boutique"
tag_rules: "Règles de tag"
@@ -2367,8 +2407,20 @@ fr_CA:
severity: Gravité
description: Description
resolve: Résoudre
tag_rules:
shipping_method_tagged_top: "Les méthodes de livraison taggées"
shipping_method_tagged_bottom: "sont:"
payment_method_tagged_top: "Les méthodes de payments taguées"
payment_method_tagged_bottom: "sont:"
order_cycle_tagged_top: "Les cycles de vente taggés"
order_cycle_tagged_bottom: "sont:"
inventory_tagged_top: "Les variantes du catalogue boutique taggées"
inventory_tagged_bottom: "sont:"
new_tag_rule_dialog:
select_rule_type: "Choisir le type de règle:"
add_rule: "Ajouter une règle"
enterprise_fees:
inherit_from_product: "Hériter du produit"
orders:
index:
per_page: " %{results}par page"
@@ -2429,6 +2481,7 @@ fr_CA:
name_required_error: "Veuillez saisir un nom pour ce rythme d'abonnement"
no_order_cycles_error: "Veuillez saisir au moins un cycle de vente (glisser déposer)"
available: "Disponible"
selected: "sélectionné"
customers:
index:
add_customer: "Ajouter un acheteur"
@@ -2623,6 +2676,7 @@ fr_CA:
fill_in_customer_info: "Veuillez saisir les informations acheteur"
new_payment: "Nouveau paiement"
capture: "Payée"
void: "Annulé"
configurations: "Configurations"
general_settings: "Configurations générales"
site_name: "Nom du site"
@@ -2724,7 +2778,16 @@ fr_CA:
no_results: "Pas de résultats"
create: "Créer"
loading: "Chargement en cours"
flat_percent: "Pourcentage net"
per_kg: "Par kg"
amount: "Montant"
currency: "Devise"
first_item: "Coût du premier produit"
additional_item: "Coût du premier produit"
max_items: "Produits max."
minimal_amount: "Montant minimal"
normal_amount: "Montant classique"
discount_amount: "Réduction"
email: Email
account_updated: "Compte mis à jour!"
my_account: "Mon compte"
@@ -2734,6 +2797,7 @@ fr_CA:
inventory: Catalogue boutique
zipcode: Code postal
weight: Poids (au kg)
error_user_destroy_with_orders: "Les utilisateurs avec des commandes finalisées pourraient ne pas être supprimés"
actions:
update: "Mettre à jour"
errors:
@@ -2801,6 +2865,8 @@ fr_CA:
title: "Distribution"
distributor: "Distributeur : "
order_cycle: "Cycle de vente : "
line_item_adjustments: "Ajustements sur la ligne produit"
order_adjustments: "Ajustements sur la commande"
order_total: "Total Commande:"
overview:
enterprises_header:
@@ -2821,15 +2887,29 @@ fr_CA:
shipping_methods:
index:
shipping_methods: "Méthodes de livraison"
new_shipping_method: "Nouvelle méthode de livraison"
name: "Nom"
products_distributor: "Hub-distributeur"
zone: "Zone"
calculator: "Calculateur"
display: "Afficher"
both: "Les deux"
front_end: "Front End"
back_end: "Back End"
no_shipping_methods_found: "Aucune méthode de livraison trouvée"
new:
new_shipping_method: "Nouvelle méthode de livraison"
back_to_shipping_methods_list: "Retour à la liste des méthodes de livraison"
edit:
editing_shipping_method: "Modifier la méthode de livraison"
new: "Nouveau"
back_to_shipping_methods_list: "Retour à la liste des méthodes de livraison"
form:
categories: "Conditions de transport"
zones: "Zones"
both: "Les deux"
front_end: "Front End"
back_end: "Back End"
payment_methods:
new:
new_payment_method: "Nouvelle méthode de paiement"
@@ -2856,6 +2936,7 @@ fr_CA:
error_saving_payment: Erreur à l'enregistrement du paiement
submitting_payment: Envoi du paiement...
products:
image_upload_error: "L'image du produit n'a pas été reconnue. Veuillez importer une image au format PNG ou JPG."
new:
title: 'Nouveau Produit'
unit_name_placeholder: 'ex: botte'
@@ -2956,6 +3037,7 @@ fr_CA:
line_item:
insufficient_stock: "Stock disponible insuffisant, il n'en reste que %{on_hand}"
out_of_stock: "En rupture de stock"
unavailable_item: "Non disponible"
shipment_states:
backorder: réapprovisionnement
partial: partiel
@@ -2975,6 +3057,8 @@ fr_CA:
invalid: invalide
order_mailer:
cancel_email:
customer_greeting: "Bonjour %{name}!"
instructions: "Votre commande a été ANNULÉE. Vous trouverez ci-dessous les informations concernant cette commande. "
order_summary_canceled: "Résumé de la commande [ANNULEE]"
subject: "Annulation de Commande"
confirm_email:

View File

@@ -244,6 +244,7 @@ nb:
reset_password_token: Tilbakestill passordtoken
expired: er utløpt, vennligst be om en ny
back_to_payments_list: "Tilbake til betalingsliste"
maestro_or_solo_cards: "Maestro/Solo kort"
actions:
create_and_add_another: "Opprett og legg til en annen"
create: "Opprett"
@@ -452,6 +453,8 @@ nb:
encoding_error: "Vennligst sjekk språkinnstillingen til kildefilen din og kontroller at den er lagret med UTF-8-koding"
unexpected_error: "Produktimport støtte på en uventet feil ved åpning av filen: %{error_message}"
index:
notice: "Beskjed"
beta_notice: "Denne funksjonen er fremdeles i beta: du kan oppleve noen feil mens du bruker den. Ikke nøl med å kontakte support."
select_file: Velg et regneark for å laste opp
spreadsheet: Regneark
choose_import_type: Velg importtype

View File

@@ -168,7 +168,7 @@ describe Spree::Admin::ProductsController, type: :controller do
end
end
describe "updating" do
describe "updating a product" do
let(:producer) { create(:enterprise) }
let!(:product) { create(:simple_product, supplier: producer) }
@@ -176,6 +176,23 @@ describe Spree::Admin::ProductsController, type: :controller do
login_as_enterprise_user [producer]
end
describe "product stock setting with errors" do
it "notifies bugsnag and still raise error" do
# forces an error in the variant
product.variants.first.stock_items = []
expect(Bugsnag).to receive(:notify)
expect do
spree_put :update,
id: product,
product: {
on_hand: 1
}
end.to raise_error(StandardError)
end
end
describe "product variant unit is items" do
it "clears unit description of all variants of the product" do
product.variants.first.update_attribute :unit_description, "grams"

View File

@@ -64,31 +64,6 @@ feature "As a consumer I want to check out my cart", js: true do
context 'login in as user' do
let(:user) { create(:user) }
def fill_out_form
choose sm1.name
choose pm1.name
within "#details" do
fill_in "First Name", with: "Will"
fill_in "Last Name", with: "Marshall"
fill_in "Email", with: "test@test.com"
fill_in "Phone", with: "0468363090"
end
check "Save as default billing address"
within "#billing" do
fill_in "City", with: "Melbourne"
fill_in "Postcode", with: "3066"
fill_in "Address", with: "123 Your Head"
select "Australia", from: "Country"
select "Victoria", from: "State"
end
check "Shipping address same as billing address?"
check "Save as default shipping address"
end
before do
quick_login_as(user)
end
@@ -205,6 +180,46 @@ feature "As a consumer I want to check out my cart", js: true do
end
end
context "in the shopfront with cache enabled" do
around do |example|
original_config = Spree::Config[:enable_products_cache?]
example.run
Spree::Config[:enable_products_cache?] = original_config
end
let(:control_product) { create(:taxed_product, supplier: supplier, price: 110, zone: zone, tax_rate_amount: 0.1) }
let(:control_variant) { control_product.variants.first }
let!(:order_cycle) { create(:simple_order_cycle, suppliers: [supplier], distributors: [distributor], coordinator: create(:distributor_enterprise), variants: [variant, control_variant]) }
it "does not show item after all stock of an item is checked out (tesging cache update on checkout)" do
Spree::Config[:enable_products_cache?] = true
variant.update_attributes on_hand: 5
flush_jobs
visit shop_path
fill_in "variants[#{variant.id}]", with: '5'
wait_until { !cart_dirty }
visit checkout_path
checkout_as_guest
fill_out_details
fill_out_billing_address
choose sm1.name
choose pm1.name
place_order
expect(page).to have_content "Your order has been processed successfully"
flush_jobs
visit shop_path
# The presence of the control product ensures the list of products is fully loaded
# before we verify the sold product is not present
page.should have_content control_product.name
page.should_not have_content product.name
end
end
context "on the checkout page" do
before do
visit checkout_path
@@ -216,7 +231,7 @@ feature "As a consumer I want to check out my cart", js: true do
page.should have_content distributor.name
end
it 'does not show the save as defalut address checkbox' do
it 'does not show the save as default address checkbox' do
page.should_not have_content "Save as default billing address"
page.should_not have_content "Save as default shipping address"
end
@@ -315,20 +330,8 @@ feature "As a consumer I want to check out my cart", js: true do
describe "purchasing" do
it "takes us to the order confirmation page when we submit a complete form" do
within "#details" do
fill_in "First Name", with: "Will"
fill_in "Last Name", with: "Marshall"
fill_in "Email", with: "test@test.com"
fill_in "Phone", with: "0468363090"
end
within "#billing" do
fill_in "Address", with: "123 Your Face"
select "Australia", from: "Country"
select "Victoria", from: "State"
fill_in "City", with: "Melbourne"
fill_in "Postcode", with: "3066"
end
fill_out_details
fill_out_billing_address
within "#shipping" do
choose sm2.name
@@ -365,22 +368,8 @@ feature "As a consumer I want to check out my cart", js: true do
before do
choose sm1.name
choose pm1.name
within "#details" do
fill_in "First Name", with: "Will"
fill_in "Last Name", with: "Marshall"
fill_in "Email", with: "test@test.com"
fill_in "Phone", with: "0468363090"
end
within "#billing" do
fill_in "City", with: "Melbourne"
fill_in "Postcode", with: "3066"
fill_in "Address", with: "123 Your Face"
select "Australia", from: "Country"
select "Victoria", from: "State"
end
fill_out_details
fill_out_billing_address
check "Shipping address same as billing address?"
end
@@ -475,4 +464,36 @@ feature "As a consumer I want to check out my cart", js: true do
end
end
end
def fill_out_details
within "#details" do
fill_in "First Name", with: "Will"
fill_in "Last Name", with: "Marshall"
fill_in "Email", with: "test@test.com"
fill_in "Phone", with: "0468363090"
end
end
def fill_out_billing_address
within "#billing" do
fill_in "City", with: "Melbourne"
fill_in "Postcode", with: "3066"
fill_in "Address", with: "123 Your Head"
select "Australia", from: "Country"
select "Victoria", from: "State"
end
end
def fill_out_form
choose sm1.name
choose pm1.name
fill_out_details
check "Save as default billing address"
fill_out_billing_address
check "Shipping address same as billing address?"
check "Save as default shipping address"
end
end

View File

@@ -118,8 +118,12 @@ describe SubscriptionPlacementJob do
end
describe "processing a subscription order" do
let(:subscription) { create(:subscription, with_items: true) }
let(:shop) { subscription.shop }
let!(:shipping_method_created_earlier) { create(:shipping_method, distributors: [shop]) }
let!(:shipping_method) { create(:shipping_method, distributors: [shop]) }
let!(:shipping_method_created_later) { create(:shipping_method, distributors: [shop]) }
let(:shop) { create(:enterprise) }
let(:subscription) { create(:subscription, shop: shop, with_items: true) }
let(:proxy_order) { create(:proxy_order, subscription: subscription) }
let(:oc) { proxy_order.order_cycle }
let(:ex) { oc.exchanges.outgoing.find_by_sender_id_and_receiver_id(shop.id, shop.id) }
@@ -146,6 +150,19 @@ describe SubscriptionPlacementJob do
end
context "when the order is not already complete" do
describe "selection of shipping method" do
let!(:subscription) do
create(:subscription, shop: shop, shipping_method: shipping_method, with_items: true)
end
it "uses the same shipping method after advancing the order" do
job.send(:process, order)
expect(order.state).to eq "complete"
order.reload
expect(order.shipping_method).to eq(shipping_method)
end
end
context "when no stock items are available after capping stock" do
before do
allow(job).to receive(:unavailable_stock_lines_for) { order.line_items }

View File

@@ -1,28 +0,0 @@
require 'spec_helper'
describe FeatureFlags do
let(:user) { build_stubbed(:user) }
let(:feature_flags) { described_class.new(user) }
describe '#product_import_enabled?' do
context 'when the user is superadmin' do
before do
allow(user).to receive(:superadmin?) { true }
end
it 'returns true' do
expect(feature_flags.product_import_enabled?).to eq(true)
end
end
context 'when the user is not superadmin' do
before do
allow(user).to receive(:superadmin?) { false }
end
it 'returns false' do
expect(feature_flags.product_import_enabled?).to eq(false)
end
end
end
end

View File

@@ -86,6 +86,10 @@ describe ProxyOrder, type: :model do
let(:proxy_order) { create(:proxy_order, order: order, canceled_at: Time.zone.now) }
let(:order_cycle) { proxy_order.order_cycle }
around do |example|
Timecop.freeze(Time.zone.now) { example.run }
end
context "when the order cycle is not yet closed" do
before { order_cycle.update_attributes(orders_open_at: 1.day.ago, orders_close_at: 3.days.from_now) }

View File

@@ -96,13 +96,34 @@ describe Spree::ProductSet do
end
context 'and the variant does not exist' do
let(:master_attributes) do
attributes_for(:variant).merge(sku: '123')
context 'and attributes provided are valid' do
let(:master_attributes) do
attributes_for(:variant).merge(sku: '123')
end
it 'creates it with the specified attributes' do
number_of_variants = Spree::Variant.all.size
product_set.save
expect(Spree::Variant.last.sku).to eq('123')
expect(Spree::Variant.all.size).to eq number_of_variants + 1
end
end
it 'creates it with the specified attributes' do
product_set.save
expect(Spree::Variant.last.sku).to eq('123')
context 'and attributes provided are not valid' do
let(:master_attributes) do
# unit_value nil makes the variant invalid
# on_hand with a value would make on_hand be updated and fail with exception
attributes_for(:variant).merge(unit_value: nil, on_hand: 1, sku: '321')
end
it 'does not create variant and notifies bugsnag still raising the exception' do
expect(Bugsnag).to receive(:notify)
number_of_variants = Spree::Variant.all.size
expect { product_set.save }
.to raise_error(StandardError)
expect(Spree::Variant.all.size).to eq number_of_variants
expect(Spree::Variant.last.sku).not_to eq('321')
end
end
end
end

View File

@@ -515,6 +515,28 @@ module Spree
it_behaves_like "a model using the LocalizedNumber module", [:price, :cost_price, :weight]
end
context "in a circular order cycle setup" do
let(:enterprise1) { create(:distributor_enterprise, is_primary_producer: true) }
let(:enterprise2) { create(:distributor_enterprise, is_primary_producer: true) }
let(:variant1) { create(:variant) }
let(:variant2) { create(:variant) }
let!(:order_cycle) do
enterprise1.supplied_products << variant1.product
enterprise2.supplied_products << variant2.product
create(
:simple_order_cycle,
coordinator: enterprise1,
suppliers: [enterprise1, enterprise2],
distributors: [enterprise1, enterprise2],
variants: [variant1, variant2]
)
end
it "saves without infinite loop" do
expect(variant1.update_attributes(cost_price: 1)).to be_truthy
end
end
end
describe "destruction" do