From 8a3110cd0f882228a455062b2d199ee0ae10eb1c Mon Sep 17 00:00:00 2001 From: Du Peng Date: Wed, 26 Jul 2023 15:48:14 +0200 Subject: [PATCH 1/7] (feat) add not valid status for event reservaiton --- app/frontend/src/javascript/controllers/admin/events.js | 3 +++ app/frontend/templates/admin/events/reservations.html | 3 ++- config/locales/app.admin.en.yml | 1 + config/locales/app.admin.fr.yml | 1 + 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/frontend/src/javascript/controllers/admin/events.js b/app/frontend/src/javascript/controllers/admin/events.js index 02b19a1d4..de6c414bf 100644 --- a/app/frontend/src/javascript/controllers/admin/events.js +++ b/app/frontend/src/javascript/controllers/admin/events.js @@ -460,6 +460,9 @@ Application.Controllers.controller('ShowEventReservationsController', ['$scope', $scope.isValidated = function (reservation) { return reservation.slots_reservations_attributes[0].is_valid === true || reservation.slots_reservations_attributes[0].is_valid === 'true'; }; + $scope.isInvalidated = function (reservation) { + return reservation.slots_reservations_attributes[0].is_valid === false || reservation.slots_reservations_attributes[0].is_valid === 'false'; + }; /** * Callback to validate a reservation diff --git a/app/frontend/templates/admin/events/reservations.html b/app/frontend/templates/admin/events/reservations.html index ea5f3d8c7..4fe2c1a1a 100644 --- a/app/frontend/templates/admin/events/reservations.html +++ b/app/frontend/templates/admin/events/reservations.html @@ -47,9 +47,10 @@ {{ticket.event_price_category.price_category.name}} : {{ticket.booked}} - {{ 'app.admin.event_reservations.event_status.pre_registered' }} + {{ 'app.admin.event_reservations.event_status.pre_registered' }} {{ 'app.admin.event_reservations.event_status.to_pay' }} {{ 'app.admin.event_reservations.event_status.registered' }} + {{ 'app.admin.event_reservations.event_status.not_validated' }} {{ 'app.admin.event_reservations.event_status.paid' }} {{ 'app.admin.event_reservations.event_status.present' }} {{ 'app.admin.event_reservations.event_status.canceled' }} diff --git a/config/locales/app.admin.en.yml b/config/locales/app.admin.en.yml index 47b95d2d8..953a4b2b8 100644 --- a/config/locales/app.admin.en.yml +++ b/config/locales/app.admin.en.yml @@ -655,6 +655,7 @@ en: canceled: "Canceled" present: "Present" registered: "Registered" + not_validated: "Not validated" affirmative: "yes" negative: "no" validate: "Validate" diff --git a/config/locales/app.admin.fr.yml b/config/locales/app.admin.fr.yml index ec0b5cdae..f30bc18db 100644 --- a/config/locales/app.admin.fr.yml +++ b/config/locales/app.admin.fr.yml @@ -655,6 +655,7 @@ fr: canceled: "Annulée" present: "Présent" registered: "Inscrit" + not_validated: "Non validée" affirmative: "Oui" negative: "Non" validate: "Valider" From ea83265b87fcb59e66812f56db67ac2b74b8fea3 Mon Sep 17 00:00:00 2001 From: Du Peng Date: Thu, 27 Jul 2023 17:34:54 +0200 Subject: [PATCH 2/7] (bug) child cannot be updated --- app/controllers/api/children_controller.rb | 2 +- .../src/javascript/components/family-account/child-form.tsx | 2 +- app/services/child_service.rb | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/children_controller.rb b/app/controllers/api/children_controller.rb index 44188807e..3725695ba 100644 --- a/app/controllers/api/children_controller.rb +++ b/app/controllers/api/children_controller.rb @@ -30,7 +30,7 @@ class API::ChildrenController < API::APIController def update authorize @child - if @child.update(child_params) + if ChildService.update(@child, child_params) render status: :ok else render json: @child.errors.full_messages, status: :unprocessable_entity diff --git a/app/frontend/src/javascript/components/family-account/child-form.tsx b/app/frontend/src/javascript/components/family-account/child-form.tsx index f9e9b4a53..1d6ebdf2e 100644 --- a/app/frontend/src/javascript/components/family-account/child-form.tsx +++ b/app/frontend/src/javascript/components/family-account/child-form.tsx @@ -116,7 +116,7 @@ export const ChildForm: React.FC = ({ child, onSubmit, supportin defaultFile={sf as FileType} id={`supporting_document_files_attributes.${index}`} accept="application/pdf" - rules={{ required: true }} + rules={{ required: !sf.attachment }} setValue={setValue} label={getSupportingDocumentsTypeName(sf.supporting_document_type_id)} showRemoveButton={false} diff --git a/app/services/child_service.rb b/app/services/child_service.rb index 45ebd1a4c..812374976 100644 --- a/app/services/child_service.rb +++ b/app/services/child_service.rb @@ -28,7 +28,9 @@ class ChildService all_files_are_upload = true SupportingDocumentType.where(document_type: 'Child').each do |sdt| file = sdt.supporting_document_files.find_by(supportable: child) - all_files_are_upload = false if file.nil? || file.attachment_identifier.nil? + if file.nil? || file.attachment_identifier.nil? || child_params['supporting_document_files_attributes']['0']['attachment'].blank? + all_files_are_upload = false + end end if all_files_are_upload NotificationCenter.call type: 'notify_admin_user_child_supporting_document_files_updated', From 5a23b8d5e55c7a12bffa90322fc70293ae7127d7 Mon Sep 17 00:00:00 2001 From: Du Peng Date: Thu, 27 Jul 2023 17:47:22 +0200 Subject: [PATCH 3/7] (bug) unable to remove supporting document type --- app/models/supporting_document_refusal.rb | 5 +++-- app/models/supporting_document_type.rb | 3 +-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/models/supporting_document_refusal.rb b/app/models/supporting_document_refusal.rb index 843bc46c8..ffbe328c7 100644 --- a/app/models/supporting_document_refusal.rb +++ b/app/models/supporting_document_refusal.rb @@ -2,8 +2,9 @@ # An admin can mark an uploaded document as refused, this will notify the member class SupportingDocumentRefusal < ApplicationRecord + include NotificationAttachedObject + belongs_to :supportable, polymorphic: true belongs_to :operator, class_name: 'User', inverse_of: :supporting_document_refusals - has_many :supporting_document_refusals_types, dependent: :destroy - has_many :supporting_document_types, through: :supporting_document_refusals_types + has_and_belongs_to_many :supporting_document_types end diff --git a/app/models/supporting_document_type.rb b/app/models/supporting_document_type.rb index d0be09fe0..afda3d4a7 100644 --- a/app/models/supporting_document_type.rb +++ b/app/models/supporting_document_type.rb @@ -6,8 +6,7 @@ class SupportingDocumentType < ApplicationRecord has_many :supporting_document_files, dependent: :destroy - has_many :supporting_document_refusals_types, dependent: :destroy - has_many :supporting_document_refusals, through: :supporting_document_refusals_types + has_and_belongs_to_many :supporting_document_refusals, dependent: :destroy validates :document_type, presence: true, inclusion: { in: %w[User Child] } end From c9f17309f90f6b60c34c0963d941bf3b5fe80b7f Mon Sep 17 00:00:00 2001 From: Du Peng Date: Thu, 27 Jul 2023 17:54:34 +0200 Subject: [PATCH 4/7] (bug) child validited cannot reserve event --- app/frontend/templates/events/show.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/frontend/templates/events/show.html b/app/frontend/templates/events/show.html index 0f0183e5b..f04d9a529 100644 --- a/app/frontend/templates/events/show.html +++ b/app/frontend/templates/events/show.html @@ -180,7 +180,7 @@ class="form-control"> - +

{{ 'app.shared.cart.child_validation_required_alert' }} From 4f26f52d854118310048ee2afff09fadcfe6b9d2 Mon Sep 17 00:00:00 2001 From: Du Peng Date: Fri, 28 Jul 2023 14:28:54 +0200 Subject: [PATCH 5/7] (feat) hide child supporting document if dont any type of supporting document --- .../src/javascript/components/family-account/child-form.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/frontend/src/javascript/components/family-account/child-form.tsx b/app/frontend/src/javascript/components/family-account/child-form.tsx index 1d6ebdf2e..00887017f 100644 --- a/app/frontend/src/javascript/components/family-account/child-form.tsx +++ b/app/frontend/src/javascript/components/family-account/child-form.tsx @@ -108,7 +108,7 @@ export const ChildForm: React.FC = ({ child, onSubmit, supportin label={t('app.public.child_form.email')} /> - {!isPrivileged() && <> + {!isPrivileged() && supportingDocumentsTypes?.length > 0 && <>

{t('app.public.child_form.supporting_documents')}

{output.supporting_document_files_attributes.map((sf, index) => { return ( @@ -132,7 +132,7 @@ export const ChildForm: React.FC = ({ child, onSubmit, supportin - {isPrivileged() && <> + {isPrivileged() && supportingDocumentsTypes?.length > 0 && <>

{t('app.public.child_form.supporting_documents')}

{output.supporting_document_files_attributes.map((sf, index) => { @@ -158,7 +158,7 @@ export const ChildForm: React.FC = ({ child, onSubmit, supportin
} - {isPrivileged() && <> + {isPrivileged() && supportingDocumentsTypes?.length > 0 && <>

{t('app.public.child_form.refuse_documents_info')}

From cc46103ecac9eacf5607c83e450956138090d56a Mon Sep 17 00:00:00 2001 From: Du Peng Date: Fri, 28 Jul 2023 16:25:39 +0200 Subject: [PATCH 6/7] (bug) family event nb free place error --- .../src/javascript/controllers/events.js.erb | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/app/frontend/src/javascript/controllers/events.js.erb b/app/frontend/src/javascript/controllers/events.js.erb index 8117807a1..c55105338 100644 --- a/app/frontend/src/javascript/controllers/events.js.erb +++ b/app/frontend/src/javascript/controllers/events.js.erb @@ -236,8 +236,19 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', ' * Callback to call when the number of tickets to book changes in the current booking */ $scope.changeNbPlaces = function (priceType) { + let reservedPlaces = 0; + if ($scope.event.event_type === 'family') { + reservedPlaces = $scope.reservations.reduce((sum, reservation) => { + return sum + reservation.booking_users_attributes.length; + }, 0); + } + let nb_free_places = $scope.event.nb_free_places; + if ($scope.event.event_type === 'family') { + const maxPlaces = $scope.children.length + 1 - reservedPlaces; + nb_free_places = Math.min(maxPlaces, $scope.event.nb_free_places); + } // compute the total remaining places - let remain = ($scope.event.event_type === 'family' ? ($scope.children.length + 1) : $scope.event.nb_free_places) - $scope.reserve.nbReservePlaces; + let remain = nb_free_places - $scope.reserve.nbReservePlaces; for (let ticket in $scope.reserve.tickets) { remain -= $scope.reserve.tickets[ticket]; } @@ -360,8 +371,8 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', ' if ($scope.ctrl.member) { Member.get({ id: $scope.ctrl.member.id }, function (member) { $scope.ctrl.member = member; - getReservations($scope.event.id, 'Event', $scope.ctrl.member.id).then(function (reservations) { - getChildren($scope.currentUser.id).then(function (children) { + getReservations($scope.event.id, 'Event', $scope.ctrl.member.id).then(function () { + getChildren($scope.ctrl.member.id).then(function (children) { updateNbReservePlaces(); }); }); @@ -678,7 +689,7 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', ' // get the current user's reservations into $scope.reservations if ($scope.currentUser) { - getReservations($scope.event.id, 'Event', $scope.currentUser.id).then(function (reservations) { + getReservations($scope.event.id, 'Event', $scope.currentUser.id).then(function () { getChildren($scope.currentUser.id).then(function (children) { updateNbReservePlaces(); }); @@ -772,7 +783,7 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', ' * update number of places available for each price category for the family event */ const updateNbReservePlaces = function () { - if ($scope.event.event_type === 'family') { + if ($scope.event.event_type === 'family' && $scope.ctrl.member.id) { const reservedPlaces = $scope.reservations.reduce((sum, reservation) => { return sum + reservation.booking_users_attributes.length; }, 0); @@ -990,7 +1001,7 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', ' const afterPayment = function (invoice) { Event.get({ id: $scope.event.id }).$promise.then(function (event) { $scope.event = event; - getReservations($scope.event.id, 'Event', $scope.ctrl.member.id).then(function (reservations) { + getReservations($scope.event.id, 'Event', $scope.ctrl.member.id).then(function () { updateNbReservePlaces(); $scope.reserveSuccess = true; $scope.coupon.applied = null; From 2a2c451d6e89516ebaca2c4a61384125e29f571e Mon Sep 17 00:00:00 2001 From: Du Peng Date: Mon, 31 Jul 2023 10:18:15 +0200 Subject: [PATCH 7/7] (bug) admin valid/pay event reservaiton error --- .../events/event-reservation-item.tsx | 8 +++--- .../javascript/controllers/admin/events.js | 27 ++++++++++++++++++- .../src/javascript/models/reservation.ts | 3 ++- .../admin/events/pay_reservation_modal.html | 12 ++++----- .../templates/admin/events/reservations.html | 12 ++++----- app/views/api/members/show.json.jbuilder | 1 + 6 files changed, 45 insertions(+), 18 deletions(-) diff --git a/app/frontend/src/javascript/components/events/event-reservation-item.tsx b/app/frontend/src/javascript/components/events/event-reservation-item.tsx index b186fd508..7075c367d 100644 --- a/app/frontend/src/javascript/components/events/event-reservation-item.tsx +++ b/app/frontend/src/javascript/components/events/event-reservation-item.tsx @@ -47,15 +47,15 @@ export const EventReservationItem: React.FC = ({ rese const preRegistrationStatus = () => { if (!_.isBoolean(reservation.is_valid) && !reservation.canceled_at && !reservation.is_paid) { return t('app.logged.event_reservation_item.in_the_process_of_validation'); - } else if (reservation.is_valid && !reservation.canceled_at && !reservation.is_paid && reservation.reservable.amount !== 0) { + } else if (reservation.is_valid && !reservation.canceled_at && !reservation.is_paid && reservation.amount !== 0) { return t('app.logged.event_reservation_item.settle_your_payment'); - } else if (reservation.is_valid && !reservation.canceled_at && !reservation.is_paid && reservation.reservable.amount === 0) { + } else if (reservation.is_valid && !reservation.canceled_at && !reservation.is_paid && reservation.amount === 0) { return t('app.logged.event_reservation_item.registered'); } else if (!reservation.is_valid && !reservation.canceled_at) { return t('app.logged.event_reservation_item.not_validated'); - } else if (reservation.is_paid && !reservation.canceled_at && reservation.reservable.amount !== 0) { + } else if (reservation.is_paid && !reservation.canceled_at && reservation.amount !== 0) { return t('app.logged.event_reservation_item.paid'); - } else if (reservation.is_paid && !reservation.canceled_at && reservation.reservable.amount === 0) { + } else if (reservation.is_paid && !reservation.canceled_at && reservation.amount === 0) { return t('app.logged.event_reservation_item.present'); } else if (reservation.canceled_at) { return t('app.logged.event_reservation_item.canceled'); diff --git a/app/frontend/src/javascript/controllers/admin/events.js b/app/frontend/src/javascript/controllers/admin/events.js index de6c414bf..420097e01 100644 --- a/app/frontend/src/javascript/controllers/admin/events.js +++ b/app/frontend/src/javascript/controllers/admin/events.js @@ -460,10 +460,35 @@ Application.Controllers.controller('ShowEventReservationsController', ['$scope', $scope.isValidated = function (reservation) { return reservation.slots_reservations_attributes[0].is_valid === true || reservation.slots_reservations_attributes[0].is_valid === 'true'; }; + + /** + * Test if the provided reservation has been invalidated + * @param reservation {Reservation} + * @returns {boolean} + */ $scope.isInvalidated = function (reservation) { return reservation.slots_reservations_attributes[0].is_valid === false || reservation.slots_reservations_attributes[0].is_valid === 'false'; }; + /** + * Get the price of a reservation + * @param reservation {Reservation} + */ + $scope.reservationAmount = function (reservation) { + let amount = 0; + for (const user of reservation.booking_users_attributes) { + if (user.event_price_category_id) { + const price_category = _.find($scope.event.event_price_categories_attributes, { id: user.event_price_category_id }); + if (price_category) { + amount += price_category.amount; + } + } else { + amount += $scope.event.amount; + } + } + return amount; + }; + /** * Callback to validate a reservation * @param reservation {Reservation} @@ -628,7 +653,7 @@ Application.Controllers.controller('ShowEventReservationsController', ['$scope', if (r.id === reservation.id) { return reservation; } - if ($scope.event.amount === 0) { + if ($scope.reservationAmount(reservation) === 0) { growl.success(_t('app.admin.event_reservations.reservation_was_successfully_present')); } else { growl.success(_t('app.admin.event_reservations.reservation_was_successfully_paid')); diff --git a/app/frontend/src/javascript/models/reservation.ts b/app/frontend/src/javascript/models/reservation.ts index dca86afa8..3c6eb0a6a 100644 --- a/app/frontend/src/javascript/models/reservation.ts +++ b/app/frontend/src/javascript/models/reservation.ts @@ -70,10 +70,11 @@ export interface Reservation { end_at: TDateISO, event_type?: string, event_title?: string, - event_pre_registration?: boolean + event_pre_registration?: boolean, canceled_at?: TDateISO, is_valid?: boolean, is_paid?: boolean, + amount?: number } export interface ReservationIndexFilter extends ApiFilter { diff --git a/app/frontend/templates/admin/events/pay_reservation_modal.html b/app/frontend/templates/admin/events/pay_reservation_modal.html index c1866fe17..b4059d18f 100644 --- a/app/frontend/templates/admin/events/pay_reservation_modal.html +++ b/app/frontend/templates/admin/events/pay_reservation_modal.html @@ -1,10 +1,10 @@