mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-16 19:16:49 +00:00
Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e876a25d59 | ||
|
|
2a780151be | ||
|
|
9d2009d2af | ||
|
|
f887533dda | ||
|
|
bef3f154d6 | ||
|
|
6fb775d5ed | ||
|
|
b5a8563725 | ||
|
|
1a9ade6de9 | ||
|
|
48df853ff5 | ||
|
|
2137a2addb | ||
|
|
e6a7239716 | ||
|
|
25bed92f2e | ||
|
|
909cd407dd | ||
|
|
f2d25748b1 | ||
|
|
6396e6e970 | ||
|
|
e52f813dae | ||
|
|
9ab2eec30c | ||
|
|
f96b37dae3 | ||
|
|
5b68b2f707 | ||
|
|
ff634bd870 | ||
|
|
5e68604f11 | ||
|
|
c4edd3a683 | ||
|
|
574781e901 | ||
|
|
8ea4f933da | ||
|
|
1e9820f291 | ||
|
|
34ed86cf2d | ||
|
|
706168f2f0 | ||
|
|
3ecb5c0c75 | ||
|
|
249a3c4e18 | ||
|
|
2b8ebba233 | ||
|
|
758394464b | ||
|
|
d3c624ae10 | ||
|
|
163c65849e | ||
|
|
99ff714913 | ||
|
|
c2f302450f | ||
|
|
9186bcd455 | ||
|
|
3d074b530f | ||
|
|
20783db373 | ||
|
|
53496ff9eb | ||
|
|
c1248857b8 | ||
|
|
e2d61f5e89 | ||
|
|
5a1ef04c67 | ||
|
|
e9e73ef0e4 | ||
|
|
001e3688da | ||
|
|
e5a9606449 | ||
|
|
1217811402 | ||
|
|
bf2c1a0c1d | ||
|
|
5d83414e9b | ||
|
|
2f5b0a5afb | ||
|
|
b3728568a8 | ||
|
|
6ba98b4b2c | ||
|
|
60bdde6349 | ||
|
|
5faf33fabe | ||
|
|
f3b1a5dd35 | ||
|
|
07ccbf7f98 | ||
|
|
ec6f6056a8 | ||
|
|
a11562e4dd | ||
|
|
986837d601 | ||
|
|
353d6fbc5f |
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
10
app/models/spree/stock_movement_decorator.rb
Normal file
10
app/models/spree/stock_movement_decorator.rb
Normal 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
|
||||
@@ -1,2 +0,0 @@
|
||||
add_to_attributes '[data-hook="admin_variant_form_fields"]'
|
||||
attributes 'ng-app' => 'admin.products'
|
||||
@@ -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']);
|
||||
});
|
||||
@@ -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
|
||||
@@ -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')
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -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')
|
||||
@@ -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'
|
||||
@@ -1,3 +0,0 @@
|
||||
/ replace "code[erb-loud]:contains('variant.options_text')"
|
||||
|
||||
= variant.full_name
|
||||
@@ -5,4 +5,11 @@
|
||||
|
||||
= render 'upload_sidebar'
|
||||
|
||||
%h5
|
||||
= t('.notice')
|
||||
%br
|
||||
%p
|
||||
= t('.beta_notice')
|
||||
%br
|
||||
|
||||
= render 'upload_form'
|
||||
|
||||
@@ -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' }
|
||||
|
||||
67
app/views/spree/admin/variants/_form.html.haml
Normal file
67
app/views/spree/admin/variants/_form.html.haml
Normal 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
|
||||
11
app/views/spree/admin/variants/edit.html.haml
Normal file
11
app/views/spree/admin/variants/edit.html.haml
Normal 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'
|
||||
54
app/views/spree/admin/variants/index.html.haml
Normal file
54
app/views/spree/admin/variants/index.html.haml
Normal 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')
|
||||
7
app/views/spree/admin/variants/new.html.haml
Normal file
7
app/views/spree/admin/variants/new.html.haml
Normal 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'
|
||||
3
app/views/spree/admin/variants/new.js.erb
Normal file
3
app/views/spree/admin/variants/new.js.erb
Normal 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();
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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
|
||||
@@ -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) }
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user