diff --git a/app/frontend/src/javascript/components/machines/reserve-button.tsx b/app/frontend/src/javascript/components/machines/reserve-button.tsx index 606a37b93..5c8869112 100644 --- a/app/frontend/src/javascript/components/machines/reserve-button.tsx +++ b/app/frontend/src/javascript/components/machines/reserve-button.tsx @@ -9,6 +9,8 @@ import MachineAPI from '../../api/machine'; import { Machine } from '../../models/machine'; import { User } from '../../models/user'; import { IApplication } from '../../models/application'; +import SettingAPI from '../../api/setting'; +import { SettingName } from '../../models/setting'; declare const Application: IApplication; @@ -36,11 +38,17 @@ const ReserveButtonComponent: React.FC = ({ currentUser, mac const [pendingTraining, setPendingTraining] = useState(false); const [trainingRequired, setTrainingRequired] = useState(false); const [proposePacks, setProposePacks] = useState(false); + const [isPackOnlyForSubscription, setIsPackOnlyForSubscription] = useState(true); // handle login from an external process useEffect(() => setUser(currentUser), [currentUser]); // check the trainings after we retrieved the machine data useEffect(() => checkTraining(), [machine]); + useEffect(() => { + SettingAPI.get(SettingName.PackOnlyForSubscription) + .then(data => setIsPackOnlyForSubscription(data.value === 'true')) + .catch(error => onError(error)); + }, []); /** * Callback triggered when the user clicks on the 'reserve' button. @@ -136,8 +144,9 @@ const ReserveButtonComponent: React.FC = ({ currentUser, mac */ const checkPrepaidPack = (): void => { // if the customer has already bought a pack or if there's no active packs for this machine, + // or customer has not any subscription if admin active pack only for subscription option // let the customer reserve - if (machine.current_user_has_packs || !machine.has_prepaid_packs_for_current_user) { + if (machine.current_user_has_packs || !machine.has_prepaid_packs_for_current_user || (isPackOnlyForSubscription && !currentUser.subscribed_plan)) { return onReserveMachine(machine); } diff --git a/app/frontend/src/javascript/components/prepaid-packs/packs-summary.tsx b/app/frontend/src/javascript/components/prepaid-packs/packs-summary.tsx index 94a4d23f0..4e455444b 100644 --- a/app/frontend/src/javascript/components/prepaid-packs/packs-summary.tsx +++ b/app/frontend/src/javascript/components/prepaid-packs/packs-summary.tsx @@ -36,11 +36,15 @@ const PacksSummaryComponent: React.FC = ({ item, itemType, cu const [userPacks, setUserPacks] = useState>(null); const [threshold, setThreshold] = useState(null); const [packsModal, setPacksModal] = useState(false); + const [isPackOnlyForSubscription, setIsPackOnlyForSubscription] = useState(true); useEffect(() => { SettingAPI.get(SettingName.RenewPackThreshold) .then(data => setThreshold(parseFloat(data.value))) .catch(error => onError(error)); + SettingAPI.get(SettingName.PackOnlyForSubscription) + .then(data => setIsPackOnlyForSubscription(data.value === 'true')) + .catch(error => onError(error)); }, []); useEffect(() => { @@ -127,13 +131,32 @@ const PacksSummaryComponent: React.FC = ({ item, itemType, cu if (_.isEmpty(customer)) return
; // prevent component rendering if ths customer have no packs and there are no packs available if (totalHours() === 0 && packs?.length === 0) return
; + // render remaining hours and a warning if customer has not any subscription if admin active pack only for subscription option + if (totalHours() > 0) { + return ( +
+

{t('app.logged.packs_summary.prepaid_hours')}

+
+ + {t('app.logged.packs_summary.remaining_HOURS', { HOURS: totalHours(), ITEM: itemType })} + {isPackOnlyForSubscription && !customer.subscribed_plan && +
+ {t('app.logged.packs_summary.unable_to_use_pack_for_subsription_is_expired')} +
+ } +
+
+
+ ); + } + // prevent component rendering buy pack button if customer has not any subscription if admin active pack only for subscription option + if (isPackOnlyForSubscription && !customer.subscribed_plan) return
; return (

{t('app.logged.packs_summary.prepaid_hours')}

- {totalHours() > 0 && t('app.logged.packs_summary.remaining_HOURS', { HOURS: totalHours(), ITEM: itemType })} {totalHours() === 0 && t('app.logged.packs_summary.no_hours', { ITEM: itemType })} {shouldDisplayButton() &&
diff --git a/app/frontend/src/javascript/models/setting.ts b/app/frontend/src/javascript/models/setting.ts index 3e5031a03..439f211c5 100644 --- a/app/frontend/src/javascript/models/setting.ts +++ b/app/frontend/src/javascript/models/setting.ts @@ -110,6 +110,7 @@ export enum SettingName { PayZenCurrency = 'payzen_currency', PublicAgendaModule = 'public_agenda_module', RenewPackThreshold = 'renew_pack_threshold', + PackOnlyForSubscription = 'pack_only_for_subscription', } export type SettingValue = string|boolean|number; diff --git a/app/frontend/src/javascript/router.js b/app/frontend/src/javascript/router.js index 70fa98b8e..cad2f9a5b 100644 --- a/app/frontend/src/javascript/router.js +++ b/app/frontend/src/javascript/router.js @@ -1080,7 +1080,7 @@ angular.module('application.router', ['ui.router']) "'reminder_delay', 'visibility_yearly', 'visibility_others', 'wallet_module', 'trainings_module', " + "'display_name_enable', 'machines_sort_by', 'fab_analytics', 'statistics_module', 'address_required', " + "'link_name', 'home_content', 'home_css', 'phone_required', 'upcoming_events_shown', 'public_agenda_module'," + - "'renew_pack_threshold']" + "'renew_pack_threshold', 'pack_only_for_subscription']" }).$promise; }], privacyDraftsPromise: ['Setting', function (Setting) { return Setting.get({ name: 'privacy_draft', history: true }).$promise; }], diff --git a/app/frontend/templates/admin/settings/reservations.html b/app/frontend/templates/admin/settings/reservations.html index ad2a10ec1..c763732c5 100644 --- a/app/frontend/templates/admin/settings/reservations.html +++ b/app/frontend/templates/admin/settings/reservations.html @@ -169,5 +169,14 @@ step="0.01">
+
+

{{ 'app.admin.settings.pack_only_for_subscription_info' }}

+

+ + +
diff --git a/app/models/setting.rb b/app/models/setting.rb index 8deaafc5a..aee06ebae 100644 --- a/app/models/setting.rb +++ b/app/models/setting.rb @@ -119,7 +119,8 @@ class Setting < ApplicationRecord payzen_hmac payzen_currency public_agenda_module - renew_pack_threshold] } + renew_pack_threshold + pack_only_for_subscription] } # WARNING: when adding a new key, you may also want to add it in app/policies/setting_policy.rb#public_whitelist def value diff --git a/app/policies/setting_policy.rb b/app/policies/setting_policy.rb index 472a8206a..e9496a6f8 100644 --- a/app/policies/setting_policy.rb +++ b/app/policies/setting_policy.rb @@ -39,7 +39,8 @@ class SettingPolicy < ApplicationPolicy tracking_id book_overlapping_slots slot_duration events_in_calendar spaces_module plans_module invoicing_module recaptcha_site_key feature_tour_display disqus_shortname allowed_cad_extensions openlab_app_id openlab_default online_payment_module stripe_public_key confirmation_required wallet_module trainings_module address_required - payment_gateway payzen_endpoint payzen_public_key public_agenda_module renew_pack_threshold statistics_module] + payment_gateway payzen_endpoint payzen_public_key public_agenda_module renew_pack_threshold statistics_module + pack_only_for_subscription] end ## diff --git a/app/services/prepaid_pack_service.rb b/app/services/prepaid_pack_service.rb index 14149a047..58ba51d8a 100644 --- a/app/services/prepaid_pack_service.rb +++ b/app/services/prepaid_pack_service.rb @@ -61,6 +61,11 @@ class PrepaidPackService ## Total number of prepaid minutes available def minutes_available(user, priceable) + is_pack_only_for_subscription = Setting.find_by(name: "pack_only_for_subscription")&.value + if is_pack_only_for_subscription == 'true' && !user.subscribed_plan + return 0 + end + user_packs = user_packs(user, priceable) total_available = user_packs.map { |up| up.prepaid_pack.minutes }.reduce(:+) || 0 total_used = user_packs.map(&:minutes_used).reduce(:+) || 0 diff --git a/config/locales/app.admin.de.yml b/config/locales/app.admin.de.yml index 17b4d2124..e6c79b700 100644 --- a/config/locales/app.admin.de.yml +++ b/config/locales/app.admin.de.yml @@ -1208,6 +1208,9 @@ de: display_invite_to_renew_pack: "Display the invite to renew prepaid-packs" packs_threshold_info_html: "You can define under how many hours the user will be invited to buy a new prepaid-pack, if his stock of prepaid hours is under this threshold.
You can set a number of hours (eg. 5) or a percentage of his current pack pack (eg. 0.05 means 5%)." renew_pack_threshold: "threshold for packs renewal" + pack_only_for_subscription_info_html: "If this option is activated, the purchase and use of a prepaid pack is only possible for the user with a valid subscription." + pack_only_for_subscription: "Subscription valid for purchase and use of a prepaid pack" + pack_only_for_subscription_info: "Make subscription mandatory for prepaid packs" general: general: "Allgemein" title: "Titel" diff --git a/config/locales/app.admin.en.yml b/config/locales/app.admin.en.yml index 309ddde02..fd2b884f7 100644 --- a/config/locales/app.admin.en.yml +++ b/config/locales/app.admin.en.yml @@ -1208,6 +1208,9 @@ en: display_invite_to_renew_pack: "Display the invite to renew prepaid-packs" packs_threshold_info_html: "You can define under how many hours the user will be invited to buy a new prepaid-pack, if his stock of prepaid hours is under this threshold.
You can set a number of hours (eg. 5) or a percentage of his current pack pack (eg. 0.05 means 5%)." renew_pack_threshold: "threshold for packs renewal" + pack_only_for_subscription_info_html: "If this option is activated, the purchase and use of a prepaid pack is only possible for the user with a valid subscription." + pack_only_for_subscription: "Subscription valid for purchase and use of a prepaid pack" + pack_only_for_subscription_info: "Make subscription mandatory for prepaid packs" general: general: "General" title: "Title" diff --git a/config/locales/app.admin.es.yml b/config/locales/app.admin.es.yml index b95f8e1d0..9d672272a 100644 --- a/config/locales/app.admin.es.yml +++ b/config/locales/app.admin.es.yml @@ -1208,6 +1208,9 @@ es: display_invite_to_renew_pack: "Display the invite to renew prepaid-packs" packs_threshold_info_html: "You can define under how many hours the user will be invited to buy a new prepaid-pack, if his stock of prepaid hours is under this threshold.
You can set a number of hours (eg. 5) or a percentage of his current pack pack (eg. 0.05 means 5%)." renew_pack_threshold: "threshold for packs renewal" + pack_only_for_subscription_info_html: "If this option is activated, the purchase and use of a prepaid pack is only possible for the user with a valid subscription." + pack_only_for_subscription: "Subscription valid for purchase and use of a prepaid pack" + pack_only_for_subscription_info: "Make subscription mandatory for prepaid packs" general: general: "General" title: "Title" diff --git a/config/locales/app.admin.fr.yml b/config/locales/app.admin.fr.yml index 023717e63..b934471ba 100644 --- a/config/locales/app.admin.fr.yml +++ b/config/locales/app.admin.fr.yml @@ -1208,6 +1208,9 @@ fr: display_invite_to_renew_pack: "Afficher l'invitation à renouveler les packs prépayés" packs_threshold_info_html: "Vous pouvez définir le nombre d'heures en dessous duquel l'utilisateur sera invité à acheter un nouveau pack prépayé, si son stock d'heures prépayées est inférieur à ce seuil.
Vous pouvez définir un nombre d'heures (par exemple. 5) ou un pourcentage de son pack actuel (par exemple 0,05 signifie 5%)." renew_pack_threshold: "seuil de renouvellement des packs" + pack_only_for_subscription_info_html: "Si cette option est activée, l'achat et l'utilisation d'un pack prépayé est seulement possible pour l'utilisateur possédant un abonnement en cours de validité." + pack_only_for_subscription: "Abonnement valide pour achat et utilisation d'un pack prépayé" + pack_only_for_subscription_info: "Rendre obligatoire l'abonnement pour les packs prépayés" general: general: "Général" title: "Titre" diff --git a/config/locales/app.admin.no.yml b/config/locales/app.admin.no.yml index b5acc400d..e02a860e6 100644 --- a/config/locales/app.admin.no.yml +++ b/config/locales/app.admin.no.yml @@ -1208,6 +1208,9 @@ display_invite_to_renew_pack: "Vis invitasjonen til å fornye forhånds-pakker" packs_threshold_info_html: "Du kan definere under hvor mange timer brukeren vil bli invitert til å kjøpe en ny prepaid-pakke, hvis hans beholdning av forhåndsbetalte timer er under denne grensen.
Du kan angi antall timer (f. eks. 5) eller en prosentenhet i sin nåværende pakningspakkef. eks. 0,05 betyr 5 %)." renew_pack_threshold: "terskel for fornyelse av pakker" + pack_only_for_subscription_info_html: "If this option is activated, the purchase and use of a prepaid pack is only possible for the user with a valid subscription." + pack_only_for_subscription: "Subscription valid for purchase and use of a prepaid pack" + pack_only_for_subscription_info: "Make subscription mandatory for prepaid packs" general: general: "Generelt" title: "Tittel" diff --git a/config/locales/app.admin.pt.yml b/config/locales/app.admin.pt.yml index 23cce9858..4b31edda8 100755 --- a/config/locales/app.admin.pt.yml +++ b/config/locales/app.admin.pt.yml @@ -1208,6 +1208,9 @@ pt: display_invite_to_renew_pack: "Display the invite to renew prepaid-packs" packs_threshold_info_html: "You can define under how many hours the user will be invited to buy a new prepaid-pack, if his stock of prepaid hours is under this threshold.
You can set a number of hours (eg. 5) or a percentage of his current pack pack (eg. 0.05 means 5%)." renew_pack_threshold: "threshold for packs renewal" + pack_only_for_subscription_info_html: "If this option is activated, the purchase and use of a prepaid pack is only possible for the user with a valid subscription." + pack_only_for_subscription: "Subscription valid for purchase and use of a prepaid pack" + pack_only_for_subscription_info: "Make subscription mandatory for prepaid packs" general: general: "Geral" title: "Título" diff --git a/config/locales/app.admin.zu.yml b/config/locales/app.admin.zu.yml index 226622c87..07c7b231c 100644 --- a/config/locales/app.admin.zu.yml +++ b/config/locales/app.admin.zu.yml @@ -1208,6 +1208,9 @@ zu: display_invite_to_renew_pack: "crwdns22000:0crwdne22000:0" packs_threshold_info_html: "crwdns22030:0crwdne22030:0" renew_pack_threshold: "crwdns22004:0crwdne22004:0" + pack_only_for_subscription_info_html: "If this option is activated, the purchase and use of a prepaid pack is only possible for the user with a valid subscription." + pack_only_for_subscription: "Subscription valid for purchase and use of a prepaid pack" + pack_only_for_subscription_info: "Make subscription mandatory for prepaid packs" general: general: "crwdns20726:0crwdne20726:0" title: "crwdns20728:0crwdne20728:0" diff --git a/config/locales/app.logged.de.yml b/config/locales/app.logged.de.yml index 546671115..a9a68014f 100644 --- a/config/locales/app.logged.de.yml +++ b/config/locales/app.logged.de.yml @@ -196,6 +196,7 @@ de: remaining_HOURS: "You have {HOURS} prepaid hours remaining for this {ITEM, select, Machine{machine} Space{space} other{}}." no_hours: "You don't have any prepaid hours for this {ITEM, select, Machine{machine} Space{space} other{}}." buy_a_new_pack: "Buy a new pack" + unable_to_use_pack_for_subsription_is_expired: "You must have a valid subscription to use your remaining hours." #book a training trainings_reserve: trainings_planning: "Schulungsplanung" diff --git a/config/locales/app.logged.en.yml b/config/locales/app.logged.en.yml index df0c17c53..6f559be96 100644 --- a/config/locales/app.logged.en.yml +++ b/config/locales/app.logged.en.yml @@ -196,6 +196,7 @@ en: remaining_HOURS: "You have {HOURS} prepaid hours remaining for this {ITEM, select, Machine{machine} Space{space} other{}}." no_hours: "You don't have any prepaid hours for this {ITEM, select, Machine{machine} Space{space} other{}}." buy_a_new_pack: "Buy a new pack" + unable_to_use_pack_for_subsription_is_expired: "You must have a valid subscription to use your remaining hours." #book a training trainings_reserve: trainings_planning: "Trainings planning" diff --git a/config/locales/app.logged.es.yml b/config/locales/app.logged.es.yml index 414615c06..ac536350d 100644 --- a/config/locales/app.logged.es.yml +++ b/config/locales/app.logged.es.yml @@ -196,6 +196,7 @@ es: remaining_HOURS: "You have {HOURS} prepaid hours remaining for this {ITEM, select, Machine{machine} Space{space} other{}}." no_hours: "You don't have any prepaid hours for this {ITEM, select, Machine{machine} Space{space} other{}}." buy_a_new_pack: "Buy a new pack" + unable_to_use_pack_for_subsription_is_expired: "You must have a valid subscription to use your remaining hours." #book a training trainings_reserve: trainings_planning: "Plan de curso" diff --git a/config/locales/app.logged.fr.yml b/config/locales/app.logged.fr.yml index 0f901e586..7de08e03f 100644 --- a/config/locales/app.logged.fr.yml +++ b/config/locales/app.logged.fr.yml @@ -196,6 +196,7 @@ fr: remaining_HOURS: "Il vous reste {HOURS} heures prépayées pour {ITEM, select, Machine{cette machine} Space{cet espace} other{}}." no_hours: "Vous n'avez aucune heure prépayée pour {ITEM, select, Machine{cette machine} Space{cet espace} other{}}." buy_a_new_pack: "Acheter un nouveau pack" + unable_to_use_pack_for_subsription_is_expired: "Vous devez avoir un abonnement en cours de validité pour consommer vos heures restantes." #book a training trainings_reserve: trainings_planning: "Planning formations" diff --git a/config/locales/app.logged.no.yml b/config/locales/app.logged.no.yml index 2e9c8be68..8e1361bef 100644 --- a/config/locales/app.logged.no.yml +++ b/config/locales/app.logged.no.yml @@ -196,6 +196,7 @@ remaining_HOURS: "Du har {HOURS} forhåndsbetalte timer igjen for denne {ITEM, select, Machine{maskinen} Space{plassen/rommet} other{}}." no_hours: "Du har ikke noen forhåndsbetalt timer for {ITEM, select, Machine{maskinen} Space{plass/rom} other{}}." buy_a_new_pack: "Kjøp en ny pakke" + unable_to_use_pack_for_subsription_is_expired: "You must have a valid subscription to use your remaining hours." #book a training trainings_reserve: trainings_planning: "Planlegging, opplæring og kurs" diff --git a/config/locales/app.logged.pt.yml b/config/locales/app.logged.pt.yml index b08cf4928..4d7d9710e 100755 --- a/config/locales/app.logged.pt.yml +++ b/config/locales/app.logged.pt.yml @@ -196,6 +196,7 @@ pt: remaining_HOURS: "You have {HOURS} prepaid hours remaining for this {ITEM, select, Machine{machine} Space{space} other{}}." no_hours: "You don't have any prepaid hours for this {ITEM, select, Machine{machine} Space{space} other{}}." buy_a_new_pack: "Buy a new pack" + unable_to_use_pack_for_subsription_is_expired: "You must have a valid subscription to use your remaining hours." #book a training trainings_reserve: trainings_planning: "Planos de treinamento" diff --git a/config/locales/app.logged.zu.yml b/config/locales/app.logged.zu.yml index 6792e8c3e..64bc38500 100644 --- a/config/locales/app.logged.zu.yml +++ b/config/locales/app.logged.zu.yml @@ -196,6 +196,7 @@ zu: remaining_HOURS: "crwdns21934:0HOURS={HOURS}crwdnd21934:0ITEM={ITEM}crwdne21934:0" no_hours: "crwdns21936:0ITEM={ITEM}crwdne21936:0" buy_a_new_pack: "crwdns21938:0crwdne21938:0" + unable_to_use_pack_for_subsription_is_expired: "You must have a valid subscription to use your remaining hours." #book a training trainings_reserve: trainings_planning: "crwdns8767:0crwdne8767:0" diff --git a/db/seeds.rb b/db/seeds.rb index 2ba5dc126..d25f4e9d6 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -899,6 +899,8 @@ Setting.set('public_agenda_module', true) unless Setting.find_by(name: 'public_a Setting.set('renew_pack_threshold', 0.2) unless Setting.find_by(name: 'renew_pack_threshold').try(:value) +Setting.set('pack_only_for_subscription', true) unless Setting.find_by(name: 'pack_only_for_subscription').try(:value) + if StatisticCustomAggregation.count.zero? # available reservations hours for machines machine_hours = StatisticType.find_by(key: 'hour', statistic_index_id: 2)