From a05ef1f0ba264da032e566d34791e6d5f31f0837 Mon Sep 17 00:00:00 2001
From: Sylvain
Date: Wed, 25 Jan 2023 16:40:55 +0100
Subject: [PATCH] (feat) auto refund after trainings cancelled and notify
---
app/models/notification_type.rb | 1 +
app/models/setting.rb | 17 ++++++++---------
app/services/training_service.rb | 19 ++++++++++++++++++-
...dmin_training_auto_cancelled.json.jbuilder | 5 ++++-
...mber_training_auto_cancelled.json.jbuilder | 7 +++++++
...ify_admin_training_auto_cancelled.html.erb | 3 +++
...fy_member_training_auto_cancelled.html.erb | 13 +++++++++++++
config/locales/en.yml | 8 +++++++-
config/locales/mails.en.yml | 13 ++++++++++---
9 files changed, 71 insertions(+), 15 deletions(-)
create mode 100644 app/views/api/notifications/notify_member_training_auto_cancelled.json.jbuilder
create mode 100644 app/views/notifications_mailer/notify_member_training_auto_cancelled.html.erb
diff --git a/app/models/notification_type.rb b/app/models/notification_type.rb
index 2bd1f4ae3..8eeb3d300 100644
--- a/app/models/notification_type.rb
+++ b/app/models/notification_type.rb
@@ -74,6 +74,7 @@ class NotificationType
notify_user_order_is_refunded
notify_admin_low_stock_threshold
notify_admin_training_auto_cancelled
+ notify_member_training_auto_cancelled
]
# deprecated:
# - notify_member_subscribed_plan_is_changed
diff --git a/app/models/setting.rb b/app/models/setting.rb
index 900adbef3..56f8b80ab 100644
--- a/app/models/setting.rb
+++ b/app/models/setting.rb
@@ -219,11 +219,10 @@ class Setting < ApplicationRecord
save && history_values.create(invoicing_profile: admin.invoicing_profile, value: val)
end
- ##
# Return the value of the requested setting, if any.
- # Usage: Setting.get('my_setting')
- # @return {String|Boolean}
- ##
+ # @example Setting.get('my_setting') #=> "foo"
+ # @param name [String]
+ # @return [String,Boolean]
def self.get(name)
res = find_by('LOWER(name) = ? ', name.downcase)&.value
@@ -234,20 +233,20 @@ class Setting < ApplicationRecord
res
end
- ##
# Create or update the provided setting with the given value
- # Usage: Setting.set('my_setting', true)
+ # @example Setting.set('my_setting', true)
# Optionally (but recommended when possible), the user updating the value can be provided as the third parameter
# Eg.: Setting.set('my_setting', true, User.find_by(slug: 'admin'))
- ##
+ # @param name [String]
+ # @param value [String,Boolean,Numeric,NilClass]
def self.set(name, value, user = User.admins.first)
setting = find_or_initialize_by(name: name)
setting.save && setting.history_values.create(invoicing_profile: user.invoicing_profile, value: value.to_s)
end
- ##
# Check if the given setting was set
- ##
+ # @param name [String]
+ # @return [Boolean]
def self.set?(name)
!find_by(name: name)&.value.nil?
end
diff --git a/app/services/training_service.rb b/app/services/training_service.rb
index 1c6287a59..c6b2ef964 100644
--- a/app/services/training_service.rb
+++ b/app/services/training_service.rb
@@ -28,12 +28,21 @@ class TrainingService
.find_each do |availability|
next if availability.reservations.count >= training.auto_cancel_threshold
+ auto_refund = Setting.get('wallet_module')
+
NotificationCenter.call type: 'notify_admin_training_auto_cancelled',
receiver: User.admins_and_managers,
- attached_object: availability
+ attached_object: availability,
+ meta_data: { auto_refund: auto_refund }
availability.slots_reservations.find_each do |sr|
+ NotificationCenter.call type: 'notify_member_training_auto_cancelled',
+ receiver: sr.reservation.user,
+ attached_object: sr,
+ meta_data: { auto_refund: auto_refund }
+
sr.update(canceled_at: DateTime.current)
+ refund_after_cancel(sr.reservation) if auto_refund
end
end
end
@@ -80,5 +89,13 @@ class TrainingService
state = filters[:public_page] == 'false' ? [nil, false] : true
trainings.where(public_page: state)
end
+
+ # @param reservation [Reservation]
+ def refund_after_cancel(reservation)
+ invoice_item = reservation.invoice_items.joins(:invoice).where(invoices: { type: nil }).first
+ service = WalletService.new(user: reservation.user, wallet: reservation.user.wallet)
+ transaction = service.credit(invoice_item.amount_after_coupon / 100.00)
+ service.create_avoir(transaction, DateTime.current, I18n.t('trainings.refund_for_auto_cancel')) if transaction
+ end
end
end
diff --git a/app/views/api/notifications/_notify_admin_training_auto_cancelled.json.jbuilder b/app/views/api/notifications/_notify_admin_training_auto_cancelled.json.jbuilder
index 604ed266a..1545a3836 100644
--- a/app/views/api/notifications/_notify_admin_training_auto_cancelled.json.jbuilder
+++ b/app/views/api/notifications/_notify_admin_training_auto_cancelled.json.jbuilder
@@ -1,4 +1,7 @@
# frozen_string_literal: true
json.title notification.notification_type
-json.description t('.auto_cancelled_training')
+json.description "#{t('.auto_cancelled_training', {
+ TRAINING: notification.attached_object.trainings.first.name,
+ DATE: I18n.l(notification.attached_object.start_at.to_date)
+ })} #{notification.meta_data['auto_refund'] == 'true' ? t('.auto_refund') : t('.manual_refund')}"
diff --git a/app/views/api/notifications/notify_member_training_auto_cancelled.json.jbuilder b/app/views/api/notifications/notify_member_training_auto_cancelled.json.jbuilder
new file mode 100644
index 000000000..af83b627c
--- /dev/null
+++ b/app/views/api/notifications/notify_member_training_auto_cancelled.json.jbuilder
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+json.title notification.notification_type
+json.description "#{t('.auto_cancelled_training', {
+ TRAINING: notification.attached_object.reservation.reservable.name,
+ DATE: I18n.l(notification.attached_object.start_at.to_date)
+ })} #{notification.meta_data['auto_refund'] == 'true' ? t('.auto_refund') : ''}"
diff --git a/app/views/notifications_mailer/notify_admin_training_auto_cancelled.html.erb b/app/views/notifications_mailer/notify_admin_training_auto_cancelled.html.erb
index 83a365261..f8e04d6e0 100644
--- a/app/views/notifications_mailer/notify_admin_training_auto_cancelled.html.erb
+++ b/app/views/notifications_mailer/notify_admin_training_auto_cancelled.html.erb
@@ -8,3 +8,6 @@
END: I18n.l(@attached_object.end_at, format: :hour_minute)
}) %>
+
+ <%= @notification.get_meta_data(:auto_refund) == 'true' ? t('.body.auto_refund') : t('.body.manual_refund') %>
+
diff --git a/app/views/notifications_mailer/notify_member_training_auto_cancelled.html.erb b/app/views/notifications_mailer/notify_member_training_auto_cancelled.html.erb
new file mode 100644
index 000000000..cc3da13fe
--- /dev/null
+++ b/app/views/notifications_mailer/notify_member_training_auto_cancelled.html.erb
@@ -0,0 +1,13 @@
+<%= render 'notifications_mailer/shared/hello', recipient: @recipient %>
+
+
+ <%= t('.body.cancelled_training', {
+ TRAINING: @attached_object.reservation.reservable.name,
+ DATE: I18n.l(@attached_object.start_at.to_date),
+ START: I18n.l(@attached_object.start_at, format: :hour_minute),
+ END: I18n.l(@attached_object.end_at, format: :hour_minute)
+ }) %>
+
+
+ <%= @notification.get_meta_data(:auto_refund) == 'true' ? t('.body.auto_refund') : '' %>
+
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 2b0e40f73..1e2d5a992 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -180,6 +180,7 @@ en:
trainings:
i_ve_reserved: "I've reserved"
completed: "Full"
+ refund_for_auto_cancel: "This training session was cancelled due to an insufficient number of participants."
#error messages when updating an event
events:
error_deleting_reserved_price: "Unable to delete the requested price because it is associated with some reservations"
@@ -297,7 +298,9 @@ en:
notify_admin_subscription_will_expire_in_7_days:
USER_s_subscription_will_expire_in_7_days: "%{USER}'s subscription will expire in 7 days."
notify_admin_training_auto_cancelled:
- auto_cancelled_training: "TODO"
+ auto_cancelled_training: "The %{TRAINING} training session scheduled for %{DATE}, has been automatically canceled due to an insufficient number of participants."
+ auto_refund: "The members were automatically refunded on their wallet."
+ manual_refund: "Please refund each members."
notify_admin_user_group_changed:
user_NAME_changed_his_group_html: "User {NAME} changed group." #messageFormat interpolation
notify_admin_user_merged:
@@ -328,6 +331,9 @@ en:
your_subscription_has_expired: "Your subscription has expired."
notify_member_subscription_will_expire_in_7_days:
your_subscription_will_expire_in_7_days: "Your subscription will expire in 7 days."
+ notify_member_training_auto_cancelled:
+ auto_cancelled_training: "The %{TRAINING} training session scheduled for %{DATE}, has been canceled due to an insufficient number of participants."
+ auto_refund: "You were refunded on your wallet."
notify_partner_subscribed_plan:
subscription_partner_PLAN_has_been_subscribed_by_USER_html: "Partner subscription %{PLAN} has been subscribed by %{USER}."
notify_project_author_when_collaborator_valid:
diff --git a/config/locales/mails.en.yml b/config/locales/mails.en.yml
index 593c908c7..2251ad5a7 100644
--- a/config/locales/mails.en.yml
+++ b/config/locales/mails.en.yml
@@ -131,10 +131,11 @@ en:
your_plan: "you plan"
expires_in_7_days: "will expire in 7 days."
to_renew_your_plan_follow_the_link: "Please, follow this link to renew your plan"
- notify_admin_training_auto_cancelled:
- subject: "A training was automatically cancelled"
+ notify_member_training_auto_cancelled:
+ subject: "Your training session was cancelled"
body:
- cancelled_training: "The %{TRAINING} training session scheduled for %{DATE}, from %{START} to %{END} has been automatically canceled due to an insufficient number of participants."
+ cancelled_training: "The %{TRAINING} training session scheduled for %{DATE}, from %{START} to %{END} has been canceled due to an insufficient number of participants."
+ auto_refund: "You were refunded on your wallet and a credit note should be available."
notify_member_subscription_is_expired:
subject: "Your subscription has expired"
body:
@@ -146,6 +147,12 @@ en:
subject: "A member subscription expires in 7 days"
body:
subscription_will_expire_html: "Subscription plan for user %{NAME} %{PLAN} will expire in 7 days."
+ notify_admin_training_auto_cancelled:
+ subject: "A training was automatically cancelled"
+ body:
+ cancelled_training: "The %{TRAINING} training session scheduled for %{DATE}, from %{START} to %{END} has been automatically canceled due to an insufficient number of participants."
+ auto_refund: "The members who have booked this training session were automatically refunded on their wallet and credit notes was generated."
+ manual_refund: "Please manually refund all members who have booked this training session and generate the credit notes."
notify_admin_subscription_is_expired:
subject: "A member subscription has expired"
body: