From 45959b1fa441847e75f62fedd1c0318fe561906e Mon Sep 17 00:00:00 2001 From: Du Peng Date: Mon, 4 Sep 2023 11:48:58 +0200 Subject: [PATCH 01/13] (bug) unable to update user profile by admin --- CHANGELOG.md | 1 + .../src/javascript/components/user/user-profile-form.tsx | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index add0e6c5c..ef3770b86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Fix a bug: for project categories, if there is no category : do not show categories panel in show view, do not show categories input field in edit view - Fix a bug: unable to update status to paid for latest payment schedule item - Fix a bug: unable to generate statistic +- Fix a bug: unable to update user profile by admin - Feature: add a filter in members list (admin) to show only "not validated" members - Concerning statistics: - removes age and type column from all statistics tabs (only in web, not in xlsx export file) diff --git a/app/frontend/src/javascript/components/user/user-profile-form.tsx b/app/frontend/src/javascript/components/user/user-profile-form.tsx index 21ce943a5..eb7911b93 100644 --- a/app/frontend/src/javascript/components/user/user-profile-form.tsx +++ b/app/frontend/src/javascript/components/user/user-profile-form.tsx @@ -136,6 +136,7 @@ export const UserProfileForm: React.FC = ({ action, size, } return handleSubmit((data: User) => { + ['events_reservations', 'space_reservations', 'training_reservations', 'machine_reservations', 'all_projects', 'invoices', 'subscribed_plan', 'subscription'].forEach(key => delete data[key]); MemberAPI[action](data) .then(res => { reset(res); From b458f03e43d257ade3684a8f881078f6e73caf0a Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Tue, 5 Sep 2023 11:15:12 +0200 Subject: [PATCH 02/13] add a notification to remind users to upload their supporting documents --- CHANGELOG.md | 2 + .../javascript/models/notification-type.ts | 1 + app/models/user.rb | 1 + app/services/members/members_service.rb | 1 + ...supporting_document_reminder.json.jbuilder | 4 + ...user_supporting_document_reminder.html.erb | 5 ++ .../supporting_documents_reminder_worker.rb | 27 +++++++ config/locales/en.yml | 2 + config/locales/fr.yml | 2 + config/locales/mails.en.yml | 4 + config/schedule.yml | 5 ++ ...ing_documents_reminder_sent_at_to_users.rb | 5 ++ db/seeds/notification_types.rb | 1 + db/structure.sql | 17 ++++- test/fixtures/notification_types.yml | 8 ++ ...pporting_documents_reminder_worker_test.rb | 73 +++++++++++++++++++ 16 files changed, 155 insertions(+), 3 deletions(-) create mode 100644 app/views/api/notifications/_notify_user_supporting_document_reminder.json.jbuilder create mode 100644 app/views/notifications_mailer/notify_user_supporting_document_reminder.html.erb create mode 100644 app/workers/supporting_documents_reminder_worker.rb create mode 100644 db/migrate/20230901090637_add_supporting_documents_reminder_sent_at_to_users.rb create mode 100644 test/workers/supporting_documents_reminder_worker_test.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index a40ad652b..34a863cb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,9 @@ - Fix a bug: for project categories, if there is no category : do not show categories panel in show view, do not show categories input field in edit view - Fix a bug: unable to update status to paid for latest payment schedule item - Fix a bug: unable to generate statistic +- Improvement : add a notification to remind users to upload their supporting documents - [TODO DEPLOY] `rails fablab:maintenance:regenerate_statistics[2014,1]` +- [TODO DEPLOY] `rails db:seed` ## v6.0.13 2023 August 28 diff --git a/app/frontend/src/javascript/models/notification-type.ts b/app/frontend/src/javascript/models/notification-type.ts index 906320abc..4089b03a1 100644 --- a/app/frontend/src/javascript/models/notification-type.ts +++ b/app/frontend/src/javascript/models/notification-type.ts @@ -74,6 +74,7 @@ export const notificationTypeNames = [ 'notify_user_is_validated', 'notify_user_is_invalidated', 'notify_user_supporting_document_refusal', + 'notify_user_supporting_document_reminder', 'notify_admin_user_supporting_document_refusal', 'notify_user_order_is_ready', 'notify_user_order_is_canceled', diff --git a/app/models/user.rb b/app/models/user.rb index 8568a444a..c8bd3135c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -89,6 +89,7 @@ class User < ApplicationRecord scope :with_subscription, -> { joins(statistic_profile: [:subscriptions]) } scope :not_confirmed, -> { where(confirmed_at: nil) } scope :inactive_for_3_years, -> { where('users.last_sign_in_at < ?', 3.years.ago) } + scope :supporting_documents_reminder_not_sent, -> { where(supporting_documents_reminder_sent_at: nil) } def to_json(*) ApplicationController.new.view_context.render( diff --git a/app/services/members/members_service.rb b/app/services/members/members_service.rb index 46c8f06da..e84966e12 100644 --- a/app/services/members/members_service.rb +++ b/app/services/members/members_service.rb @@ -27,6 +27,7 @@ class Members::MembersService if @member.validated_at? && !(new_types - current_types).empty? validated_at_changed = true @member.validated_at = nil + @member.supporting_documents_reminder_sent_at = nil end end diff --git a/app/views/api/notifications/_notify_user_supporting_document_reminder.json.jbuilder b/app/views/api/notifications/_notify_user_supporting_document_reminder.json.jbuilder new file mode 100644 index 000000000..279b0fe0a --- /dev/null +++ b/app/views/api/notifications/_notify_user_supporting_document_reminder.json.jbuilder @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +json.title notification.notification_type +json.description t('.reminder_message') diff --git a/app/views/notifications_mailer/notify_user_supporting_document_reminder.html.erb b/app/views/notifications_mailer/notify_user_supporting_document_reminder.html.erb new file mode 100644 index 000000000..dfa3ed300 --- /dev/null +++ b/app/views/notifications_mailer/notify_user_supporting_document_reminder.html.erb @@ -0,0 +1,5 @@ +<%= render 'notifications_mailer/shared/hello', recipient: @recipient %> + +

+ <%= t('.body.user_supporting_document_reminder') %> +

\ No newline at end of file diff --git a/app/workers/supporting_documents_reminder_worker.rb b/app/workers/supporting_documents_reminder_worker.rb new file mode 100644 index 000000000..91a54f2b5 --- /dev/null +++ b/app/workers/supporting_documents_reminder_worker.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +# Asynchronously export the accounting data (AccountingLines) to an external accounting software +class SupportingDocumentsReminderWorker + include Sidekiq::Worker + + def perform + users_to_notify = User.members + .supporting_documents_reminder_not_sent + .where("users.created_at < ?", 2.days.ago) + .left_outer_joins(supporting_document_files: { supporting_document_type: :groups }) + .where("groups.id = users.group_id OR groups.id IS NULL") + .select("users.*, count(supporting_document_files.id)") + .group("users.id") + .having("(count(supporting_document_files.id)) < (SELECT count(supporting_document_types.id) "\ + "FROM supporting_document_types "\ + "INNER JOIN supporting_document_types_groups "\ + "ON supporting_document_types_groups.supporting_document_type_id = supporting_document_types.id "\ + "WHERE supporting_document_types_groups.group_id = users.group_id)") + users_to_notify.each do |user| + NotificationCenter.call type: 'notify_user_supporting_document_reminder', + receiver: user, + attached_object: user + user.update_column(:supporting_documents_reminder_sent_at, DateTime.current) + end + end +end \ No newline at end of file diff --git a/config/locales/en.yml b/config/locales/en.yml index f78c2203c..bc4aa012d 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -446,6 +446,8 @@ en: account_invalidated: "Your account is invalid." notify_user_supporting_document_refusal: refusal: "Your supporting documents were refused" + notify_user_supporting_document_reminder: + reminder_message: "This is a reminder for you to upload your supporting documents." notify_admin_user_supporting_document_refusal: refusal: "Member's supporting document %{NAME} was refused." notify_user_order_is_ready: diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 6722847d0..d62dda346 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -446,6 +446,8 @@ fr: account_invalidated: "Votre compte est invalide." notify_user_supporting_document_refusal: refusal: "Vos pièces justificatives ont été refusées" + notify_user_supporting_document_reminder: + reminder_message: "Ceci est un message de rappel pour vous inviter à uploader vos pièces justificatives." notify_admin_user_supporting_document_refusal: refusal: "Le justificatif du membre %{NAME} a été refusé." notify_user_order_is_ready: diff --git a/config/locales/mails.en.yml b/config/locales/mails.en.yml index 6151da3c6..ee299f0ab 100644 --- a/config/locales/mails.en.yml +++ b/config/locales/mails.en.yml @@ -402,6 +402,10 @@ en: body: user_supporting_document_files_refusal: "Your supporting documents were refused:" action: "Please re-upload some new supporting documents." + notify_user_supporting_document_reminder: + subject: "Reminder to upload your supporting documents" + body: + user_supporting_document_reminder: "This is a reminder for you to upload your supporting documents." notify_admin_user_supporting_document_refusal: subject: "A member's supporting documents were refused" body: diff --git a/config/schedule.yml b/config/schedule.yml index 31e0c7f81..953a374e5 100644 --- a/config/schedule.yml +++ b/config/schedule.yml @@ -62,4 +62,9 @@ auto_cancel_authorizations: class: TrainingAuthorizationWorker queue: default +supporting_documents_reminder_worker: + cron: "0 8 * * *" # every day, at 8 + class: SupportingDocumentsReminderWorker + queue: default + <%= PluginRegistry.insert_code('yml.schedule') %> diff --git a/db/migrate/20230901090637_add_supporting_documents_reminder_sent_at_to_users.rb b/db/migrate/20230901090637_add_supporting_documents_reminder_sent_at_to_users.rb new file mode 100644 index 000000000..d7842242e --- /dev/null +++ b/db/migrate/20230901090637_add_supporting_documents_reminder_sent_at_to_users.rb @@ -0,0 +1,5 @@ +class AddSupportingDocumentsReminderSentAtToUsers < ActiveRecord::Migration[7.0] + def change + add_column :users, :supporting_documents_reminder_sent_at, :datetime + end +end diff --git a/db/seeds/notification_types.rb b/db/seeds/notification_types.rb index a181bd344..b93ad7b87 100644 --- a/db/seeds/notification_types.rb +++ b/db/seeds/notification_types.rb @@ -69,6 +69,7 @@ NOTIFICATIONS_TYPES = [ { name: 'notify_user_is_validated', category: 'users_accounts', is_configurable: false }, { name: 'notify_user_is_invalidated', category: 'users_accounts', is_configurable: false }, { name: 'notify_user_supporting_document_refusal', category: 'supporting_documents', is_configurable: false }, + { name: 'notify_user_supporting_document_reminder', category: 'supporting_documents', is_configurable: false }, { name: 'notify_admin_user_supporting_document_refusal', category: 'supporting_documents', is_configurable: true }, { name: 'notify_user_order_is_ready', category: 'shop', is_configurable: false }, { name: 'notify_user_order_is_canceled', category: 'shop', is_configurable: false }, diff --git a/db/structure.sql b/db/structure.sql index 7ef685d2d..c9683cb21 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -1726,7 +1726,8 @@ CREATE TABLE public.notification_types ( category character varying NOT NULL, is_configurable boolean NOT NULL, created_at timestamp without time zone NOT NULL, - updated_at timestamp without time zone NOT NULL + updated_at timestamp without time zone NOT NULL, + roles character varying[] DEFAULT '{}'::character varying[] ); @@ -4193,7 +4194,8 @@ CREATE TABLE public.users ( current_sign_in_ip inet, last_sign_in_ip inet, mapped_from_sso character varying, - validated_at timestamp without time zone + validated_at timestamp without time zone, + supporting_documents_reminder_sent_at timestamp(6) without time zone ); @@ -6651,6 +6653,13 @@ CREATE UNIQUE INDEX index_notification_preferences_on_user_and_notification_type CREATE UNIQUE INDEX index_notification_types_on_name ON public.notification_types USING btree (name); +-- +-- Name: index_notification_types_on_roles; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_notification_types_on_roles ON public.notification_types USING btree (roles); + + -- -- Name: index_notifications_on_notification_type_id; Type: INDEX; Schema: public; Owner: - -- @@ -8900,6 +8909,8 @@ INSERT INTO "schema_migrations" (version) VALUES ('20230626122947'), ('20230718133636'), ('20230718134350'), -('20230720085857'); +('20230720085857'), +('20230828073428'), +('20230901090637'); diff --git a/test/fixtures/notification_types.yml b/test/fixtures/notification_types.yml index 579c9b9d5..4324e3748 100644 --- a/test/fixtures/notification_types.yml +++ b/test/fixtures/notification_types.yml @@ -573,3 +573,11 @@ notification_type_72: is_configurable: true created_at: 2023-02-16 10:42:39.143888000 Z updated_at: 2023-02-16 10:42:39.143888000 Z + +notification_type_73: + id: 73 + name: notify_user_supporting_document_reminder + category: supporting_documents + is_configurable: false + created_at: 2023-02-02 08:25:33.439078000 Z + updated_at: 2023-02-02 08:25:33.439078000 Z \ No newline at end of file diff --git a/test/workers/supporting_documents_reminder_worker_test.rb b/test/workers/supporting_documents_reminder_worker_test.rb new file mode 100644 index 000000000..34f64cbd0 --- /dev/null +++ b/test/workers/supporting_documents_reminder_worker_test.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true + +require 'test_helper' +require 'minitest/autorun' +#require 'sidekiq/testing' + +class SupportingDocumentsReminderWorkerTest < ActiveSupport::TestCase + include ActionMailer::TestHelper + setup do + # Sidekiq::Testing.inline! + + @worker = SupportingDocumentsReminderWorker.new + + group = groups(:group_1) + @users = User.where(group_id: group.id).members + @supporting_document_type_1 = SupportingDocumentType.create!(name: "doc1", groups: [group]) + @supporting_document_type_2 = SupportingDocumentType.create!(name: "doc2", groups: [group]) + end + + teardown do + # Sidekiq::Testing.fake! + end + + test 'notify every users who did not upload supporting document files' do + @users.each do |user| + assert_nil user.supporting_documents_reminder_sent_at + end + + assert_enqueued_emails @users.length do + @worker.perform + end + + @users.reload.each do |user| + assert user.supporting_documents_reminder_sent_at + end + + assert_enqueued_emails 0 do + @worker.perform + end + end + + test 'notify users even if they have uploaded 1 document of the 2' do + @users.each do |user| + user.supporting_document_files.create!(supporting_document_type: @supporting_document_type_1, + attachment: fixture_file_upload('document.pdf')) + end + + assert_enqueued_emails @users.length do + @worker.perform + end + end + + test 'do not notify users if they have uploaded all documents' do + @users.each do |user| + user.supporting_document_files.create!(supporting_document_type: @supporting_document_type_1, + attachment: fixture_file_upload('document.pdf')) + user.supporting_document_files.create!(supporting_document_type: @supporting_document_type_2, + attachment: fixture_file_upload('document.pdf')) + end + + assert_enqueued_emails 0 do + @worker.perform + end + end + + test 'do not notify users if they were created too recently' do + @users.update_all(created_at: 2.minutes.ago) + + assert_enqueued_emails 0 do + @worker.perform + end + end +end From dd2fcbd3522dec423976c837d50c0bda412fa74b Mon Sep 17 00:00:00 2001 From: Vincent Date: Wed, 6 Sep 2023 15:52:05 +0200 Subject: [PATCH 03/13] (ui) Remove liste style on statistics table --- app/frontend/src/stylesheets/app.utilities.scss | 5 +++++ app/frontend/templates/admin/statistics/index.html | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/frontend/src/stylesheets/app.utilities.scss b/app/frontend/src/stylesheets/app.utilities.scss index 999d0ee4d..b69f33737 100644 --- a/app/frontend/src/stylesheets/app.utilities.scss +++ b/app/frontend/src/stylesheets/app.utilities.scss @@ -989,6 +989,11 @@ p, .widget p { cursor: pointer; } +.list-none { + list-style-type: none; + padding-inline-start: 0; +} + @media screen and (min-width: $screen-lg-min) { .b-r-lg { border-right: 1px solid $border-color; diff --git a/app/frontend/templates/admin/statistics/index.html b/app/frontend/templates/admin/statistics/index.html index 2a19a017b..7a85e3f04 100644 --- a/app/frontend/templates/admin/statistics/index.html +++ b/app/frontend/templates/admin/statistics/index.html @@ -288,7 +288,7 @@ {{formatDate(datum._source[field.key])}} -
    +
    • {{elem.name}}
    {{datum._source[field.key]}} From ccfa7aeb39ef6ea20825f612e7e75e26ce4b09b5 Mon Sep 17 00:00:00 2001 From: Du Peng Date: Wed, 6 Sep 2023 16:34:18 +0200 Subject: [PATCH 04/13] (bug) unable to generate stat for reservation no invoice --- app/services/statistics/fetcher_service.rb | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/app/services/statistics/fetcher_service.rb b/app/services/statistics/fetcher_service.rb index d6b3867ed..81e79f287 100644 --- a/app/services/statistics/fetcher_service.rb +++ b/app/services/statistics/fetcher_service.rb @@ -50,7 +50,6 @@ class Statistics::FetcherService .eager_load(:slots, :slots_reservations, :invoice_items, :reservation_context, statistic_profile: [:group]) .find_each do |r| next unless r.reservable - next unless r.original_invoice next if r.slots.empty? profile = r.statistic_profile @@ -63,7 +62,7 @@ class Statistics::FetcherService nb_hours: (r.slots.map(&:duration).map(&:to_i).reduce(:+) / 3600.0).to_f, ca: calcul_ca(r.original_invoice), reservation_context_id: r.reservation_context_id, - coupon: r.original_invoice.coupon&.code }.merge(user_info(profile)) + coupon: r&.original_invoice&.coupon&.code }.merge(user_info(profile)) yield result end end @@ -78,7 +77,6 @@ class Statistics::FetcherService .eager_load(:slots, :slots_reservations, :invoice_items, :reservation_context, statistic_profile: [:group]) .find_each do |r| next unless r.reservable - next unless r.original_invoice next if r.slots.empty? profile = r.statistic_profile @@ -91,7 +89,7 @@ class Statistics::FetcherService nb_hours: (r.slots.map(&:duration).map(&:to_i).reduce(:+) / 3600.0).to_f, ca: calcul_ca(r.original_invoice), reservation_context_id: r.reservation_context_id, - coupon: r.original_invoice.coupon&.code }.merge(user_info(profile)) + coupon: r&.original_invoice&.coupon&.code }.merge(user_info(profile)) yield result end end @@ -106,7 +104,7 @@ class Statistics::FetcherService .eager_load(:slots, :slots_reservations, :invoice_items, :reservation_context, statistic_profile: [:group]) .find_each do |r| next unless r.reservable - next unless r.original_invoice + next if r.slots.empty? profile = r.statistic_profile slot = r.slots.first @@ -119,7 +117,7 @@ class Statistics::FetcherService nb_hours: difference_in_hours(slot.start_at, slot.end_at), ca: calcul_ca(r.original_invoice), reservation_context_id: r.reservation_context_id, - coupon: r.original_invoice&.coupon&.code }.merge(user_info(profile)) + coupon: r&.original_invoice&.coupon&.code }.merge(user_info(profile)) yield result end end @@ -134,7 +132,7 @@ class Statistics::FetcherService .eager_load(:slots, :slots_reservations, :invoice_items, statistic_profile: [:group]) .find_each do |r| next unless r.reservable - next unless r.original_invoice + next if r.slots.empty? profile = r.statistic_profile slot = r.slots.first @@ -148,7 +146,7 @@ class Statistics::FetcherService age_range: (r.reservable.age_range_id ? r.reservable.age_range.name : ''), nb_places: r.total_booked_seats, nb_hours: difference_in_hours(slot.start_at, slot.end_at), - coupon: r.original_invoice.coupon&.code, + coupon: r&.original_invoice&.coupon&.code, ca: calcul_ca(r.original_invoice) }.merge(user_info(profile)) yield result end From 48d76fa783ae67c63b3ffee37df1b94cd377cf30 Mon Sep 17 00:00:00 2001 From: Du Peng Date: Wed, 6 Sep 2023 16:44:37 +0200 Subject: [PATCH 05/13] Version 6.0.14 --- CHANGELOG.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef3770b86..df4bcb8e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## next deploy +## v6.0.14 2023 September 6 + - Fix a bug: for project categories, if there is no category : do not show categories panel in show view, do not show categories input field in edit view - Fix a bug: unable to update status to paid for latest payment schedule item - Fix a bug: unable to generate statistic diff --git a/package.json b/package.json index e9d45480c..fb7e247d0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fab-manager", - "version": "6.0.13", + "version": "6.0.14", "description": "Fab-manager is the FabLab management solution. It provides a comprehensive, web-based, open-source tool to simplify your administrative tasks and your marker's projects.", "keywords": [ "fablab", From a72c2e580cec035974c49e24153adcddaca58ab1 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Thu, 7 Sep 2023 10:30:48 +0200 Subject: [PATCH 06/13] improves api/notification controller to avoid failing when there is a notification with wrong notification_type in db --- CHANGELOG.md | 2 + .../api/notifications_controller.rb | 15 ++-- app/models/notification.rb | 2 + app/models/notification_type.rb | 2 +- config/initializers/notification_types.rb | 80 +++++++++++++++++++ db/seeds/notification_types.rb | 79 ------------------ 6 files changed, 94 insertions(+), 86 deletions(-) create mode 100644 config/initializers/notification_types.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index df4bcb8e6..4df4f4a82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## next deploy +- improves api/notification controller to avoid failing when there is a notification with wrong notification_type in db + ## v6.0.14 2023 September 6 - Fix a bug: for project categories, if there is no category : do not show categories panel in show view, do not show categories input field in edit view diff --git a/app/controllers/api/notifications_controller.rb b/app/controllers/api/notifications_controller.rb index 919d1aa5a..7a76c20e6 100644 --- a/app/controllers/api/notifications_controller.rb +++ b/app/controllers/api/notifications_controller.rb @@ -15,6 +15,7 @@ class API::NotificationsController < API::APIController def index loop do @notifications = current_user.notifications + .with_valid_notification_type .delivered_in_system(current_user) .includes(:attached_object) .page(params[:page]) @@ -24,8 +25,8 @@ class API::NotificationsController < API::APIController break unless delete_obsoletes(@notifications) end @totals = { - total: current_user.notifications.delivered_in_system(current_user).count, - unread: current_user.notifications.delivered_in_system(current_user).where(is_read: false).count + total: current_user.notifications.with_valid_notification_type.delivered_in_system(current_user).count, + unread: current_user.notifications.with_valid_notification_type.delivered_in_system(current_user).where(is_read: false).count } render :index end @@ -33,6 +34,7 @@ class API::NotificationsController < API::APIController def last_unread loop do @notifications = current_user.notifications + .with_valid_notification_type .delivered_in_system(current_user) .includes(:attached_object) .where(is_read: false) @@ -42,19 +44,20 @@ class API::NotificationsController < API::APIController break unless delete_obsoletes(@notifications) end @totals = { - total: current_user.notifications.delivered_in_system(current_user).count, - unread: current_user.notifications.delivered_in_system(current_user).where(is_read: false).count + total: current_user.notifications.with_valid_notification_type.delivered_in_system(current_user).count, + unread: current_user.notifications.with_valid_notification_type.delivered_in_system(current_user).where(is_read: false).count } render :index end def polling @notifications = current_user.notifications + .with_valid_notification_type .where('is_read = false AND created_at >= :date', date: params[:last_poll]) .order('created_at DESC') @totals = { - total: current_user.notifications.delivered_in_system(current_user).count, - unread: current_user.notifications.delivered_in_system(current_user).where(is_read: false).count + total: current_user.notifications.with_valid_notification_type.delivered_in_system(current_user).count, + unread: current_user.notifications.with_valid_notification_type.delivered_in_system(current_user).where(is_read: false).count } render :index end diff --git a/app/models/notification.rb b/app/models/notification.rb index e89f36691..dfcc90ac1 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -19,6 +19,8 @@ class Notification < ApplicationRecord SQL } + scope :with_valid_notification_type, -> { joins(:notification_type).where(notification_types: { name: NOTIFICATIONS_TYPES.map { |nt| nt[:name] } }) } + validates :receiver_id, :receiver_type, :attached_object_id, diff --git a/app/models/notification_type.rb b/app/models/notification_type.rb index 135cb513c..b6531b0e7 100644 --- a/app/models/notification_type.rb +++ b/app/models/notification_type.rb @@ -2,7 +2,7 @@ # NotificationType defines the different types of Notification. # To add a new notification type in db, you must add it in: -# - db/seeds/notification_types.rb +# - config/initializers/notification_types.rb # - app/views/api/notifications/_XXXXXX.json.jbuilder # - app/views/notifications_mailer/XXXXXX.html.erb # - app/frontend/src/javascript/models/notification-type.ts diff --git a/config/initializers/notification_types.rb b/config/initializers/notification_types.rb new file mode 100644 index 000000000..1a23e40aa --- /dev/null +++ b/config/initializers/notification_types.rb @@ -0,0 +1,80 @@ +# frozen_string_literal: true + +NOTIFICATIONS_TYPES = [ + { name: 'notify_admin_when_project_published', category: 'projects', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_project_collaborator_to_valid', category: 'projects', is_configurable: false }, + { name: 'notify_project_author_when_collaborator_valid', category: 'projects', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_user_training_valid', category: 'trainings', is_configurable: false }, + { name: 'notify_member_subscribed_plan', category: 'subscriptions', is_configurable: false }, + { name: 'notify_member_create_reservation', category: 'agenda', is_configurable: false }, + { name: 'notify_member_subscribed_plan_is_changed', category: 'deprecated', is_configurable: false }, + { name: 'notify_admin_member_create_reservation', category: 'agenda', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_member_slot_is_modified', category: 'agenda', is_configurable: false }, + { name: 'notify_admin_slot_is_modified', category: 'agenda', is_configurable: true, roles: ['admin', 'manager'] }, + + { name: 'notify_admin_when_user_is_created', category: 'users_accounts', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_admin_subscribed_plan', category: 'subscriptions', is_configurable: true, roles: ['admin'] }, + { name: 'notify_user_when_invoice_ready', category: 'payments', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_member_subscription_will_expire_in_7_days', category: 'subscriptions', is_configurable: false }, + { name: 'notify_member_subscription_is_expired', category: 'subscriptions', is_configurable: false }, + { name: 'notify_admin_subscription_will_expire_in_7_days', category: 'subscriptions', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_admin_subscription_is_expired', category: 'subscriptions', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_admin_subscription_canceled', category: 'subscriptions', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_member_subscription_canceled', category: 'subscriptions', is_configurable: false }, + { name: 'notify_user_when_avoir_ready', category: 'wallet', is_configurable: false }, + + { name: 'notify_member_slot_is_canceled', category: 'agenda', is_configurable: false }, + { name: 'notify_admin_slot_is_canceled', category: 'agenda', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_partner_subscribed_plan', category: 'subscriptions', is_configurable: false }, + { name: 'notify_member_subscription_extended', category: 'subscriptions', is_configurable: false }, + { name: 'notify_admin_subscription_extended', category: 'subscriptions', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_admin_user_group_changed', category: 'users_accounts', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_user_user_group_changed', category: 'users_accounts', is_configurable: false }, + { name: 'notify_admin_when_user_is_imported', category: 'users_accounts', is_configurable: true, roles: ['admin'] }, + { name: 'notify_user_profile_complete', category: 'users_accounts', is_configurable: false }, + { name: 'notify_user_auth_migration', category: 'user', is_configurable: false }, + + { name: 'notify_admin_user_merged', category: 'users_accounts', is_configurable: true, roles: ['admin'] }, + { name: 'notify_admin_profile_complete', category: 'users_accounts', is_configurable: true, roles: ['admin'] }, + { name: 'notify_admin_abuse_reported', category: 'projects', is_configurable: true, roles: ['admin'] }, + { name: 'notify_admin_invoicing_changed', category: 'deprecated', is_configurable: false }, + { name: 'notify_user_wallet_is_credited', category: 'wallet', is_configurable: false }, + { name: 'notify_admin_user_wallet_is_credited', category: 'wallet', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_admin_export_complete', category: 'exports', is_configurable: false }, + { name: 'notify_member_about_coupon', category: 'agenda', is_configurable: false }, + { name: 'notify_member_reservation_reminder', category: 'agenda', is_configurable: false }, + + { name: 'notify_admin_free_disk_space', category: 'app_management', is_configurable: false }, + { name: 'notify_admin_close_period_reminder', category: 'accountings', is_configurable: true, roles: ['admin'] }, + { name: 'notify_admin_archive_complete', category: 'accountings', is_configurable: true, roles: ['admin'] }, + { name: 'notify_privacy_policy_changed', category: 'app_management', is_configurable: false }, + { name: 'notify_admin_import_complete', category: 'app_management', is_configurable: false }, + { name: 'notify_admin_refund_created', category: 'wallet', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_admins_role_update', category: 'users_accounts', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_user_role_update', category: 'users_accounts', is_configurable: false }, + { name: 'notify_admin_objects_stripe_sync', category: 'payments', is_configurable: false }, + { name: 'notify_user_when_payment_schedule_ready', category: 'payments', is_configurable: false }, + + { name: 'notify_admin_payment_schedule_failed', category: 'payments', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_member_payment_schedule_failed', category: 'payments', is_configurable: false }, + { name: 'notify_admin_payment_schedule_check_deadline', category: 'payments', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_admin_payment_schedule_transfer_deadline', category: 'payments', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_admin_payment_schedule_error', category: 'payments', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_member_payment_schedule_error', category: 'payments', is_configurable: false }, + { name: 'notify_admin_payment_schedule_gateway_canceled', category: 'payments', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_member_payment_schedule_gateway_canceled', category: 'payments', is_configurable: false }, + { name: 'notify_admin_user_supporting_document_files_created', category: 'supporting_documents', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_admin_user_supporting_document_files_updated', category: 'supporting_documents', is_configurable: true, roles: ['admin', 'manager'] }, + + { name: 'notify_user_is_validated', category: 'users_accounts', is_configurable: false }, + { name: 'notify_user_is_invalidated', category: 'users_accounts', is_configurable: false }, + { name: 'notify_user_supporting_document_refusal', category: 'supporting_documents', is_configurable: false }, + { name: 'notify_admin_user_supporting_document_refusal', category: 'supporting_documents', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_admin_order_is_paid', category: 'shop', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_user_order_is_ready', category: 'shop', is_configurable: false }, + { name: 'notify_user_order_is_canceled', category: 'shop', is_configurable: false }, + { name: 'notify_user_order_is_refunded', category: 'shop', is_configurable: false }, + { name: 'notify_admin_low_stock_threshold', category: 'shop', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_admin_training_auto_cancelled', category: 'trainings', is_configurable: true, roles: ['admin', 'manager'] }, + { name: 'notify_member_training_auto_cancelled', category: 'trainings', is_configurable: false } +].freeze \ No newline at end of file diff --git a/db/seeds/notification_types.rb b/db/seeds/notification_types.rb index ff894b640..9308d897f 100644 --- a/db/seeds/notification_types.rb +++ b/db/seeds/notification_types.rb @@ -1,84 +1,5 @@ # frozen_string_literal: true -NOTIFICATIONS_TYPES = [ - { name: 'notify_admin_when_project_published', category: 'projects', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_project_collaborator_to_valid', category: 'projects', is_configurable: false }, - { name: 'notify_project_author_when_collaborator_valid', category: 'projects', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_user_training_valid', category: 'trainings', is_configurable: false }, - { name: 'notify_member_subscribed_plan', category: 'subscriptions', is_configurable: false }, - { name: 'notify_member_create_reservation', category: 'agenda', is_configurable: false }, - { name: 'notify_member_subscribed_plan_is_changed', category: 'deprecated', is_configurable: false }, - { name: 'notify_admin_member_create_reservation', category: 'agenda', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_member_slot_is_modified', category: 'agenda', is_configurable: false }, - { name: 'notify_admin_slot_is_modified', category: 'agenda', is_configurable: true, roles: ['admin', 'manager'] }, - - { name: 'notify_admin_when_user_is_created', category: 'users_accounts', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_admin_subscribed_plan', category: 'subscriptions', is_configurable: true, roles: ['admin'] }, - { name: 'notify_user_when_invoice_ready', category: 'payments', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_member_subscription_will_expire_in_7_days', category: 'subscriptions', is_configurable: false }, - { name: 'notify_member_subscription_is_expired', category: 'subscriptions', is_configurable: false }, - { name: 'notify_admin_subscription_will_expire_in_7_days', category: 'subscriptions', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_admin_subscription_is_expired', category: 'subscriptions', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_admin_subscription_canceled', category: 'subscriptions', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_member_subscription_canceled', category: 'subscriptions', is_configurable: false }, - { name: 'notify_user_when_avoir_ready', category: 'wallet', is_configurable: false }, - - { name: 'notify_member_slot_is_canceled', category: 'agenda', is_configurable: false }, - { name: 'notify_admin_slot_is_canceled', category: 'agenda', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_partner_subscribed_plan', category: 'subscriptions', is_configurable: false }, - { name: 'notify_member_subscription_extended', category: 'subscriptions', is_configurable: false }, - { name: 'notify_admin_subscription_extended', category: 'subscriptions', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_admin_user_group_changed', category: 'users_accounts', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_user_user_group_changed', category: 'users_accounts', is_configurable: false }, - { name: 'notify_admin_when_user_is_imported', category: 'users_accounts', is_configurable: true, roles: ['admin'] }, - { name: 'notify_user_profile_complete', category: 'users_accounts', is_configurable: false }, - { name: 'notify_user_auth_migration', category: 'user', is_configurable: false }, - - { name: 'notify_admin_user_merged', category: 'users_accounts', is_configurable: true, roles: ['admin'] }, - { name: 'notify_admin_profile_complete', category: 'users_accounts', is_configurable: true, roles: ['admin'] }, - { name: 'notify_admin_abuse_reported', category: 'projects', is_configurable: true, roles: ['admin'] }, - { name: 'notify_admin_invoicing_changed', category: 'deprecated', is_configurable: false }, - { name: 'notify_user_wallet_is_credited', category: 'wallet', is_configurable: false }, - { name: 'notify_admin_user_wallet_is_credited', category: 'wallet', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_admin_export_complete', category: 'exports', is_configurable: false }, - { name: 'notify_member_about_coupon', category: 'agenda', is_configurable: false }, - { name: 'notify_member_reservation_reminder', category: 'agenda', is_configurable: false }, - - { name: 'notify_admin_free_disk_space', category: 'app_management', is_configurable: false }, - { name: 'notify_admin_close_period_reminder', category: 'accountings', is_configurable: true, roles: ['admin'] }, - { name: 'notify_admin_archive_complete', category: 'accountings', is_configurable: true, roles: ['admin'] }, - { name: 'notify_privacy_policy_changed', category: 'app_management', is_configurable: false }, - { name: 'notify_admin_import_complete', category: 'app_management', is_configurable: false }, - { name: 'notify_admin_refund_created', category: 'wallet', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_admins_role_update', category: 'users_accounts', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_user_role_update', category: 'users_accounts', is_configurable: false }, - { name: 'notify_admin_objects_stripe_sync', category: 'payments', is_configurable: false }, - { name: 'notify_user_when_payment_schedule_ready', category: 'payments', is_configurable: false }, - - { name: 'notify_admin_payment_schedule_failed', category: 'payments', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_member_payment_schedule_failed', category: 'payments', is_configurable: false }, - { name: 'notify_admin_payment_schedule_check_deadline', category: 'payments', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_admin_payment_schedule_transfer_deadline', category: 'payments', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_admin_payment_schedule_error', category: 'payments', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_member_payment_schedule_error', category: 'payments', is_configurable: false }, - { name: 'notify_admin_payment_schedule_gateway_canceled', category: 'payments', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_member_payment_schedule_gateway_canceled', category: 'payments', is_configurable: false }, - { name: 'notify_admin_user_supporting_document_files_created', category: 'supporting_documents', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_admin_user_supporting_document_files_updated', category: 'supporting_documents', is_configurable: true, roles: ['admin', 'manager'] }, - - { name: 'notify_user_is_validated', category: 'users_accounts', is_configurable: false }, - { name: 'notify_user_is_invalidated', category: 'users_accounts', is_configurable: false }, - { name: 'notify_user_supporting_document_refusal', category: 'supporting_documents', is_configurable: false }, - { name: 'notify_admin_user_supporting_document_refusal', category: 'supporting_documents', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_admin_order_is_paid', category: 'shop', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_user_order_is_ready', category: 'shop', is_configurable: false }, - { name: 'notify_user_order_is_canceled', category: 'shop', is_configurable: false }, - { name: 'notify_user_order_is_refunded', category: 'shop', is_configurable: false }, - { name: 'notify_admin_low_stock_threshold', category: 'shop', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_admin_training_auto_cancelled', category: 'trainings', is_configurable: true, roles: ['admin', 'manager'] }, - { name: 'notify_member_training_auto_cancelled', category: 'trainings', is_configurable: false } -].freeze - NOTIFICATIONS_TYPES.each do |notification_type_attrs| notification_type = NotificationType.find_by(name: notification_type_attrs[:name]) From 6806a60f5af75a0fb3af3050f6c044b726065ea5 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Thu, 7 Sep 2023 10:51:11 +0200 Subject: [PATCH 07/13] improves supporting documents reminder worker test --- ...upporting_documents_reminder_worker_test.rb | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/test/workers/supporting_documents_reminder_worker_test.rb b/test/workers/supporting_documents_reminder_worker_test.rb index 34f64cbd0..a8be8c007 100644 --- a/test/workers/supporting_documents_reminder_worker_test.rb +++ b/test/workers/supporting_documents_reminder_worker_test.rb @@ -7,8 +7,6 @@ require 'minitest/autorun' class SupportingDocumentsReminderWorkerTest < ActiveSupport::TestCase include ActionMailer::TestHelper setup do - # Sidekiq::Testing.inline! - @worker = SupportingDocumentsReminderWorker.new group = groups(:group_1) @@ -17,8 +15,20 @@ class SupportingDocumentsReminderWorkerTest < ActiveSupport::TestCase @supporting_document_type_2 = SupportingDocumentType.create!(name: "doc2", groups: [group]) end - teardown do - # Sidekiq::Testing.fake! + test 'do nothing if it concerns another group' do + group = Group.create!(name: 'test', slug: 'test') + SupportingDocumentType.destroy_all + supporting_document_type = SupportingDocumentType.create!(name: "doc3", groups: [group]) + + @users.each do |user| + assert_nil user.supporting_documents_reminder_sent_at + end + assert_enqueued_emails 0 do + @worker.perform + end + @users.reload.each do |user| + assert_nil user.supporting_documents_reminder_sent_at + end end test 'notify every users who did not upload supporting document files' do From e4bd077907b8dc431acfdb61ddf3a30316e14979 Mon Sep 17 00:00:00 2001 From: Du Peng Date: Thu, 7 Sep 2023 16:22:57 +0200 Subject: [PATCH 08/13] (feat) Add extra_authorize_params to OpenIdConnect config --- CHANGELOG.md | 1 + .../api/auth_providers_controller.rb | 2 +- .../openid-connect-form.tsx | 15 + .../models/authentication-provider.ts | 3 +- .../api/auth_providers/show.json.jbuilder | 2 +- .../auth_provider/provider.json.jbuilder | 4 +- config/locales/app.admin.de.yml | 2 + config/locales/app.admin.en.yml | 2 + config/locales/app.admin.es.yml | 2 + config/locales/app.admin.fr.yml | 2 + config/locales/app.admin.it.yml | 2 + config/locales/app.admin.no.yml | 2 + config/locales/app.admin.pt.yml | 2 + config/locales/app.admin.zu.yml | 2 + ...rize_params_to_open_id_connect_provider.rb | 5 + db/structure.sql | 456 ++++++++++++++++-- 16 files changed, 448 insertions(+), 56 deletions(-) create mode 100644 db/migrate/20230907124230_add_extra_authorize_params_to_open_id_connect_provider.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 4df4f4a82..ccd34ae1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## next deploy - improves api/notification controller to avoid failing when there is a notification with wrong notification_type in db +- Add extra_authorize_params to OpenIdConnect config ## v6.0.14 2023 September 6 diff --git a/app/controllers/api/auth_providers_controller.rb b/app/controllers/api/auth_providers_controller.rb index 97a5c0ceb..82fa50388 100644 --- a/app/controllers/api/auth_providers_controller.rb +++ b/app/controllers/api/auth_providers_controller.rb @@ -99,7 +99,7 @@ class API::AuthProvidersController < API::APIController providable_attributes: [:id, :issuer, :discovery, :client_auth_method, :prompt, :send_scope_to_token_endpoint, :client__identifier, :client__secret, :client__authorization_endpoint, :client__token_endpoint, :client__userinfo_endpoint, :client__jwks_uri, :client__end_session_endpoint, :profile_url, - { scope: [] }], + :extra_authorize_params, { scope: [] }], auth_provider_mappings_attributes: [:id, :local_model, :local_field, :api_field, :api_endpoint, :api_data_type, :_destroy, { transformation: [:type, :format, :true_value, :false_value, { mapping: %i[from to] }] }]) diff --git a/app/frontend/src/javascript/components/authentication-provider/openid-connect-form.tsx b/app/frontend/src/javascript/components/authentication-provider/openid-connect-form.tsx index 58fd7041a..467f3cd09 100644 --- a/app/frontend/src/javascript/components/authentication-provider/openid-connect-form.tsx +++ b/app/frontend/src/javascript/components/authentication-provider/openid-connect-form.tsx @@ -34,6 +34,15 @@ export const OpenidConnectForm = (0); + useEffect(() => { + if (!currentFormValues?.extra_authorize_params) { + setValue( + 'providable_attributes.extra_authorize_params' as Path, + '{}' as UnpackNestedValue>> + ); + } + }, []); + // when we have detected a discovery endpoint, we mark it as available useEffect(() => { setValue( @@ -160,6 +169,12 @@ export const OpenidConnectForm = +

    {t('app.admin.authentication.openid_connect_form.client_options')}

    Date: Mon, 11 Sep 2023 09:07:27 +0200 Subject: [PATCH 09/13] fix NotificationsController#polling failing request --- app/controllers/api/notifications_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/notifications_controller.rb b/app/controllers/api/notifications_controller.rb index 7a76c20e6..c226d2b82 100644 --- a/app/controllers/api/notifications_controller.rb +++ b/app/controllers/api/notifications_controller.rb @@ -53,8 +53,8 @@ class API::NotificationsController < API::APIController def polling @notifications = current_user.notifications .with_valid_notification_type - .where('is_read = false AND created_at >= :date', date: params[:last_poll]) - .order('created_at DESC') + .where('notifications.is_read = false AND notifications.created_at >= :date', date: params[:last_poll]) + .order('notifications.created_at DESC') @totals = { total: current_user.notifications.with_valid_notification_type.delivered_in_system(current_user).count, unread: current_user.notifications.with_valid_notification_type.delivered_in_system(current_user).where(is_read: false).count From aad5da63be8b4d2f30bd8b8d3c936d9aa35be1fd Mon Sep 17 00:00:00 2001 From: Vincent Date: Mon, 11 Sep 2023 09:15:00 +0200 Subject: [PATCH 10/13] (i18n) Typo --- config/locales/app.public.fr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/app.public.fr.yml b/config/locales/app.public.fr.yml index 155fa832d..605236d83 100644 --- a/config/locales/app.public.fr.yml +++ b/config/locales/app.public.fr.yml @@ -99,7 +99,7 @@ fr: _the_fablab_policy: "les conditions d'utilisation" field_required: "Champ requis" profile_custom_field_is_required: "{FEILD} est requis" - user_supporting_documents_required: "Attention !
    Vous avez déclarez être \"{GROUP}\", des pièces justificatives pourront vous être demandées." + user_supporting_documents_required: "Attention !
    Vous avez déclaré être \"{GROUP}\", des pièces justificatives pourront vous être demandées." unexpected_error_occurred: "Une erreur inattendue s'est produite. Veuillez réessayer ultérieurement." used_for_statistics: "Cette donnée sera utilisée à des fins statistiques" used_for_invoicing: "Cette donnée sera utilisée à des fins de facturation" From 48bf00f6e675d08dbe7f132c781b8ca7e1434c0b Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Mon, 11 Sep 2023 09:22:30 +0200 Subject: [PATCH 11/13] adds test for NotificationsController#polling --- .../notifications/notifications_test.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/integration/notifications/notifications_test.rb b/test/integration/notifications/notifications_test.rb index 69b6ce9d2..840573fd5 100644 --- a/test/integration/notifications/notifications_test.rb +++ b/test/integration/notifications/notifications_test.rb @@ -39,6 +39,21 @@ class NotificationsTest < ActionDispatch::IntegrationTest assert_equal (Notification.where(receiver_id: @admin.id).count - 1), notifications_total end + test 'polling endpoint' do + @admin = User.find_by(username: 'admin') + login_as(@admin, scope: :user) + + get '/api/notifications/polling', params: { last_poll: Notification.order(:created_at).pick(:created_at) } + + # Check response format & status + assert_equal 200, response.status, response.body + assert_match Mime[:json].to_s, response.content_type + + # Check the list items are ok + notifications_total = json_response(response.body)[:totals][:total] + assert_not_equal notifications.count, 0 + end + test 'Last unread returns last 3 unread notifications' do @member = User.find(4) login_as(@member, scope: :user) From 35c72cc5ced17e84204e68147f5b417b41ac9263 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Mon, 11 Sep 2023 14:21:51 +0200 Subject: [PATCH 12/13] fix comment --- app/workers/supporting_documents_reminder_worker.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/workers/supporting_documents_reminder_worker.rb b/app/workers/supporting_documents_reminder_worker.rb index 91a54f2b5..5adb7c66a 100644 --- a/app/workers/supporting_documents_reminder_worker.rb +++ b/app/workers/supporting_documents_reminder_worker.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Asynchronously export the accounting data (AccountingLines) to an external accounting software +# Send a notification to users who did not upload their supporting document files yet class SupportingDocumentsReminderWorker include Sidekiq::Worker From 16925bf12985a1a8119bf12fbf9a415b430c9c09 Mon Sep 17 00:00:00 2001 From: Du Peng Date: Mon, 11 Sep 2023 17:08:43 +0200 Subject: [PATCH 13/13] (i18n) update translations --- config/locales/app.admin.de.yml | 4 ++++ config/locales/app.admin.es.yml | 4 ++++ config/locales/app.admin.fr.yml | 8 ++++---- config/locales/app.admin.it.yml | 4 ++++ config/locales/app.admin.no.yml | 4 ++++ config/locales/app.admin.pt.yml | 4 ++++ config/locales/app.admin.zu.yml | 4 ++++ config/locales/de.yml | 4 ++++ config/locales/es.yml | 4 ++++ config/locales/fr.yml | 4 ++-- config/locales/it.yml | 4 ++++ config/locales/mails.de.yml | 4 ++++ config/locales/mails.es.yml | 4 ++++ config/locales/mails.fr.yml | 4 ++++ config/locales/mails.it.yml | 4 ++++ config/locales/mails.no.yml | 4 ++++ config/locales/mails.pt.yml | 4 ++++ config/locales/mails.zu.yml | 4 ++++ config/locales/no.yml | 4 ++++ config/locales/pt.yml | 4 ++++ config/locales/zu.yml | 4 ++++ 21 files changed, 82 insertions(+), 6 deletions(-) diff --git a/config/locales/app.admin.de.yml b/config/locales/app.admin.de.yml index ab269c3c7..f36a5662a 100644 --- a/config/locales/app.admin.de.yml +++ b/config/locales/app.admin.de.yml @@ -111,6 +111,10 @@ de: save: "Speichern" create_success: "Der Raum wurde erfolgreich erstellt" update_success: "Der Raum wurde erfolgreich aktualisiert" + associated_machines: "Included machines" + children_spaces: "Included spaces" + associated_objects: "Associated objects" + associated_objects_warning: "Only use these fields if you want interblocking reservation between spaces, child spaces and machines. If you want machine and space reservations to remain independent, please leave the following fields blank." event_form: ACTION_title: "{ACTION, select, create{Neue} other{Aktualisiere die}} Veranstaltung" title: "Titel" diff --git a/config/locales/app.admin.es.yml b/config/locales/app.admin.es.yml index 20d4e8ad8..35f294d4f 100644 --- a/config/locales/app.admin.es.yml +++ b/config/locales/app.admin.es.yml @@ -111,6 +111,10 @@ es: save: "Guardar" create_success: "El espacio se ha creado correctamente" update_success: "El espacio se ha actualizado correctamente" + associated_machines: "Included machines" + children_spaces: "Included spaces" + associated_objects: "Associated objects" + associated_objects_warning: "Only use these fields if you want interblocking reservation between spaces, child spaces and machines. If you want machine and space reservations to remain independent, please leave the following fields blank." event_form: ACTION_title: "{ACTION, select, create{Nuevo} other{Actualiza el}} evento" title: "Título" diff --git a/config/locales/app.admin.fr.yml b/config/locales/app.admin.fr.yml index dbf0edb20..d36efb352 100644 --- a/config/locales/app.admin.fr.yml +++ b/config/locales/app.admin.fr.yml @@ -111,10 +111,10 @@ fr: save: "Enregistrer" create_success: "L'espace a bien été créé" update_success: "L'espace a bien été mis à jour" - associated_machines: "Machines" - children_spaces: "Espaces" - associated_objects: "Machines et sous-espaces" - associated_objects_warning: "Utilisez ces champs uniquement si vous souhaitez que la réservation de l'espace bloque la réservation des machines associées et des sous-espaces (et vice-versa). Si vous souhaitez que les réservations restent indépendantes, veuillez laisser les champs suivants vides." + associated_machines: "Machines incluses" + children_spaces: "Espaces inclus" + associated_objects: "Objet associé" + associated_objects_warning: "Utilisez uniquement ces champs si vous souhaitez une réservation d'interblocage entre les espaces, les sous-espaces et les machines. Si vous voulez que les réservations de machines et d'espaces restent indépendantes, veuillez laisser les champs suivants vides." event_form: ACTION_title: "{ACTION, select, create{Nouvel } other{Mettre à jour l''}}événement" title: "Titre" diff --git a/config/locales/app.admin.it.yml b/config/locales/app.admin.it.yml index b7a5a64e3..258a6fbe5 100644 --- a/config/locales/app.admin.it.yml +++ b/config/locales/app.admin.it.yml @@ -111,6 +111,10 @@ it: save: "Salva" create_success: "Lo spazio è stato creato correttamente" update_success: "Lo spazio è stato aggiornato correttamente" + associated_machines: "Included machines" + children_spaces: "Included spaces" + associated_objects: "Associated objects" + associated_objects_warning: "Only use these fields if you want interblocking reservation between spaces, child spaces and machines. If you want machine and space reservations to remain independent, please leave the following fields blank." event_form: ACTION_title: "{ACTION, select, create{Nuovo} other{Aggiorna}} evento" title: "Titolo" diff --git a/config/locales/app.admin.no.yml b/config/locales/app.admin.no.yml index 092a4769c..708ece1ca 100644 --- a/config/locales/app.admin.no.yml +++ b/config/locales/app.admin.no.yml @@ -111,6 +111,10 @@ save: "Save" create_success: "The space was created successfully" update_success: "The space was updated successfully" + associated_machines: "Included machines" + children_spaces: "Included spaces" + associated_objects: "Associated objects" + associated_objects_warning: "Only use these fields if you want interblocking reservation between spaces, child spaces and machines. If you want machine and space reservations to remain independent, please leave the following fields blank." event_form: ACTION_title: "{ACTION, select, create{New} other{Update the}} event" title: "Title" diff --git a/config/locales/app.admin.pt.yml b/config/locales/app.admin.pt.yml index 38d1181f5..680842515 100644 --- a/config/locales/app.admin.pt.yml +++ b/config/locales/app.admin.pt.yml @@ -111,6 +111,10 @@ pt: save: "Save" create_success: "The space was created successfully" update_success: "The space was updated successfully" + associated_machines: "Included machines" + children_spaces: "Included spaces" + associated_objects: "Associated objects" + associated_objects_warning: "Only use these fields if you want interblocking reservation between spaces, child spaces and machines. If you want machine and space reservations to remain independent, please leave the following fields blank." event_form: ACTION_title: "{ACTION, select, create{New} other{Update the}} event" title: "Title" diff --git a/config/locales/app.admin.zu.yml b/config/locales/app.admin.zu.yml index d56cab190..257ec281c 100644 --- a/config/locales/app.admin.zu.yml +++ b/config/locales/app.admin.zu.yml @@ -111,6 +111,10 @@ zu: save: "crwdns36885:0crwdne36885:0" create_success: "crwdns31813:0crwdne31813:0" update_success: "crwdns31815:0crwdne31815:0" + associated_machines: "crwdns37729:0crwdne37729:0" + children_spaces: "crwdns37731:0crwdne37731:0" + associated_objects: "crwdns37733:0crwdne37733:0" + associated_objects_warning: "crwdns37735:0crwdne37735:0" event_form: ACTION_title: "crwdns36887:0ACTION={ACTION}crwdne36887:0" title: "crwdns31817:0crwdne31817:0" diff --git a/config/locales/de.yml b/config/locales/de.yml index 101773e34..a91036804 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -65,6 +65,7 @@ de: not_available: "Nicht verfügbar" reserving: "Ich reserviere" i_ve_reserved: "Ich reservierte" + blocked: "Blocked" length_must_be_slot_multiple: "muss mindestens %{MIN} Minuten nach dem Startdatum liegen" must_be_associated_with_at_least_1_machine: "muss mindestens einer Maschine zugeordnet sein" deleted_user: "Gelöschte Benutzer" @@ -446,6 +447,8 @@ de: account_invalidated: "Dein Account ist ungültig." notify_user_supporting_document_refusal: refusal: "Your supporting documents were refused" + notify_user_supporting_document_reminder: + reminder_message: "This is a reminder for you to upload your supporting documents." notify_admin_user_supporting_document_refusal: refusal: "Member's supporting document %{NAME} was refused." notify_user_order_is_ready: @@ -538,6 +541,7 @@ de: space: "Dieser Space ist deaktiviert" machine: "Diese Maschine ist deaktiviert" reservable: "Diese Maschine ist nicht reservierbar" + blocked_by_another_reservation: "This slot is blocked by another reservation" cart_validation: select_user: "Please select a user before continuing" settings: diff --git a/config/locales/es.yml b/config/locales/es.yml index b1f1918ec..637a2c531 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -65,6 +65,7 @@ es: not_available: "No disponible" reserving: "Me reservo" i_ve_reserved: "He reservado" + blocked: "Blocked" length_must_be_slot_multiple: "Debe ser al menos %{MIN} minutos después de la fecha de inicio" must_be_associated_with_at_least_1_machine: "debe estar asociado con al menos 1 máquina" deleted_user: "Usuario eliminado" @@ -446,6 +447,8 @@ es: account_invalidated: "Su cuenta no es válida." notify_user_supporting_document_refusal: refusal: "Sus justificantes han sido rechazados" + notify_user_supporting_document_reminder: + reminder_message: "This is a reminder for you to upload your supporting documents." notify_admin_user_supporting_document_refusal: refusal: "El justificante del afiliado %{NAME} ha sido rechazado." notify_user_order_is_ready: @@ -538,6 +541,7 @@ es: space: "Este espacio está desactivado" machine: "Esta máquina está desactivada" reservable: "Esta máquina no se puede reservar" + blocked_by_another_reservation: "This slot is blocked by another reservation" cart_validation: select_user: "Por favor, seleccione un usuario antes de continuar" settings: diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 3e3c09f64..1fd3bed8d 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -65,7 +65,7 @@ fr: not_available: "Non disponible" reserving: "Je réserve" i_ve_reserved: "J'ai réservé" - blocked: "Bloquée" + blocked: "Bloqué" length_must_be_slot_multiple: "doit être au moins %{MIN} minutes après la date de début" must_be_associated_with_at_least_1_machine: "doit être associé avec au moins 1 machine" deleted_user: "Utilisateur supprimé" @@ -448,7 +448,7 @@ fr: notify_user_supporting_document_refusal: refusal: "Vos pièces justificatives ont été refusées" notify_user_supporting_document_reminder: - reminder_message: "Ceci est un message de rappel pour vous inviter à uploader vos pièces justificatives." + reminder_message: "Ceci est un rappel pour vous demander de télécharger vos documents justificatifs." notify_admin_user_supporting_document_refusal: refusal: "Le justificatif du membre %{NAME} a été refusé." notify_user_order_is_ready: diff --git a/config/locales/it.yml b/config/locales/it.yml index 5e3cd0173..106244325 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -65,6 +65,7 @@ it: not_available: "Non disponibile" reserving: "Sto prenotando" i_ve_reserved: "Ho prenotato" + blocked: "Blocked" length_must_be_slot_multiple: "deve essere almeno %{MIN} minuti dopo la data di inizio" must_be_associated_with_at_least_1_machine: "deve essere associata ad almeno 1 macchina" deleted_user: "Utente eliminato" @@ -446,6 +447,8 @@ it: account_invalidated: "Il tuo account non è valido." notify_user_supporting_document_refusal: refusal: "I tuoi documenti aggiuntivi sono stati rifiutati" + notify_user_supporting_document_reminder: + reminder_message: "This is a reminder for you to upload your supporting documents." notify_admin_user_supporting_document_refusal: refusal: "Il documento aggiuntivo del membro %{NAME} è stato rifiutato." notify_user_order_is_ready: @@ -538,6 +541,7 @@ it: space: "Questo spazio è disabilitato" machine: "Questa macchina è disabilitata" reservable: "Questa macchina non è prenotabile" + blocked_by_another_reservation: "This slot is blocked by another reservation" cart_validation: select_user: "Seleziona un utente prima di continuare" settings: diff --git a/config/locales/mails.de.yml b/config/locales/mails.de.yml index 0d29d6ec9..1ca61c7c1 100644 --- a/config/locales/mails.de.yml +++ b/config/locales/mails.de.yml @@ -402,6 +402,10 @@ de: body: user_supporting_document_files_refusal: "Your supporting documents were refused:" action: "Please re-upload some new supporting documents." + notify_user_supporting_document_reminder: + subject: "Reminder to upload your supporting documents" + body: + user_supporting_document_reminder: "This is a reminder for you to upload your supporting documents." notify_admin_user_supporting_document_refusal: subject: "A member's supporting documents were refused" body: diff --git a/config/locales/mails.es.yml b/config/locales/mails.es.yml index 8d2d6f563..7f1406c21 100644 --- a/config/locales/mails.es.yml +++ b/config/locales/mails.es.yml @@ -402,6 +402,10 @@ es: body: user_supporting_document_files_refusal: "Sus justificantes han sido rechazados:" action: "Por favor, vuelva a subir nuevos documentos justificativos." + notify_user_supporting_document_reminder: + subject: "Reminder to upload your supporting documents" + body: + user_supporting_document_reminder: "This is a reminder for you to upload your supporting documents." notify_admin_user_supporting_document_refusal: subject: "Los justificantes del afiliado de un miembro han sido rechazados" body: diff --git a/config/locales/mails.fr.yml b/config/locales/mails.fr.yml index 0517ad9e2..47cd1bd75 100644 --- a/config/locales/mails.fr.yml +++ b/config/locales/mails.fr.yml @@ -402,6 +402,10 @@ fr: body: user_supporting_document_files_refusal: "Vos pièces justificatives ont été refusées :" action: "Veuillez téléverser de nouvelles pièces justificatives." + notify_user_supporting_document_reminder: + subject: "Rappel de télécharger vos documents justificatifs" + body: + user_supporting_document_reminder: "Ceci est un rappel pour vous demander de télécharger vos documents justificatifs." notify_admin_user_supporting_document_refusal: subject: "Les justificatifs d'un membre ont été refusés" body: diff --git a/config/locales/mails.it.yml b/config/locales/mails.it.yml index c0d842a27..1b17ef14b 100644 --- a/config/locales/mails.it.yml +++ b/config/locales/mails.it.yml @@ -402,6 +402,10 @@ it: body: user_supporting_document_files_refusal: "I tuoi documenti aggiuntivi sono stati rifiutati:" action: "Si prega di ricaricare nuovi documenti di supporto." + notify_user_supporting_document_reminder: + subject: "Reminder to upload your supporting documents" + body: + user_supporting_document_reminder: "This is a reminder for you to upload your supporting documents." notify_admin_user_supporting_document_refusal: subject: "I documenti aggiuntivi di un membro sono stati rifiutati" body: diff --git a/config/locales/mails.no.yml b/config/locales/mails.no.yml index a4ed1ec5e..4d69e9d83 100644 --- a/config/locales/mails.no.yml +++ b/config/locales/mails.no.yml @@ -402,6 +402,10 @@ body: user_supporting_document_files_refusal: "Your supporting documents were refused:" action: "Please re-upload some new supporting documents." + notify_user_supporting_document_reminder: + subject: "Reminder to upload your supporting documents" + body: + user_supporting_document_reminder: "This is a reminder for you to upload your supporting documents." notify_admin_user_supporting_document_refusal: subject: "A member's supporting documents were refused" body: diff --git a/config/locales/mails.pt.yml b/config/locales/mails.pt.yml index 99eb43143..c1408a120 100644 --- a/config/locales/mails.pt.yml +++ b/config/locales/mails.pt.yml @@ -402,6 +402,10 @@ pt: body: user_supporting_document_files_refusal: "Os seus documentos de apoio foram recusados:" action: "Por favor, recarregue novos documentos de apoio." + notify_user_supporting_document_reminder: + subject: "Reminder to upload your supporting documents" + body: + user_supporting_document_reminder: "This is a reminder for you to upload your supporting documents." notify_admin_user_supporting_document_refusal: subject: "Documentos de apoio de um membro foram recusados" body: diff --git a/config/locales/mails.zu.yml b/config/locales/mails.zu.yml index 6aca672d6..7d831a98e 100644 --- a/config/locales/mails.zu.yml +++ b/config/locales/mails.zu.yml @@ -402,6 +402,10 @@ zu: body: user_supporting_document_files_refusal: "crwdns37363:0crwdne37363:0" action: "crwdns37365:0crwdne37365:0" + notify_user_supporting_document_reminder: + subject: "crwdns37743:0crwdne37743:0" + body: + user_supporting_document_reminder: "crwdns37745:0crwdne37745:0" notify_admin_user_supporting_document_refusal: subject: "crwdns37367:0crwdne37367:0" body: diff --git a/config/locales/no.yml b/config/locales/no.yml index 3ea449d2f..22e5e5c53 100644 --- a/config/locales/no.yml +++ b/config/locales/no.yml @@ -65,6 +65,7 @@ not_available: "Ikke tilgjengelig" reserving: "I'm reserving" i_ve_reserved: "Jeg har reservert" + blocked: "Blocked" length_must_be_slot_multiple: "må være minst %{MIN} minutter etter startdatoen" must_be_associated_with_at_least_1_machine: "må være tilknyttet minst 1 maskin" deleted_user: "Deleted user" @@ -446,6 +447,8 @@ account_invalidated: "Your account is invalid." notify_user_supporting_document_refusal: refusal: "Your supporting documents were refused" + notify_user_supporting_document_reminder: + reminder_message: "This is a reminder for you to upload your supporting documents." notify_admin_user_supporting_document_refusal: refusal: "Member's supporting document %{NAME} was refused." notify_user_order_is_ready: @@ -538,6 +541,7 @@ space: "This space is disabled" machine: "This machine is disabled" reservable: "This machine is not reservable" + blocked_by_another_reservation: "This slot is blocked by another reservation" cart_validation: select_user: "Please select a user before continuing" settings: diff --git a/config/locales/pt.yml b/config/locales/pt.yml index 1c02c1c9a..584a3b76c 100644 --- a/config/locales/pt.yml +++ b/config/locales/pt.yml @@ -65,6 +65,7 @@ pt: not_available: "Não disponível " reserving: "I'm reserving" i_ve_reserved: "Eu reservei" + blocked: "Blocked" length_must_be_slot_multiple: "deve ser pelo menos %{MIN} minutos após a data de início" must_be_associated_with_at_least_1_machine: "deve estar associada a pelo menos uma máquina" deleted_user: "Usuário deletado" @@ -446,6 +447,8 @@ pt: account_invalidated: "Sua conta é inválida." notify_user_supporting_document_refusal: refusal: "Your supporting documents were refused" + notify_user_supporting_document_reminder: + reminder_message: "This is a reminder for you to upload your supporting documents." notify_admin_user_supporting_document_refusal: refusal: "Member's supporting document %{NAME} was refused." notify_user_order_is_ready: @@ -538,6 +541,7 @@ pt: space: "Este espaço está desativado" machine: "Esta máquina está desativada" reservable: "Esta máquina não é reservável" + blocked_by_another_reservation: "This slot is blocked by another reservation" cart_validation: select_user: "Por favor, selecione um usuário antes de continuar" settings: diff --git a/config/locales/zu.yml b/config/locales/zu.yml index 9e9b08728..5d4ed4b32 100644 --- a/config/locales/zu.yml +++ b/config/locales/zu.yml @@ -65,6 +65,7 @@ zu: not_available: "crwdns3267:0crwdne3267:0" reserving: "crwdns37199:0crwdne37199:0" i_ve_reserved: "crwdns3269:0crwdne3269:0" + blocked: "crwdns37737:0crwdne37737:0" length_must_be_slot_multiple: "crwdns3271:0%{MIN}crwdne3271:0" must_be_associated_with_at_least_1_machine: "crwdns3273:0crwdne3273:0" deleted_user: "crwdns22460:0crwdne22460:0" @@ -446,6 +447,8 @@ zu: account_invalidated: "crwdns23006:0crwdne23006:0" notify_user_supporting_document_refusal: refusal: "crwdns37345:0crwdne37345:0" + notify_user_supporting_document_reminder: + reminder_message: "crwdns37739:0crwdne37739:0" notify_admin_user_supporting_document_refusal: refusal: "crwdns37347:0%{NAME}crwdne37347:0" notify_user_order_is_ready: @@ -538,6 +541,7 @@ zu: space: "crwdns36283:0crwdne36283:0" machine: "crwdns36285:0crwdne36285:0" reservable: "crwdns36287:0crwdne36287:0" + blocked_by_another_reservation: "crwdns37741:0crwdne37741:0" cart_validation: select_user: "crwdns37211:0crwdne37211:0" settings: