Skip to content

Commit

Permalink
DeliveriesCycle, add minimum_gap_in_days and all_but_first results
Browse files Browse the repository at this point in the history
ACP with a different deliveries schedule across they year, for example
40 deliveries but every week during summer and every 2 weeks during
winter, that want to propose a cycle every 2 weeks weren't able to do
it. As the cycle was every 2 results, it switched to every 4 weeks
during winter.

This patch introduces a new `minimum_gap_in_days` attribute that allows
to define the minimum number of days between 2 deliveries. For example
13 for a delivery every 2 weeks.

The new `all_but_first` results allows to skip the first result of the
cycle. For example, if the cycle is every 2 weeks, it will skip the
first week of the year.

Close #102
  • Loading branch information
thibaudgg committed Aug 25, 2023
1 parent 7fd6668 commit 0556dc6
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 3 deletions.
3 changes: 3 additions & 0 deletions app/admin/deliveries_cycle.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
end
}
row(:results) { t("deliveries_cycle.results.#{dc.results}") }
row(:minimum_gap_in_days) { dc.minimum_gap_in_days }
end

panel Depot.model_name.human(count: 2) do
Expand Down Expand Up @@ -137,6 +138,7 @@
as: :select,
collection: results_collection,
include_blank: false
f.input :minimum_gap_in_days
end

f.inputs do
Expand All @@ -153,6 +155,7 @@
:member_order_priority,
:week_numbers,
:results,
:minimum_gap_in_days,
*I18n.available_locales.map { |l| "name_#{l}" },
*I18n.available_locales.map { |l| "public_name_#{l}" },
wdays: [],
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 4 additions & 1 deletion app/helpers/deliveries_cycles_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@ def week_numbers_collection
end

def results_collection
DeliveriesCycle.results.map { |enum, _|
col = DeliveriesCycle.results.map { |enum, _|
[I18n.t("deliveries_cycle.results.#{enum}"), enum]
}
# Move "all_but_first" just after "all"
col.insert(1, col.delete_at(7))
col
end

def depot_ids_with_only(delivery_cycle)
Expand Down
25 changes: 24 additions & 1 deletion app/models/deliveries_cycle.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class DeliveriesCycle < ApplicationRecord
all
odd even
quarter_1 quarter_2 quarter_3 quarter_4
all_but_first
], _suffix: true

has_many :memberships
Expand All @@ -25,6 +26,13 @@ class DeliveriesCycle < ApplicationRecord

default_scope { order_by_name }

validates :minimum_gap_in_days,
numericality: {
greater_than_or_equal_to: 1,
only_integer: true,
allow_nil: true
}

after_save :reset_cache!
after_commit :update_baskets_async, on: :update

Expand Down Expand Up @@ -141,7 +149,9 @@ def deliveries(year)
elsif even_week_numbers?
scoped = scoped.where('EXTRACT(WEEK FROM date)::integer % 2 = ?', 0)
end
if odd_results?
if all_but_first_results?
scoped = scoped.to_a[1..-1] || []
elsif odd_results?
scoped = scoped.to_a.select.with_index { |_, i| (i + 1).odd? }
elsif even_results?
scoped = scoped.to_a.select.with_index { |_, i| (i + 1).even? }
Expand All @@ -154,6 +164,9 @@ def deliveries(year)
elsif quarter_4_results?
scoped = scoped.to_a.select.with_index { |_, i| i % 4 == 3 }
end
if minimum_gap_in_days.present?
scoped = enforce_minimum_gap_in_days(scoped.to_a)
end
scoped
end

Expand All @@ -162,4 +175,14 @@ def deliveries(year)
def update_baskets_async
DeliveriesCycleBasketsUpdaterJob.perform_later(self)
end

def enforce_minimum_gap_in_days(deliveries)
past_date = nil
deliveries.select { |d|
if past_date.nil? || (d.date - past_date) >= minimum_gap_in_days
past_date = d.date
true
end
}
end
end
4 changes: 4 additions & 0 deletions config/locales/activerecord.yml
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,10 @@ _:
_fr: Complément
_it: Aggiunte
deliveries_cycle:
minimum_gap_in_days:
_de: Minimale Lücke (in Tagen)
_fr: Écart minimum (en jours)
_it: Intervallo minimo (in giorni)
months:
_de: Monate
_fr: Mois
Expand Down
4 changes: 4 additions & 0 deletions config/locales/deliveries_cycle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ _:
_de: Alle
_fr: Tous
_it: Tutti
all_but_first:
_de: Alle außer dem 1.
_fr: Tous sauf le 1er
_it: Tutti tranne il 1°
even:
_de: Geraden
_fr: Pairs
Expand Down
4 changes: 4 additions & 0 deletions config/locales/formtastic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,10 @@ _:
_de: Wenn ein Depot von der Liste entfernt wird, werden laufende oder zukünftige Abonnements dieses Depots, die diesen Lieferungszyklus verwenden, automatisch mit einem anderen Lieferungszyklus dieses Depots (dem mit den meisten Lieferungen) aktualisiert. Depots, die nur diesen einen Lieferzyklus haben, können nicht von der Liste entfernt werden.
_fr: Si un dépôt est enlevé de la liste, les abonnements en cours ou future de ce dépôt utilisant ce cycle de livraisons seront automatiquement mis à jour avec un autre cycle de livraisons de ce dépôt (celui avec le plus de livraisons). Les dépôts qui n'ont que ce cycle de livraisons ne peuvent pas être enlevés de la liste.
_it: Se un punto di ritiro viene rimosso dalla lista, gli abbonamenti attuali o futuri di questo punto di ritiro che utilizzano questo ciclo di consegna saranno automaticamente aggiornati con un altro ciclo di consegna di questo punto di ritiro (quello con più consegne). I punti di ritiro che hanno solo questa corsa di consegna non possono essere rimossi dalla lista.
minimum_gap_in_days:
_de: Ermöglicht es Ihnen, die Mindestanzahl von Tagen zwischen zwei Lieferungen festzulegen. Zum Beispiel 13 für eine Lieferung alle 2 Wochen.
_fr: Permet de définir le nombre minimum de jours entre deux livraisons. Par exemple 13 pour une livraison tous les 2 semaines.
_it: Permette di definire il numero minimo di giorni tra due consegne. Ad esempio 13 per una consegna ogni 2 settimane.
public_name:
_de: Wenn vorhanden, ersetzt den für Mitglieder angezeigten Namen (Registrierungsformular).
_fr: Si présent, remplace le nom affiché pour les membres (formulaire d'inscription).
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddMinimumGapInDaysToDeliveriesCycles < ActiveRecord::Migration[7.0]
def change
add_column :deliveries_cycles, :minimum_gap_in_days, :integer
end
end
3 changes: 2 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2023_08_10_153313) do
ActiveRecord::Schema[7.0].define(version: 2023_08_25_070903) do
# These are extensions that must be enabled in order to support this database
enable_extension "hstore"
enable_extension "plpgsql"
Expand Down Expand Up @@ -373,6 +373,7 @@
t.datetime "updated_at", null: false
t.jsonb "deliveries_counts", default: {}, null: false
t.integer "member_order_priority", default: 1, null: false
t.integer "minimum_gap_in_days"
t.index ["visible"], name: "index_deliveries_cycles_on_visible"
end

Expand Down
24 changes: 24 additions & 0 deletions spec/models/deliveries_cycle_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ def member_ordered_names
expect(cycle.current_deliveries.pluck(:date).map(&:cweek)).to eq [52, 2, 4, 6, 8]
end

specify 'all but first results' do
Array(0..9).each do |i|
create(:delivery, date: Date.today + i.day)
end

cycle = create(:deliveries_cycle, results: :all_but_first)
expect(cycle.current_deliveries_count).to eq 9
expect(cycle.current_deliveries.pluck(:number)).to eq (2..10).to_a
end

specify 'only odd results' do
Array(0..9).each do |i|
create(:delivery, date: Date.today + i.day)
Expand Down Expand Up @@ -129,6 +139,20 @@ def member_ordered_names
expect(cycle.current_deliveries.pluck(:number)).to eq [4, 8]
end

specify 'minimum 3 days gap' do
Array(0..9).each do |i|
create(:delivery, date: Date.today + i.day)
end

cycle = create(:deliveries_cycle, minimum_gap_in_days: 3)
expect(cycle.current_deliveries_count).to eq 4
expect(cycle.current_deliveries.pluck(:number)).to eq [1, 4, 7, 10]

cycle = create(:deliveries_cycle, minimum_gap_in_days: 3, results: :all_but_first)
expect(cycle.current_deliveries_count).to eq 3
expect(cycle.current_deliveries.pluck(:number)).to eq [2, 5, 8]
end

specify 'only Tuesday, in Janury, odd weeks, and even results' do
Array(0..60).each do |i|
create(:delivery, date: Date.today + i.day)
Expand Down

0 comments on commit 0556dc6

Please sign in to comment.