From d271fa59e662decddc4aad2eb6b8dfcc4a9c760a Mon Sep 17 00:00:00 2001 From: Du Peng Date: Tue, 11 Jul 2023 10:36:44 +0200 Subject: [PATCH] (feat) valid/invalid pre registration event --- .../api/slots_reservations_controller.rb | 7 ++- .../events/event-reservation-item.tsx | 4 +- .../javascript/controllers/admin/events.js | 45 ++++++++++--------- .../src/javascript/controllers/events.js.erb | 4 +- .../src/javascript/models/reservation.ts | 3 +- .../javascript/services/slots_reservation.js | 4 ++ .../templates/admin/events/reservations.html | 9 ++-- app/frontend/templates/events/show.html | 4 +- app/models/event.rb | 4 +- app/policies/slots_reservation_policy.rb | 4 ++ app/services/slots_reservations_service.rb | 14 +++++- app/views/api/members/show.json.jbuilder | 2 +- .../reservations/_reservation.json.jbuilder | 3 +- config/locales/app.admin.en.yml | 3 ++ config/locales/app.admin.fr.yml | 5 +++ config/routes.rb | 1 + ...2403_add_is_valid_to_slots_reservations.rb | 19 ++++++++ db/structure.sql | 24 ++++++---- 18 files changed, 112 insertions(+), 47 deletions(-) create mode 100644 db/migrate/20230710072403_add_is_valid_to_slots_reservations.rb diff --git a/app/controllers/api/slots_reservations_controller.rb b/app/controllers/api/slots_reservations_controller.rb index c0f002f94..00a355735 100644 --- a/app/controllers/api/slots_reservations_controller.rb +++ b/app/controllers/api/slots_reservations_controller.rb @@ -5,7 +5,7 @@ # availability by Availability.slot_duration, or otherwise globally by Setting.get('slot_duration') class API::SlotsReservationsController < API::APIController before_action :authenticate_user! - before_action :set_slots_reservation, only: %i[update cancel validate] + before_action :set_slots_reservation, only: %i[update cancel validate invalidate] respond_to :json def update @@ -28,6 +28,11 @@ class API::SlotsReservationsController < API::APIController SlotsReservationsService.validate(@slot_reservation) end + def invalidate + authorize @slot_reservation + SlotsReservationsService.invalidate(@slot_reservation) + end + private def set_slots_reservation 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 d9cd2ca4c..12b619fae 100644 --- a/app/frontend/src/javascript/components/events/event-reservation-item.tsx +++ b/app/frontend/src/javascript/components/events/event-reservation-item.tsx @@ -44,9 +44,9 @@ export const EventReservationItem: React.FC = ({ rese * Return the pre-registration status */ const preRegistrationStatus = () => { - if (!reservation.validated_at && !reservation.canceled_at && !reservation.is_paid) { + if (!reservation.is_valid && !reservation.canceled_at && !reservation.is_paid) { return t('app.logged.event_reservation_item.in_the_process_of_validation'); - } else if (reservation.validated_at && !reservation.canceled_at && !reservation.is_paid) { + } else if (reservation.is_valid && !reservation.canceled_at && !reservation.is_paid) { return t('app.logged.event_reservation_item.settle_your_payment'); } else if (reservation.is_paid && !reservation.canceled_at) { return t('app.logged.event_reservation_item.paid'); diff --git a/app/frontend/src/javascript/controllers/admin/events.js b/app/frontend/src/javascript/controllers/admin/events.js index ebc30999b..87cade06b 100644 --- a/app/frontend/src/javascript/controllers/admin/events.js +++ b/app/frontend/src/javascript/controllers/admin/events.js @@ -458,7 +458,7 @@ Application.Controllers.controller('ShowEventReservationsController', ['$scope', * @returns {boolean} */ $scope.isValidated = function (reservation) { - return !!(reservation.slots_reservations_attributes[0].validated_at); + return reservation.slots_reservations_attributes[0].is_valid === true || reservation.slots_reservations_attributes[0].is_valid === 'true'; }; /** @@ -466,25 +466,30 @@ Application.Controllers.controller('ShowEventReservationsController', ['$scope', * @param reservation {Reservation} */ $scope.validateReservation = function (reservation) { - dialogs.confirm({ - resolve: { - object: function () { - return { - title: _t('app.admin.event_reservations.validate_the_reservation'), - msg: _t('app.admin.event_reservations.do_you_really_want_to_validate_this_reservation_this_apply_to_all_booked_tickets') - }; - } - } - }, function () { // validate confirmed - SlotsReservation.validate({ - id: reservation.slots_reservations_attributes[0].id - }, () => { // successfully validated - growl.success(_t('app.admin.event_reservations.reservation_was_successfully_validated')); - const index = $scope.reservations.indexOf(reservation); - $scope.reservations[index].slots_reservations_attributes[0].validated_at = new Date(); - }, () => { - growl.warning(_t('app.admin.event_reservations.validation_failed')); - }); + SlotsReservation.validate({ + id: reservation.slots_reservations_attributes[0].id + }, () => { // successfully validated + growl.success(_t('app.admin.event_reservations.reservation_was_successfully_validated')); + const index = $scope.reservations.indexOf(reservation); + $scope.reservations[index].slots_reservations_attributes[0].is_valid = true; + }, () => { + growl.warning(_t('app.admin.event_reservations.validation_failed')); + }); + }; + + /** + * Callback to invalidate a reservation + * @param reservation {Reservation} + */ + $scope.invalidateReservation = function (reservation) { + SlotsReservation.invalidate({ + id: reservation.slots_reservations_attributes[0].id + }, () => { // successfully validated + growl.success(_t('app.admin.event_reservations.reservation_was_successfully_invalidated')); + const index = $scope.reservations.indexOf(reservation); + $scope.reservations[index].slots_reservations_attributes[0].is_valid = false; + }, () => { + growl.warning(_t('app.admin.event_reservations.invalidation_failed')); }); }; diff --git a/app/frontend/src/javascript/controllers/events.js.erb b/app/frontend/src/javascript/controllers/events.js.erb index 3fbcd3fdf..c08a98530 100644 --- a/app/frontend/src/javascript/controllers/events.js.erb +++ b/app/frontend/src/javascript/controllers/events.js.erb @@ -644,7 +644,7 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', ' if (!user.booked) { return false; } - if ($scope.enableChildValidationRequired && user.booked.type === 'Child' && !user.booked.validatedAt) { + if ($scope.enableChildValidationRequired && user.booked.type === 'Child' && !user.booked.is_valid) { return false; } } @@ -748,7 +748,7 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', ' name: child.first_name + ' ' + child.last_name, id: child.id, type: 'Child', - validatedAt: child.validated_at, + is_valid: child.is_valid, birthday: child.birthday }); } diff --git a/app/frontend/src/javascript/models/reservation.ts b/app/frontend/src/javascript/models/reservation.ts index f5abfe7b9..7f2d7d415 100644 --- a/app/frontend/src/javascript/models/reservation.ts +++ b/app/frontend/src/javascript/models/reservation.ts @@ -70,7 +70,8 @@ export interface Reservation { event_type?: string, event_title?: string, event_pre_registration?: boolean - validated_at?: TDateISO, + canceled_at?: TDateISO, + is_valid?: boolean, is_paid?: boolean, } diff --git a/app/frontend/src/javascript/services/slots_reservation.js b/app/frontend/src/javascript/services/slots_reservation.js index ed833cbb5..c6d59c9cf 100644 --- a/app/frontend/src/javascript/services/slots_reservation.js +++ b/app/frontend/src/javascript/services/slots_reservation.js @@ -13,6 +13,10 @@ Application.Services.factory('SlotsReservation', ['$resource', function ($resour validate: { method: 'PUT', url: '/api/slots_reservations/:id/validate' + }, + invalidate: { + method: 'PUT', + url: '/api/slots_reservations/:id/invalidate' } } ); diff --git a/app/frontend/templates/admin/events/reservations.html b/app/frontend/templates/admin/events/reservations.html index 64c93d542..5d65e4310 100644 --- a/app/frontend/templates/admin/events/reservations.html +++ b/app/frontend/templates/admin/events/reservations.html @@ -53,19 +53,16 @@
-
+
- diff --git a/app/frontend/templates/events/show.html b/app/frontend/templates/events/show.html index 81827e975..045e35deb 100644 --- a/app/frontend/templates/events/show.html +++ b/app/frontend/templates/events/show.html @@ -142,7 +142,7 @@ class="form-control"> - + {{ 'app.shared.cart.child_validation_required_alert' }} @@ -180,7 +180,7 @@ class="form-control"> - +

{{ 'app.shared.cart.child_validation_required_alert' }} diff --git a/app/models/event.rb b/app/models/event.rb index c91011998..af039ca81 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -89,7 +89,7 @@ class Event < ApplicationRecord else reserved_places = reservations.joins(:slots_reservations) .where('slots_reservations.canceled_at': nil) - .where.not('slots_reservations.validated_at': nil) + .where('slots_reservations.is_valid': true) .map(&:total_booked_seats) .inject(0) { |sum, t| sum + t } self.nb_free_places = (nb_total_places - reserved_places) @@ -99,7 +99,7 @@ class Event < ApplicationRecord def nb_places_for_pre_registration reservations.joins(:slots_reservations) .where('slots_reservations.canceled_at': nil) - .where('slots_reservations.validated_at': nil) + .where('slots_reservations.is_valid': nil) .map(&:total_booked_seats) .inject(0) { |sum, t| sum + t } end diff --git a/app/policies/slots_reservation_policy.rb b/app/policies/slots_reservation_policy.rb index 4490d5316..8774a770f 100644 --- a/app/policies/slots_reservation_policy.rb +++ b/app/policies/slots_reservation_policy.rb @@ -19,4 +19,8 @@ class SlotsReservationPolicy < ApplicationPolicy def validate? user.admin? || user.manager? end + + def invalidate? + user.admin? || user.manager? + end end diff --git a/app/services/slots_reservations_service.rb b/app/services/slots_reservations_service.rb index 668868ba1..a0d53bdfa 100644 --- a/app/services/slots_reservations_service.rb +++ b/app/services/slots_reservations_service.rb @@ -23,7 +23,7 @@ class SlotsReservationsService end def validate(slot_reservation) - if slot_reservation.update(validated_at: Time.current) + if slot_reservation.update(is_valid: true) reservable = slot_reservation.reservation.reservable if reservable.is_a?(Event) reservable.update_nb_free_places @@ -39,5 +39,17 @@ class SlotsReservationsService end false end + + def invalidate(slot_reservation) + if slot_reservation.update(is_valid: false) + reservable = slot_reservation.reservation.reservable + if reservable.is_a?(Event) + reservable.update_nb_free_places + reservable.save + end + return true + end + false + end end end diff --git a/app/views/api/members/show.json.jbuilder b/app/views/api/members/show.json.jbuilder index 28bdadf3f..0ff25f4da 100644 --- a/app/views/api/members/show.json.jbuilder +++ b/app/views/api/members/show.json.jbuilder @@ -87,7 +87,7 @@ json.events_reservations @member.reservations.where(reservable_type: 'Event').jo json.event_type sr.reservation.reservable.event_type json.event_title sr.reservation.reservable.title json.event_pre_registration sr.reservation.reservable.pre_registration - json.validated_at sr.validated_at + json.is_valid sr.is_valid json.is_paid sr.reservation.invoice_items.count.positive? json.canceled_at sr.canceled_at json.booking_users_attributes sr.reservation.booking_users.order(booked_type: :desc) do |bu| diff --git a/app/views/api/reservations/_reservation.json.jbuilder b/app/views/api/reservations/_reservation.json.jbuilder index 8e91cc028..478ba4ce7 100644 --- a/app/views/api/reservations/_reservation.json.jbuilder +++ b/app/views/api/reservations/_reservation.json.jbuilder @@ -7,7 +7,7 @@ json.message reservation.message json.slots_reservations_attributes reservation.slots_reservations do |sr| json.id sr.id json.canceled_at sr.canceled_at&.iso8601 - json.validated_at sr.validated_at&.iso8601 + json.is_valid sr.is_valid json.slot_id sr.slot_id json.slot_attributes do json.id sr.slot_id @@ -41,4 +41,5 @@ json.booking_users_attributes reservation.booking_users.order(booked_type: :desc json.booked_id bu.booked_id json.booked_type bu.booked_type end +json.is_valid reservation.slots_reservations[0].is_valid json.is_paid reservation.invoice_items.count.positive? diff --git a/config/locales/app.admin.en.yml b/config/locales/app.admin.en.yml index 9fa022844..27bb5ca10 100644 --- a/config/locales/app.admin.en.yml +++ b/config/locales/app.admin.en.yml @@ -646,6 +646,7 @@ en: booked_by: "Booked by" reservations: "Reservations" status: "Status" + gestion: "Gestion" validation: "Validation" event_status: pre_registered: "Pre-registered" @@ -660,6 +661,8 @@ en: do_you_really_want_to_validate_this_reservation_this_apply_to_all_booked_tickets: "Do you really want to validate this reservation? This apply to ALL booked tickets." reservation_was_successfully_validated: "Reservation was successfully validated." validation_failed: "Validation failed." + reservation_was_successfully_invalidated: "Reservation was successfully invalidated." + invalidation_failed: "Invalidation failed." confirm_payment: "Confirm payment" confirm_payment_of_html: "{ROLE, select, admin{Cash} other{Pay}}: {AMOUNT}" #(contexte : validate a payment of $20,00) offer_this_reservation: "I offer this reservation" diff --git a/config/locales/app.admin.fr.yml b/config/locales/app.admin.fr.yml index 48d19dbbb..337b37dd5 100644 --- a/config/locales/app.admin.fr.yml +++ b/config/locales/app.admin.fr.yml @@ -647,17 +647,22 @@ fr: reservations: "Réservations" status: "Statut" gestion: "Gestion" + validation: "Validation" event_status: pre_registered: "Pré-inscrit" to_pay: "À payer" paid: "Payé" canceled: "Annulée" + affirmative: "Oui" + negative: "Non" validate: "Valider" pay: "Payer" validate_the_reservation: "Valider la réservation" do_you_really_want_to_validate_this_reservation_this_apply_to_all_booked_tickets: "Êtes vous sur de vouloir valider cette réservation? Ceci s'applique à TOUTES les places réservées." reservation_was_successfully_validated: "La réservation a bien été validé." validation_failed: "La validation a échoué." + reservation_was_successfully_invalidated: "La réservation a bien été invalidée." + invalidation_failed: "L'invalidation a échoué." confirm_payment: "Confirmer le paiement" confirm_payment_of_html: "{ROLE, select, admin{Encaisser} other{Payer}} : {AMOUNT}" #(contexte : validate a payment of $20,00) offer_this_reservation: "J'offre cette réservation" diff --git a/config/routes.rb b/config/routes.rb index 3e9192499..ea732b1cd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -126,6 +126,7 @@ Rails.application.routes.draw do resources :slots_reservations, only: [:update] do put 'cancel', on: :member put 'validate', on: :member + put 'invalidate', on: :member end resources :events do diff --git a/db/migrate/20230710072403_add_is_valid_to_slots_reservations.rb b/db/migrate/20230710072403_add_is_valid_to_slots_reservations.rb new file mode 100644 index 000000000..64f851e4a --- /dev/null +++ b/db/migrate/20230710072403_add_is_valid_to_slots_reservations.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +# add is_valid to slots_reservations +# remove validated_at from slots_reservations +class AddIsValidToSlotsReservations < ActiveRecord::Migration[7.0] + def up + add_column :slots_reservations, :is_valid, :boolean + SlotsReservation.reset_column_information + SlotsReservation.all.each do |sr| + sr.update_column(:is_valid, true) if sr.validated_at.present? + end + remove_column :slots_reservations, :validated_at + end + + def down + remove_column :slots_reservations, :is_valid + add_column :slots_reservations, :validated_at, :datetime + end +end diff --git a/db/structure.sql b/db/structure.sql index 820ccb267..9d16cfde4 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -9,6 +9,13 @@ SET xmloption = content; SET client_min_messages = warning; SET row_security = off; +-- +-- Name: public; Type: SCHEMA; Schema: -; Owner: - +-- + +-- *not* creating schema, since initdb creates it + + -- -- Name: fuzzystrmatch; Type: EXTENSION; Schema: -; Owner: - -- @@ -3273,7 +3280,7 @@ CREATE TABLE public.slots_reservations ( ex_end_at timestamp without time zone, canceled_at timestamp without time zone, offered boolean DEFAULT false, - validated_at timestamp(6) without time zone + is_valid boolean ); @@ -9056,17 +9063,18 @@ INSERT INTO "schema_migrations" (version) VALUES ('20230328094809'), ('20230331132506'), ('20230509121907'), -('20230509161557'); -('20230510141305'); +('20230509161557'), +('20230510141305'), ('20230511080650'), -('20230511081018'); +('20230511081018'), ('20230524080448'), ('20230524083558'), -('20230524110215'); +('20230524110215'), ('20230525101006'), +('20230612123250'), +('20230626103314'), ('20230626122844'), -('20230626122947'); -('20230612123250'); -('20230626103314'); +('20230626122947'), +('20230710072403');