mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-19 19:46:51 +00:00
Compare commits
55 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97ef93b840 | ||
|
|
6db15a0a20 | ||
|
|
c8395a487a | ||
|
|
1e948735fb | ||
|
|
0ef4247914 | ||
|
|
6d1fb63a21 | ||
|
|
9bcd303f4f | ||
|
|
38c327dae0 | ||
|
|
51177b833e | ||
|
|
cc3368704a | ||
|
|
2d53fbbe8c | ||
|
|
3959f16d65 | ||
|
|
fb28826d92 | ||
|
|
beaa8ffa27 | ||
|
|
da6d035a1d | ||
|
|
5cb77c443b | ||
|
|
8d16f496f4 | ||
|
|
82b274e522 | ||
|
|
484cdd1e07 | ||
|
|
bb2e6324bd | ||
|
|
89056e13ed | ||
|
|
df0458743b | ||
|
|
1476859c83 | ||
|
|
c6fb7dafec | ||
|
|
80069731ed | ||
|
|
dfa3d40665 | ||
|
|
00c2b95a0e | ||
|
|
4a82a26830 | ||
|
|
f1831fc6bb | ||
|
|
4c91a5571a | ||
|
|
ccb7a305bc | ||
|
|
0c87afefce | ||
|
|
d546817f0a | ||
|
|
e0e833b2f3 | ||
|
|
7cc034c2bc | ||
|
|
15bcde36cb | ||
|
|
6e69960ee9 | ||
|
|
a7a03b04a9 | ||
|
|
5759dcee48 | ||
|
|
a9672011a5 | ||
|
|
808aa188ab | ||
|
|
ad7fc61228 | ||
|
|
3e32e5c16e | ||
|
|
f67a2120f4 | ||
|
|
a4ee562387 | ||
|
|
6df7ec9dbd | ||
|
|
0f7357166d | ||
|
|
50093c325a | ||
|
|
4288428c70 | ||
|
|
dc122a9450 | ||
|
|
ec1b5a7a92 | ||
|
|
df2306cf82 | ||
|
|
172a79acc7 | ||
|
|
6e51be095b | ||
|
|
1c7237869a |
10
.github/ISSUE_TEMPLATE/release-template.md
vendored
10
.github/ISSUE_TEMPLATE/release-template.md
vendored
@@ -1,10 +0,0 @@
|
||||
Draft: x
|
||||
|
||||
Target commit: x
|
||||
|
||||
Build: x
|
||||
|
||||
- [ ] Draft
|
||||
- [ ] Test
|
||||
- [ ] Publish
|
||||
- [ ] Deploy
|
||||
19
.github/ISSUE_TEMPLATE/release.md
vendored
Normal file
19
.github/ISSUE_TEMPLATE/release.md
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
name: Release task
|
||||
about: Track the process of a new release
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Steps:
|
||||
|
||||
- [ ] Include translations
|
||||
- [ ] Draft: https://github.com/openfoodfoundation/openfoodnetwork/releases/new <!-- replace the URL -->
|
||||
- [ ] Test: https://semaphoreci.com/openfoodfoundation/openfoodnetwork-2/branches/master <!-- replace the URL -->
|
||||
- [ ] Publish and notify #global-community
|
||||
- [ ] Deploy and notify #instance-managers
|
||||
- [ ] Nudge next release manager
|
||||
|
||||
The full process is described at https://github.com/openfoodfoundation/openfoodnetwork/wiki/Releasing.
|
||||
@@ -45,7 +45,6 @@ Metrics/LineLength:
|
||||
- app/controllers/spree/admin/base_controller_decorator.rb
|
||||
- app/controllers/spree/admin/orders_controller_decorator.rb
|
||||
- app/controllers/spree/admin/payments_controller_decorator.rb
|
||||
- app/controllers/spree/admin/reports_controller_decorator.rb
|
||||
- app/controllers/spree/credit_cards_controller.rb
|
||||
- app/controllers/spree/paypal_controller_decorator.rb
|
||||
- app/controllers/stripe/callbacks_controller.rb
|
||||
@@ -121,7 +120,6 @@ Metrics/LineLength:
|
||||
- lib/open_food_network/order_cycle_management_report.rb
|
||||
- lib/open_food_network/payments_report.rb
|
||||
- lib/open_food_network/reports/bulk_coop_allocation_report.rb
|
||||
- lib/open_food_network/reports/line_items.rb
|
||||
- lib/open_food_network/sales_tax_report.rb
|
||||
- lib/open_food_network/variant_and_line_item_naming.rb
|
||||
- lib/open_food_network/xero_invoices_report.rb
|
||||
|
||||
13
Dockerfile
13
Dockerfile
@@ -6,16 +6,19 @@ RUN apt-get update && apt-get install -y curl git build-essential software-prope
|
||||
# Setup ENV variables
|
||||
ENV PATH /usr/local/src/rbenv/shims:/usr/local/src/rbenv/bin:$PATH
|
||||
ENV RBENV_ROOT /usr/local/src/rbenv
|
||||
ENV RUBY_VERSION 2.1.9
|
||||
ENV CONFIGURE_OPTS --disable-install-doc
|
||||
ENV BUNDLE_PATH /bundles
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
COPY .ruby-version .
|
||||
|
||||
# Rbenv & Ruby part
|
||||
RUN git clone https://github.com/rbenv/rbenv.git ${RBENV_ROOT} && \
|
||||
git clone https://github.com/rbenv/ruby-build.git ${RBENV_ROOT}/plugins/ruby-build && \
|
||||
${RBENV_ROOT}/plugins/ruby-build/install.sh && \
|
||||
echo 'eval "$(rbenv init -)"' >> /etc/profile.d/rbenv.sh && \
|
||||
rbenv install $RUBY_VERSION && \
|
||||
rbenv global $RUBY_VERSION && \
|
||||
rbenv install $(cat .ruby-version) && \
|
||||
rbenv global $(cat .ruby-version) && \
|
||||
gem install bundler --version=1.17.2
|
||||
|
||||
# Postgres
|
||||
@@ -24,8 +27,4 @@ RUN sh -c "echo 'deb https://apt.postgresql.org/pub/repos/apt/ bionic-pgdg main'
|
||||
apt-get update && \
|
||||
apt-get install -yqq --no-install-recommends postgresql-client-9.5 libpq-dev
|
||||
|
||||
ENV BUNDLE_PATH /bundles
|
||||
|
||||
COPY . /usr/src/app/
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
@@ -225,7 +225,7 @@ GEM
|
||||
activerecord (>= 3.2.0, < 5.0)
|
||||
fog (~> 1.0)
|
||||
rails (>= 3.2.0, < 5.0)
|
||||
ddtrace (0.28.0)
|
||||
ddtrace (0.29.0)
|
||||
msgpack
|
||||
debugger-linecache (1.2.0)
|
||||
deface (1.0.2)
|
||||
@@ -615,7 +615,7 @@ GEM
|
||||
rspec-expectations (~> 3.9.0)
|
||||
rspec-mocks (~> 3.9.0)
|
||||
rspec-support (~> 3.9.0)
|
||||
rspec-retry (0.6.1)
|
||||
rspec-retry (0.6.2)
|
||||
rspec-core (> 3.3)
|
||||
rspec-support (3.9.0)
|
||||
rubocop (0.68.1)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
.exchange-products
|
||||
-# Scope product list based on permissions the current user has to view variants in this exchange
|
||||
.exchange-product{'ng-repeat' => 'product in supplied_products | filter:productSuppliedToOrderCycle | visibleProducts:exchange:order_cycle.visible_variants_for_outgoing_exchanges | orderBy:"name"' }
|
||||
.exchange-product{'ng-repeat' => 'product in supplied_products | filter:productSuppliedToOrderCycle | visibleProducts:exchange:order_cycle.visible_variants_for_outgoing_exchanges' }
|
||||
.exchange-product-details
|
||||
%label
|
||||
%img{'ng-src' => '{{ product.image_url }}'}
|
||||
|
||||
@@ -5,10 +5,11 @@ module Admin
|
||||
def index
|
||||
order_params = params[:q].andand.delete :order
|
||||
|
||||
orders = OpenFoodNetwork::Permissions.new(spree_current_user).
|
||||
order_permissions = ::Permissions::Order.new(spree_current_user)
|
||||
orders = order_permissions.
|
||||
editable_orders.ransack(order_params).result
|
||||
|
||||
line_items = OpenFoodNetwork::Permissions.new(spree_current_user).
|
||||
line_items = order_permissions.
|
||||
editable_line_items.where(order_id: orders).
|
||||
includes(variant: { option_values: :option_type }).
|
||||
ransack(params[:q]).result.
|
||||
|
||||
@@ -3,6 +3,10 @@ require 'open_food_network/address_finder'
|
||||
class CheckoutController < Spree::CheckoutController
|
||||
layout 'darkswarm'
|
||||
|
||||
# We need pessimistic locking to avoid race conditions.
|
||||
# Otherwise we fail on duplicate indexes or end up with negative stock.
|
||||
prepend_around_filter CurrentOrderLocker, only: :update
|
||||
|
||||
prepend_before_filter :check_hub_ready_for_checkout
|
||||
prepend_before_filter :check_order_cycle_expiry
|
||||
prepend_before_filter :require_order_cycle
|
||||
|
||||
@@ -23,7 +23,8 @@ Spree::Admin::ReportsController.class_eval do
|
||||
|
||||
before_filter :cache_search_state
|
||||
# Fetches user's distributors, suppliers and order_cycles
|
||||
before_filter :load_data, only: [:customers, :products_and_inventory, :order_cycle_management, :packing]
|
||||
before_filter :load_data,
|
||||
only: [:customers, :products_and_inventory, :order_cycle_management, :packing]
|
||||
|
||||
def report_types
|
||||
OpenFoodNetwork::Reports::List.all
|
||||
@@ -49,7 +50,9 @@ Spree::Admin::ReportsController.class_eval do
|
||||
@report_type = params[:report_type]
|
||||
|
||||
# -- Build Report with Order Grouper
|
||||
@report = OpenFoodNetwork::OrderCycleManagementReport.new spree_current_user, params, render_content?
|
||||
@report = OpenFoodNetwork::OrderCycleManagementReport.new spree_current_user,
|
||||
params,
|
||||
render_content?
|
||||
@table = @report.table_items
|
||||
|
||||
render_report(@report.header, @table, params[:csv], "order_cycle_management_#{timestamp}.csv")
|
||||
@@ -69,7 +72,9 @@ Spree::Admin::ReportsController.class_eval do
|
||||
end
|
||||
|
||||
def orders_and_distributors
|
||||
@report = OpenFoodNetwork::OrderAndDistributorReport.new spree_current_user, params, render_content?
|
||||
@report = OpenFoodNetwork::OrderAndDistributorReport.new spree_current_user,
|
||||
params,
|
||||
render_content?
|
||||
@search = @report.search
|
||||
csv_file_name = "orders_and_distributors_#{timestamp}.csv"
|
||||
render_report(@report.header, @report.table, params[:csv], csv_file_name)
|
||||
@@ -126,8 +131,9 @@ Spree::Admin::ReportsController.class_eval do
|
||||
@include_blank = I18n.t(:all)
|
||||
|
||||
# -- Build Report with Order Grouper
|
||||
@report = OpenFoodNetwork::OrdersAndFulfillmentsReport.new(permissions,
|
||||
params, render_content?)
|
||||
@report = OpenFoodNetwork::OrdersAndFulfillmentsReport.new spree_current_user,
|
||||
params,
|
||||
render_content?
|
||||
@table = order_grouper_table
|
||||
csv_file_name = "#{params[:report_type]}_#{timestamp}.csv"
|
||||
|
||||
@@ -137,16 +143,24 @@ Spree::Admin::ReportsController.class_eval do
|
||||
def products_and_inventory
|
||||
@report_types = report_types[:products_and_inventory]
|
||||
@report = if params[:report_type] != 'lettuce_share'
|
||||
OpenFoodNetwork::ProductsAndInventoryReport.new spree_current_user, params, render_content?
|
||||
OpenFoodNetwork::ProductsAndInventoryReport.new spree_current_user,
|
||||
params,
|
||||
render_content?
|
||||
else
|
||||
OpenFoodNetwork::LettuceShareReport.new spree_current_user, params, render_content?
|
||||
end
|
||||
render_report(@report.header, @report.table, params[:csv], "products_and_inventory_#{timestamp}.csv")
|
||||
render_report(@report.header,
|
||||
@report.table,
|
||||
params[:csv],
|
||||
"products_and_inventory_#{timestamp}.csv")
|
||||
end
|
||||
|
||||
def users_and_enterprises
|
||||
@report = OpenFoodNetwork::UsersAndEnterprisesReport.new params, render_content?
|
||||
render_report(@report.header, @report.table, params[:csv], "users_and_enterprises_#{timestamp}.csv")
|
||||
render_report(@report.header,
|
||||
@report.table,
|
||||
params[:csv],
|
||||
"users_and_enterprises_#{timestamp}.csv")
|
||||
end
|
||||
|
||||
def xero_invoices
|
||||
@@ -222,7 +236,8 @@ Spree::Admin::ReportsController.class_eval do
|
||||
end
|
||||
|
||||
def suppliers_of_products_distributed_by(distributors)
|
||||
distributors.map { |d| Spree::Product.in_distributor(d) }.flatten.map(&:supplier).uniq
|
||||
distributors.map { |d| Spree::Product.in_distributor(d).includes(:supplier).all }.
|
||||
flatten.map(&:supplier).uniq
|
||||
end
|
||||
|
||||
# Load order cycles the current user has access to
|
||||
|
||||
@@ -34,11 +34,11 @@ class Api::Admin::ForOrderCycle::EnterpriseSerializer < ActiveModel::Serializer
|
||||
private
|
||||
|
||||
def products_scope
|
||||
products_relation = object.supplied_products
|
||||
if order_cycle.prefers_product_selection_from_coordinator_inventory_only?
|
||||
object.supplied_products.visible_for(order_cycle.coordinator)
|
||||
else
|
||||
object.supplied_products
|
||||
products_relation = products_relation.visible_for(order_cycle.coordinator)
|
||||
end
|
||||
products_relation.order(:name)
|
||||
end
|
||||
|
||||
def products
|
||||
|
||||
40
app/services/current_order_locker.rb
Normal file
40
app/services/current_order_locker.rb
Normal file
@@ -0,0 +1,40 @@
|
||||
# Locks a controller's current order including its variants.
|
||||
#
|
||||
# It should be used when making major changes like checking out the order.
|
||||
# It can keep stock checking in sync and prevent overselling of an item.
|
||||
class CurrentOrderLocker
|
||||
# This interface follows the ActionController filters convention:
|
||||
#
|
||||
# https://guides.rubyonrails.org/action_controller_overview.html#filters
|
||||
#
|
||||
def self.around(controller)
|
||||
lock_order_and_variants(controller.current_order) { yield }
|
||||
end
|
||||
|
||||
# Locking will not prevent all access to these rows. Other processes are
|
||||
# only waiting if they try to lock one of these rows as well.
|
||||
#
|
||||
# https://api.rubyonrails.org/classes/ActiveRecord/Locking/Pessimistic.html
|
||||
#
|
||||
def self.lock_order_and_variants(order)
|
||||
return yield if order.nil?
|
||||
|
||||
order.with_lock do
|
||||
lock_variants_of(order)
|
||||
yield
|
||||
end
|
||||
end
|
||||
private_class_method :lock_order_and_variants
|
||||
|
||||
# There are many places in which stock is stored in the database. Row locking
|
||||
# on variant level ensures that there are no conflicts even when an item is
|
||||
# sold through multiple shops.
|
||||
def self.lock_variants_of(order)
|
||||
variant_ids = order.line_items.select(:variant_id)
|
||||
|
||||
# Ordering the variants by id prevents deadlocks. Plucking the ids sends
|
||||
# the locking query without building Spree::Variant objects.
|
||||
Spree::Variant.where(id: variant_ids).order(:id).lock.pluck(:id)
|
||||
end
|
||||
private_class_method :lock_variants_of
|
||||
end
|
||||
80
app/services/permissions/order.rb
Normal file
80
app/services/permissions/order.rb
Normal file
@@ -0,0 +1,80 @@
|
||||
module Permissions
|
||||
class Order
|
||||
def initialize(user)
|
||||
@user = user
|
||||
@permissions = OpenFoodNetwork::Permissions.new(@user)
|
||||
end
|
||||
|
||||
# Find orders that the user can see
|
||||
def visible_orders
|
||||
Spree::Order.where(id:
|
||||
managed_orders.select(:id) |
|
||||
coordinated_orders.select(:id) |
|
||||
produced_orders.select("spree_orders.id"))
|
||||
end
|
||||
|
||||
# Any orders that the user can edit
|
||||
def editable_orders
|
||||
Spree::Order.where(id:
|
||||
managed_orders.select(:id) |
|
||||
coordinated_orders.select(:id) )
|
||||
end
|
||||
|
||||
def visible_line_items
|
||||
Spree::LineItem.where(id:
|
||||
editable_line_items.select(:id) |
|
||||
produced_line_items.select("spree_line_items.id"))
|
||||
end
|
||||
|
||||
# Any line items that I can edit
|
||||
def editable_line_items
|
||||
Spree::LineItem.where(order_id: editable_orders)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Any orders placed through any hub that I manage
|
||||
def managed_orders
|
||||
Spree::Order.where(distributor_id: @permissions.managed_enterprises.select("enterprises.id"))
|
||||
end
|
||||
|
||||
# Any order that is placed through an order cycle one of my managed enterprises coordinates
|
||||
def coordinated_orders
|
||||
Spree::Order.where(order_cycle_id: @permissions.coordinated_order_cycles.select(:id))
|
||||
end
|
||||
|
||||
def produced_orders
|
||||
Spree::Order.with_line_items_variants_and_products_outer.
|
||||
where(
|
||||
distributor_id: granted_distributor_ids,
|
||||
spree_products: { supplier_id: enterprises_with_associated_orders }
|
||||
)
|
||||
end
|
||||
|
||||
def enterprises_with_associated_orders
|
||||
# Any orders placed through hubs that my producers have granted P-OC,
|
||||
# and which contain their products. This is pretty complicated but it's looking for order
|
||||
# where at least one of my producers has granted P-OC to the distributor
|
||||
# AND the order contains products of at least one of THE SAME producers
|
||||
@permissions.related_enterprises_granting(:add_to_order_cycle, to: granted_distributor_ids).
|
||||
merge(@permissions.managed_enterprises.is_primary_producer)
|
||||
end
|
||||
|
||||
def granted_distributor_ids
|
||||
@granted_distributor_ids ||= @permissions.related_enterprises_granted(
|
||||
:add_to_order_cycle,
|
||||
by: @permissions.managed_enterprises.is_primary_producer.select("enterprises.id")
|
||||
).select("enterprises.id")
|
||||
end
|
||||
|
||||
# Any from visible orders, where the product is produced by one of my managed producers
|
||||
def produced_line_items
|
||||
Spree::LineItem.where(order_id: visible_orders.select(:id)).
|
||||
joins(:product).
|
||||
where(spree_products:
|
||||
{
|
||||
supplier_id: @permissions.managed_enterprises.is_primary_producer.select("enterprises.id")
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -24,7 +24,7 @@ class SearchOrders
|
||||
attr_reader :params, :current_user
|
||||
|
||||
def fetch_orders
|
||||
@search = OpenFoodNetwork::Permissions.new(current_user).editable_orders.ransack(params[:q])
|
||||
@search = ::Permissions::Order.new(current_user).editable_orders.ransack(params[:q])
|
||||
|
||||
return paginated_results if using_pagination?
|
||||
|
||||
|
||||
@@ -262,6 +262,7 @@ ar:
|
||||
cancel: "إلغاء"
|
||||
save: "حفظ"
|
||||
edit: "تعديل"
|
||||
update: "تحديث"
|
||||
delete: "حذف"
|
||||
admin:
|
||||
begins_at: يبدأ عند
|
||||
@@ -2872,6 +2873,37 @@ ar:
|
||||
form:
|
||||
name: "الاسم"
|
||||
presentation: "عرض"
|
||||
return_authorizations:
|
||||
index:
|
||||
new_return_authorization: "عودة الترخيص جديد"
|
||||
return_authorizations: "عودة التراخيص"
|
||||
back_to_orders_list: "العودة إلى قائمة الطلبات"
|
||||
rma_number: "رقم RMA"
|
||||
status: "الحالة"
|
||||
amount: "القيمة"
|
||||
cannot_create_returns: "لا يمكن إنشاء عوائد لأن هذا الطلب لا يحتوي على وحدات مشحونة."
|
||||
continue: "تابع"
|
||||
new:
|
||||
new_return_authorization: "عودة الترخيص جديد"
|
||||
back_to_return_authorizations_list: "العودة إلى قائمة عودة الترخيص"
|
||||
continue: "تابع"
|
||||
edit:
|
||||
receive: "استلام"
|
||||
are_you_sure: "هل أنت واثق؟"
|
||||
return_authorization: "عودة التراخيص"
|
||||
form:
|
||||
product: "المنتج"
|
||||
quantity_shipped: "الكمية التي تم شحنها"
|
||||
quantity_returned: "الكمية المرتجعة"
|
||||
return_quantity: "عودة الكمية"
|
||||
amount: "القيمة"
|
||||
rma_value: "قيمة RMA"
|
||||
reason: "السبب"
|
||||
stock_location: "موقع المخزن"
|
||||
states:
|
||||
authorized: "مخول"
|
||||
received: "تم الاستلام"
|
||||
canceled: "ألغيت"
|
||||
orders:
|
||||
index:
|
||||
listing_orders: "لائحة الطلبات"
|
||||
|
||||
@@ -262,6 +262,7 @@ ca:
|
||||
cancel: "Cancel·lar"
|
||||
save: "Desa"
|
||||
edit: "Editar"
|
||||
update: "Actualitzar"
|
||||
delete: "Suprimir"
|
||||
admin:
|
||||
begins_at: Comença a
|
||||
@@ -832,10 +833,24 @@ ca:
|
||||
loading_flash:
|
||||
loading_order_cycles: CÀRREGUES CICLES DE COMANDA
|
||||
loading: CARREGANT...
|
||||
new:
|
||||
create: "Crear"
|
||||
cancel: "Cancel·lar"
|
||||
edit:
|
||||
advanced_settings: Configuració avançada
|
||||
update_and_close: Actualitza i tanca
|
||||
choose_products_from: 'Trieu Productes des de:'
|
||||
advanced_settings: "Configuració avançada"
|
||||
save: "Desa"
|
||||
next: "Següent"
|
||||
cancel: "Cancel·lar"
|
||||
choose_products_from: "Trieu Productes des de:"
|
||||
incoming:
|
||||
previous: "Anterior"
|
||||
save: "Desa"
|
||||
next: "Següent"
|
||||
cancel: "Cancel·lar"
|
||||
outgoing:
|
||||
previous: "Anterior"
|
||||
save: "Desa"
|
||||
cancel: "Cancel·lar"
|
||||
exchange_form:
|
||||
pickup_time_tip: Quan les comandes d'aquest cicle de comandes estiguin preparades per a les consumidores
|
||||
pickup_instructions_placeholder: "Instruccions de recollida"
|
||||
@@ -862,6 +877,7 @@ ca:
|
||||
any_enterprise: "Qualsevol organització"
|
||||
any_schedule: "Qualsevol programació"
|
||||
form:
|
||||
general_settings: "Configuració general"
|
||||
incoming: Entrant
|
||||
supplier: Proveïdora
|
||||
receival_details: Detalls de recepció
|
||||
@@ -2824,6 +2840,27 @@ ca:
|
||||
product_properties:
|
||||
index:
|
||||
inherits_properties_checkbox_hint: "heredar propietats de %{supplier}? (llevat que es sobreescrigui a dalt)"
|
||||
properties:
|
||||
index:
|
||||
properties: "Propietats"
|
||||
name: "Nom"
|
||||
form:
|
||||
name: "Nom"
|
||||
return_authorizations:
|
||||
index:
|
||||
return_authorizations: "Autoritzacions de devolució"
|
||||
back_to_orders_list: "Tornar a la llista de comandes"
|
||||
status: "Estat"
|
||||
amount: "Quantitat"
|
||||
cannot_create_returns: "No es poden crear devolucions ja que aquesta comanda no té cap unitat enviada."
|
||||
continue: "Continua"
|
||||
new:
|
||||
continue: "Continua"
|
||||
edit:
|
||||
are_you_sure: "Estàs segur?"
|
||||
form:
|
||||
product: "Producte"
|
||||
amount: "Quantitat"
|
||||
orders:
|
||||
index:
|
||||
listing_orders: "Llistat comandes"
|
||||
|
||||
@@ -113,6 +113,10 @@ de_DE:
|
||||
subject: "%{enterprise} ist jetzt auf %{sitename}"
|
||||
email_welcome: "Willkommen"
|
||||
email_registered: "ist jetzt Teil von"
|
||||
email_userguide_html: "Das Benutzerhandbuch mit detaillierter Unterstützung für die Einrichtung Ihres Produzenten oder Hubs finden Sie hier: %{link}"
|
||||
userguide: "Öffnen Sie das Food Network-Benutzerhandbuch"
|
||||
email_admin_html: "Sie können Ihr Konto verwalten, indem Sie sich bei %{link} anmelden oder auf das Zahnrad oben rechts auf der Startseite klicken und Administration auswählen."
|
||||
admin_panel: "Administrationsmenü"
|
||||
email_community_html: "Wir haben auch ein Online-Forum für Community-Diskussionen in Bezug auf OFN-Software und die einzigartigen Herausforderungen eines Lebensmittelunternehmens. Reden Sie doch mit. Wir entwickeln uns ständig weiter und Ihr Beitrag in diesem Forum prägt, was als nächstes passiert. %{link}"
|
||||
join_community: "Treten Sie der Community bei"
|
||||
invite_manager:
|
||||
@@ -258,6 +262,7 @@ de_DE:
|
||||
cancel: "Abbrechen"
|
||||
save: "Speichern"
|
||||
edit: "Bearbeiten"
|
||||
update: "Aktualisieren"
|
||||
delete: "Löschen"
|
||||
admin:
|
||||
begins_at: Beginnt um
|
||||
@@ -429,9 +434,12 @@ de_DE:
|
||||
infinity: "Unendlichkeit"
|
||||
to_order_tip: "Artikel, die auf Bestellung hergestellt werden, haben keinen festgelegten Lagerbestand."
|
||||
back_to_products_list: "Zurück zur Produktliste"
|
||||
editing_product: "Produkt bearbeiten"
|
||||
tabs:
|
||||
product_details: "Produktdetails"
|
||||
group_buy_options: "Gruppenkaufoptionen"
|
||||
images: "Bilder"
|
||||
variants: "Varianten"
|
||||
product_properties: "Produkteigenschaften"
|
||||
product_import:
|
||||
title: Produkte importieren
|
||||
@@ -534,6 +542,7 @@ de_DE:
|
||||
title: Katalog
|
||||
description: Verwenden Sie diese Seite, um Bestände für Ihre Unternehmen zu verwalten. Alle hier eingestellten Produktdetails überschreiben diejenigen, die auf der Seite "Produkte" eingestellt sind
|
||||
enable_reset?: Lagerbestand zurücksetzbar?
|
||||
default_stock: "Standardbestand"
|
||||
inherit?: Übernehmen?
|
||||
add: Hinzufügen
|
||||
hide: Verbergen
|
||||
@@ -827,10 +836,36 @@ de_DE:
|
||||
loading_flash:
|
||||
loading_order_cycles: LADEN VON AUFTRAGSZYKLEN
|
||||
loading: WIRD GELADEN...
|
||||
new:
|
||||
create: "Neu"
|
||||
cancel: "Abbrechen"
|
||||
back_to_list: "Zurück zur Liste"
|
||||
edit:
|
||||
advanced_settings: Erweiterte Einstellungen
|
||||
update_and_close: Aktualisieren und schließen
|
||||
choose_products_from: 'Wählen Sie Produkte von:'
|
||||
advanced_settings: "Erweiterte Einstellungen"
|
||||
save: "Speichern"
|
||||
save_and_next: "Speichern und weiter"
|
||||
next: "Weiter"
|
||||
cancel: "Abbrechen"
|
||||
back_to_list: "Zurück zur Liste"
|
||||
save_and_back_to_list: "Speichern und zurück zur Liste"
|
||||
choose_products_from: "Wählen Sie Produkte von:"
|
||||
incoming:
|
||||
previous: "Bisherige"
|
||||
save: "Speichern"
|
||||
save_and_next: "Speichern und weiter"
|
||||
next: "Weiter"
|
||||
cancel: "Abbrechen"
|
||||
back_to_list: "Zurück zur Liste"
|
||||
outgoing:
|
||||
previous: "Bisherige"
|
||||
save: "Speichern"
|
||||
save_and_back_to_list: "Speichern und zurück zur Liste"
|
||||
cancel: "Abbrechen"
|
||||
back_to_list: "Zurück zur Liste"
|
||||
wizard_progress:
|
||||
edit: "1. Allgemeine Einstellungen"
|
||||
incoming: "2. Eingehende Produkte"
|
||||
outgoing: "3. Ausgehende Produkte"
|
||||
exchange_form:
|
||||
pickup_time_tip: Wenn Bestellungen von diesem OC für den Kunden bereit sind
|
||||
pickup_instructions_placeholder: "Abholungsinformationen"
|
||||
@@ -857,6 +892,7 @@ de_DE:
|
||||
any_enterprise: "Alle Unternehmen"
|
||||
any_schedule: "Alle Zeitpläne"
|
||||
form:
|
||||
general_settings: "Allgemeine Einstellungen"
|
||||
incoming: Eingehend
|
||||
supplier: Anbieter
|
||||
receival_details: Lieferinformation
|
||||
@@ -2777,6 +2813,12 @@ de_DE:
|
||||
minimal_amount: "Minimale Menge"
|
||||
normal_amount: "Normaler Betrag"
|
||||
discount_amount: "Rabattbetrag"
|
||||
no_images_found: "Keine Bilder gefunden"
|
||||
new_image: "Neues Bild"
|
||||
filename: "Dateiname"
|
||||
alt_text: "alternativer Text"
|
||||
thumbnail: "Miniaturansicht"
|
||||
back_to_images_list: "Zurück zur Bilderliste"
|
||||
email: Email
|
||||
account_updated: "Konto aktualisiert!"
|
||||
email_updated: "Das Konto wird aktualisiert, sobald die neue E-Mail bestätigt wurde."
|
||||
@@ -2788,6 +2830,7 @@ de_DE:
|
||||
zipcode: Postleitzahl
|
||||
weight: Gewicht (pro kg)
|
||||
error_user_destroy_with_orders: "Benutzer mit abgeschlossenen Bestellungen dürfen nicht gelöscht werden"
|
||||
options: "Optionen"
|
||||
actions:
|
||||
update: "Aktualisieren"
|
||||
errors:
|
||||
@@ -2819,6 +2862,53 @@ de_DE:
|
||||
product_properties:
|
||||
index:
|
||||
inherits_properties_checkbox_hint: "Vererben Eigenschaften von %{supplier}? (außer oben aufgehoben)"
|
||||
add_product_properties: "Produkteigenschaften hinzufügen"
|
||||
select_from_prototype: "Wählen Sie Aus Prototyp"
|
||||
properties:
|
||||
index:
|
||||
properties: "Eigenschaften"
|
||||
new_property: "Neues Eigentum"
|
||||
name: "Name"
|
||||
presentation: "Präsentation"
|
||||
new:
|
||||
new_property: "Neues Eigentum"
|
||||
edit:
|
||||
editing_property: "Eigenschaft bearbeiten"
|
||||
back_to_properties_list: "Zurück zur Eigenschaftenliste"
|
||||
form:
|
||||
name: "Name"
|
||||
presentation: "Präsentation"
|
||||
return_authorizations:
|
||||
index:
|
||||
new_return_authorization: "Neue Rücksendegenehmigung"
|
||||
return_authorizations: "Rückgabeberechtigungen"
|
||||
back_to_orders_list: "Zurück zur Bestellliste"
|
||||
rma_number: "RMA-Nummer"
|
||||
status: "Status"
|
||||
amount: "Betrag"
|
||||
cannot_create_returns: "Retouren können nicht erstellt werden, da für diese Bestellung keine Versandeinheiten vorhanden sind."
|
||||
continue: "Fortsetzen"
|
||||
new:
|
||||
new_return_authorization: "Neue Rücksendegenehmigung"
|
||||
back_to_return_authorizations_list: "Zurück zur Autorisierungsliste"
|
||||
continue: "Fortsetzen"
|
||||
edit:
|
||||
receive: "erhalten"
|
||||
are_you_sure: "Bist du sicher?"
|
||||
return_authorization: "Rücksendegenehmigung"
|
||||
form:
|
||||
product: "Produkt"
|
||||
quantity_shipped: "Menge ausgeliefert"
|
||||
quantity_returned: "Menge zurückgegeben"
|
||||
return_quantity: "Rückgabemenge"
|
||||
amount: "Betrag"
|
||||
rma_value: "RMA-Wert"
|
||||
reason: "Grund"
|
||||
stock_location: "Lagerort"
|
||||
states:
|
||||
authorized: "Autorisiert"
|
||||
received: "Empfangen"
|
||||
canceled: "Abgesagt"
|
||||
orders:
|
||||
index:
|
||||
listing_orders: "Bestellungen auflisten"
|
||||
@@ -3009,10 +3099,23 @@ de_DE:
|
||||
index:
|
||||
sku: "Artikelnummer"
|
||||
price: "Preis"
|
||||
options: "Optionen"
|
||||
no_results: "Keine Ergebnisse"
|
||||
to_add_variants_you_must_first_define: "Um Varianten hinzuzufügen, müssen Sie zuerst definieren"
|
||||
option_types: "Optionstypen"
|
||||
option_values: "Optionswerte"
|
||||
and: "und"
|
||||
new_variant: "Neue Variante"
|
||||
show_active: "Aktiv anzeigen"
|
||||
show_deleted: "Show gelöscht"
|
||||
new:
|
||||
new_variant: "Neue Variante"
|
||||
form:
|
||||
cost_price: "Selbstkostenpreis"
|
||||
sku: "Artikelnummer"
|
||||
price: "Preis"
|
||||
display_as: "Angezeigt als"
|
||||
display_name: "Anzeigename"
|
||||
autocomplete:
|
||||
producer_name: "Produzent"
|
||||
unit: "Einheit"
|
||||
@@ -3152,3 +3255,19 @@ de_DE:
|
||||
allow_charges?: "Gebühren erlauben?"
|
||||
localized_number:
|
||||
invalid_format: hat ein ungültiges Format. Bitte Ziffern eingeben.
|
||||
api:
|
||||
invalid_api_key: "Ungültiger API-Schlüssel (%{key}) angegeben."
|
||||
unauthorized: "Sie sind nicht berechtigt, diese Aktion auszuführen."
|
||||
invalid_resource: "Ungültige Ressource. Bitte beheben Sie die Fehler und versuchen Sie es erneut."
|
||||
resource_not_found: "Die gesuchte Ressource wurde nicht gefunden."
|
||||
access: "API-Zugriff"
|
||||
key: "Schlüssel"
|
||||
clear_key: "Schlüssel löschen"
|
||||
regenerate_key: "Schlüssel neu generieren"
|
||||
no_key: "Kein Schlüssel"
|
||||
generate_key: "API-Schlüssel generieren"
|
||||
key_generated: "Schlüssel generiert"
|
||||
key_cleared: "Schlüssel gelöscht"
|
||||
shipment:
|
||||
cannot_ready: "Versand nicht möglich."
|
||||
invalid_taxonomy_id: "Ungültige Taxonomie-ID"
|
||||
|
||||
@@ -114,7 +114,9 @@ en_AU:
|
||||
email_welcome: "Welcome"
|
||||
email_registered: "is now part of"
|
||||
email_userguide_html: "The User Guide with detailed support for setting up your Producer or Hub is here: %{link}"
|
||||
userguide: "Open Food Network User Guide"
|
||||
email_admin_html: "You can manage your account by logging into the %{link} or by clicking on the cog in the top right hand side of the homepage, and selecting Administration."
|
||||
admin_panel: "Admin Panel"
|
||||
email_community_html: "We also have an online forum for community discussion related to OFN software and the unique challenges of running a food enterprise. You are encouraged to join in. We are constantly evolving and your input into this forum will shape what happens next. %{link}"
|
||||
join_community: "Join the community"
|
||||
invite_manager:
|
||||
@@ -251,6 +253,7 @@ en_AU:
|
||||
expired: has expired, please request a new one
|
||||
back_to_payments_list: "Back to Payments List"
|
||||
maestro_or_solo_cards: "Maestro/Solo cards"
|
||||
backordered: "Backordered"
|
||||
on hand: "On Hand"
|
||||
ship: "Ship"
|
||||
actions:
|
||||
@@ -259,6 +262,7 @@ en_AU:
|
||||
cancel: "Cancel"
|
||||
save: "Save"
|
||||
edit: "Edit"
|
||||
update: "Update"
|
||||
delete: "Delete"
|
||||
admin:
|
||||
begins_at: Begins At
|
||||
@@ -430,9 +434,12 @@ en_AU:
|
||||
infinity: "Infinity"
|
||||
to_order_tip: "Items made to order do not have a set stock level, such as loaves of bread made fresh to order."
|
||||
back_to_products_list: "Back to products list"
|
||||
editing_product: "Editing Product"
|
||||
tabs:
|
||||
product_details: "Product Details"
|
||||
group_buy_options: "Group Buy Options"
|
||||
images: "Images"
|
||||
variants: "Variants"
|
||||
product_properties: "Product Properties"
|
||||
product_import:
|
||||
title: Product Import
|
||||
@@ -535,6 +542,7 @@ en_AU:
|
||||
title: Inventory
|
||||
description: Use this page to manage inventories for your enterprises. Any product details set here will override those set on the 'Products' page
|
||||
enable_reset?: Enable Stock Reset?
|
||||
default_stock: "Default stock"
|
||||
inherit?: Inherit?
|
||||
add: Add
|
||||
hide: Hide
|
||||
@@ -826,10 +834,36 @@ en_AU:
|
||||
loading_flash:
|
||||
loading_order_cycles: LOADING ORDER CYCLES
|
||||
loading: LOADING...
|
||||
new:
|
||||
create: "Create"
|
||||
cancel: "Cancel"
|
||||
back_to_list: "Back To List"
|
||||
edit:
|
||||
advanced_settings: Advanced Settings
|
||||
update_and_close: Update and Close
|
||||
choose_products_from: 'Choose Products From:'
|
||||
advanced_settings: "Advanced Settings"
|
||||
save: "Save"
|
||||
save_and_next: "Save and Next"
|
||||
next: "Next"
|
||||
cancel: "Cancel"
|
||||
back_to_list: "Back To List"
|
||||
save_and_back_to_list: "Save and Back to List"
|
||||
choose_products_from: "Choose Products From:"
|
||||
incoming:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
save_and_next: "Save and Next"
|
||||
next: "Next"
|
||||
cancel: "Cancel"
|
||||
back_to_list: "Back To List"
|
||||
outgoing:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
save_and_back_to_list: "Save and Back to List"
|
||||
cancel: "Cancel"
|
||||
back_to_list: "Back To List"
|
||||
wizard_progress:
|
||||
edit: "1. General Settings"
|
||||
incoming: "2. Incoming Products"
|
||||
outgoing: "3. Outgoing Products"
|
||||
exchange_form:
|
||||
pickup_time_tip: When orders from this OC will be ready for the customer
|
||||
pickup_instructions_placeholder: "Pick-up instructions"
|
||||
@@ -856,6 +890,7 @@ en_AU:
|
||||
any_enterprise: "Any Enterprise"
|
||||
any_schedule: "Any Schedule"
|
||||
form:
|
||||
general_settings: "General Settings"
|
||||
incoming: Incoming
|
||||
supplier: Supplier
|
||||
receival_details: Receival details
|
||||
@@ -2623,6 +2658,8 @@ en_AU:
|
||||
name_or_sku: "Name or SKU (enter at least first 4 characters of product name)"
|
||||
resend: Resend
|
||||
back_to_orders_list: Back To Orders List
|
||||
return_authorizations: Return Authorizations
|
||||
cannot_create_returns: Cannot create returns as this order has no shipped units.
|
||||
select_stock: "Select stock"
|
||||
location: "Location"
|
||||
count_on_hand: "Count On Hand"
|
||||
@@ -2771,8 +2808,15 @@ en_AU:
|
||||
minimal_amount: "Minimal Amount"
|
||||
normal_amount: "Normal Amount"
|
||||
discount_amount: "Discount Amount"
|
||||
no_images_found: "No Images Found"
|
||||
new_image: "New Image"
|
||||
filename: "Filename"
|
||||
alt_text: "Alternative Text"
|
||||
thumbnail: "Thumbnail"
|
||||
back_to_images_list: "Back To Images List"
|
||||
email: Email
|
||||
account_updated: "Account updated!"
|
||||
email_updated: "The account will be updated once the new email is confirmed."
|
||||
my_account: "My account"
|
||||
date: "Date"
|
||||
time: "Time"
|
||||
@@ -2781,6 +2825,7 @@ en_AU:
|
||||
zipcode: Postcode
|
||||
weight: Weight (per kg)
|
||||
error_user_destroy_with_orders: "Users with completed orders may not be deleted"
|
||||
options: "Options"
|
||||
actions:
|
||||
update: "Update"
|
||||
errors:
|
||||
@@ -2812,6 +2857,53 @@ en_AU:
|
||||
product_properties:
|
||||
index:
|
||||
inherits_properties_checkbox_hint: "Inherit properties from %{supplier}? (unless overridden above)"
|
||||
add_product_properties: "Add Product Properties"
|
||||
select_from_prototype: "Select From Prototype"
|
||||
properties:
|
||||
index:
|
||||
properties: "Properties"
|
||||
new_property: "New Property"
|
||||
name: "Name"
|
||||
presentation: "Presentation"
|
||||
new:
|
||||
new_property: "New Property"
|
||||
edit:
|
||||
editing_property: "Editing Property"
|
||||
back_to_properties_list: "Back To Properties List"
|
||||
form:
|
||||
name: "Name"
|
||||
presentation: "Presentation"
|
||||
return_authorizations:
|
||||
index:
|
||||
new_return_authorization: "New Return Authorization"
|
||||
return_authorizations: "Return Authorizations"
|
||||
back_to_orders_list: "Back To Orders List"
|
||||
rma_number: "RMA Number"
|
||||
status: "Status"
|
||||
amount: "Amount"
|
||||
cannot_create_returns: "Cannot create returns as this order has no shipped units."
|
||||
continue: "Continue"
|
||||
new:
|
||||
new_return_authorization: "New Return Authorization"
|
||||
back_to_return_authorizations_list: "Back To Return Authorization List"
|
||||
continue: "Continue"
|
||||
edit:
|
||||
receive: "receive"
|
||||
are_you_sure: "Are you sure?"
|
||||
return_authorization: "Return Authorization"
|
||||
form:
|
||||
product: "Product"
|
||||
quantity_shipped: "Quantity Shipped"
|
||||
quantity_returned: "Quantity Returned"
|
||||
return_quantity: "Return Quantity"
|
||||
amount: "Amount"
|
||||
rma_value: "RMA Value"
|
||||
reason: "Reason"
|
||||
stock_location: "Stock Location"
|
||||
states:
|
||||
authorized: "Authorized"
|
||||
received: "Received"
|
||||
canceled: "Canceled"
|
||||
orders:
|
||||
index:
|
||||
listing_orders: "Listing Orders"
|
||||
@@ -3002,12 +3094,23 @@ en_AU:
|
||||
index:
|
||||
sku: "SKU"
|
||||
price: "Price"
|
||||
options: "Options"
|
||||
no_results: "No results"
|
||||
to_add_variants_you_must_first_define: "To add variants, you must first define"
|
||||
option_types: "Option Types"
|
||||
option_values: "Option Values"
|
||||
and: "and"
|
||||
new_variant: "New Variant"
|
||||
show_active: "Show Active"
|
||||
show_deleted: "Show Deleted"
|
||||
new:
|
||||
new_variant: "New Variant"
|
||||
form:
|
||||
cost_price: "Cost Price"
|
||||
sku: "SKU"
|
||||
price: "Price"
|
||||
display_as: "Display As"
|
||||
display_name: "Display Name"
|
||||
autocomplete:
|
||||
producer_name: "Producer"
|
||||
unit: "Unit"
|
||||
@@ -3147,3 +3250,19 @@ en_AU:
|
||||
allow_charges?: "Allow Charges?"
|
||||
localized_number:
|
||||
invalid_format: has an invalid format. Please enter a number.
|
||||
api:
|
||||
invalid_api_key: "Invalid API key (%{key}) specified."
|
||||
unauthorized: "You are not authorized to perform that action."
|
||||
invalid_resource: "Invalid resource. Please fix errors and try again."
|
||||
resource_not_found: "The resource you were looking for could not be found."
|
||||
access: "API Access"
|
||||
key: "Key"
|
||||
clear_key: "Clear key"
|
||||
regenerate_key: "Regenerate Key"
|
||||
no_key: "No key"
|
||||
generate_key: "Generate API key"
|
||||
key_generated: "Key generated"
|
||||
key_cleared: "Key cleared"
|
||||
shipment:
|
||||
cannot_ready: "Cannot ready shipment."
|
||||
invalid_taxonomy_id: "Invalid taxonomy id."
|
||||
|
||||
@@ -257,6 +257,7 @@ en_BE:
|
||||
cancel: "Cancel"
|
||||
save: "Save"
|
||||
edit: "Edit"
|
||||
update: "Update"
|
||||
delete: "Delete"
|
||||
admin:
|
||||
begins_at: Begins At
|
||||
@@ -822,10 +823,24 @@ en_BE:
|
||||
loading_flash:
|
||||
loading_order_cycles: LOADING ORDER CYCLES
|
||||
loading: LOADING...
|
||||
new:
|
||||
create: "Create"
|
||||
cancel: "Cancel"
|
||||
edit:
|
||||
advanced_settings: Advanced Settings
|
||||
update_and_close: Update and Close
|
||||
choose_products_from: 'Choose Products From:'
|
||||
advanced_settings: "Advanced Settings"
|
||||
save: "Save"
|
||||
next: "Next"
|
||||
cancel: "Cancel"
|
||||
choose_products_from: "Choose Products From:"
|
||||
incoming:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
next: "Next"
|
||||
cancel: "Cancel"
|
||||
outgoing:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
cancel: "Cancel"
|
||||
exchange_form:
|
||||
pickup_time_tip: When orders from this OC will be ready for the customer
|
||||
pickup_instructions_placeholder: "Pick-up instructions"
|
||||
@@ -852,6 +867,7 @@ en_BE:
|
||||
any_enterprise: "Any Enterprise"
|
||||
any_schedule: "Any Schedule"
|
||||
form:
|
||||
general_settings: "General Settings"
|
||||
incoming: Incoming
|
||||
supplier: Supplier
|
||||
receival_details: Receival details
|
||||
@@ -2805,6 +2821,25 @@ en_BE:
|
||||
product_properties:
|
||||
index:
|
||||
inherits_properties_checkbox_hint: "Inherit properties from %{supplier}? (unless overridden above)"
|
||||
properties:
|
||||
index:
|
||||
properties: "Properties"
|
||||
name: "Name"
|
||||
form:
|
||||
name: "Name"
|
||||
return_authorizations:
|
||||
index:
|
||||
back_to_orders_list: "Back To Orders List"
|
||||
status: "Status"
|
||||
amount: "Amount"
|
||||
continue: "Continue"
|
||||
new:
|
||||
continue: "Continue"
|
||||
edit:
|
||||
are_you_sure: "Are you sure?"
|
||||
form:
|
||||
product: "Product"
|
||||
amount: "Amount"
|
||||
orders:
|
||||
index:
|
||||
listing_orders: "Listing Orders"
|
||||
|
||||
@@ -262,6 +262,7 @@ en_CA:
|
||||
cancel: "Cancel"
|
||||
save: "Save"
|
||||
edit: "Edit"
|
||||
update: "Update"
|
||||
delete: "Delete"
|
||||
admin:
|
||||
begins_at: Begins At
|
||||
@@ -2872,6 +2873,21 @@ en_CA:
|
||||
form:
|
||||
name: "Name"
|
||||
presentation: "Presentation"
|
||||
return_authorizations:
|
||||
index:
|
||||
return_authorizations: "Return Authoriations"
|
||||
back_to_orders_list: "Back to Orders List"
|
||||
status: "Status"
|
||||
amount: "Amount"
|
||||
cannot_create_returns: "Cannot create returns as this order has no shipped units"
|
||||
continue: "Continue"
|
||||
new:
|
||||
continue: "Continue"
|
||||
edit:
|
||||
are_you_sure: "Are you sure?"
|
||||
form:
|
||||
product: "Product"
|
||||
amount: "Amount"
|
||||
orders:
|
||||
index:
|
||||
listing_orders: "Listing Orders"
|
||||
|
||||
@@ -262,6 +262,7 @@ en_DE:
|
||||
cancel: "Cancel"
|
||||
save: "Save"
|
||||
edit: "Edit"
|
||||
update: "Update"
|
||||
delete: "Delete"
|
||||
admin:
|
||||
begins_at: Begins At
|
||||
@@ -830,10 +831,24 @@ en_DE:
|
||||
loading_flash:
|
||||
loading_order_cycles: LOADING ORDER CYCLES
|
||||
loading: LOADING...
|
||||
new:
|
||||
create: "Create"
|
||||
cancel: "Cancel"
|
||||
edit:
|
||||
advanced_settings: Advanced Settings
|
||||
update_and_close: Update and Close
|
||||
choose_products_from: 'Choose Products From:'
|
||||
advanced_settings: "Advanced Settings"
|
||||
save: "Save"
|
||||
next: "Next"
|
||||
cancel: "Cancel"
|
||||
choose_products_from: "Choose Products From:"
|
||||
incoming:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
next: "Next"
|
||||
cancel: "Cancel"
|
||||
outgoing:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
cancel: "Cancel"
|
||||
exchange_form:
|
||||
pickup_time_tip: When orders from this OC will be ready for the customer
|
||||
pickup_instructions_placeholder: "Pick-up instructions"
|
||||
@@ -860,6 +875,7 @@ en_DE:
|
||||
any_enterprise: "Any Enterprise"
|
||||
any_schedule: "Any Schedule"
|
||||
form:
|
||||
general_settings: "General Settings"
|
||||
incoming: Incoming
|
||||
supplier: Supplier
|
||||
receival_details: Receival details
|
||||
@@ -2819,6 +2835,27 @@ en_DE:
|
||||
product_properties:
|
||||
index:
|
||||
inherits_properties_checkbox_hint: "Inherit properties from %{supplier}? (unless overridden above)"
|
||||
properties:
|
||||
index:
|
||||
properties: "Properties"
|
||||
name: "Name"
|
||||
form:
|
||||
name: "Name"
|
||||
return_authorizations:
|
||||
index:
|
||||
return_authorizations: "Return Authorizations"
|
||||
back_to_orders_list: "Back To Orders List"
|
||||
status: "Status"
|
||||
amount: "Amount"
|
||||
cannot_create_returns: "Cannot create returns as this order has no shipped units."
|
||||
continue: "Continue"
|
||||
new:
|
||||
continue: "Continue"
|
||||
edit:
|
||||
are_you_sure: "Are you sure?"
|
||||
form:
|
||||
product: "Product"
|
||||
amount: "Amount"
|
||||
orders:
|
||||
index:
|
||||
listing_orders: "Listing Orders"
|
||||
|
||||
@@ -262,6 +262,7 @@ en_GB:
|
||||
cancel: "Cancel"
|
||||
save: "Save"
|
||||
edit: "Edit"
|
||||
update: "Update"
|
||||
delete: "Delete"
|
||||
admin:
|
||||
begins_at: Begins At
|
||||
@@ -833,10 +834,36 @@ en_GB:
|
||||
loading_flash:
|
||||
loading_order_cycles: LOADING ORDER CYCLES
|
||||
loading: LOADING...
|
||||
new:
|
||||
create: "Create"
|
||||
cancel: "Cancel"
|
||||
back_to_list: "Back To List"
|
||||
edit:
|
||||
advanced_settings: Advanced Settings
|
||||
update_and_close: Update and Close
|
||||
choose_products_from: 'Choose Products From:'
|
||||
advanced_settings: "Advanced Settings"
|
||||
save: "Save"
|
||||
save_and_next: "Save and Next"
|
||||
next: "Next"
|
||||
cancel: "Cancel"
|
||||
back_to_list: "Back To List"
|
||||
save_and_back_to_list: "Save and Back to List"
|
||||
choose_products_from: "Choose Products From:"
|
||||
incoming:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
save_and_next: "Save and Next"
|
||||
next: "Next"
|
||||
cancel: "Cancel"
|
||||
back_to_list: "Back To List"
|
||||
outgoing:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
save_and_back_to_list: "Save and Back to List"
|
||||
cancel: "Cancel"
|
||||
back_to_list: "Back To List"
|
||||
wizard_progress:
|
||||
edit: "1. General Settings"
|
||||
incoming: "2. Incoming Products"
|
||||
outgoing: "3. Outgoing Products"
|
||||
exchange_form:
|
||||
pickup_time_tip: When orders from this OC will be ready for the customer
|
||||
pickup_instructions_placeholder: "Pick-up instructions"
|
||||
@@ -863,6 +890,7 @@ en_GB:
|
||||
any_enterprise: "Any Enterprise"
|
||||
any_schedule: "Any Schedule"
|
||||
form:
|
||||
general_settings: "General Settings"
|
||||
incoming: Incoming
|
||||
supplier: Supplier
|
||||
receival_details: Receival details
|
||||
@@ -2837,6 +2865,51 @@ en_GB:
|
||||
inherits_properties_checkbox_hint: "Inherit properties from %{supplier}? (unless overridden above)"
|
||||
add_product_properties: "Add Product Properties"
|
||||
select_from_prototype: "Select From Prototype"
|
||||
properties:
|
||||
index:
|
||||
properties: "Properties"
|
||||
new_property: "New Property"
|
||||
name: "Name"
|
||||
presentation: "Presentation"
|
||||
new:
|
||||
new_property: "New Property"
|
||||
edit:
|
||||
editing_property: "Editing Property"
|
||||
back_to_properties_list: "Back To Properties List"
|
||||
form:
|
||||
name: "Name"
|
||||
presentation: "Presentation"
|
||||
return_authorizations:
|
||||
index:
|
||||
new_return_authorization: "New Return Authorisation"
|
||||
return_authorizations: "Return Authorisations"
|
||||
back_to_orders_list: "Back To Orders List"
|
||||
rma_number: "RMA Number"
|
||||
status: "Status"
|
||||
amount: "Amount"
|
||||
cannot_create_returns: "Cannot create returns as this order has no shipped units."
|
||||
continue: "Continue"
|
||||
new:
|
||||
new_return_authorization: "New Return Authorisation"
|
||||
back_to_return_authorizations_list: "Back To Return Authorisation List"
|
||||
continue: "Continue"
|
||||
edit:
|
||||
receive: "receive"
|
||||
are_you_sure: "Are you sure?"
|
||||
return_authorization: "Return Authorisation"
|
||||
form:
|
||||
product: "Product"
|
||||
quantity_shipped: "Quantity Shipped"
|
||||
quantity_returned: "Quantity Returned"
|
||||
return_quantity: "Return Quantity"
|
||||
amount: "Amount"
|
||||
rma_value: "RMA Value"
|
||||
reason: "Reason"
|
||||
stock_location: "Stock Location"
|
||||
states:
|
||||
authorized: "Authorised"
|
||||
received: "Received"
|
||||
canceled: "Canceled"
|
||||
orders:
|
||||
index:
|
||||
listing_orders: "Listing Orders"
|
||||
|
||||
@@ -262,6 +262,7 @@ en_NZ:
|
||||
cancel: "Cancel"
|
||||
save: "Save"
|
||||
edit: "Edit"
|
||||
update: "Update"
|
||||
delete: "Delete"
|
||||
admin:
|
||||
begins_at: Begins At
|
||||
@@ -833,10 +834,36 @@ en_NZ:
|
||||
loading_flash:
|
||||
loading_order_cycles: LOADING ORDER CYCLES
|
||||
loading: LOADING...
|
||||
new:
|
||||
create: "Create"
|
||||
cancel: "Cancel"
|
||||
back_to_list: "Back To List"
|
||||
edit:
|
||||
advanced_settings: Advanced Settings
|
||||
update_and_close: Update and Close
|
||||
choose_products_from: 'Choose Products From:'
|
||||
advanced_settings: "Advanced Settings"
|
||||
save: "Save"
|
||||
save_and_next: "Save and Next"
|
||||
next: "Next"
|
||||
cancel: "Cancel"
|
||||
back_to_list: "Back To List"
|
||||
save_and_back_to_list: "Save and Back to List"
|
||||
choose_products_from: "Choose Products From:"
|
||||
incoming:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
save_and_next: "Save and Next"
|
||||
next: "Next"
|
||||
cancel: "Cancel"
|
||||
back_to_list: "Back To List"
|
||||
outgoing:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
save_and_back_to_list: "Save and Back to List"
|
||||
cancel: "Cancel"
|
||||
back_to_list: "Back To List"
|
||||
wizard_progress:
|
||||
edit: "1. General Settings"
|
||||
incoming: "2. Incoming Products"
|
||||
outgoing: "3. Outgoing Products"
|
||||
exchange_form:
|
||||
pickup_time_tip: When orders from this OC will be ready for the customer
|
||||
pickup_instructions_placeholder: "Pick-up instructions"
|
||||
@@ -863,6 +890,7 @@ en_NZ:
|
||||
any_enterprise: "Any Enterprise"
|
||||
any_schedule: "Any Schedule"
|
||||
form:
|
||||
general_settings: "General Settings"
|
||||
incoming: Incoming
|
||||
supplier: Supplier
|
||||
receival_details: Receival details
|
||||
@@ -2845,6 +2873,37 @@ en_NZ:
|
||||
form:
|
||||
name: "Name"
|
||||
presentation: "Presentation"
|
||||
return_authorizations:
|
||||
index:
|
||||
new_return_authorization: "New Return Authorization"
|
||||
return_authorizations: "Return Authorizations"
|
||||
back_to_orders_list: "Back To Orders List"
|
||||
rma_number: "RMA Number"
|
||||
status: "Status"
|
||||
amount: "Amount"
|
||||
cannot_create_returns: "Cannot create returns as this order has no shipped units."
|
||||
continue: "Continue"
|
||||
new:
|
||||
new_return_authorization: "New Return Authorization"
|
||||
back_to_return_authorizations_list: "Back To Return Authorization List"
|
||||
continue: "Continue"
|
||||
edit:
|
||||
receive: "receive"
|
||||
are_you_sure: "Are you sure?"
|
||||
return_authorization: "Return Authorization"
|
||||
form:
|
||||
product: "Product"
|
||||
quantity_shipped: "Quantity Shipped"
|
||||
quantity_returned: "Quantity Returned"
|
||||
return_quantity: "Return Quantity"
|
||||
amount: "Amount"
|
||||
rma_value: "RMA Value"
|
||||
reason: "Reason"
|
||||
stock_location: "Stock Location"
|
||||
states:
|
||||
authorized: "Authorized"
|
||||
received: "Received"
|
||||
canceled: "Canceled"
|
||||
orders:
|
||||
index:
|
||||
listing_orders: "Listing Orders"
|
||||
|
||||
@@ -260,6 +260,7 @@ en_US:
|
||||
cancel: "Cancel"
|
||||
save: "Save"
|
||||
edit: "Edit"
|
||||
update: "Update"
|
||||
delete: "Delete"
|
||||
admin:
|
||||
begins_at: Begins At
|
||||
@@ -827,10 +828,24 @@ en_US:
|
||||
loading_flash:
|
||||
loading_order_cycles: LOADING ORDER CYCLES
|
||||
loading: LOADING...
|
||||
new:
|
||||
create: "Create"
|
||||
cancel: "Cancel"
|
||||
edit:
|
||||
advanced_settings: Advanced Settings
|
||||
update_and_close: Update and Close
|
||||
choose_products_from: 'Choose Products From:'
|
||||
advanced_settings: "Advanced Settings"
|
||||
save: "Save"
|
||||
next: "Next"
|
||||
cancel: "Cancel"
|
||||
choose_products_from: "Choose Products From:"
|
||||
incoming:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
next: "Next"
|
||||
cancel: "Cancel"
|
||||
outgoing:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
cancel: "Cancel"
|
||||
exchange_form:
|
||||
pickup_time_tip: When orders from this OC will be ready for the customer
|
||||
pickup_instructions_placeholder: "Pick-up instructions"
|
||||
@@ -857,6 +872,7 @@ en_US:
|
||||
any_enterprise: "Any Enterprise"
|
||||
any_schedule: "Any Schedule"
|
||||
form:
|
||||
general_settings: "General Settings"
|
||||
incoming: Incoming
|
||||
supplier: Supplier
|
||||
receival_details: Receival details
|
||||
@@ -2816,6 +2832,27 @@ en_US:
|
||||
product_properties:
|
||||
index:
|
||||
inherits_properties_checkbox_hint: "Inherit properties from %{supplier}? (unless overridden above)"
|
||||
properties:
|
||||
index:
|
||||
properties: "Properties"
|
||||
name: "Name"
|
||||
form:
|
||||
name: "Name"
|
||||
return_authorizations:
|
||||
index:
|
||||
return_authorizations: "Return Authorizations"
|
||||
back_to_orders_list: "Back To Orders List"
|
||||
status: "Status"
|
||||
amount: "Amount"
|
||||
cannot_create_returns: "Cannot create returns as this order has no shipped units."
|
||||
continue: "Continue"
|
||||
new:
|
||||
continue: "Continue"
|
||||
edit:
|
||||
are_you_sure: "Are you sure?"
|
||||
form:
|
||||
product: "Product"
|
||||
amount: "Amount"
|
||||
orders:
|
||||
index:
|
||||
listing_orders: "Listing Orders"
|
||||
|
||||
@@ -259,6 +259,7 @@ en_ZA:
|
||||
cancel: "Cancel"
|
||||
save: "Save"
|
||||
edit: "Edit"
|
||||
update: "Update"
|
||||
delete: "Delete"
|
||||
admin:
|
||||
begins_at: Begins At
|
||||
@@ -826,10 +827,24 @@ en_ZA:
|
||||
loading_flash:
|
||||
loading_order_cycles: LOADING ORDER CYCLES
|
||||
loading: LOADING...
|
||||
new:
|
||||
create: "Create"
|
||||
cancel: "Cancel"
|
||||
edit:
|
||||
advanced_settings: Advanced Settings
|
||||
update_and_close: Update and Close
|
||||
choose_products_from: 'Choose Products From:'
|
||||
advanced_settings: "Advanced Settings"
|
||||
save: "Save"
|
||||
next: "Next"
|
||||
cancel: "Cancel"
|
||||
choose_products_from: "Choose Products From:"
|
||||
incoming:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
next: "Next"
|
||||
cancel: "Cancel"
|
||||
outgoing:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
cancel: "Cancel"
|
||||
exchange_form:
|
||||
pickup_time_tip: When orders from this OC will be ready for the customer
|
||||
pickup_instructions_placeholder: "Pick-up instructions"
|
||||
@@ -856,6 +871,7 @@ en_ZA:
|
||||
any_enterprise: "Any Enterprise"
|
||||
any_schedule: "Any Schedule"
|
||||
form:
|
||||
general_settings: "General Settings"
|
||||
incoming: Incoming
|
||||
supplier: Supplier
|
||||
receival_details: Receival details
|
||||
@@ -2819,6 +2835,25 @@ en_ZA:
|
||||
product_properties:
|
||||
index:
|
||||
inherits_properties_checkbox_hint: "Inherit properties from %{supplier}? (unless overridden above)"
|
||||
properties:
|
||||
index:
|
||||
properties: "Properties"
|
||||
name: "Name"
|
||||
form:
|
||||
name: "Name"
|
||||
return_authorizations:
|
||||
index:
|
||||
back_to_orders_list: "Back To Orders List"
|
||||
status: "Status"
|
||||
amount: "Amount"
|
||||
continue: "Continue"
|
||||
new:
|
||||
continue: "Continue"
|
||||
edit:
|
||||
are_you_sure: "Are you sure?"
|
||||
form:
|
||||
product: "Product"
|
||||
amount: "Amount"
|
||||
orders:
|
||||
index:
|
||||
listing_orders: "Listing Orders"
|
||||
|
||||
@@ -262,6 +262,7 @@ es:
|
||||
cancel: "Cancelar"
|
||||
save: "Guardar"
|
||||
edit: "Editar"
|
||||
update: "Actualizar"
|
||||
delete: "Borrar"
|
||||
admin:
|
||||
begins_at: Empieza en
|
||||
@@ -832,10 +833,24 @@ es:
|
||||
loading_flash:
|
||||
loading_order_cycles: Cargando ciclos de pedido
|
||||
loading: Cargando...
|
||||
new:
|
||||
create: "Crear"
|
||||
cancel: "Cancelar"
|
||||
edit:
|
||||
advanced_settings: Configuración Avanzada
|
||||
update_and_close: Actualizar y Cerrar
|
||||
choose_products_from: 'Escoger Productos desde:'
|
||||
advanced_settings: "Configuración Avanzada"
|
||||
save: "Guardar"
|
||||
next: "Siguiente"
|
||||
cancel: "Cancelar"
|
||||
choose_products_from: "Escoger Productos desde:"
|
||||
incoming:
|
||||
previous: "Anterior"
|
||||
save: "Guardar"
|
||||
next: "Siguiente"
|
||||
cancel: "Cancelar"
|
||||
outgoing:
|
||||
previous: "Anterior"
|
||||
save: "Guardar"
|
||||
cancel: "Cancelar"
|
||||
exchange_form:
|
||||
pickup_time_tip: Cuando los pedidos de este ciclo de pedido estarán listos para la consumidora
|
||||
pickup_instructions_placeholder: "Instrucciones de recogida"
|
||||
@@ -862,6 +877,7 @@ es:
|
||||
any_enterprise: "Cualquier organización"
|
||||
any_schedule: "Cualquier programación"
|
||||
form:
|
||||
general_settings: "Configuración general"
|
||||
incoming: Entrante
|
||||
supplier: Proveedora
|
||||
receival_details: Detalles de la recepción
|
||||
@@ -2825,6 +2841,27 @@ es:
|
||||
product_properties:
|
||||
index:
|
||||
inherits_properties_checkbox_hint: "¿Heredar propiedades desde %{supplier}? (a menos que sea anulado arriba)"
|
||||
properties:
|
||||
index:
|
||||
properties: "Propiedades"
|
||||
name: "Nombre"
|
||||
form:
|
||||
name: "Nombre"
|
||||
return_authorizations:
|
||||
index:
|
||||
return_authorizations: "Autorizaciones de devolución"
|
||||
back_to_orders_list: "Volver a la lista de pedidos"
|
||||
status: "Estado"
|
||||
amount: "Cantidad"
|
||||
cannot_create_returns: "No se pueden crear devoluciones ya que este pedido no tiene unidades enviadas."
|
||||
continue: "Continuar"
|
||||
new:
|
||||
continue: "Continuar"
|
||||
edit:
|
||||
are_you_sure: "¿Está seguro?"
|
||||
form:
|
||||
product: "Producto"
|
||||
amount: "Cantidad"
|
||||
orders:
|
||||
index:
|
||||
listing_orders: "Pedidos de listado"
|
||||
|
||||
@@ -257,6 +257,7 @@ fr_BE:
|
||||
cancel: "Annuler"
|
||||
save: "Sauvergarder"
|
||||
edit: "Modifier"
|
||||
update: "Mettre à jour"
|
||||
delete: "Supprimer"
|
||||
admin:
|
||||
begins_at: Commence
|
||||
@@ -823,10 +824,24 @@ fr_BE:
|
||||
loading_flash:
|
||||
loading_order_cycles: CHARGEMENT DES CYCLES DE VENTES
|
||||
loading: CHARGEMENT...
|
||||
new:
|
||||
create: "Créer"
|
||||
cancel: "Annuler"
|
||||
edit:
|
||||
advanced_settings: Paramétrages avancés
|
||||
update_and_close: Mettre à jour et fermer
|
||||
choose_products_from: 'Choisir produits depuis :'
|
||||
advanced_settings: "Paramétrages avancés"
|
||||
save: "Sauvergarder"
|
||||
next: "Suivant"
|
||||
cancel: "Annuler"
|
||||
choose_products_from: "Choisir produits depuis :"
|
||||
incoming:
|
||||
previous: "Précédent"
|
||||
save: "Sauvergarder"
|
||||
next: "Suivant"
|
||||
cancel: "Annuler"
|
||||
outgoing:
|
||||
previous: "Précédent"
|
||||
save: "Sauvergarder"
|
||||
cancel: "Annuler"
|
||||
exchange_form:
|
||||
pickup_time_tip: Quand des commandes liées à ce cycle de vente seront prêtes à être soumises à l'acheteur
|
||||
pickup_instructions_placeholder: "Modalités de retrait/livraison"
|
||||
@@ -853,6 +868,7 @@ fr_BE:
|
||||
any_enterprise: "Toutes les entreprises"
|
||||
any_schedule: "Tous"
|
||||
form:
|
||||
general_settings: "Réglages Généraux"
|
||||
incoming: Produits entrants (pouvant être mis en vente par les hubs)
|
||||
supplier: Fournisseur
|
||||
receival_details: Détails livraison produits
|
||||
@@ -2819,6 +2835,25 @@ fr_BE:
|
||||
product_properties:
|
||||
index:
|
||||
inherits_properties_checkbox_hint: "Hériter des propriétés de %{supplier} ? (non applicable si information de remplacement déjà saisie)"
|
||||
properties:
|
||||
index:
|
||||
properties: "Labels / propriétés"
|
||||
name: "Nom"
|
||||
form:
|
||||
name: "Nom"
|
||||
return_authorizations:
|
||||
index:
|
||||
back_to_orders_list: "Retour vers la liste des commandes "
|
||||
status: "Statut"
|
||||
amount: "Quantité"
|
||||
continue: "Suivant"
|
||||
new:
|
||||
continue: "Suivant"
|
||||
edit:
|
||||
are_you_sure: "Confirmer?"
|
||||
form:
|
||||
product: "Produit"
|
||||
amount: "Quantité"
|
||||
orders:
|
||||
index:
|
||||
listing_orders: "Liste des commandes"
|
||||
|
||||
@@ -261,6 +261,7 @@ fr_CA:
|
||||
cancel: "Annuler"
|
||||
save: "Enregistrer"
|
||||
edit: "Modifier"
|
||||
update: "Mettre à jour"
|
||||
delete: "Supprimer"
|
||||
admin:
|
||||
begins_at: Commence à
|
||||
@@ -829,10 +830,24 @@ fr_CA:
|
||||
loading_flash:
|
||||
loading_order_cycles: Cycles de vente en cours de chargement
|
||||
loading: Chargement en cours...
|
||||
new:
|
||||
create: "Créer"
|
||||
cancel: "Annuler"
|
||||
edit:
|
||||
advanced_settings: Paramétrages avancés
|
||||
update_and_close: Mettre à jour et fermer
|
||||
choose_products_from: 'Choisir produits depuis :'
|
||||
advanced_settings: "Paramétrages avancés"
|
||||
save: "Enregistrer"
|
||||
next: "Suivant"
|
||||
cancel: "Annuler"
|
||||
choose_products_from: "Choisir produits depuis :"
|
||||
incoming:
|
||||
previous: "Précédent"
|
||||
save: "Enregistrer"
|
||||
next: "Suivant"
|
||||
cancel: "Annuler"
|
||||
outgoing:
|
||||
previous: "Précédent"
|
||||
save: "Enregistrer"
|
||||
cancel: "Annuler"
|
||||
exchange_form:
|
||||
pickup_time_tip: Quand des commandes liées à ce cycle de vente seront prêtes à être soumises à l'acheteur
|
||||
pickup_instructions_placeholder: "Modalités de retrait/livraison"
|
||||
@@ -859,6 +874,7 @@ fr_CA:
|
||||
any_enterprise: "Toutes les entreprises"
|
||||
any_schedule: "Tous"
|
||||
form:
|
||||
general_settings: "Configurations générales"
|
||||
incoming: Produits entrants (pouvant être mis en vente par les hubs)
|
||||
supplier: Fournisseur
|
||||
receival_details: Détails livraison produits
|
||||
@@ -2827,6 +2843,27 @@ fr_CA:
|
||||
product_properties:
|
||||
index:
|
||||
inherits_properties_checkbox_hint: "Hériter des propriétés de %{supplier}? (non applicable si information de remplacement déjà saisie)"
|
||||
properties:
|
||||
index:
|
||||
properties: "Labels / propriétés"
|
||||
name: "Nom"
|
||||
form:
|
||||
name: "Nom"
|
||||
return_authorizations:
|
||||
index:
|
||||
return_authorizations: "Autorisations de retours"
|
||||
back_to_orders_list: "Retour à la liste des commandes"
|
||||
status: "Statut"
|
||||
amount: "Montant"
|
||||
cannot_create_returns: "Impossible de créer une autorisation de retour car aucun produit n'a été livré pour cette commande."
|
||||
continue: "Suivant"
|
||||
new:
|
||||
continue: "Suivant"
|
||||
edit:
|
||||
are_you_sure: "Confirmer?"
|
||||
form:
|
||||
product: "Produit"
|
||||
amount: "Montant"
|
||||
orders:
|
||||
index:
|
||||
listing_orders: "Liste des commandes"
|
||||
|
||||
@@ -251,6 +251,7 @@ it:
|
||||
cancel: "Annulla"
|
||||
save: "Salva"
|
||||
edit: "Modifica"
|
||||
update: "Aggiorna"
|
||||
delete: "Annulla"
|
||||
admin:
|
||||
begins_at: Inizia a
|
||||
@@ -808,10 +809,24 @@ it:
|
||||
user_already_exists: "L'Utente esiste già"
|
||||
error: "Qualcosa è andato storto"
|
||||
order_cycles:
|
||||
new:
|
||||
create: "Crea"
|
||||
cancel: "Annulla"
|
||||
edit:
|
||||
advanced_settings: Impostazioni avanzate
|
||||
update_and_close: Aggiorna e chiudi
|
||||
choose_products_from: 'Scegli i prodotti da:'
|
||||
advanced_settings: "Impostazioni avanzate"
|
||||
save: "Salva"
|
||||
next: "Prossimo"
|
||||
cancel: "Annulla"
|
||||
choose_products_from: "Scegli i prodotti da:"
|
||||
incoming:
|
||||
previous: "Precedente"
|
||||
save: "Salva"
|
||||
next: "Prossimo"
|
||||
cancel: "Annulla"
|
||||
outgoing:
|
||||
previous: "Precedente"
|
||||
save: "Salva"
|
||||
cancel: "Annulla"
|
||||
exchange_form:
|
||||
pickup_time_tip: Quando gli ordini di questa Lista d'ordine saranno pronti per il cliente
|
||||
pickup_instructions_placeholder: "Istruzioni per la consegna"
|
||||
@@ -837,6 +852,7 @@ it:
|
||||
any_enterprise: "Qualsiasi Impresa"
|
||||
any_schedule: "Qualunque Orario"
|
||||
form:
|
||||
general_settings: "Impostazioni generali"
|
||||
incoming: In arrivo
|
||||
supplier: Fornitore
|
||||
receival_details: Dettagli ritiro
|
||||
@@ -2753,6 +2769,25 @@ it:
|
||||
product_properties:
|
||||
index:
|
||||
inherits_properties_checkbox_hint: "Eredita le proprietà da %{supplier}? (se non sovrascritto)"
|
||||
properties:
|
||||
index:
|
||||
properties: "Proprietà"
|
||||
name: "Nome"
|
||||
form:
|
||||
name: "Nome"
|
||||
return_authorizations:
|
||||
index:
|
||||
back_to_orders_list: "Torna alla lista delle richieste"
|
||||
status: "Stato"
|
||||
amount: "Quantità"
|
||||
continue: "Continua"
|
||||
new:
|
||||
continue: "Continua"
|
||||
edit:
|
||||
are_you_sure: "Sei sicuro?"
|
||||
form:
|
||||
product: "Prodotto"
|
||||
amount: "Quantità"
|
||||
orders:
|
||||
index:
|
||||
listing_orders: "Listino Ordini"
|
||||
|
||||
@@ -262,6 +262,7 @@ nb:
|
||||
cancel: "Avbryt"
|
||||
save: "Lagre"
|
||||
edit: "Rediger"
|
||||
update: "Oppdater"
|
||||
delete: "Slett"
|
||||
admin:
|
||||
begins_at: Begynner på
|
||||
@@ -2871,6 +2872,37 @@ nb:
|
||||
form:
|
||||
name: "Navn"
|
||||
presentation: "Presentasjon"
|
||||
return_authorizations:
|
||||
index:
|
||||
new_return_authorization: "Ny Returautorisasjon"
|
||||
return_authorizations: "Returautorisasjoner"
|
||||
back_to_orders_list: "Tilbake til Bestillingsliste"
|
||||
rma_number: "RMA-nummer"
|
||||
status: "Status"
|
||||
amount: "Antall"
|
||||
cannot_create_returns: "Kan ikke opprette retur da denne bestillingen ikke har noen sendte elementer."
|
||||
continue: "Fortsett"
|
||||
new:
|
||||
new_return_authorization: "Ny Returautorisasjon"
|
||||
back_to_return_authorizations_list: "Tilbake til liste over Returautorisasjoner"
|
||||
continue: "Fortsett"
|
||||
edit:
|
||||
receive: "motta"
|
||||
are_you_sure: "Er du sikker?"
|
||||
return_authorization: "Returautorisasjon"
|
||||
form:
|
||||
product: "Produkt"
|
||||
quantity_shipped: "Mengde Sendt"
|
||||
quantity_returned: "Mengde Returnert"
|
||||
return_quantity: "Returneringsmengde"
|
||||
amount: "Antall"
|
||||
rma_value: "RMA-verdi"
|
||||
reason: "Grunn"
|
||||
stock_location: "Lagerplassering"
|
||||
states:
|
||||
authorized: "Autorisert"
|
||||
received: "Mottatt"
|
||||
canceled: "Avbrutt"
|
||||
orders:
|
||||
index:
|
||||
listing_orders: "Lister opp bestillinger"
|
||||
|
||||
@@ -257,6 +257,7 @@ nl_BE:
|
||||
cancel: "Annuleren"
|
||||
save: "Save"
|
||||
edit: "bewerking"
|
||||
update: "Update"
|
||||
delete: "Uitwissen "
|
||||
admin:
|
||||
begins_at: Begint Bij
|
||||
@@ -825,10 +826,24 @@ nl_BE:
|
||||
loading_flash:
|
||||
loading_order_cycles: LOADING ORDER CYCLES
|
||||
loading: BEZIG MET LADEN...
|
||||
new:
|
||||
create: "Maak"
|
||||
cancel: "Annuleren"
|
||||
edit:
|
||||
advanced_settings: Geavanceerde Instellingen
|
||||
update_and_close: Update en Sluit
|
||||
choose_products_from: 'Kies Producten Uit:'
|
||||
advanced_settings: "Geavanceerde Instellingen"
|
||||
save: "Save"
|
||||
next: "Volgende"
|
||||
cancel: "Annuleren"
|
||||
choose_products_from: "Kies Producten Uit:"
|
||||
incoming:
|
||||
previous: "Voorgaande"
|
||||
save: "Save"
|
||||
next: "Volgende"
|
||||
cancel: "Annuleren"
|
||||
outgoing:
|
||||
previous: "Voorgaande"
|
||||
save: "Save"
|
||||
cancel: "Annuleren"
|
||||
exchange_form:
|
||||
pickup_time_tip: Wanneer bestellingen van deze OC klaar staan voor de klant
|
||||
pickup_instructions_placeholder: "Aanwijzingen voor ophaling"
|
||||
@@ -855,6 +870,7 @@ nl_BE:
|
||||
any_enterprise: "Een Onderneming"
|
||||
any_schedule: "Een Planning"
|
||||
form:
|
||||
general_settings: "Algemene instellingen"
|
||||
incoming: Binnenkomend
|
||||
supplier: Leverancier
|
||||
receival_details: Ontvangstspecificaties
|
||||
@@ -2814,6 +2830,25 @@ nl_BE:
|
||||
product_properties:
|
||||
index:
|
||||
inherits_properties_checkbox_hint: "De kenmerken van 1%{supplier} krijgen ? (niet ter toepassing in geval van invoer van de vervanging)"
|
||||
properties:
|
||||
index:
|
||||
properties: "Eigenschappen"
|
||||
name: "Naam"
|
||||
form:
|
||||
name: "Naam"
|
||||
return_authorizations:
|
||||
index:
|
||||
back_to_orders_list: "Terug naar de bestellingslijst"
|
||||
status: "Status"
|
||||
amount: "Bedrag"
|
||||
continue: "Ga verder"
|
||||
new:
|
||||
continue: "Ga verder"
|
||||
edit:
|
||||
are_you_sure: "Ben je zeker?"
|
||||
form:
|
||||
product: "Product"
|
||||
amount: "Bedrag"
|
||||
orders:
|
||||
index:
|
||||
listing_orders: "Lijst van de bestellingen"
|
||||
|
||||
@@ -251,6 +251,7 @@ pt:
|
||||
cancel: "Cancelar"
|
||||
save: "Guardar"
|
||||
edit: "Editar"
|
||||
update: "Atualizar"
|
||||
delete: "Apagar"
|
||||
admin:
|
||||
begins_at: Começa às
|
||||
@@ -813,10 +814,24 @@ pt:
|
||||
loading_flash:
|
||||
loading_order_cycles: A carregar ciclos de encomenda
|
||||
loading: A carregar...
|
||||
new:
|
||||
create: "Criar"
|
||||
cancel: "Cancelar"
|
||||
edit:
|
||||
advanced_settings: Configurações Avançadas
|
||||
update_and_close: Atualizar e fechar
|
||||
choose_products_from: 'Escolha produtos de:'
|
||||
advanced_settings: "Configurações Avançadas"
|
||||
save: "Guardar"
|
||||
next: "Seguinte"
|
||||
cancel: "Cancelar"
|
||||
choose_products_from: "Escolha produtos de:"
|
||||
incoming:
|
||||
previous: "Anterior"
|
||||
save: "Guardar"
|
||||
next: "Seguinte"
|
||||
cancel: "Cancelar"
|
||||
outgoing:
|
||||
previous: "Anterior"
|
||||
save: "Guardar"
|
||||
cancel: "Cancelar"
|
||||
exchange_form:
|
||||
pickup_time_tip: Quando as encomendas deste ciclo ficam prontas para o consumidor
|
||||
pickup_instructions_placeholder: "Instruções para levantamento"
|
||||
@@ -842,6 +857,7 @@ pt:
|
||||
any_enterprise: "Qualquer Organização"
|
||||
any_schedule: "Qualquer Horário"
|
||||
form:
|
||||
general_settings: "Configurações Gerais"
|
||||
incoming: Entrada
|
||||
supplier: Fornecedor
|
||||
receival_details: Detalhes de recebimento
|
||||
@@ -2761,6 +2777,25 @@ pt:
|
||||
product_properties:
|
||||
index:
|
||||
inherits_properties_checkbox_hint: "Herdar propriedades de %{supplier}? (excepto se já alterado em cima)"
|
||||
properties:
|
||||
index:
|
||||
properties: "Propriedades"
|
||||
name: "Nome"
|
||||
form:
|
||||
name: "Nome"
|
||||
return_authorizations:
|
||||
index:
|
||||
back_to_orders_list: "Voltar à Lista de Encomendas"
|
||||
status: "Estado"
|
||||
amount: "Quantia"
|
||||
continue: "Continuar"
|
||||
new:
|
||||
continue: "Continuar"
|
||||
edit:
|
||||
are_you_sure: "Tem a certeza?"
|
||||
form:
|
||||
product: "Produto"
|
||||
amount: "Quantia"
|
||||
orders:
|
||||
index:
|
||||
listing_orders: "Lista de Encomendas"
|
||||
|
||||
@@ -260,6 +260,7 @@ pt_BR:
|
||||
cancel: "Cancelar"
|
||||
save: "Salvar"
|
||||
edit: "Editar"
|
||||
update: "Atualizar"
|
||||
delete: "Deletar"
|
||||
admin:
|
||||
begins_at: Começa em
|
||||
@@ -827,10 +828,24 @@ pt_BR:
|
||||
loading_flash:
|
||||
loading_order_cycles: CARREGANDO CICLOS DE PEDIDOS
|
||||
loading: CARREGANDO...
|
||||
new:
|
||||
create: "Criar"
|
||||
cancel: "Cancelar"
|
||||
edit:
|
||||
advanced_settings: Configurações avançadas
|
||||
update_and_close: Atualizar e fechar
|
||||
choose_products_from: 'Escolha produtos de:'
|
||||
advanced_settings: "Configurações avançadas"
|
||||
save: "Salvar"
|
||||
next: "Próximo"
|
||||
cancel: "Cancelar"
|
||||
choose_products_from: "Escolha produtos de:"
|
||||
incoming:
|
||||
previous: "Anterior"
|
||||
save: "Salvar"
|
||||
next: "Próximo"
|
||||
cancel: "Cancelar"
|
||||
outgoing:
|
||||
previous: "Anterior"
|
||||
save: "Salvar"
|
||||
cancel: "Cancelar"
|
||||
exchange_form:
|
||||
pickup_time_tip: Quando os pedidos desse ciclo de pedidos estarão prontos para os consumidores
|
||||
pickup_instructions_placeholder: "Instruções para retirada"
|
||||
@@ -857,6 +872,7 @@ pt_BR:
|
||||
any_enterprise: "Qualquer empresa"
|
||||
any_schedule: "Qualquer cronograma"
|
||||
form:
|
||||
general_settings: "Configurações Gerais"
|
||||
incoming: Entrada
|
||||
supplier: Fornecedor
|
||||
receival_details: Detalhes de recebimento
|
||||
@@ -2817,6 +2833,24 @@ pt_BR:
|
||||
product_properties:
|
||||
index:
|
||||
inherits_properties_checkbox_hint: "Herdar propriedades de %{supplier}? (a menos que substituído acima)"
|
||||
properties:
|
||||
index:
|
||||
properties: "Propriedades"
|
||||
name: "Nome"
|
||||
form:
|
||||
name: "Nome"
|
||||
return_authorizations:
|
||||
index:
|
||||
status: "Status"
|
||||
amount: "Montante"
|
||||
continue: "Continuar"
|
||||
new:
|
||||
continue: "Continuar"
|
||||
edit:
|
||||
are_you_sure: "Tem certeza?"
|
||||
form:
|
||||
product: "Produto"
|
||||
amount: "Montante"
|
||||
orders:
|
||||
index:
|
||||
listing_orders: "Listagem de Pedidos"
|
||||
|
||||
@@ -111,6 +111,7 @@ sv:
|
||||
create: "Skapa"
|
||||
cancel: "Avbryt"
|
||||
edit: "Redigera"
|
||||
update: "Uppdatera"
|
||||
admin:
|
||||
date: Datum
|
||||
email: epost
|
||||
@@ -483,10 +484,19 @@ sv:
|
||||
profile: 'Profil'
|
||||
producer_profile: 'Producentprofil'
|
||||
order_cycles:
|
||||
new:
|
||||
create: "Skapa"
|
||||
cancel: "Avbryt"
|
||||
edit:
|
||||
advanced_settings: Avancerade inställningar
|
||||
update_and_close: Uppdatera och Stäng
|
||||
choose_products_from: 'Välj produkter från:'
|
||||
advanced_settings: "Avancerade inställningar"
|
||||
next: "Näst"
|
||||
cancel: "Avbryt"
|
||||
choose_products_from: "Välj produkter från:"
|
||||
incoming:
|
||||
next: "Näst"
|
||||
cancel: "Avbryt"
|
||||
outgoing:
|
||||
cancel: "Avbryt"
|
||||
exchange_form:
|
||||
pickup_instructions_placeholder: "Instruktioner för upphämtning"
|
||||
pickup_time_placeholder: "Klar för (dvs. Datum/Tid)"
|
||||
@@ -1941,6 +1951,24 @@ sv:
|
||||
enterprises: "Företag"
|
||||
customers: "Kunder"
|
||||
groups: "Grupper"
|
||||
properties:
|
||||
index:
|
||||
properties: "Egenskaper"
|
||||
name: "Namn"
|
||||
form:
|
||||
name: "Namn"
|
||||
return_authorizations:
|
||||
index:
|
||||
status: "Status"
|
||||
amount: "Belopp"
|
||||
continue: "Fortsätt"
|
||||
new:
|
||||
continue: "Fortsätt"
|
||||
edit:
|
||||
are_you_sure: "Är du säker?"
|
||||
form:
|
||||
product: "Produkt"
|
||||
amount: "Belopp"
|
||||
orders:
|
||||
index:
|
||||
capture: "Fånga"
|
||||
|
||||
@@ -46,12 +46,12 @@ module OpenFoodNetwork
|
||||
end
|
||||
|
||||
def search
|
||||
Reports::LineItems.search_orders(permissions, params)
|
||||
report_line_items.orders
|
||||
end
|
||||
|
||||
def table_items
|
||||
return [] unless @render_table
|
||||
Reports::LineItems.list(permissions, report_options)
|
||||
report_line_items.list(line_item_includes)
|
||||
end
|
||||
|
||||
def rules
|
||||
@@ -121,18 +121,18 @@ module OpenFoodNetwork
|
||||
|
||||
private
|
||||
|
||||
def report_options
|
||||
@params.merge(line_item_includes: line_item_includes)
|
||||
end
|
||||
|
||||
def line_item_includes
|
||||
[{ order: [:bill_address],
|
||||
variant: [{ option_values: :option_type }, { product: :supplier }] }]
|
||||
end
|
||||
|
||||
def permissions
|
||||
return @permissions unless @permissions.nil?
|
||||
@permissions = OpenFoodNetwork::Permissions.new(@user)
|
||||
def order_permissions
|
||||
return @order_permissions unless @order_permissions.nil?
|
||||
@order_permissions = ::Permissions::Order.new(@user)
|
||||
end
|
||||
|
||||
def report_line_items
|
||||
@report_line_items ||= Reports::LineItems.new(order_permissions, @params)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,7 +5,7 @@ module OpenFoodNetwork
|
||||
@user = user
|
||||
@render_table = render_table
|
||||
|
||||
@permissions = OpenFoodNetwork::Permissions.new(user)
|
||||
@permissions = ::Permissions::Order.new(user)
|
||||
end
|
||||
|
||||
def header
|
||||
|
||||
@@ -13,28 +13,24 @@ module OpenFoodNetwork
|
||||
|
||||
delegate :header, :rules, :columns, to: :report
|
||||
|
||||
def initialize(permissions, options = {}, render_table = false)
|
||||
def initialize(user, options = {}, render_table = false)
|
||||
@user = user
|
||||
@options = options
|
||||
@report_type = options[:report_type]
|
||||
@permissions = permissions
|
||||
@render_table = render_table
|
||||
end
|
||||
|
||||
def search
|
||||
Reports::LineItems.search_orders(permissions, options)
|
||||
report_line_items.orders
|
||||
end
|
||||
|
||||
def table_items
|
||||
return [] unless @render_table
|
||||
|
||||
list_options = options.merge(line_item_includes: report.line_item_includes)
|
||||
Reports::LineItems.list(permissions, list_options)
|
||||
report_line_items.list(report.line_item_includes)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :permissions
|
||||
|
||||
def report
|
||||
@report ||= report_klass.new(self)
|
||||
end
|
||||
@@ -84,5 +80,14 @@ module OpenFoodNetwork
|
||||
def scale_factor(product)
|
||||
product.variant_unit == 'weight' ? 1000 : 1
|
||||
end
|
||||
|
||||
def order_permissions
|
||||
return @order_permissions unless @order_permissions.nil?
|
||||
@order_permissions = ::Permissions::Order.new(@user)
|
||||
end
|
||||
|
||||
def report_line_items
|
||||
@report_line_items ||= Reports::LineItems.new(order_permissions, options)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -38,12 +38,12 @@ module OpenFoodNetwork
|
||||
end
|
||||
|
||||
def search
|
||||
Reports::LineItems.search_orders(permissions, params)
|
||||
report_line_items.orders
|
||||
end
|
||||
|
||||
def table_items
|
||||
return [] unless @render_table
|
||||
Reports::LineItems.list(permissions, report_options)
|
||||
report_line_items.list(line_item_includes)
|
||||
end
|
||||
|
||||
def rules
|
||||
@@ -95,7 +95,7 @@ module OpenFoodNetwork
|
||||
def columns
|
||||
if is_by_customer?
|
||||
[proc { |line_items| line_items.first.order.distributor.name },
|
||||
proc { |line_items| customer_code(line_items.first.order.email) },
|
||||
proc { |line_items| customer_code(line_items.first.order) },
|
||||
proc { |line_items| line_items.first.order.bill_address.firstname },
|
||||
proc { |line_items| line_items.first.order.bill_address.lastname },
|
||||
proc { |line_items| line_items.first.product.supplier.name },
|
||||
@@ -107,7 +107,7 @@ module OpenFoodNetwork
|
||||
[
|
||||
proc { |line_items| line_items.first.order.distributor.name },
|
||||
proc { |line_items| line_items.first.product.supplier.name },
|
||||
proc { |line_items| customer_code(line_items.first.order.email) },
|
||||
proc { |line_items| customer_code(line_items.first.order) },
|
||||
proc { |line_items| line_items.first.order.bill_address.firstname },
|
||||
proc { |line_items| line_items.first.order.bill_address.lastname },
|
||||
proc { |line_items| line_items.first.product.name },
|
||||
@@ -120,18 +120,15 @@ module OpenFoodNetwork
|
||||
|
||||
private
|
||||
|
||||
def report_options
|
||||
@params.merge(line_item_includes: line_item_includes)
|
||||
end
|
||||
|
||||
def line_item_includes
|
||||
[{ order: [:bill_address, :distributor],
|
||||
variant: [{ option_values: :option_type }, { product: :supplier }] }]
|
||||
[{ option_values: :option_type,
|
||||
order: [:bill_address, :distributor, :customer],
|
||||
variant: { product: [:supplier, :shipping_category] } }]
|
||||
end
|
||||
|
||||
def permissions
|
||||
return @permissions unless @permissions.nil?
|
||||
@permissions = OpenFoodNetwork::Permissions.new(@user)
|
||||
def order_permissions
|
||||
return @order_permissions unless @order_permissions.nil?
|
||||
@order_permissions = ::Permissions::Order.new(@user)
|
||||
end
|
||||
|
||||
def is_temperature_controlled?(line_item)
|
||||
@@ -146,9 +143,13 @@ module OpenFoodNetwork
|
||||
params[:report_type] == "pack_by_customer"
|
||||
end
|
||||
|
||||
def customer_code(email)
|
||||
customer = Customer.where(email: email).first
|
||||
def customer_code(order)
|
||||
customer = order.customer
|
||||
customer.nil? ? "" : customer.code
|
||||
end
|
||||
|
||||
def report_line_items
|
||||
@report_line_items ||= Reports::LineItems.new(order_permissions, @params)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -58,55 +58,12 @@ module OpenFoodNetwork
|
||||
permissions
|
||||
end
|
||||
|
||||
# Find enterprises that an admin is allowed to add to an order cycle
|
||||
def visible_orders
|
||||
# Any orders that I can edit
|
||||
editable = editable_orders.pluck(:id)
|
||||
|
||||
produced = Spree::Order.with_line_items_variants_and_products_outer.
|
||||
where(
|
||||
distributor_id: granted_distributor_ids,
|
||||
spree_products: { supplier_id: enterprises_with_associated_orders }
|
||||
).pluck(:id)
|
||||
|
||||
Spree::Order.where(id: editable | produced)
|
||||
end
|
||||
|
||||
# Find enterprises that an admin is allowed to add to an order cycle
|
||||
def editable_orders
|
||||
# Any orders placed through any hub that I manage
|
||||
managed = Spree::Order.where(distributor_id: managed_enterprises.pluck(:id)).pluck(:id)
|
||||
|
||||
# Any order that is placed through an order cycle one of my managed enterprises coordinates
|
||||
coordinated = Spree::Order.
|
||||
where(order_cycle_id: coordinated_order_cycles.pluck(:id)).
|
||||
pluck(:id)
|
||||
|
||||
Spree::Order.where(id: managed | coordinated )
|
||||
end
|
||||
|
||||
def visible_line_items
|
||||
# Any line items that I can edit
|
||||
editable = editable_line_items.pluck(:id)
|
||||
|
||||
# Any from visible orders, where the product is produced by one of my managed producers
|
||||
produced = Spree::LineItem.where(order_id: visible_orders.pluck(:id)).
|
||||
joins(:product).
|
||||
where(spree_products: { supplier_id: managed_enterprises.is_primary_producer.pluck(:id) })
|
||||
|
||||
Spree::LineItem.where(id: editable | produced)
|
||||
end
|
||||
|
||||
def editable_line_items
|
||||
Spree::LineItem.where(order_id: editable_orders)
|
||||
end
|
||||
|
||||
def editable_products
|
||||
permitted_enterprise_products_ids = product_ids_supplied_by(
|
||||
related_enterprises_granting(:manage_products)
|
||||
)
|
||||
Spree::Product.where(
|
||||
id: managed_enterprise_products.pluck(:id) | permitted_enterprise_products_ids
|
||||
id: managed_enterprise_products.select(:id) | permitted_enterprise_products_ids
|
||||
)
|
||||
end
|
||||
|
||||
@@ -116,10 +73,14 @@ module OpenFoodNetwork
|
||||
related_enterprises_granting(:add_to_order_cycle)
|
||||
)
|
||||
Spree::Product.where(
|
||||
id: managed_enterprise_products.pluck(:id) | permitted_enterprise_products_ids
|
||||
id: managed_enterprise_products.select(:id) | permitted_enterprise_products_ids
|
||||
)
|
||||
end
|
||||
|
||||
def product_ids_supplied_by(supplier_ids)
|
||||
Spree::Product.where(supplier_id: supplier_ids).select(:id)
|
||||
end
|
||||
|
||||
def managed_product_enterprises
|
||||
managed_and_related_enterprises_granting :manage_products
|
||||
end
|
||||
@@ -129,14 +90,16 @@ module OpenFoodNetwork
|
||||
end
|
||||
|
||||
def editable_schedules
|
||||
Schedule.joins(:order_cycles).
|
||||
where(order_cycles: { id: OrderCycle.managed_by(@user).pluck(:id) }).
|
||||
Schedule.
|
||||
joins(:order_cycles).
|
||||
where(order_cycles: { id: OrderCycle.managed_by(@user).select("order_cycles.id") }).
|
||||
select("DISTINCT schedules.*")
|
||||
end
|
||||
|
||||
def visible_schedules
|
||||
Schedule.joins(:order_cycles).
|
||||
where(order_cycles: { id: OrderCycle.accessible_by(@user).pluck(:id) }).
|
||||
Schedule.
|
||||
joins(:order_cycles).
|
||||
where(order_cycles: { id: OrderCycle.managed_by(@user).select("order_cycles.id") }).
|
||||
select("DISTINCT schedules.*")
|
||||
end
|
||||
|
||||
@@ -148,53 +111,6 @@ module OpenFoodNetwork
|
||||
editable_subscriptions
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def admin?
|
||||
@user.admin?
|
||||
end
|
||||
|
||||
def granted_distributor_ids
|
||||
@granted_distributor_ids ||= related_enterprises_granted(
|
||||
:add_to_order_cycle,
|
||||
by: managed_enterprises.is_primary_producer.pluck(:id)
|
||||
).pluck(:id)
|
||||
end
|
||||
|
||||
def enterprises_with_associated_orders
|
||||
# Any orders placed through hubs that my producers have granted P-OC,
|
||||
# and which contain their products. This is pretty complicated but it's looking for order
|
||||
# where at least one of my producers has granted P-OC to the distributor
|
||||
# AND the order contains products of at least one of THE SAME producers
|
||||
|
||||
related_enterprises_granting(:add_to_order_cycle, to: granted_distributor_ids).
|
||||
merge(managed_enterprises.is_primary_producer)
|
||||
end
|
||||
|
||||
def managed_and_related_enterprises_granting(permission)
|
||||
if admin?
|
||||
Enterprise.scoped
|
||||
else
|
||||
Enterprise.where(
|
||||
id: managed_enterprises.pluck(:id) | related_enterprises_granting(permission)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def managed_and_related_enterprises_with(permission)
|
||||
if admin?
|
||||
Enterprise.scoped
|
||||
else
|
||||
managed_enterprise_ids = managed_enterprises.pluck(:id)
|
||||
granting_enterprise_ids = related_enterprises_granting(permission)
|
||||
granted_enterprise_ids = related_enterprises_granted(permission)
|
||||
|
||||
Enterprise.where(
|
||||
id: managed_enterprise_ids | granting_enterprise_ids | granted_enterprise_ids
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def managed_enterprises
|
||||
@managed_enterprises ||= Enterprise.managed_by(@user)
|
||||
end
|
||||
@@ -209,7 +125,7 @@ module OpenFoodNetwork
|
||||
parent_ids = EnterpriseRelationship.
|
||||
permitting(options[:to] || managed_enterprises.select("enterprises.id")).
|
||||
with_permission(permission).
|
||||
pluck(:parent_id)
|
||||
select(:parent_id)
|
||||
|
||||
(options[:scope] || Enterprise).where(id: parent_ids).select("enterprises.id")
|
||||
end
|
||||
@@ -218,17 +134,44 @@ module OpenFoodNetwork
|
||||
child_ids = EnterpriseRelationship.
|
||||
permitted_by(options[:by] || managed_enterprises.select("enterprises.id")).
|
||||
with_permission(permission).
|
||||
pluck(:child_id)
|
||||
select(:child_id)
|
||||
|
||||
(options[:scope] || Enterprise).where(id: child_ids).select("enterprises.id")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def admin?
|
||||
@user.admin?
|
||||
end
|
||||
|
||||
def managed_and_related_enterprises_granting(permission)
|
||||
if admin?
|
||||
Enterprise.scoped
|
||||
else
|
||||
Enterprise.where(
|
||||
id: managed_enterprises.select("enterprises.id") |
|
||||
related_enterprises_granting(permission)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def managed_and_related_enterprises_with(permission)
|
||||
if admin?
|
||||
Enterprise.scoped
|
||||
else
|
||||
managed_enterprise_ids = managed_enterprises.select("enterprises.id")
|
||||
granting_enterprise_ids = related_enterprises_granting(permission)
|
||||
granted_enterprise_ids = related_enterprises_granted(permission)
|
||||
|
||||
Enterprise.where(
|
||||
id: managed_enterprise_ids | granting_enterprise_ids | granted_enterprise_ids
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def managed_enterprise_products
|
||||
Spree::Product.managed_by(@user)
|
||||
end
|
||||
|
||||
def product_ids_supplied_by(supplier_ids)
|
||||
Spree::Product.where(supplier_id: supplier_ids).pluck(:id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,43 +1,66 @@
|
||||
module OpenFoodNetwork
|
||||
module Reports
|
||||
# shared code to search and list line items
|
||||
module LineItems
|
||||
def self.search_orders(permissions, params)
|
||||
permissions.visible_orders.complete.not_state(:canceled).search(params[:q])
|
||||
class LineItems
|
||||
def initialize(order_permissions, params)
|
||||
@order_permissions = order_permissions
|
||||
@params = params
|
||||
end
|
||||
|
||||
def self.list(permissions, params)
|
||||
orders = search_orders(permissions, params).result
|
||||
def orders
|
||||
@orders ||= search_orders
|
||||
end
|
||||
|
||||
line_items = permissions.visible_line_items.merge(Spree::LineItem.where(order_id: orders))
|
||||
line_items = line_items.supplied_by_any(params[:supplier_id_in]) if params[:supplier_id_in].present?
|
||||
def list(line_item_includes = nil)
|
||||
line_items = @order_permissions.
|
||||
visible_line_items.
|
||||
merge(Spree::LineItem.where(order_id: orders.result))
|
||||
|
||||
if params[:line_item_includes].present?
|
||||
line_items = line_items.includes(*params[:line_item_includes])
|
||||
if @params[:supplier_id_in].present?
|
||||
line_items = line_items.supplied_by_any(@params[:supplier_id_in])
|
||||
end
|
||||
|
||||
hidden_line_items = line_items_with_hidden_details(permissions, line_items)
|
||||
if line_item_includes.present?
|
||||
line_items = line_items.includes(*line_item_includes)
|
||||
end
|
||||
|
||||
editable_line_items = editable_line_items(line_items)
|
||||
|
||||
line_items.select{ |li|
|
||||
hidden_line_items.include? li
|
||||
!editable_line_items.include? li
|
||||
}.each do |line_item|
|
||||
# TODO We should really be hiding customer code here too, but until we
|
||||
# have an actual association between order and customer, it's a bit tricky
|
||||
line_item.order.bill_address.andand.assign_attributes(firstname: I18n.t('admin.reports.hidden'), lastname: "", phone: "", address1: "", address2: "", city: "", zipcode: "", state: nil)
|
||||
line_item.order.ship_address.andand.assign_attributes(firstname: I18n.t('admin.reports.hidden'), lastname: "", phone: "", address1: "", address2: "", city: "", zipcode: "", state: nil)
|
||||
line_item.order.bill_address.andand.
|
||||
assign_attributes(firstname: I18n.t('admin.reports.hidden'),
|
||||
lastname: "", phone: "", address1: "", address2: "",
|
||||
city: "", zipcode: "", state: nil)
|
||||
line_item.order.ship_address.andand.
|
||||
assign_attributes(firstname: I18n.t('admin.reports.hidden'),
|
||||
lastname: "", phone: "", address1: "", address2: "",
|
||||
city: "", zipcode: "", state: nil)
|
||||
line_item.order.assign_attributes(email: I18n.t('admin.reports.hidden'))
|
||||
end
|
||||
|
||||
line_items
|
||||
end
|
||||
|
||||
def self.line_items_with_hidden_details(permissions, line_items)
|
||||
editable_line_items = permissions.editable_line_items.pluck(:id)
|
||||
private
|
||||
|
||||
if editable_line_items.empty?
|
||||
line_items
|
||||
else
|
||||
line_items.where('"spree_line_items"."id" NOT IN (?)', editable_line_items)
|
||||
end
|
||||
def search_orders
|
||||
@order_permissions.visible_orders.complete.not_state(:canceled).search(@params[:q])
|
||||
end
|
||||
|
||||
# From the line_items given, returns the ones that are editable by the user
|
||||
def editable_line_items(line_items)
|
||||
editable_line_items_ids = @order_permissions.editable_line_items.select(:id)
|
||||
|
||||
# Although merge could take a relation, here we convert line_items to array
|
||||
# because, if we pass a relation, merge will overwrite the conditions on the same field
|
||||
# In this case: the IN clause on spree_line_items.order_id from line_items
|
||||
# overwrites the IN clause on spree_line_items.order_id on editable_line_items_ids
|
||||
# We convert to array the relation with less elements: line_items
|
||||
editable_line_items_ids.merge(line_items.to_a)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -34,7 +34,7 @@ module OpenFoodNetwork
|
||||
end
|
||||
|
||||
def search
|
||||
permissions = OpenFoodNetwork::Permissions.new(user)
|
||||
permissions = ::Permissions::Order.new(user)
|
||||
permissions.editable_orders.complete.not_state(:canceled).search(params[:q])
|
||||
end
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ module OpenFoodNetwork
|
||||
end
|
||||
|
||||
def search
|
||||
permissions = OpenFoodNetwork::Permissions.new(@user)
|
||||
permissions = ::Permissions::Order.new(@user)
|
||||
permissions.editable_orders.complete.not_state(:canceled).search(@opts[:q])
|
||||
end
|
||||
|
||||
|
||||
@@ -30,7 +30,8 @@ describe Api::TaxonsController do
|
||||
it "gets all taxons" do
|
||||
api_get :index
|
||||
|
||||
expect(json_response.first['name']).to eq taxonomy.root.name
|
||||
json_names = json_response.map { |taxon_data| taxon_data["name"] }
|
||||
expect(json_names).to include(taxon.name, taxon2.name)
|
||||
end
|
||||
|
||||
it "can search for a single taxon" do
|
||||
|
||||
89
spec/controllers/checkout_controller_concurrency_spec.rb
Normal file
89
spec/controllers/checkout_controller_concurrency_spec.rb
Normal file
@@ -0,0 +1,89 @@
|
||||
require 'spec_helper'
|
||||
|
||||
# This is the first example of testing concurrency in the Open Food Network.
|
||||
# If we want to do this more often, we should look at:
|
||||
#
|
||||
# https://github.com/forkbreak/fork_break
|
||||
#
|
||||
# The concurrency flag enables multiple threads to see the same database
|
||||
# without isolated transactions.
|
||||
describe CheckoutController, concurrency: true, type: :controller do
|
||||
let(:order_cycle) { create(:order_cycle) }
|
||||
let(:distributor) { order_cycle.distributors.first }
|
||||
let(:order) { create(:order, order_cycle: order_cycle, distributor: distributor) }
|
||||
let(:address) { create(:address) }
|
||||
let(:payment_method) { create(:payment_method, distributors: [distributor]) }
|
||||
let(:breakpoint) { Mutex.new }
|
||||
|
||||
before do
|
||||
# Create a valid order ready for checkout:
|
||||
create(:shipping_method, distributors: [distributor])
|
||||
variant = order_cycle.variants_distributed_by(distributor).first
|
||||
order.line_items << create(:line_item, variant: variant)
|
||||
|
||||
# Set up controller environment:
|
||||
session[:order_id] = order.id
|
||||
allow(controller).to receive(:spree_current_user).and_return(order.user)
|
||||
allow(controller).to receive(:current_distributor).and_return(order.distributor)
|
||||
allow(controller).to receive(:current_order_cycle).and_return(order.order_cycle)
|
||||
|
||||
# New threads start running straight away. The breakpoint is after loading
|
||||
# the order and before advancing the order's state and making payments.
|
||||
breakpoint.lock
|
||||
allow(controller).to receive(:check_order_for_phantom_fees) do
|
||||
breakpoint.synchronize {}
|
||||
end
|
||||
end
|
||||
|
||||
it "waits for concurrent checkouts" do
|
||||
# Basic data the user submits during checkout:
|
||||
address_params = address.attributes.except("id")
|
||||
order_params = {
|
||||
"payments_attributes" => [
|
||||
{
|
||||
"payment_method_id" => payment_method.id,
|
||||
"amount" => order.total
|
||||
}
|
||||
],
|
||||
"bill_address_attributes" => address_params,
|
||||
"ship_address_attributes" => address_params,
|
||||
}
|
||||
|
||||
# Starting two checkout threads. The controller code will determine if
|
||||
# these two threads are synchronised correctly or run into a race condition.
|
||||
#
|
||||
# 1. If the controller synchronises correctly:
|
||||
# The first thread locks required resources and then waits at the
|
||||
# breakpoint. The second thread waits for the first one.
|
||||
# 2. If the controller fails to prevent the race condition:
|
||||
# Both threads load required resources and wait at the breakpoint to do
|
||||
# the same checkout action. This will lead to (random) errors.
|
||||
#
|
||||
# I observed:
|
||||
# ActiveRecord::RecordNotUnique: duplicate key value violates unique
|
||||
# constraint "index_spree_shipments_on_order_id"
|
||||
# on `INSERT INTO "spree_shipments" ...`.
|
||||
#
|
||||
# Or:
|
||||
# ActiveRecord::InvalidForeignKey: insert or update on table
|
||||
# "spree_orders" violates foreign key constraint
|
||||
# "spree_orders_customer_id_fk"
|
||||
threads = [
|
||||
Thread.new { spree_post :update, format: :json, order: order_params },
|
||||
Thread.new { spree_post :update, format: :json, order: order_params },
|
||||
]
|
||||
# Let the threads run again. They should not be in a race condition.
|
||||
breakpoint.unlock
|
||||
# Wait for both threads to finish.
|
||||
threads.each(&:join)
|
||||
order.reload
|
||||
|
||||
# When the spec passes, both threads have the same result. The user should
|
||||
# see the order page. This is basically verifying a "double click"
|
||||
# scenario.
|
||||
expect(response.status).to eq(200)
|
||||
expect(response.body).to eq({ path: spree.order_path(order) }.to_json)
|
||||
expect(order.payments.count).to eq 1
|
||||
expect(order.completed?).to be true
|
||||
end
|
||||
end
|
||||
@@ -130,6 +130,7 @@ describe CheckoutController, type: :controller do
|
||||
context 'when completing the order' do
|
||||
before do
|
||||
order.state = 'complete'
|
||||
order.save!
|
||||
allow(order).to receive(:update_attributes).and_return(true)
|
||||
allow(order).to receive(:next).and_return(true)
|
||||
allow(order).to receive(:set_distributor!).and_return(true)
|
||||
|
||||
@@ -415,14 +415,17 @@ feature '
|
||||
|
||||
expect(page).to have_selector "a.clone-product", count: 1
|
||||
find("a.clone-product").click
|
||||
expect(page).to have_field "product_name", with: "COPY OF #{p.name}"
|
||||
|
||||
fill_in "product_name", with: "new product name"
|
||||
within "#p_#{p.id}" do
|
||||
fill_in "product_name", with: "new product name"
|
||||
end
|
||||
|
||||
within "#save-bar" do
|
||||
click_button 'Save Changes'
|
||||
end
|
||||
|
||||
expect(page.find("#status-message")).to have_content "Changes saved."
|
||||
|
||||
p.reload
|
||||
expect(p.name).to eq "new product name"
|
||||
end
|
||||
|
||||
@@ -62,7 +62,7 @@ module OpenFoodNetwork
|
||||
o2.line_items << li2
|
||||
end
|
||||
|
||||
it "shows line items supplied by my producers, with names hidden" do
|
||||
it "does not show line items supplied by my producers" do
|
||||
expect(subject.table_items).to eq([])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,11 +4,10 @@ RSpec.describe OpenFoodNetwork::OrdersAndFulfillmentsReport::CustomerTotalsRepor
|
||||
let!(:distributor) { create(:distributor_enterprise) }
|
||||
let!(:customer) { create(:customer, enterprise: distributor) }
|
||||
let(:current_user) { distributor.owner }
|
||||
let(:permissions) { OpenFoodNetwork::Permissions.new(current_user) }
|
||||
|
||||
let(:report) do
|
||||
report_options = { report_type: described_class::REPORT_TYPE }
|
||||
OpenFoodNetwork::OrdersAndFulfillmentsReport.new(permissions, report_options, true)
|
||||
OpenFoodNetwork::OrdersAndFulfillmentsReport.new(current_user, report_options, true)
|
||||
end
|
||||
|
||||
let(:report_table) do
|
||||
|
||||
@@ -8,11 +8,10 @@ RSpec.describe OpenFoodNetwork::OrdersAndFulfillmentsReport::DistributorTotalsBy
|
||||
end
|
||||
|
||||
let(:current_user) { distributor.owner }
|
||||
let(:permissions) { OpenFoodNetwork::Permissions.new(current_user) }
|
||||
|
||||
let(:report) do
|
||||
report_options = { report_type: described_class::REPORT_TYPE }
|
||||
OpenFoodNetwork::OrdersAndFulfillmentsReport.new(permissions, report_options, true)
|
||||
OpenFoodNetwork::OrdersAndFulfillmentsReport.new(current_user, report_options, true)
|
||||
end
|
||||
|
||||
let(:report_table) do
|
||||
|
||||
@@ -8,11 +8,10 @@ RSpec.describe OpenFoodNetwork::OrdersAndFulfillmentsReport::SupplierTotalsByDis
|
||||
end
|
||||
|
||||
let(:current_user) { distributor.owner }
|
||||
let(:permissions) { OpenFoodNetwork::Permissions.new(current_user) }
|
||||
|
||||
let(:report) do
|
||||
report_options = { report_type: described_class::REPORT_TYPE }
|
||||
OpenFoodNetwork::OrdersAndFulfillmentsReport.new(permissions, report_options, true)
|
||||
OpenFoodNetwork::OrdersAndFulfillmentsReport.new(current_user, report_options, true)
|
||||
end
|
||||
|
||||
let(:report_table) do
|
||||
|
||||
@@ -8,11 +8,10 @@ RSpec.describe OpenFoodNetwork::OrdersAndFulfillmentsReport::SupplierTotalsRepor
|
||||
end
|
||||
|
||||
let(:current_user) { distributor.owner }
|
||||
let(:permissions) { OpenFoodNetwork::Permissions.new(current_user) }
|
||||
|
||||
let(:report) do
|
||||
report_options = { report_type: described_class::REPORT_TYPE }
|
||||
OpenFoodNetwork::OrdersAndFulfillmentsReport.new(permissions, report_options, true)
|
||||
OpenFoodNetwork::OrdersAndFulfillmentsReport.new(current_user, report_options, true)
|
||||
end
|
||||
|
||||
let(:report_table) do
|
||||
|
||||
@@ -23,7 +23,7 @@ describe OpenFoodNetwork::OrdersAndFulfillmentsReport do
|
||||
before { order.line_items << line_item }
|
||||
|
||||
context "as a site admin" do
|
||||
subject { described_class.new OpenFoodNetwork::Permissions.new(admin_user), {}, true }
|
||||
subject { described_class.new(admin_user, {}, true) }
|
||||
|
||||
it "fetches completed orders" do
|
||||
o2 = create(:order)
|
||||
@@ -39,7 +39,7 @@ describe OpenFoodNetwork::OrdersAndFulfillmentsReport do
|
||||
end
|
||||
|
||||
context "as a manager of a supplier" do
|
||||
subject { described_class.new OpenFoodNetwork::Permissions.new(user), {}, true }
|
||||
subject { described_class.new(user, {}, true) }
|
||||
|
||||
let(:s1) { create(:supplier_enterprise) }
|
||||
|
||||
@@ -91,14 +91,14 @@ describe OpenFoodNetwork::OrdersAndFulfillmentsReport do
|
||||
o2.line_items << li2
|
||||
end
|
||||
|
||||
it "shows line items supplied by my producers, with names hidden" do
|
||||
it "does not show line items supplied by my producers" do
|
||||
expect(subject.table_items).to eq([])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "as a manager of a distributor" do
|
||||
subject { described_class.new OpenFoodNetwork::Permissions.new(user), {}, true }
|
||||
subject { described_class.new(user, {}, true) }
|
||||
|
||||
before do
|
||||
distributor.enterprise_roles.create!(user: user)
|
||||
@@ -133,8 +133,7 @@ describe OpenFoodNetwork::OrdersAndFulfillmentsReport do
|
||||
]
|
||||
|
||||
report_types.each do |report_type|
|
||||
report = described_class.new OpenFoodNetwork::Permissions.new(admin_user),
|
||||
report_type: report_type
|
||||
report = described_class.new(admin_user, report_type: report_type)
|
||||
expect(report.header.size).to eq(report.columns.size)
|
||||
end
|
||||
end
|
||||
@@ -150,9 +149,7 @@ describe OpenFoodNetwork::OrdersAndFulfillmentsReport do
|
||||
end
|
||||
|
||||
let(:items) {
|
||||
report = described_class.new(OpenFoodNetwork::Permissions.new(admin_user),
|
||||
{ report_type: "order_cycle_customer_totals" },
|
||||
true)
|
||||
report = described_class.new(admin_user, { report_type: "order_cycle_customer_totals" }, true)
|
||||
OpenFoodNetwork::OrderGrouper.new(report.rules, report.columns).table(report.table_items)
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ module OpenFoodNetwork
|
||||
o2.line_items << li2
|
||||
end
|
||||
|
||||
it "shows line items supplied by my producers, with names hidden" do
|
||||
it "does not show line items supplied by my producers" do
|
||||
expect(subject.table_items).to eq([])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -269,137 +269,6 @@ module OpenFoodNetwork
|
||||
end
|
||||
end
|
||||
|
||||
describe "finding orders that are visible in reports" do
|
||||
let(:distributor) { create(:distributor_enterprise) }
|
||||
let(:coordinator) { create(:distributor_enterprise) }
|
||||
let(:random_enterprise) { create(:distributor_enterprise) }
|
||||
let(:order_cycle) { create(:simple_order_cycle, coordinator: coordinator, distributors: [distributor]) }
|
||||
let(:order) { create(:order, order_cycle: order_cycle, distributor: distributor ) }
|
||||
let!(:line_item) { create(:line_item, order: order) }
|
||||
let!(:producer) { create(:supplier_enterprise) }
|
||||
|
||||
before do
|
||||
allow(permissions).to receive(:coordinated_order_cycles) { Enterprise.where("1=0") }
|
||||
end
|
||||
|
||||
context "as the hub through which the order was placed" do
|
||||
before do
|
||||
allow(permissions).to receive(:managed_enterprises) { Enterprise.where(id: distributor) }
|
||||
end
|
||||
|
||||
it "should let me see the order" do
|
||||
expect(permissions.visible_orders).to include order
|
||||
end
|
||||
end
|
||||
|
||||
context "as the coordinator of the order cycle through which the order was placed" do
|
||||
before do
|
||||
allow(permissions).to receive(:managed_enterprises) { Enterprise.where(id: coordinator) }
|
||||
allow(permissions).to receive(:coordinated_order_cycles) { OrderCycle.where(id: order_cycle) }
|
||||
end
|
||||
|
||||
it "should let me see the order" do
|
||||
expect(permissions.visible_orders).to include order
|
||||
end
|
||||
end
|
||||
|
||||
context "as a producer which has granted P-OC to the distributor of an order" do
|
||||
before do
|
||||
allow(permissions).to receive(:managed_enterprises) { Enterprise.where(id: producer) }
|
||||
create(:enterprise_relationship, parent: producer, child: distributor, permissions_list: [:add_to_order_cycle])
|
||||
end
|
||||
|
||||
context "which contains my products" do
|
||||
before do
|
||||
line_item.product.supplier = producer
|
||||
line_item.product.save
|
||||
end
|
||||
|
||||
it "should let me see the order" do
|
||||
expect(permissions.visible_orders).to include order
|
||||
end
|
||||
end
|
||||
|
||||
context "which does not contain my products" do
|
||||
it "should not let me see the order" do
|
||||
expect(permissions.visible_orders).to_not include order
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "as an enterprise that is a distributor in the order cycle, but not the distributor of the order" do
|
||||
before do
|
||||
allow(permissions).to receive(:managed_enterprises) { Enterprise.where(id: random_enterprise) }
|
||||
end
|
||||
|
||||
it "should not let me see the order" do
|
||||
expect(permissions.visible_orders).to_not include order
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "finding line items that are visible in reports" do
|
||||
let(:distributor) { create(:distributor_enterprise) }
|
||||
let(:coordinator) { create(:distributor_enterprise) }
|
||||
let(:random_enterprise) { create(:distributor_enterprise) }
|
||||
let(:order_cycle) { create(:simple_order_cycle, coordinator: coordinator, distributors: [distributor]) }
|
||||
let(:order) { create(:order, order_cycle: order_cycle, distributor: distributor ) }
|
||||
let!(:line_item1) { create(:line_item, order: order) }
|
||||
let!(:line_item2) { create(:line_item, order: order) }
|
||||
let!(:producer) { create(:supplier_enterprise) }
|
||||
|
||||
before do
|
||||
allow(permissions).to receive(:coordinated_order_cycles) { Enterprise.where("1=0") }
|
||||
end
|
||||
|
||||
context "as the hub through which the parent order was placed" do
|
||||
before do
|
||||
allow(permissions).to receive(:managed_enterprises) { Enterprise.where(id: distributor) }
|
||||
end
|
||||
|
||||
it "should let me see the line_items" do
|
||||
expect(permissions.visible_line_items).to include line_item1, line_item2
|
||||
end
|
||||
end
|
||||
|
||||
context "as the coordinator of the order cycle through which the parent order was placed" do
|
||||
before do
|
||||
allow(permissions).to receive(:managed_enterprises) { Enterprise.where(id: coordinator) }
|
||||
allow(permissions).to receive(:coordinated_order_cycles) { OrderCycle.where(id: order_cycle) }
|
||||
end
|
||||
|
||||
it "should let me see the line_items" do
|
||||
expect(permissions.visible_line_items).to include line_item1, line_item2
|
||||
end
|
||||
end
|
||||
|
||||
context "as the manager producer which has granted P-OC to the distributor of the parent order" do
|
||||
before do
|
||||
allow(permissions).to receive(:managed_enterprises) { Enterprise.where(id: producer) }
|
||||
create(:enterprise_relationship, parent: producer, child: distributor, permissions_list: [:add_to_order_cycle])
|
||||
|
||||
line_item1.product.supplier = producer
|
||||
line_item1.product.save
|
||||
end
|
||||
|
||||
it "should let me see the line_items pertaining to variants I produce" do
|
||||
ps = permissions.visible_line_items
|
||||
expect(ps).to include line_item1
|
||||
expect(ps).to_not include line_item2
|
||||
end
|
||||
end
|
||||
|
||||
context "as an enterprise that is a distributor in the order cycle, but not the distributor of the parent order" do
|
||||
before do
|
||||
allow(permissions).to receive(:managed_enterprises) { Enterprise.where(id: random_enterprise) }
|
||||
end
|
||||
|
||||
it "should not let me see the line_items" do
|
||||
expect(permissions.visible_line_items).to_not include line_item1, line_item2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "finding visible subscriptions" do
|
||||
let!(:so1) { create(:subscription) }
|
||||
let!(:so2) { create(:subscription) }
|
||||
|
||||
142
spec/services/permissions/order_spec.rb
Normal file
142
spec/services/permissions/order_spec.rb
Normal file
@@ -0,0 +1,142 @@
|
||||
require 'spec_helper'
|
||||
|
||||
module Permissions
|
||||
describe Order do
|
||||
let(:user) { double(:user) }
|
||||
let(:permissions) { Permissions::Order.new(user) }
|
||||
let!(:basic_permissions) { OpenFoodNetwork::Permissions.new(user) }
|
||||
|
||||
before { allow(OpenFoodNetwork::Permissions).to receive(:new) { basic_permissions } }
|
||||
|
||||
describe "finding orders that are visible in reports" do
|
||||
let(:distributor) { create(:distributor_enterprise) }
|
||||
let(:coordinator) { create(:distributor_enterprise) }
|
||||
let(:random_enterprise) { create(:distributor_enterprise) }
|
||||
let(:order_cycle) { create(:simple_order_cycle, coordinator: coordinator, distributors: [distributor]) }
|
||||
let(:order) { create(:order, order_cycle: order_cycle, distributor: distributor ) }
|
||||
let!(:line_item) { create(:line_item, order: order) }
|
||||
let!(:producer) { create(:supplier_enterprise) }
|
||||
|
||||
before do
|
||||
allow(basic_permissions).to receive(:coordinated_order_cycles) { Enterprise.where("1=0") }
|
||||
end
|
||||
|
||||
context "as the hub through which the order was placed" do
|
||||
before do
|
||||
allow(basic_permissions).to receive(:managed_enterprises) { Enterprise.where(id: distributor) }
|
||||
end
|
||||
|
||||
it "should let me see the order" do
|
||||
expect(permissions.visible_orders).to include order
|
||||
end
|
||||
end
|
||||
|
||||
context "as the coordinator of the order cycle through which the order was placed" do
|
||||
before do
|
||||
allow(basic_permissions).to receive(:managed_enterprises) { Enterprise.where(id: coordinator) }
|
||||
allow(basic_permissions).to receive(:coordinated_order_cycles) { OrderCycle.where(id: order_cycle) }
|
||||
end
|
||||
|
||||
it "should let me see the order" do
|
||||
expect(permissions.visible_orders).to include order
|
||||
end
|
||||
end
|
||||
|
||||
context "as a producer which has granted P-OC to the distributor of an order" do
|
||||
before do
|
||||
allow(basic_permissions).to receive(:managed_enterprises) { Enterprise.where(id: producer) }
|
||||
create(:enterprise_relationship, parent: producer, child: distributor, permissions_list: [:add_to_order_cycle])
|
||||
end
|
||||
|
||||
context "which contains my products" do
|
||||
before do
|
||||
line_item.product.supplier = producer
|
||||
line_item.product.save
|
||||
end
|
||||
|
||||
it "should let me see the order" do
|
||||
expect(permissions.visible_orders).to include order
|
||||
end
|
||||
end
|
||||
|
||||
context "which does not contain my products" do
|
||||
it "should not let me see the order" do
|
||||
expect(permissions.visible_orders).to_not include order
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "as an enterprise that is a distributor in the order cycle, but not the distributor of the order" do
|
||||
before do
|
||||
allow(basic_permissions).to receive(:managed_enterprises) { Enterprise.where(id: random_enterprise) }
|
||||
end
|
||||
|
||||
it "should not let me see the order" do
|
||||
expect(permissions.visible_orders).to_not include order
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "finding line items that are visible in reports" do
|
||||
let(:distributor) { create(:distributor_enterprise) }
|
||||
let(:coordinator) { create(:distributor_enterprise) }
|
||||
let(:random_enterprise) { create(:distributor_enterprise) }
|
||||
let(:order_cycle) { create(:simple_order_cycle, coordinator: coordinator, distributors: [distributor]) }
|
||||
let(:order) { create(:order, order_cycle: order_cycle, distributor: distributor ) }
|
||||
let!(:line_item1) { create(:line_item, order: order) }
|
||||
let!(:line_item2) { create(:line_item, order: order) }
|
||||
let!(:producer) { create(:supplier_enterprise) }
|
||||
|
||||
before do
|
||||
allow(basic_permissions).to receive(:coordinated_order_cycles) { Enterprise.where("1=0") }
|
||||
end
|
||||
|
||||
context "as the hub through which the parent order was placed" do
|
||||
before do
|
||||
allow(basic_permissions).to receive(:managed_enterprises) { Enterprise.where(id: distributor) }
|
||||
end
|
||||
|
||||
it "should let me see the line_items" do
|
||||
expect(permissions.visible_line_items).to include line_item1, line_item2
|
||||
end
|
||||
end
|
||||
|
||||
context "as the coordinator of the order cycle through which the parent order was placed" do
|
||||
before do
|
||||
allow(basic_permissions).to receive(:managed_enterprises) { Enterprise.where(id: coordinator) }
|
||||
allow(basic_permissions).to receive(:coordinated_order_cycles) { OrderCycle.where(id: order_cycle) }
|
||||
end
|
||||
|
||||
it "should let me see the line_items" do
|
||||
expect(permissions.visible_line_items).to include line_item1, line_item2
|
||||
end
|
||||
end
|
||||
|
||||
context "as the manager producer which has granted P-OC to the distributor of the parent order" do
|
||||
before do
|
||||
allow(basic_permissions).to receive(:managed_enterprises) { Enterprise.where(id: producer) }
|
||||
create(:enterprise_relationship, parent: producer, child: distributor, permissions_list: [:add_to_order_cycle])
|
||||
|
||||
line_item1.product.supplier = producer
|
||||
line_item1.product.save
|
||||
end
|
||||
|
||||
it "should let me see the line_items pertaining to variants I produce" do
|
||||
ps = permissions.visible_line_items
|
||||
expect(ps).to include line_item1
|
||||
expect(ps).to_not include line_item2
|
||||
end
|
||||
end
|
||||
|
||||
context "as an enterprise that is a distributor in the order cycle, but not the distributor of the parent order" do
|
||||
before do
|
||||
allow(basic_permissions).to receive(:managed_enterprises) { Enterprise.where(id: random_enterprise) }
|
||||
end
|
||||
|
||||
it "should not let me see the line_items" do
|
||||
expect(permissions.visible_line_items).to_not include line_item1, line_item2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -100,6 +100,7 @@ RSpec.configure do |config|
|
||||
config.before(:suite) { DatabaseCleaner.clean_with :deletion, except: ['spree_countries', 'spree_states'] }
|
||||
config.before(:each) { DatabaseCleaner.strategy = :transaction }
|
||||
config.before(:each, js: true) { DatabaseCleaner.strategy = :deletion, { except: ['spree_countries', 'spree_states'] } }
|
||||
config.before(:each, concurrency: true) { DatabaseCleaner.strategy = :deletion, { except: ['spree_countries', 'spree_states'] } }
|
||||
config.before(:each) { DatabaseCleaner.start }
|
||||
config.after(:each) { DatabaseCleaner.clean }
|
||||
config.after(:each, js: true) do
|
||||
|
||||
Reference in New Issue
Block a user