1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2024-11-28 09:24:24 +01:00

add an option Subscription valid for purchase and use of a prepaid pack

This commit is contained in:
Du Peng 2021-09-20 19:43:05 +02:00
parent a9901fccb2
commit f2dd1bbcd2
23 changed files with 84 additions and 5 deletions

View File

@ -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<ReserveButtonProps> = ({ currentUser, mac
const [pendingTraining, setPendingTraining] = useState<boolean>(false);
const [trainingRequired, setTrainingRequired] = useState<boolean>(false);
const [proposePacks, setProposePacks] = useState<boolean>(false);
const [isPackOnlyForSubscription, setIsPackOnlyForSubscription] = useState<boolean>(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<ReserveButtonProps> = ({ 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);
}

View File

@ -36,11 +36,15 @@ const PacksSummaryComponent: React.FC<PacksSummaryProps> = ({ item, itemType, cu
const [userPacks, setUserPacks] = useState<Array<UserPack>>(null);
const [threshold, setThreshold] = useState<number>(null);
const [packsModal, setPacksModal] = useState<boolean>(false);
const [isPackOnlyForSubscription, setIsPackOnlyForSubscription] = useState<boolean>(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<PacksSummaryProps> = ({ item, itemType, cu
if (_.isEmpty(customer)) return <div />;
// prevent component rendering if ths customer have no packs and there are no packs available
if (totalHours() === 0 && packs?.length === 0) return <div/>;
// render remaining hours and a warning if customer has not any subscription if admin active pack only for subscription option
if (totalHours() > 0) {
return (
<div className="packs-summary">
<h3>{t('app.logged.packs_summary.prepaid_hours')}</h3>
<div className="content">
<span className="remaining-hours">
{t('app.logged.packs_summary.remaining_HOURS', { HOURS: totalHours(), ITEM: itemType })}
{isPackOnlyForSubscription && !customer.subscribed_plan &&
<div className="alert alert-warning m-t m-b">
{t('app.logged.packs_summary.unable_to_use_pack_for_subsription_is_expired')}
</div>
}
</span>
</div>
</div>
);
}
// 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 <div/>;
return (
<div className="packs-summary">
<h3>{t('app.logged.packs_summary.prepaid_hours')}</h3>
<div className="content">
<span className="remaining-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 })}
</span>
{shouldDisplayButton() && <div className="button-wrapper">

View File

@ -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;

View File

@ -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; }],

View File

@ -169,5 +169,14 @@
step="0.01">
</number-setting>
</div>
<div class="row">
<h3 class="m-l" translate>{{ 'app.admin.settings.pack_only_for_subscription_info' }}</h3>
<p class="alert alert-warning m-h-md" ng-bind-html="'app.admin.settings.pack_only_for_subscription_info_html' | translate"></p>
<boolean-setting name="pack_only_for_subscription"
settings="allSettings"
label="app.admin.settings.pack_only_for_subscription"
classes="m-l">
</boolean-setting>
</div>
</div>
</div>

View File

@ -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

View File

@ -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
##

View File

@ -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

View File

@ -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.<br/>You can set a <strong>number of hours</strong> (<em>eg. 5</em>) or a <strong>percentage</strong> of his current pack pack (<em>eg. 0.05 means 5%</em>)."
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"

View File

@ -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.<br/>You can set a <strong>number of hours</strong> (<em>eg. 5</em>) or a <strong>percentage</strong> of his current pack pack (<em>eg. 0.05 means 5%</em>)."
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"

View File

@ -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.<br/>You can set a <strong>number of hours</strong> (<em>eg. 5</em>) or a <strong>percentage</strong> of his current pack pack (<em>eg. 0.05 means 5%</em>)."
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"

View File

@ -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.<br/>Vous pouvez définir un <strong>nombre d'heures</strong> (<em>par exemple. 5</em>) ou un <strong>pourcentage</strong> de son pack actuel (<em>par exemple 0,05 signifie 5%</em>)."
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"

View File

@ -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.<br/>Du kan angi <strong>antall timer</strong> (<em>f. eks. 5</em>) eller en <strong>prosentenhet</strong> i sin nåværende pakningspakke<em>f. eks. 0,05 betyr 5 %</em>)."
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"

View File

@ -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.<br/>You can set a <strong>number of hours</strong> (<em>eg. 5</em>) or a <strong>percentage</strong> of his current pack pack (<em>eg. 0.05 means 5%</em>)."
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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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)