Skip to content

Commit

Permalink
MembershipRenewal, allow to configure optional attributes
Browse files Browse the repository at this point in the history
This patch allows to configure certain memberships attributes that will
be ignored when renewing a membership. This is useful for attributes
that are not always relevant a year to another, like the number of
activity participations or some temporary price adjustments.

Close #72
  • Loading branch information
thibaudgg committed Aug 25, 2023
1 parent 0556dc6 commit 20b45ce
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 8 deletions.
5 changes: 4 additions & 1 deletion app/admin/acp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@
*I18n.available_locales.map { |l| "member_information_text_#{l}" },
billing_year_divisions: [],
languages: [],
features: []
features: [],
membership_renewed_attributes: []

form data: { controller: 'code-editor' } do |f|
div do
Expand Down Expand Up @@ -218,6 +219,8 @@
required: false,
hint: t('formtastic.hints.acp.open_renewal_text'))
f.input :open_renewal_reminder_sent_after_in_days
f.input :membership_renewed_attributes, as: :check_boxes,
collection: membership_renewed_attributes_collection
f.input :membership_renewal_depot_update

handbook_button(self, 'membership_renewal')
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions app/helpers/acps_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,28 @@ def fiscal_year_months_range
def link_to_acp_website(options = {})
link_to Current.acp.url.sub(/https?:\/\//, ''), Current.acp.url, options
end

def membership_renewed_attributes_collection
col = [[
Membership.human_attribute_name(:baskets_annual_price_change),
'baskets_annual_price_change'
]]
if BasketComplement.any?
col << [
Membership.human_attribute_name(:basket_complements_annual_price_change),
'basket_complements_annual_price_change'
]
end
if feature?('activity')
col << [
"#{t('formtastic.labels.membership.activity_participations_annual_price_change')} (#{activities_human_name})",
'activity_participations_annual_price_change'
]
col << [
"#{activities_human_name} (#{t('active_admin.resource.edit.full_year')})",
'activity_participations_demanded_annualy'
]
end
col
end
end
16 changes: 16 additions & 0 deletions app/models/acp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,22 @@ def calculate_basket_price_extra(extra, basket_price, basket_size_id, deliveries
).to_f
end

def membership_renewed_attributes=(attrs)
super
unless feature?('activity')
self[:membership_renewed_attributes] += %w[
activity_participations_demanded_annualy
activity_participations_annual_price_change
]
end
unless BasketComplement.any?
self[:membership_renewed_attributes] += %w[
basket_complements_annual_price_change
]
end
self[:membership_renewed_attributes].uniq!
end

private

def activity_participations_demanded_logic_must_be_valid
Expand Down
15 changes: 9 additions & 6 deletions app/models/membership_renewal.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
class MembershipRenewal
MissingDeliveriesError = Class.new(StandardError)

OPTIONAL_ATTRIBUTES = %w[
baskets_annual_price_change
basket_complements_annual_price_change
activity_participations_demanded_annualy
activity_participations_annual_price_change
]

attr_reader :membership, :fiscal_year

def initialize(membership)
Expand Down Expand Up @@ -32,18 +39,14 @@ def renew!(attrs = {})
def renewed_attrs(attrs = {})
membership
.attributes
.slice(*%w[
.slice(*(%w[
member_id
basket_size_id
basket_quantity
basket_price_extra
baskets_annual_price_change
depot_id
deliveries_cycle_id
activity_participations_demanded_annualy
activity_participations_annual_price_change
basket_complements_annual_price_change
])
] + (OPTIONAL_ATTRIBUTES & Current.acp.membership_renewed_attributes)))
.symbolize_keys
.merge(
started_on: fiscal_year.beginning_of_year,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Renouvellement: configurations reprises

Il est maintenant possible [de paramétrer si certaines configurations](/settings#membership_renewal) sont reprises ou non lors du renouvellement d'un abonnement. Historiquement ces configurations étaient toujours reprises, ce qui pouvait poser problème dans certaines situations.

Dans tous les cas, et comme précédemment, si un changement de taille du panier ou de compléments est choisi par le membre, les configurations correspondantes ne sont pas reprises lors du renouvellement.

![Paramètres](<%= image_url('updates/20230825_membership_renewed_attributes/settings.png') %>){:width="90%"}

Retrouvez plus d'informations sur le renouvellement des abonnements dans [le manuel](handbook/membership_renewal).
4 changes: 4 additions & 0 deletions config/locales/activerecord.yml
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,10 @@ _:
_de: Erlauben Sie die Änderung das Depot
_fr: Permettre le changement du dépôt
_it: Permettere il cambiamento del punto di ritiro
membership_renewed_attributes:
_de: Übernommene Konfigurationen
_fr: Configurations reprises
_it: Configurazioni riprese
membership_update_text:
_de: Erläuterung
_fr: Explication
Expand Down
8 changes: 8 additions & 0 deletions config/locales/formtastic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,14 @@ _:
_de: Nur die Änderung zukünftiger Lieferungen ist erlaubt.
_fr: Seule la modification des futures livraisons est autorisée.
_it: È consentita solo la modifica delle consegne future.
membership_renewal_depot_update:
_de: Ermöglicht es Mitgliedern, das Depot bei der Verlängerung ihres Abonnements über das Formular zu ändern.
_fr: Permettre au membre de changer de dépôt lors du renouvellement de son abonnement via le formulaire.
_it: Permettere al socio di cambiare il punto di ritiro al momento del rinnovo dell'abbonamento tramite il modulo.
membership_renewed_attributes:
_de: Die ausgewählten Konfigurationen werden beim Verlängern des Abonnements automatisch übernommen. Wenn die Korbgröße oder die Zusätze vom Mitglied geändert werden, werden die entsprechenden Konfigurationen sowieso gelöscht.
_fr: Les configurations sélectionnées seront automatiquement reprises lors du renouvellement de l'abonnement tel quel. Si la taille du panier ou les compléments sont modifiés par le membre, alors les configurations correspondantes seront de toute façon effacées.
_it: Le configurazioni selezionate saranno automaticamente riprese al momento del rinnovo dell'abbonamento. Se la dimensione del cesto o gli extra vengono modificati dal socio, le configurazioni corrispondenti saranno comunque cancellate.
membership_update_text:
_de: Optionaler Text, der auf der Mitgliederseite über dem Formular zur Änderung des Abonnements oder der Tasche angezeigt wird.
_fr: Texte optionnel affiché sur la page de membre au-dessus du formulaire de modification de l'abonnement ou du panier.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddMembershipRenewedAttributesToAcps < ActiveRecord::Migration[7.0]
def change
add_column :acps, :membership_renewed_attributes, :string, array: true, default: MembershipRenewal::OPTIONAL_ATTRIBUTES
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_25_070903) do
ActiveRecord::Schema[7.0].define(version: 2023_08_25_120451) do
# These are extensions that must be enabled in order to support this database
enable_extension "hstore"
enable_extension "plpgsql"
Expand Down Expand Up @@ -111,6 +111,7 @@
t.string "depots_member_order_mode", default: "price_asc", null: false
t.string "deliveries_cycles_member_order_mode", default: "deliveries_count_desc", null: false
t.integer "shop_order_automatic_invoicing_delay_in_days"
t.string "membership_renewed_attributes", default: ["baskets_annual_price_change", "basket_complements_annual_price_change", "activity_participations_demanded_annualy", "activity_participations_annual_price_change"], array: true
t.index ["host"], name: "index_acps_on_host"
t.index ["tenant_name"], name: "index_acps_on_tenant_name"
end
Expand Down
32 changes: 32 additions & 0 deletions spec/models/membership_renewal_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,36 @@
basket_complements_annual_price_change: 0)
expect(renewed.memberships_basket_complements.count).to eq 1
end

specify 'ignore optional attributes' do
create(:delivery, date: next_fy.beginning_of_year)
create(:basket_complement, id: 1, price: 3.2)
create(:basket_complement, id: 2, price: 4.5)
membership = create(:membership,
baskets_annual_price_change: 130,
activity_participations_demanded_annualy: 5,
activity_participations_annual_price_change: -60,
basket_complements_annual_price_change: -32,
memberships_basket_complements_attributes: {
'0' => { basket_complement_id: 1, quantity: 1 }
})

Current.acp.update!(membership_renewed_attributes: %w[
activity_participations_demanded_annualy
])

expect {
MembershipRenewal.new(membership).renew!(
memberships_basket_complements_attributes: {
'0' => { basket_complement_id: 1, quantity: 1 },
}
)
}.to change(Membership, :count).by(1)

expect(membership.renewed_membership).to have_attributes(
baskets_annual_price_change: 0,
activity_participations_demanded_annualy: 5,
activity_participations_annual_price_change: 0,
basket_complements_annual_price_change: 0)
end
end

0 comments on commit 20b45ce

Please sign in to comment.