mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-18 07:52:23 +01:00
(feat) notify member on limit reached
This commit is contained in:
parent
6026189e59
commit
25cbf63b48
@ -1,5 +1,7 @@
|
||||
# Changelog Fab-manager
|
||||
|
||||
- [TODO DEPLOY] `rails db:seed`
|
||||
|
||||
## v5.8.2 2023 March 13
|
||||
|
||||
- Improved upgrade script
|
||||
|
@ -32,6 +32,7 @@ class Reservation < ApplicationRecord
|
||||
after_commit :notify_member_create_reservation, on: :create
|
||||
after_commit :notify_admin_member_create_reservation, on: :create
|
||||
after_commit :extend_subscription, on: :create
|
||||
after_commit :notify_member_limitation_reached, on: :create
|
||||
|
||||
delegate :user, to: :statistic_profile
|
||||
|
||||
@ -137,4 +138,14 @@ class Reservation < ApplicationRecord
|
||||
receiver: User.admins_and_managers,
|
||||
attached_object: self
|
||||
end
|
||||
|
||||
def notify_member_limitation_reached
|
||||
date = ReservationLimitService.reached_limit_date(self)
|
||||
return if date.nil?
|
||||
|
||||
NotificationCenter.call type: 'notify_member_reservation_limit_reached',
|
||||
receiver: user,
|
||||
attached_object: ReservationLimitService.limit(user.subscribed_plan, reservable),
|
||||
meta_data: { date: date }
|
||||
end
|
||||
end
|
||||
|
@ -19,20 +19,39 @@ class ReservationLimitService
|
||||
reservation.cart_item_reservation_slots.group_by { |sr| sr.slot.start_at.to_date }.each_pair do |date, reservation_slots|
|
||||
daily_duration = reservations_duration(customer, date, reservation, cart_items) +
|
||||
(reservation_slots.map { |sr| sr.slot.duration }.reduce(:+) || 0)
|
||||
return false if Rational(daily_duration / 3600).to_f > limit
|
||||
return false if Rational(daily_duration / 3600).to_f > limit.limit
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
# @param reservation [Reservation]
|
||||
# @return [Date,NilClass]
|
||||
def reached_limit_date(reservation)
|
||||
user = reservation.user
|
||||
plan = user.subscribed_plan
|
||||
return nil if plan.nil? || !plan.limiting
|
||||
|
||||
limit = limit(plan, reservation.reservable)
|
||||
return nil if limit.nil?
|
||||
|
||||
reservation.slots_reservations.group_by { |sr| sr.slot.start_at.to_date }.each_pair do |date, reservation_slots|
|
||||
daily_duration = saved_reservations_durations(user, reservation.reservable, date, reservation) +
|
||||
(reservation_slots.map { |sr| sr.slot.duration }.reduce(:+) || 0)
|
||||
return date if Rational(daily_duration / 3600).to_f >= limit.limit
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
# @param plan [Plan,NilClass]
|
||||
# @param reservable [Machine,Event,Space,Training]
|
||||
# @return [Integer,NilClass] in hours
|
||||
# @return [PlanLimitation] in hours
|
||||
def limit(plan, reservable)
|
||||
return nil unless plan&.limiting
|
||||
|
||||
limitations = plan&.plan_limitations&.filter { |limit| limit.reservables.include?(reservable) }
|
||||
limitations&.find { |limit| limit.limitable_type != 'MachineCategory' }&.limit || limitations&.first&.limit
|
||||
limitations&.find { |limit| limit.limitable_type != 'MachineCategory' } || limitations&.first
|
||||
end
|
||||
|
||||
private
|
||||
@ -43,11 +62,7 @@ class ReservationLimitService
|
||||
# @param cart_items [Array<CartItem::BaseItem>]
|
||||
# @return [Integer] in seconds
|
||||
def reservations_duration(customer, date, reservation, cart_items)
|
||||
daily_reservations = customer.reservations
|
||||
.includes(slots_reservations: :slot)
|
||||
.where(reservable: reservation.reservable)
|
||||
.where(slots_reservations: { canceled_at: nil })
|
||||
.where("date_trunc('day', slots.start_at) = :date", date: date)
|
||||
daily_reservations_hours = saved_reservations_durations(customer, reservation.reservable, date)
|
||||
|
||||
cart_daily_reservations = cart_items.filter do |item|
|
||||
item.is_a?(CartItem::Reservation) &&
|
||||
@ -58,8 +73,25 @@ class ReservationLimitService
|
||||
.where("date_trunc('day', slots.start_at) = :date", date: date)
|
||||
end
|
||||
|
||||
(daily_reservations.map { |r| r.slots_reservations.map { |sr| sr.slot.duration } }.flatten.reduce(:+) || 0) +
|
||||
daily_reservations_hours +
|
||||
(cart_daily_reservations.map { |r| r.cart_item_reservation_slots.map { |sr| sr.slot.duration } }.flatten.reduce(:+) || 0)
|
||||
end
|
||||
|
||||
# @param customer [User]
|
||||
# @param reservable [Machine,Event,Space,Training]
|
||||
# @param date [Date]
|
||||
# @param reservation [Reservation]
|
||||
# @return [Integer] in seconds
|
||||
def saved_reservations_durations(customer, reservable, date, reservation = nil)
|
||||
daily_reservations = customer.reservations
|
||||
.includes(slots_reservations: :slot)
|
||||
.where(reservable: reservable)
|
||||
.where(slots_reservations: { canceled_at: nil })
|
||||
.where("date_trunc('day', slots.start_at) = :date", date: date)
|
||||
|
||||
daily_reservations = daily_reservations.where.not(id: reservation.id) unless reservation.nil?
|
||||
|
||||
(daily_reservations.map { |r| r.slots_reservations.map { |sr| sr.slot.duration } }.flatten.reduce(:+) || 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -0,0 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
json.title notification.notification_type
|
||||
json.description t('.limit_reached',
|
||||
HOURS: notification.attached_object.limit,
|
||||
ITEM: notification.attached_object.limitable.name,
|
||||
DATE: I18n.l(notification.get_meta_data(:date).to_date))
|
@ -0,0 +1,9 @@
|
||||
<%= render 'notifications_mailer/shared/hello', recipient: @recipient %>
|
||||
|
||||
<p>
|
||||
<%= t('.body.limit_reached',
|
||||
HOURS: @attached_object.limit,
|
||||
ITEM: @attached_object.limitable.name,
|
||||
DATE: I18n.l(@notification.get_meta_data(:date).to_date)) %>
|
||||
</p>
|
||||
|
@ -230,7 +230,7 @@ de:
|
||||
email: "Email address"
|
||||
plan_pricing_form:
|
||||
prices: "Prices"
|
||||
about_prices: "The prices defined here will apply to members subscribing to this plan, for machines and spaces."
|
||||
about_prices: "The prices defined here will apply to members subscribing to this plan, for machines and spaces. All prices are per hour."
|
||||
copy_prices_from: "Copy prices from"
|
||||
copy_prices_from_help: "This will replace all the prices of this plan with the prices of the selected plan"
|
||||
machines: "Machines"
|
||||
@ -321,7 +321,7 @@ de:
|
||||
manage_trainings: "Klicke hier, um Schulungen hinzuzufügen oder zu entfernen."
|
||||
number_of_tickets: "Anzahl der Tickets: "
|
||||
adjust_the_opening_hours: "Öffnungszeiten anpassen"
|
||||
to_time: "bis" #eg. from 18:00 to 21:00
|
||||
to_time: "bis" #e.g. from 18:00 to 21:00
|
||||
restrict_options: "Einschränkungsoptionen"
|
||||
restrict_with_labels: "Diesen Slot mit Labels einschränken"
|
||||
restrict_for_subscriptions: "Diesen Slot auf Abonnenten einschränken"
|
||||
@ -543,8 +543,8 @@ de:
|
||||
on_DATE: "am {DATE}"
|
||||
from_DATE: "von {DATE}"
|
||||
from_TIME: "ab {TIME}"
|
||||
to_date: "bis" #eg: from 01/01 to 01/05
|
||||
to_time: "bis" #eg. from 18:00 to 21:00
|
||||
to_date: "bis" #e.g.: from 01/01 to 01/05
|
||||
to_time: "bis" #e.g. from 18:00 to 21:00
|
||||
title: "Titel"
|
||||
dates: "Datum"
|
||||
booking: "Buchung"
|
||||
@ -1488,8 +1488,8 @@ de:
|
||||
statistics: "Statistiken"
|
||||
evolution: "Entwicklung"
|
||||
age_filter: "Altersfilter"
|
||||
from_age: "Von" #eg. from 8 to 40 years old
|
||||
to_age: "bis" #eg. from 8 to 40 years old
|
||||
from_age: "Von" #e.g. from 8 to 40 years old
|
||||
to_age: "bis" #e.g. from 8 to 40 years old
|
||||
start: "Start:"
|
||||
end: "Ende:"
|
||||
custom_filter: "Benutzerderfinierter Filter"
|
||||
|
@ -180,7 +180,6 @@ en:
|
||||
rolling_subscription_help: "A rolling subscription will begin the day of the first trainings. Otherwise, it will begin as soon as it is bought."
|
||||
monthly_payment: "Monthly payment?"
|
||||
monthly_payment_help: "If monthly payment is enabled, the members will be able to choose between a one-time payment or a payment schedule staged each months."
|
||||
description: "Description"
|
||||
information_sheet: "Information sheet"
|
||||
notified_partner: "Notified partner"
|
||||
new_user: "New user"
|
||||
@ -231,7 +230,7 @@ en:
|
||||
email: "Email address"
|
||||
plan_pricing_form:
|
||||
prices: "Prices"
|
||||
about_prices: "The prices defined here will apply to members subscribing to this plan, for machines and spaces."
|
||||
about_prices: "The prices defined here will apply to members subscribing to this plan, for machines and spaces. All prices are per hour."
|
||||
copy_prices_from: "Copy prices from"
|
||||
copy_prices_from_help: "This will replace all the prices of this plan with the prices of the selected plan"
|
||||
machines: "Machines"
|
||||
@ -322,7 +321,7 @@ en:
|
||||
manage_trainings: "Click here to add or remove trainings."
|
||||
number_of_tickets: "Number of tickets: "
|
||||
adjust_the_opening_hours: "Adjust the opening hours"
|
||||
to_time: "to" #eg. from 18:00 to 21:00
|
||||
to_time: "to" #e.g. from 18:00 to 21:00
|
||||
restrict_options: "Restriction options"
|
||||
restrict_with_labels: "Restrict this slot with labels"
|
||||
restrict_for_subscriptions: "Restrict this slot for subscription users"
|
||||
@ -544,8 +543,8 @@ en:
|
||||
on_DATE: "on {DATE}"
|
||||
from_DATE: "from {DATE}"
|
||||
from_TIME: "from {TIME}"
|
||||
to_date: "to" #eg: from 01/01 to 01/05
|
||||
to_time: "to" #eg. from 18:00 to 21:00
|
||||
to_date: "to" #e.g.: from 01/01 to 01/05
|
||||
to_time: "to" #e.g. from 18:00 to 21:00
|
||||
title: "Title"
|
||||
dates: "Dates"
|
||||
booking: "Booking"
|
||||
@ -1489,8 +1488,8 @@ en:
|
||||
statistics: "Statistics"
|
||||
evolution: "Evolution"
|
||||
age_filter: "Age filter"
|
||||
from_age: "From" #eg. from 8 to 40 years old
|
||||
to_age: "to" #eg. from 8 to 40 years old
|
||||
from_age: "From" #e.g. from 8 to 40 years old
|
||||
to_age: "to" #e.g. from 8 to 40 years old
|
||||
start: "Start:"
|
||||
end: "End:"
|
||||
custom_filter: "Custom filter"
|
||||
|
@ -230,7 +230,7 @@ es:
|
||||
email: "Email address"
|
||||
plan_pricing_form:
|
||||
prices: "Prices"
|
||||
about_prices: "The prices defined here will apply to members subscribing to this plan, for machines and spaces."
|
||||
about_prices: "The prices defined here will apply to members subscribing to this plan, for machines and spaces. All prices are per hour."
|
||||
copy_prices_from: "Copy prices from"
|
||||
copy_prices_from_help: "This will replace all the prices of this plan with the prices of the selected plan"
|
||||
machines: "Machines"
|
||||
@ -321,7 +321,7 @@ es:
|
||||
manage_trainings: "Click here to add or remove trainings."
|
||||
number_of_tickets: "Número de tickets: "
|
||||
adjust_the_opening_hours: "Ajustar el horario de apertura"
|
||||
to_time: "a" #eg. from 18:00 to 21:00
|
||||
to_time: "a" #e.g. from 18:00 to 21:00
|
||||
restrict_options: "Restriction options"
|
||||
restrict_with_labels: "Restringir este horario con etiquetas"
|
||||
restrict_for_subscriptions: "Restrict this slot for subscription users"
|
||||
@ -543,8 +543,8 @@ es:
|
||||
on_DATE: "on {DATE}"
|
||||
from_DATE: "Desde {DATE}"
|
||||
from_TIME: "Desde {TIME}"
|
||||
to_date: "to" #eg: from 01/01 to 01/05
|
||||
to_time: "to" #eg. from 18:00 to 21:00
|
||||
to_date: "to" #e.g.: from 01/01 to 01/05
|
||||
to_time: "to" #e.g. from 18:00 to 21:00
|
||||
title: "Title"
|
||||
dates: "Dates"
|
||||
booking: "Booking"
|
||||
@ -1488,8 +1488,8 @@ es:
|
||||
statistics: "Statistics"
|
||||
evolution: "Evolución"
|
||||
age_filter: "Filtro de edad"
|
||||
from_age: "Desde" #eg. from 8 to 40 years old
|
||||
to_age: "a" #eg. from 8 to 40 years old
|
||||
from_age: "Desde" #e.g. from 8 to 40 years old
|
||||
to_age: "a" #e.g. from 8 to 40 years old
|
||||
start: "Principio:"
|
||||
end: "Final:"
|
||||
custom_filter: "Filtro personalizado"
|
||||
|
@ -321,7 +321,7 @@ fr:
|
||||
manage_trainings: "Cliquez-ici pour ajouter ou supprimer des formations."
|
||||
number_of_tickets: "Nombre de places : "
|
||||
adjust_the_opening_hours: "Ajuster l'horaire"
|
||||
to_time: "à" #eg. from 18:00 to 21:00
|
||||
to_time: "à" #e.g. from 18:00 to 21:00
|
||||
restrict_options: "Options de restriction"
|
||||
restrict_with_labels: "Restreindre ce créneau avec des étiquettes"
|
||||
restrict_for_subscriptions: "Restreindre ce créneau pour les abonnements"
|
||||
@ -543,8 +543,8 @@ fr:
|
||||
on_DATE: "le {DATE}"
|
||||
from_DATE: "du {DATE}"
|
||||
from_TIME: "de {TIME}"
|
||||
to_date: "au" #eg: from 01/01 to 01/05
|
||||
to_time: "à" #eg. from 18:00 to 21:00
|
||||
to_date: "au" #e.g.: from 01/01 to 01/05
|
||||
to_time: "à" #e.g. from 18:00 to 21:00
|
||||
title: "Titre"
|
||||
dates: "Dates"
|
||||
booking: "Réservations"
|
||||
@ -1488,8 +1488,8 @@ fr:
|
||||
statistics: "Statistiques"
|
||||
evolution: "Évolution"
|
||||
age_filter: "Filtre d'âge"
|
||||
from_age: "De" #eg. from 8 to 40 years old
|
||||
to_age: "à" #eg. from 8 to 40 years old
|
||||
from_age: "De" #e.g. from 8 to 40 years old
|
||||
to_age: "à" #e.g. from 8 to 40 years old
|
||||
start: "Début :"
|
||||
end: "Fin :"
|
||||
custom_filter: "Filtre personnalisé"
|
||||
|
@ -230,7 +230,7 @@
|
||||
email: "Email address"
|
||||
plan_pricing_form:
|
||||
prices: "Prices"
|
||||
about_prices: "The prices defined here will apply to members subscribing to this plan, for machines and spaces."
|
||||
about_prices: "The prices defined here will apply to members subscribing to this plan, for machines and spaces. All prices are per hour."
|
||||
copy_prices_from: "Copy prices from"
|
||||
copy_prices_from_help: "This will replace all the prices of this plan with the prices of the selected plan"
|
||||
machines: "Machines"
|
||||
@ -321,7 +321,7 @@
|
||||
manage_trainings: "Klikk her for å legge til eller endre opplæring."
|
||||
number_of_tickets: "Antall billetter: "
|
||||
adjust_the_opening_hours: "Endre åpningstid"
|
||||
to_time: "til" #eg. from 18:00 to 21:00
|
||||
to_time: "til" #e.g. from 18:00 to 21:00
|
||||
restrict_options: "Alternativer for begrensning"
|
||||
restrict_with_labels: "Begrens denne reservasjonen med etiketter"
|
||||
restrict_for_subscriptions: "Begrens denne reservasjoen til medlemmer"
|
||||
@ -543,8 +543,8 @@
|
||||
on_DATE: "{DATE}"
|
||||
from_DATE: "fra {DATE}"
|
||||
from_TIME: "fra {TIME}"
|
||||
to_date: "til" #eg: from 01/01 to 01/05
|
||||
to_time: "til" #eg. from 18:00 to 21:00
|
||||
to_date: "til" #e.g.: from 01/01 to 01/05
|
||||
to_time: "til" #e.g. from 18:00 to 21:00
|
||||
title: "Tittel"
|
||||
dates: "Datoer"
|
||||
booking: "Reservasjon"
|
||||
@ -1488,8 +1488,8 @@
|
||||
statistics: "Statistikk"
|
||||
evolution: "Utvikling"
|
||||
age_filter: "Aldersfilter"
|
||||
from_age: "Fra" #eg. from 8 to 40 years old
|
||||
to_age: "til" #eg. from 8 to 40 years old
|
||||
from_age: "Fra" #e.g. from 8 to 40 years old
|
||||
to_age: "til" #e.g. from 8 to 40 years old
|
||||
start: "Start:"
|
||||
end: "Slutt:"
|
||||
custom_filter: "Egendefinerte filtre"
|
||||
|
@ -230,7 +230,7 @@ pt:
|
||||
email: "Email address"
|
||||
plan_pricing_form:
|
||||
prices: "Prices"
|
||||
about_prices: "The prices defined here will apply to members subscribing to this plan, for machines and spaces."
|
||||
about_prices: "The prices defined here will apply to members subscribing to this plan, for machines and spaces. All prices are per hour."
|
||||
copy_prices_from: "Copy prices from"
|
||||
copy_prices_from_help: "This will replace all the prices of this plan with the prices of the selected plan"
|
||||
machines: "Machines"
|
||||
@ -321,7 +321,7 @@ pt:
|
||||
manage_trainings: "Clique aqui para adicionar ou remover treinamentos."
|
||||
number_of_tickets: "Número de vagas: "
|
||||
adjust_the_opening_hours: "Ajustar o horário de funcionamento"
|
||||
to_time: "ás" #eg. from 18:00 to 21:00
|
||||
to_time: "ás" #e.g. from 18:00 to 21:00
|
||||
restrict_options: "Opções de restrição"
|
||||
restrict_with_labels: "Restrinja este slot com etiquetas"
|
||||
restrict_for_subscriptions: "Restringir este slot para os usuários da assinatura"
|
||||
@ -543,8 +543,8 @@ pt:
|
||||
on_DATE: "No {DATE}"
|
||||
from_DATE: "Em {DATE}"
|
||||
from_TIME: "Ás {TIME}"
|
||||
to_date: "ás" #eg: from 01/01 to 01/05
|
||||
to_time: "ás" #eg. from 18:00 to 21:00
|
||||
to_date: "ás" #e.g.: from 01/01 to 01/05
|
||||
to_time: "ás" #e.g. from 18:00 to 21:00
|
||||
title: "Título"
|
||||
dates: "Datas"
|
||||
booking: "Reserva"
|
||||
@ -1488,8 +1488,8 @@ pt:
|
||||
statistics: "Estatísticas"
|
||||
evolution: "Evolução"
|
||||
age_filter: "Filtro de idade"
|
||||
from_age: "Dos" #eg. from 8 to 40 years old
|
||||
to_age: "aos" #eg. from 8 to 40 years old
|
||||
from_age: "Dos" #e.g. from 8 to 40 years old
|
||||
to_age: "aos" #e.g. from 8 to 40 years old
|
||||
start: "Início:"
|
||||
end: "Fim:"
|
||||
custom_filter: "Filtro customizado"
|
||||
|
@ -321,7 +321,7 @@ zu:
|
||||
manage_trainings: "crwdns24132:0crwdne24132:0"
|
||||
number_of_tickets: "crwdns24134:0crwdne24134:0"
|
||||
adjust_the_opening_hours: "crwdns24136:0crwdne24136:0"
|
||||
to_time: "crwdns24138:0crwdne24138:0" #eg. from 18:00 to 21:00
|
||||
to_time: "crwdns24138:0crwdne24138:0" #e.g. from 18:00 to 21:00
|
||||
restrict_options: "crwdns24140:0crwdne24140:0"
|
||||
restrict_with_labels: "crwdns24142:0crwdne24142:0"
|
||||
restrict_for_subscriptions: "crwdns24144:0crwdne24144:0"
|
||||
@ -543,8 +543,8 @@ zu:
|
||||
on_DATE: "crwdns24452:0{DATE}crwdne24452:0"
|
||||
from_DATE: "crwdns24454:0{DATE}crwdne24454:0"
|
||||
from_TIME: "crwdns24456:0{TIME}crwdne24456:0"
|
||||
to_date: "crwdns24458:0crwdne24458:0" #eg: from 01/01 to 01/05
|
||||
to_time: "crwdns24460:0crwdne24460:0" #eg. from 18:00 to 21:00
|
||||
to_date: "crwdns24458:0crwdne24458:0" #e.g.: from 01/01 to 01/05
|
||||
to_time: "crwdns24460:0crwdne24460:0" #e.g. from 18:00 to 21:00
|
||||
title: "crwdns24462:0crwdne24462:0"
|
||||
dates: "crwdns24464:0crwdne24464:0"
|
||||
booking: "crwdns24466:0crwdne24466:0"
|
||||
@ -1488,8 +1488,8 @@ zu:
|
||||
statistics: "crwdns26224:0crwdne26224:0"
|
||||
evolution: "crwdns26226:0crwdne26226:0"
|
||||
age_filter: "crwdns26228:0crwdne26228:0"
|
||||
from_age: "crwdns26230:0crwdne26230:0" #eg. from 8 to 40 years old
|
||||
to_age: "crwdns26232:0crwdne26232:0" #eg. from 8 to 40 years old
|
||||
from_age: "crwdns26230:0crwdne26230:0" #e.g. from 8 to 40 years old
|
||||
to_age: "crwdns26232:0crwdne26232:0" #e.g. from 8 to 40 years old
|
||||
start: "crwdns26234:0crwdne26234:0"
|
||||
end: "crwdns26236:0crwdne26236:0"
|
||||
custom_filter: "crwdns26238:0crwdne26238:0"
|
||||
|
@ -433,6 +433,8 @@ de:
|
||||
schedule_deadline: "Sie müssen den Scheck zur %{DATE} -Frist einlösen, für den Zeitplan %{REFERENCE}"
|
||||
notify_admin_payment_schedule_transfer_deadline:
|
||||
schedule_deadline: "Sie müssen das Lastschriftverfahren für die %{DATE} -Frist bestätigen, für Zeitplan %{REFERENCE}"
|
||||
notify_member_reservation_limit_reached:
|
||||
limit_reached: "For %{DATE}, you have reached your daily limit of %{HOURS} hours of %{ITEM} reservation."
|
||||
notify_admin_user_supporting_document_files_created:
|
||||
supporting_document_files_uploaded: "Supporting document uploaded by member <strong><em>%{NAME}</strong></em>."
|
||||
notify_admin_user_supporting_document_files_updated:
|
||||
|
@ -433,6 +433,8 @@ en:
|
||||
schedule_deadline: "You must cash the check for the %{DATE} deadline, for schedule %{REFERENCE}"
|
||||
notify_admin_payment_schedule_transfer_deadline:
|
||||
schedule_deadline: "You must confirm the bank direct debit for the %{DATE} deadline, for schedule %{REFERENCE}"
|
||||
notify_member_reservation_limit_reached:
|
||||
limit_reached: "For %{DATE}, you have reached your daily limit of %{HOURS} hours of %{ITEM} reservation."
|
||||
notify_admin_user_supporting_document_files_created:
|
||||
supporting_document_files_uploaded: "Supporting document uploaded by member <strong><em>%{NAME}</strong></em>."
|
||||
notify_admin_user_supporting_document_files_updated:
|
||||
|
@ -433,6 +433,8 @@ es:
|
||||
schedule_deadline: "You must cash the check for the %{DATE} deadline, for schedule %{REFERENCE}"
|
||||
notify_admin_payment_schedule_transfer_deadline:
|
||||
schedule_deadline: "You must confirm the bank direct debit for the %{DATE} deadline, for schedule %{REFERENCE}"
|
||||
notify_member_reservation_limit_reached:
|
||||
limit_reached: "For %{DATE}, you have reached your daily limit of %{HOURS} hours of %{ITEM} reservation."
|
||||
notify_admin_user_supporting_document_files_created:
|
||||
supporting_document_files_uploaded: "Supporting document uploaded by member <strong><em>%{NAME}</strong></em>."
|
||||
notify_admin_user_supporting_document_files_updated:
|
||||
|
@ -433,6 +433,8 @@ fr:
|
||||
schedule_deadline: "Vous devez encaisser le chèque de l'échéance du %{DATE}, pour l'échéancier %{REFERENCE}"
|
||||
notify_admin_payment_schedule_transfer_deadline:
|
||||
schedule_deadline: "Vous devez confirmer le prélèvement bancaire pour l'échéance du %{DATE} , pour l'échéancier %{REFERENCE}"
|
||||
notify_member_reservation_limit_reached:
|
||||
limit_reached: "Pour le %{DATE}, vous avez atteint votre limite quotidienne de %{HOURS} heures de réservation de la %{ITEM}."
|
||||
notify_admin_user_supporting_document_files_created:
|
||||
supporting_document_files_uploaded: "Le membre <strong><em>%{NAME}</strong></em> a téléversé un nouveau justificatif."
|
||||
notify_admin_user_supporting_document_files_updated:
|
||||
|
@ -375,6 +375,10 @@ de:
|
||||
remember: "Gemäß Ihrem Zahlungsplan von %{REFERENCE} wurde zum %{DATE} eine Belastung der Karte in Höhe von %{AMOUNT} geplant."
|
||||
date: "Dies ist eine Erinnerung zur Prüfung, ob das Bankkonto erfolgreich belastet werden konnte."
|
||||
confirm: "Bitte bestätigen Sie den Erhalt des Guthabens in Ihrer Zahlungsverwaltung, damit die entsprechende Rechnung generiert werden kann."
|
||||
notify_member_reservation_limit_reached:
|
||||
subject: "Daily reservation limit reached"
|
||||
body:
|
||||
limit_reached: "For %{DATE}, you have reached your daily limit of %{HOURS} hours of %{ITEM} reservation."
|
||||
notify_admin_user_supporting_document_files_created:
|
||||
subject: "Supporting documents uploaded by a member"
|
||||
body:
|
||||
|
@ -375,6 +375,10 @@ en:
|
||||
remember: "In accordance with your %{REFERENCE} payment schedule, %{AMOUNT} was due to be debited on %{DATE}."
|
||||
date: "This is a reminder to verify that the direct bank debit was successfull."
|
||||
confirm: "Please confirm the receipt of funds in your payment schedule management interface, so that the corresponding invoice will be generated."
|
||||
notify_member_reservation_limit_reached:
|
||||
subject: "Daily reservation limit reached"
|
||||
body:
|
||||
limit_reached: "For %{DATE}, you have reached your daily limit of %{HOURS} hours of %{ITEM} reservation."
|
||||
notify_admin_user_supporting_document_files_created:
|
||||
subject: "Supporting documents uploaded by a member"
|
||||
body:
|
||||
|
@ -375,6 +375,10 @@ es:
|
||||
remember: "In accordance with your %{REFERENCE} payment schedule, %{AMOUNT} was due to be debited on %{DATE}."
|
||||
date: "This is a reminder to verify that the direct bank debit was successfull."
|
||||
confirm: "Please confirm the receipt of funds in your payment schedule management interface, so that the corresponding invoice will be generated."
|
||||
notify_member_reservation_limit_reached:
|
||||
subject: "Daily reservation limit reached"
|
||||
body:
|
||||
limit_reached: "For %{DATE}, you have reached your daily limit of %{HOURS} hours of %{ITEM} reservation."
|
||||
notify_admin_user_supporting_document_files_created:
|
||||
subject: "Supporting documents uploaded by a member"
|
||||
body:
|
||||
|
@ -375,6 +375,10 @@ fr:
|
||||
remember: "Conformément à l'échéancier de paiement %{REFERENCE}, une échéance de %{AMOUNT} était prévu pour être prélevée le %{DATE}."
|
||||
date: "Ceci est un rappel pour vérifier que le prélèvement bancaire a bien été effectué."
|
||||
confirm: "Veuillez confirmer la réception des fonds dans votre interface de gestion des échéanciers de paiement, afin que la facture correspondante soit générée."
|
||||
notify_member_reservation_limit_reached:
|
||||
subject: "Limite de réservation quotidienne atteinte"
|
||||
body:
|
||||
limit_reached: "Pour le %{DATE}, vous avez atteint votre limite quotidienne de %{HOURS} heures de réservation de la %{ITEM}."
|
||||
notify_admin_user_supporting_document_files_created:
|
||||
subject: "Justificatif téléversé par un membre"
|
||||
body:
|
||||
|
@ -375,6 +375,10 @@
|
||||
remember: "In accordance with your %{REFERENCE} payment schedule, %{AMOUNT} was due to be debited on %{DATE}."
|
||||
date: "This is a reminder to verify that the direct bank debit was successfull."
|
||||
confirm: "Please confirm the receipt of funds in your payment schedule management interface, so that the corresponding invoice will be generated."
|
||||
notify_member_reservation_limit_reached:
|
||||
subject: "Daily reservation limit reached"
|
||||
body:
|
||||
limit_reached: "For %{DATE}, you have reached your daily limit of %{HOURS} hours of %{ITEM} reservation."
|
||||
notify_admin_user_supporting_document_files_created:
|
||||
subject: "Supporting documents uploaded by a member"
|
||||
body:
|
||||
|
@ -375,6 +375,10 @@ pt:
|
||||
remember: "De acordo com a agenda de pagamento %{REFERENCE}, %{AMOUNT} deveria ser debitado em %{DATE}."
|
||||
date: "Este é um lembrete para verificar se o débito bancário foi bem sucedido."
|
||||
confirm: "Não se esqueça de confirmar o recibo na interface de gestão de pagamento, para que a fatura correspondente seja gerada."
|
||||
notify_member_reservation_limit_reached:
|
||||
subject: "Daily reservation limit reached"
|
||||
body:
|
||||
limit_reached: "For %{DATE}, you have reached your daily limit of %{HOURS} hours of %{ITEM} reservation."
|
||||
notify_admin_user_supporting_document_files_created:
|
||||
subject: "Supporting documents uploaded by a member"
|
||||
body:
|
||||
|
@ -375,6 +375,10 @@ zu:
|
||||
remember: "crwdns29938:0%{REFERENCE}crwdnd29938:0%{AMOUNT}crwdnd29938:0%{DATE}crwdne29938:0"
|
||||
date: "crwdns29940:0crwdne29940:0"
|
||||
confirm: "crwdns29942:0crwdne29942:0"
|
||||
notify_member_reservation_limit_reached:
|
||||
subject: "crwdns37483:0crwdne37483:0"
|
||||
body:
|
||||
limit_reached: "crwdns37485:0%{DATE}crwdnd37485:0%{HOURS}crwdnd37485:0%{ITEM}crwdne37485:0"
|
||||
notify_admin_user_supporting_document_files_created:
|
||||
subject: "crwdns37349:0crwdne37349:0"
|
||||
body:
|
||||
|
@ -433,6 +433,8 @@
|
||||
schedule_deadline: "You must cash the check for the %{DATE} deadline, for schedule %{REFERENCE}"
|
||||
notify_admin_payment_schedule_transfer_deadline:
|
||||
schedule_deadline: "You must confirm the bank direct debit for the %{DATE} deadline, for schedule %{REFERENCE}"
|
||||
notify_member_reservation_limit_reached:
|
||||
limit_reached: "For %{DATE}, you have reached your daily limit of %{HOURS} hours of %{ITEM} reservation."
|
||||
notify_admin_user_supporting_document_files_created:
|
||||
supporting_document_files_uploaded: "Supporting document uploaded by member <strong><em>%{NAME}</strong></em>."
|
||||
notify_admin_user_supporting_document_files_updated:
|
||||
|
@ -433,6 +433,8 @@ pt:
|
||||
schedule_deadline: "Você deve realizar a verificação para a data limite de %{DATE} para agendar %{REFERENCE}"
|
||||
notify_admin_payment_schedule_transfer_deadline:
|
||||
schedule_deadline: "Você deve realizar a verificação do débito para a data limite de %{DATE}, para o agendamento %{REFERENCE}"
|
||||
notify_member_reservation_limit_reached:
|
||||
limit_reached: "For %{DATE}, you have reached your daily limit of %{HOURS} hours of %{ITEM} reservation."
|
||||
notify_admin_user_supporting_document_files_created:
|
||||
supporting_document_files_uploaded: "Supporting document uploaded by member <strong><em>%{NAME}</strong></em>."
|
||||
notify_admin_user_supporting_document_files_updated:
|
||||
|
@ -433,6 +433,8 @@ zu:
|
||||
schedule_deadline: "crwdns21120:0%{DATE}crwdnd21120:0%{REFERENCE}crwdne21120:0"
|
||||
notify_admin_payment_schedule_transfer_deadline:
|
||||
schedule_deadline: "crwdns22305:0%{DATE}crwdnd22305:0%{REFERENCE}crwdne22305:0"
|
||||
notify_member_reservation_limit_reached:
|
||||
limit_reached: "crwdns37481:0%{DATE}crwdnd37481:0%{HOURS}crwdnd37481:0%{ITEM}crwdne37481:0"
|
||||
notify_admin_user_supporting_document_files_created:
|
||||
supporting_document_files_uploaded: "crwdns37341:0%{NAME}crwdne37341:0"
|
||||
notify_admin_user_supporting_document_files_updated:
|
||||
|
@ -23,3 +23,11 @@ unless NotificationType.find_by(name: 'notify_admin_order_is_paid')
|
||||
is_configurable: true
|
||||
)
|
||||
end
|
||||
|
||||
unless NotificationType.find_by(name: 'notify_member_reservation_limit_reached')
|
||||
NotificationType.create!(
|
||||
name: 'notify_member_reservation_limit_reached',
|
||||
category: 'agenda',
|
||||
is_configurable: false
|
||||
)
|
||||
end
|
||||
|
@ -50,7 +50,7 @@ class ReservationLimitServiceTest < ActiveSupport::TestCase
|
||||
customer_profile: @acamus.invoicing_profile,
|
||||
operator_profile: @acamus.invoicing_profile,
|
||||
reservable: @machine,
|
||||
cart_item_reservation_slots_attributes: [{ slot: slots[0] }, { slot: slots[1] }, { slot: slots[2] }]
|
||||
cart_item_reservation_slots_attributes: [{ slot: slots[2] }, { slot: slots[3] }, { slot: slots[4] }]
|
||||
)
|
||||
assert_not ReservationLimitService.authorized?(@plan, @acamus, reservation, [])
|
||||
end
|
||||
@ -118,7 +118,7 @@ class ReservationLimitServiceTest < ActiveSupport::TestCase
|
||||
|
||||
test 'get plan limit' do
|
||||
@plan.update(limiting: true, plan_limitations_attributes: [{ limitable_id: @machine.id, limitable_type: 'Machine', limit: 2 }])
|
||||
assert_equal 2, ReservationLimitService.limit(@plan, @machine)
|
||||
assert_equal 2, ReservationLimitService.limit(@plan, @machine).limit
|
||||
end
|
||||
|
||||
test 'get plan without limit' do
|
||||
@ -129,13 +129,45 @@ class ReservationLimitServiceTest < ActiveSupport::TestCase
|
||||
category = MachineCategory.find(1)
|
||||
category.update(machine_ids: [@machine.id])
|
||||
@plan.update(limiting: true, plan_limitations_attributes: [{ limitable: category, limit: 4 }])
|
||||
assert_equal 4, ReservationLimitService.limit(@plan, @machine)
|
||||
assert_equal 4, ReservationLimitService.limit(@plan, @machine).limit
|
||||
end
|
||||
|
||||
test 'machine limit should override the category limit' do
|
||||
category = MachineCategory.find(1)
|
||||
category.update(machine_ids: [@machine.id])
|
||||
@plan.update(limiting: true, plan_limitations_attributes: [{ limitable: @machine, limit: 2 }, { limitable: category, limit: 4 }])
|
||||
assert_equal 2, ReservationLimitService.limit(@plan, @machine)
|
||||
limit = ReservationLimitService.limit(@plan, @machine)
|
||||
assert_equal 2, limit.limit
|
||||
assert_equal @machine, limit.limitable
|
||||
end
|
||||
|
||||
test 'reservation reaches the limit' do
|
||||
user = User.find_by(username: 'kdumas')
|
||||
plan = user.subscribed_plan
|
||||
plan.update(limiting: true, plan_limitations_attributes: [{ limitable: @machine, limit: 1 }])
|
||||
slots = Availabilities::AvailabilitiesService.new(user)
|
||||
.machines([@machine], user, { start: Time.current, end: 10.days.from_now })
|
||||
reservation = Reservation.create!(
|
||||
statistic_profile: user.statistic_profile,
|
||||
reservable: @machine,
|
||||
slots_reservations_attributes: [{ slot: slots.last }]
|
||||
)
|
||||
reservation.reload
|
||||
assert_equal slots.last.start_at.to_date, ReservationLimitService.reached_limit_date(reservation)
|
||||
end
|
||||
|
||||
test 'reservation does not reaches the limit' do
|
||||
user = User.find_by(username: 'kdumas')
|
||||
plan = user.subscribed_plan
|
||||
plan.update(limiting: true, plan_limitations_attributes: [{ limitable: @machine, limit: 2 }])
|
||||
slots = Availabilities::AvailabilitiesService.new(user)
|
||||
.machines([@machine], user, { start: Time.current, end: 10.days.from_now })
|
||||
reservation = Reservation.create!(
|
||||
statistic_profile: user.statistic_profile,
|
||||
reservable: @machine,
|
||||
slots_reservations_attributes: [{ slot: slots.last }]
|
||||
)
|
||||
reservation.reload
|
||||
assert_nil ReservationLimitService.reached_limit_date(reservation)
|
||||
end
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user