Add option to ignore delivered amounts in order group distribution (#765)

This commit is contained in:
lentschi 2021-02-05 16:19:05 +01:00 committed by GitHub
parent ecda1c1478
commit 45a8911ca6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 69 additions and 4 deletions

View File

@ -128,15 +128,18 @@ class GroupOrderArticle < ApplicationRecord
order_quantities = GroupOrderArticleQuantity.where(group_order_article_id: order_article.group_order_article_ids).order('created_on') order_quantities = GroupOrderArticleQuantity.where(group_order_article_id: order_article.group_order_article_ids).order('created_on')
logger.debug "GroupOrderArticleQuantity records found: #{order_quantities.size}" logger.debug "GroupOrderArticleQuantity records found: #{order_quantities.size}"
first_order_first_serve = (FoodsoftConfig[:distribution_strategy] == FoodsoftConfig::DistributionStrategy::FIRST_ORDER_FIRST_SERVE)
# Determine quantities to be ordered... # Determine quantities to be ordered...
order_quantities.each do |goaq| order_quantities.each do |goaq|
q = [goaq.quantity, total - total_quantity].min q = goaq.quantity
q = [q, total - total_quantity].min if first_order_first_serve
total_quantity += q total_quantity += q
if goaq.group_order_article_id == self.id if goaq.group_order_article_id == self.id
logger.debug "increasing quantity by #{q}" logger.debug "increasing quantity by #{q}"
quantity += q quantity += q
end end
break if total_quantity >= total break if total_quantity >= total && first_order_first_serve
end end
# Determine tolerance to be ordered... # Determine tolerance to be ordered...

View File

@ -1,11 +1,10 @@
class ConfigSerializer < ActiveModel::Serializer class ConfigSerializer < ActiveModel::Serializer
# details # details
attributes :name, :homepage, :contact attributes :name, :homepage, :contact
# settings # settings
attributes :currency_unit, :currency_space, :default_locale, :price_markup, attributes :currency_unit, :currency_space, :default_locale, :price_markup,
:tolerance_is_costly, :use_apple_points, :use_tolerance :tolerance_is_costly, :distribution_strategy, :use_apple_points, :use_tolerance
# layout # layout
attributes :page_footer_html, :webstats_tracking_code_html attributes :page_footer_html, :webstats_tracking_code_html

View File

@ -1,5 +1,8 @@
= config_input form, :use_nick, as: :boolean = config_input form, :use_nick, as: :boolean
= config_input form, :tolerance_is_costly, as: :boolean = config_input form, :tolerance_is_costly, as: :boolean
- distribution_strategy_options = FoodsoftConfig::DistributionStrategy.constants.map { |c| FoodsoftConfig::DistributionStrategy.const_get(c) }
= config_input form, :distribution_strategy, as: :select, collection: distribution_strategy_options,
include_blank: false, input_html: {class: 'input-xxlarge'}, label_method: ->(s){ t("config.keys.distribution_strategy_options.#{s}") }
= config_input form, :disable_invite, as: :boolean = config_input form, :disable_invite, as: :boolean
= config_input form, :help_url, as: :url, input_html: {class: 'input-xlarge'} = config_input form, :help_url, as: :url, input_html: {class: 'input-xlarge'}
= config_input form, :webstats_tracking_code, as: :text, input_html: {class: 'input-xxlarge', rows: 3} = config_input form, :webstats_tracking_code, as: :text, input_html: {class: 'input-xxlarge', rows: 3}

View File

@ -597,6 +597,7 @@ de:
tasks_upfront_days: Anzahl der Tage, für welche du im Voraus wiederkehrende Aufgaben definieren möchtest tasks_upfront_days: Anzahl der Tage, für welche du im Voraus wiederkehrende Aufgaben definieren möchtest
tax_default: Standard Mehrwertsteuersatz für neue Artikel tax_default: Standard Mehrwertsteuersatz für neue Artikel
tolerance_is_costly: Eine möglichst große Menge im Rahmen der Tolerenz bestellen. Wenn dies nicht aktiviert ist, wird im Rahmen der Toleranz nur so viel bestellt, dass damit komplette Einheiten (Boxen) bestellt werden können. Die Option wirkt sich auch auf die Toleranz des Gesamtpreises einer offenen Mitgliederbestellung aus. tolerance_is_costly: Eine möglichst große Menge im Rahmen der Tolerenz bestellen. Wenn dies nicht aktiviert ist, wird im Rahmen der Toleranz nur so viel bestellt, dass damit komplette Einheiten (Boxen) bestellt werden können. Die Option wirkt sich auch auf die Toleranz des Gesamtpreises einer offenen Mitgliederbestellung aus.
distribution_strategy: Wie bei der Verteilung von Artikeln nach dem Empfangen einer Bestellung vorgegangen werden soll.
use_apple_points: Wenn das Apfel Punktesystem aktiviert ist, ist es erforderlich, dass Mitglieder Aufgaben erledigen um bestellen zu können. use_apple_points: Wenn das Apfel Punktesystem aktiviert ist, ist es erforderlich, dass Mitglieder Aufgaben erledigen um bestellen zu können.
use_boxfill: Wenn aktiviert, können Benutzer nahe am Ende der Bestellung diese nur mehr so verändern, dass sich die Gesamtsumme erhöht. Dies hilft beim auffüllen der verbleibenden Kisten. Es muss trotzdem noch das Kistenauffülldatum bei der Bestellung gesetzt werden. use_boxfill: Wenn aktiviert, können Benutzer nahe am Ende der Bestellung diese nur mehr so verändern, dass sich die Gesamtsumme erhöht. Dies hilft beim auffüllen der verbleibenden Kisten. Es muss trotzdem noch das Kistenauffülldatum bei der Bestellung gesetzt werden.
use_iban: Zusätzlich Feld für die internationale Kontonummer bei Benutzern und Lieferanten anzeigen use_iban: Zusätzlich Feld für die internationale Kontonummer bei Benutzern und Lieferanten anzeigen
@ -650,6 +651,10 @@ de:
tax_default: Mehrwertsteuer tax_default: Mehrwertsteuer
time_zone: Zeitzone time_zone: Zeitzone
tolerance_is_costly: Bestelltoleranz maximal ausnutzen, um möglichst große Mengen zu bestellen tolerance_is_costly: Bestelltoleranz maximal ausnutzen, um möglichst große Mengen zu bestellen
distribution_strategy: Verteilungs-Strategie
distribution_strategy_options:
first_order_first_serve: Zuerst an die verteilen, die zuerst bestellt haben
no_automatic_distribution: Keine automatische Verteilung
use_apple_points: Apfelpunkte verwenden use_apple_points: Apfelpunkte verwenden
use_boxfill: Kistenauffüllphase use_boxfill: Kistenauffüllphase
use_iban: IBAN verwenden use_iban: IBAN verwenden

View File

@ -597,6 +597,7 @@ en:
tasks_upfront_days: For how many days in advance you would like to schedule periodic tasks. tasks_upfront_days: For how many days in advance you would like to schedule periodic tasks.
tax_default: Default VAT percentage for new articles. tax_default: Default VAT percentage for new articles.
tolerance_is_costly: Order as much of the member tolerance as possible (compared to only as much needed to fill the last box). Enabling this also includes the tolerance in the total price of the open member order. tolerance_is_costly: Order as much of the member tolerance as possible (compared to only as much needed to fill the last box). Enabling this also includes the tolerance in the total price of the open member order.
distribution_strategy: How articles should be distributed after an order has been received.
use_apple_points: When the apple point system is enabled, members are required to do some tasks to be able to keep ordering. use_apple_points: When the apple point system is enabled, members are required to do some tasks to be able to keep ordering.
use_boxfill: When enabled, near end of an order, members are only able to change their order when increases the total amount ordered. This helps to fill any remaining boxes. You still need to set a box-fill date for the orders. use_boxfill: When enabled, near end of an order, members are only able to change their order when increases the total amount ordered. This helps to fill any remaining boxes. You still need to set a box-fill date for the orders.
use_iban: When enabled, supplier and user provide an additonal field for storing the international bank account number. use_iban: When enabled, supplier and user provide an additonal field for storing the international bank account number.
@ -650,6 +651,10 @@ en:
tax_default: Default VAT tax_default: Default VAT
time_zone: Time zone time_zone: Time zone
tolerance_is_costly: Tolerance is costly tolerance_is_costly: Tolerance is costly
distribution_strategy: Distribution strategy
distribution_strategy_options:
first_order_first_serve: First distribute to those who ordered first
no_automatic_distribution: No automatic distribution
use_apple_points: Apple points use_apple_points: Apple points
use_boxfill: Box-fill phase use_boxfill: Box-fill phase
use_iban: Use IBAN use_iban: Use IBAN

View File

@ -561,6 +561,7 @@ es:
tasks_upfront_days: Con cuántos días de antelación te gustaría programar las tareas periódicas. tasks_upfront_days: Con cuántos días de antelación te gustaría programar las tareas periódicas.
tax_default: Porcentaje por defecto del IVA para artículos nuevos. tax_default: Porcentaje por defecto del IVA para artículos nuevos.
tolerance_is_costly: Pide lo que más permita la tolerancia de los miembros (en lugar de sólo lo necesario para llenar la última caja). Permitir esto también incluye la tolerancia en el precio final del pedido abierto de cada miembro. tolerance_is_costly: Pide lo que más permita la tolerancia de los miembros (en lugar de sólo lo necesario para llenar la última caja). Permitir esto también incluye la tolerancia en el precio final del pedido abierto de cada miembro.
distribution_strategy: Cómo se deben distribuir los artículos después de recibir un pedido.
use_apple_points: Cuando el sistema de puntos-manzana está habilitado los miembros deberán realizar algunas tareas para poder hacer pedidos. use_apple_points: Cuando el sistema de puntos-manzana está habilitado los miembros deberán realizar algunas tareas para poder hacer pedidos.
use_boxfill: Cuando está activado, cerca del cierre de un pedido los miembros no podrán cambiar su pedido a menos que se incremente el valor pedido total. Esto ayudará a llenar las cajas que faltan. Igualmente deberás decidir una fecha de llenado de cajas para los pedidos. use_boxfill: Cuando está activado, cerca del cierre de un pedido los miembros no podrán cambiar su pedido a menos que se incremente el valor pedido total. Esto ayudará a llenar las cajas que faltan. Igualmente deberás decidir una fecha de llenado de cajas para los pedidos.
use_iban: Cuando esta opción está habilitada, el proveedor y el usuario pueden guardan también su número de cuenta bancaria internacional (IBAN). use_iban: Cuando esta opción está habilitada, el proveedor y el usuario pueden guardan también su número de cuenta bancaria internacional (IBAN).
@ -605,6 +606,10 @@ es:
tax_default: IVA por defecto tax_default: IVA por defecto
time_zone: Zona horaria time_zone: Zona horaria
tolerance_is_costly: La tolerancia es prioritaria tolerance_is_costly: La tolerancia es prioritaria
distribution_strategy: Estrategia de distribución
distribution_strategy_options:
first_order_first_serve: Primero distribuya a quienes ordenaron primero
no_automatic_distribution: Sin distribución automática
use_apple_points: Puntos-manzana use_apple_points: Puntos-manzana
use_boxfill: Fase de llenar las cajas use_boxfill: Fase de llenar las cajas
use_iban: Usar IBAN use_iban: Usar IBAN

View File

@ -403,6 +403,7 @@ fr:
hints: hints:
homepage: Site de votre coop. homepage: Site de votre coop.
name: Le nom de votre coop. name: Le nom de votre coop.
distribution_strategy: Comment procéder à la distribution des articles après réception d'une commande.
keys: keys:
contact: contact:
city: Ville city: Ville
@ -413,6 +414,10 @@ fr:
zip_code: Code postal zip_code: Code postal
currency_unit: Monnaie currency_unit: Monnaie
name: Nom name: Nom
distribution_strategy: Stratégie de distribution
distribution_strategy_options:
first_order_first_serve: Distribuez d'abord à ceux qui ont commandé en premier
no_automatic_distribution: Pas de distribution automatique
tabs: tabs:
language: Langue language: Langue
list: Liste list: Liste

View File

@ -597,6 +597,7 @@ nl:
tasks_upfront_days: Hoeveel dagen vantevoren je periodieke taken wil aanmaken. tasks_upfront_days: Hoeveel dagen vantevoren je periodieke taken wil aanmaken.
tax_default: Standaard BTW percentage voor nieuwe artikelen. tax_default: Standaard BTW percentage voor nieuwe artikelen.
tolerance_is_costly: Bestel zoveel artikelen als mogelijk in de tolerantie (in plaats van net genoeg om de laatste doos te vullen). Dit zorgt er ook voor dat de tolerantie in de prijs van open ledenbestellingen wordt meegenomen. tolerance_is_costly: Bestel zoveel artikelen als mogelijk in de tolerantie (in plaats van net genoeg om de laatste doos te vullen). Dit zorgt er ook voor dat de tolerantie in de prijs van open ledenbestellingen wordt meegenomen.
distribution_strategy: Hoe verder te gaan met de distributie van artikelen na ontvangst van een bestelling.
use_apple_points: Wanneer het appelpunten systeem is geactiveerd, kunnen leden slechts bestellen wanneer ze meewerken aan taken. use_apple_points: Wanneer het appelpunten systeem is geactiveerd, kunnen leden slechts bestellen wanneer ze meewerken aan taken.
use_boxfill: Wanneer dit aan staat, kunnen gebruikers aan het einde van de bestelfase hun bestelling alleen wijzigen als het de totale bestelling vergroot. Dit helpt om dozen te vullen. Bij de bestelling moet nog wel de dozen-vul-datum ingevuld worden. use_boxfill: Wanneer dit aan staat, kunnen gebruikers aan het einde van de bestelfase hun bestelling alleen wijzigen als het de totale bestelling vergroot. Dit helpt om dozen te vullen. Bij de bestelling moet nog wel de dozen-vul-datum ingevuld worden.
use_iban: Om leverancier en gebruiker een extra veld te geven voor het internationale bankrekeningnummer (IBAN). use_iban: Om leverancier en gebruiker een extra veld te geven voor het internationale bankrekeningnummer (IBAN).
@ -650,6 +651,10 @@ nl:
tax_default: Standaard BTW tax_default: Standaard BTW
time_zone: Tijdzone time_zone: Tijdzone
tolerance_is_costly: Tolerantie is duur tolerance_is_costly: Tolerantie is duur
distribution_strategy: Distributie strategie
distribution_strategy_options:
first_order_first_serve: Verdeel eerst onder degenen die het eerst hebben besteld
no_automatic_distribution: Geen automatische distributie
use_apple_points: Appelpunten use_apple_points: Appelpunten
use_boxfill: Dozen vullen fase use_boxfill: Dozen vullen fase
use_iban: IBAN gebruiken use_iban: IBAN gebruiken

View File

@ -54,6 +54,12 @@ class FoodsoftConfig
# Loaded configuration # Loaded configuration
APP_CONFIG = ActiveSupport::HashWithIndifferentAccess.new APP_CONFIG = ActiveSupport::HashWithIndifferentAccess.new
# distribution strategy config values enum
module DistributionStrategy
FIRST_ORDER_FIRST_SERVE = 'first_order_first_serve'
NO_AUTOMATIC_DISTRIBUTION = 'no_automatic_distribution'
end
class << self class << self
# Load and initialize foodcoop configuration file. # Load and initialize foodcoop configuration file.
@ -260,6 +266,7 @@ class FoodsoftConfig
tasks_period_days: 7, tasks_period_days: 7,
tasks_upfront_days: 49, tasks_upfront_days: 49,
shared_supplier_article_sync_limit: 200, shared_supplier_article_sync_limit: 200,
distribution_strategy: FoodsoftConfig::DistributionStrategy::FIRST_ORDER_FIRST_SERVE,
# The following keys cannot, by default, be set by foodcoops themselves. # The following keys cannot, by default, be set by foodcoops themselves.
protected: { protected: {
multi_coop_install: true, multi_coop_install: true,

View File

@ -0,0 +1,9 @@
require 'factory_bot'
FactoryBot.define do
# requires order_article
factory :group_order_article_quantity do
end
end

View File

@ -42,4 +42,23 @@ describe GroupOrderArticle do
end end
end end
describe 'distribution strategy' do
let(:article) { create :article, supplier: order.supplier, unit_quantity: 1 }
let(:oa) { order.order_articles.create(:article => article) }
let(:goa) { create :group_order_article, group_order: go, order_article: oa }
let!(:goaq) { create :group_order_article_quantity, group_order_article: goa, quantity: 4 }
it 'can calculate the result for the distribution strategy "first order first serve"' do
res = goa.calculate_result(2)
expect(res).to eq(quantity: 2, tolerance: 0, total: 2)
end
it 'can calculate the result for the distribution strategy "no automatic distribution"' do
FoodsoftConfig[:distribution_strategy] = FoodsoftConfig::DistributionStrategy::NO_AUTOMATIC_DISTRIBUTION
res = goa.calculate_result(2)
expect(res).to eq(quantity: 4, tolerance: 0, total: 4)
end
end
end end