1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-29 18:52:22 +01:00

fixes for card payment

This commit is contained in:
Sylvain 2020-12-02 14:28:41 +01:00
parent 6c39191efa
commit 5941446a72
12 changed files with 62 additions and 42 deletions

View File

@ -23,7 +23,7 @@ class API::SubscriptionsController < API::ApiController
.pay_and_save(@subscription, coupon: coupon_params[:coupon_code],
invoice: true,
schedule: params[:subscription][:payment_schedule],
payment_method: params[:reservation][:payment_method])
payment_method: params[:subscription][:payment_method])
if is_subscribe
render :show, status: :created, location: @subscription

View File

@ -17,5 +17,4 @@ class SocialBotController < ActionController::Base
puts "unknown bot request : #{request.original_url}"
end
end
end
end

View File

@ -2,7 +2,7 @@
* This component is a "card" publicly presenting the details of a plan
*/
import React from 'react';
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { react2angular } from 'react2angular';
import moment from 'moment';
@ -19,13 +19,14 @@ declare var Fablab: IFablab;
interface PlanCardProps {
plan: Plan,
user: User,
userId?: number,
subscribedPlanId?: number,
operator: User,
isSelected: boolean,
onSelectPlan: (plan: Plan) => void,
}
const PlanCard: React.FC<PlanCardProps> = ({ plan, user, operator, onSelectPlan, isSelected }) => {
const PlanCard: React.FC<PlanCardProps> = ({ plan, userId, subscribedPlanId, operator, onSelectPlan, isSelected }) => {
const { t } = useTranslation('public');
/**
* Return the formatted localized amount of the given plan (eg. 20.5 => "20,50 €")
@ -50,19 +51,19 @@ const PlanCard: React.FC<PlanCardProps> = ({ plan, user, operator, onSelectPlan,
* Check if the user can subscribe to the current plan, for himself
*/
const canSubscribeForMe = (): boolean => {
return operator?.role === UserRole.Member || (operator?.role === UserRole.Manager && user?.id === operator?.id)
return operator?.role === UserRole.Member || (operator?.role === UserRole.Manager && userId === operator?.id)
}
/**
* Check if the user can subscribe to the current plan, for someone else
*/
const canSubscribeForOther = (): boolean => {
return operator?.role === UserRole.Admin || (operator?.role === UserRole.Manager && user?.id !== operator?.id)
return operator?.role === UserRole.Admin || (operator?.role === UserRole.Manager && userId !== operator?.id)
}
/**
* Check it the user has subscribed to this plan or not
*/
const hasSubscribedToThisPlan = (): boolean => {
return user?.subscription?.plan?.id === plan.id;
return subscribedPlanId === plan.id;
}
/**
* Check if the plan has an attached file
@ -102,18 +103,18 @@ const PlanCard: React.FC<PlanCardProps> = ({ plan, user, operator, onSelectPlan,
{canSubscribeForMe() && <div className="cta-button">
{!hasSubscribedToThisPlan() && <button className={`subscribe-button ${isSelected ? 'selected-card' : ''}`}
onClick={handleSelectPlan}
disabled={!_.isNil(user.subscription)}>
{user && <span>{t('app.public.plans.i_choose_that_plan')}</span>}
{!user && <span>{t('app.public.plans.i_subscribe_online')}</span>}
disabled={!_.isNil(subscribedPlanId)}>
{userId && <span>{t('app.public.plans.i_choose_that_plan')}</span>}
{!userId && <span>{t('app.public.plans.i_subscribe_online')}</span>}
</button>}
{hasSubscribedToThisPlan() && <button className="subscribe-button" disabled>
{hasSubscribedToThisPlan() && <button className="subscribe-button selected-card" disabled>
{ t('app.public.plans.i_already_subscribed') }
</button>}
</div>}
{canSubscribeForOther() && <div className="cta-button">
<button className={`subscribe-button ${isSelected ? 'selected-card' : ''}`}
onClick={handleSelectPlan}
disabled={_.isNil(user)}>
disabled={_.isNil(userId)}>
<span>{ t('app.public.plans.i_choose_that_plan') }</span>
</button>
</div>}
@ -122,12 +123,12 @@ const PlanCard: React.FC<PlanCardProps> = ({ plan, user, operator, onSelectPlan,
);
}
const PlanCardWrapper: React.FC<PlanCardProps> = ({ plan, user, operator, onSelectPlan, isSelected }) => {
const PlanCardWrapper: React.FC<PlanCardProps> = ({ plan, userId, subscribedPlanId, operator, onSelectPlan, isSelected }) => {
return (
<Loader>
<PlanCard plan={plan} user={user} operator={operator} isSelected={isSelected} onSelectPlan={onSelectPlan}/>
<PlanCard plan={plan} userId={userId} subscribedPlanId={subscribedPlanId} operator={operator} isSelected={isSelected} onSelectPlan={onSelectPlan}/>
</Loader>
);
}
Application.Components.component('planCard', react2angular(PlanCardWrapper, ['plan', 'user', 'operator', 'onSelectPlan', 'isSelected']));
Application.Components.component('planCard', react2angular(PlanCardWrapper, ['plan', 'userId', 'subscribedPlanId', 'operator', 'onSelectPlan', 'isSelected']));

View File

@ -665,7 +665,9 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
if ($scope.selectedPlan) {
$scope.ctrl.member.subscribed_plan = angular.copy($scope.selectedPlan);
Auth._currentUser.subscribed_plan = angular.copy($scope.selectedPlan);
if ($scope.ctrl.member.id === Auth._currentUser.id) {
Auth._currentUser.subscribed_plan = angular.copy($scope.selectedPlan);
}
$scope.plansAreShown = false;
$scope.selectedPlan = null;
}

View File

@ -167,7 +167,9 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
*/
$scope.afterPayment = function () {
$scope.ctrl.member.subscribed_plan = angular.copy($scope.selectedPlan);
Auth._currentUser.subscribed_plan = angular.copy($scope.selectedPlan);
if ($scope.ctrl.member.id === Auth._currentUser.id) {
Auth._currentUser.subscribed_plan = angular.copy($scope.selectedPlan);
}
$scope.paid.plan = angular.copy($scope.selectedPlan);
$scope.selectedPlan = null;
$scope.coupon.applied = null;

View File

@ -571,14 +571,18 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
if ($scope.selectedPlan) {
$scope.ctrl.member.subscribed_plan = angular.copy($scope.selectedPlan);
Auth._currentUser.subscribed_plan = angular.copy($scope.selectedPlan);
if ($scope.ctrl.member.id === Auth._currentUser.id) {
Auth._currentUser.subscribed_plan = angular.copy($scope.selectedPlan);
}
$scope.plansAreShown = false;
$scope.selectedPlan = null;
}
$scope.ctrl.member.training_credits = angular.copy(reservation.user.training_credits);
$scope.ctrl.member.machine_credits = angular.copy(reservation.user.machine_credits);
Auth._currentUser.training_credits = angular.copy(reservation.user.training_credits);
Auth._currentUser.machine_credits = angular.copy(reservation.user.machine_credits);
if ($scope.ctrl.member.id === Auth._currentUser.id) {
Auth._currentUser.training_credits = angular.copy(reservation.user.training_credits);
Auth._currentUser.machine_credits = angular.copy(reservation.user.machine_credits);
}
refetchCalendar();
};

View File

@ -361,14 +361,18 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
if ($scope.selectedPlan) {
$scope.ctrl.member.subscribed_plan = angular.copy($scope.selectedPlan);
Auth._currentUser.subscribed_plan = angular.copy($scope.selectedPlan);
if ($scope.ctrl.member.id === Auth._currentUser.id) {
Auth._currentUser.subscribed_plan = angular.copy($scope.selectedPlan);
}
$scope.plansAreShown = false;
$scope.selectedPlan = null;
}
$scope.ctrl.member.training_credits = angular.copy(reservation.user.training_credits);
$scope.ctrl.member.machine_credits = angular.copy(reservation.user.machine_credits);
Auth._currentUser.training_credits = angular.copy(reservation.user.training_credits);
Auth._currentUser.machine_credits = angular.copy(reservation.user.machine_credits);
if ($scope.ctrl.member.id === Auth._currentUser.id) {
Auth._currentUser.training_credits = angular.copy(reservation.user.training_credits);
Auth._currentUser.machine_credits = angular.copy(reservation.user.machine_credits);
}
refetchCalendar();
};

View File

@ -779,7 +779,7 @@ Application.Directives.directive('cart', ['$rootScope', '$uibModal', 'dialogs',
* Callback to process the local payment, triggered on button click
*/
$scope.ok = function () {
if ($scope.method.payment_method === 'stripe') {
if ($scope.schedule && $scope.method.payment_method === 'stripe') {
return $scope.toggleStripeModal();
}
$scope.attempting = true;
@ -843,10 +843,12 @@ Application.Directives.directive('cart', ['$rootScope', '$uibModal', 'dialogs',
*/
const computeValidButtonName = function () {
let method = '';
if (AuthService.isAuthorized(['admin', 'manager']) && $rootScope.currentUser.id !== reservation.user_id) {
method = $scope.method.payment_method;
} else {
method = 'stripe';
if ($scope.schedule) {
if (AuthService.isAuthorized(['admin', 'manager']) && $rootScope.currentUser.id !== reservation.user_id) {
method = $scope.method.payment_method;
} else {
method = 'stripe';
}
}
if ($scope.amount > 0) {
return _t('app.shared.cart.confirm_payment_of_html', { METHOD: method, AMOUNT: $filter('currency')($scope.amount) });

View File

@ -6,18 +6,22 @@
<div class="row row-centered padder">
<div class="col-xs-12 col-md-12 col-lg-10 col-centered no-gutter">
<!-- ng-class directive center the last item if the list length is odd -->
<div class="pricing-panel col-xs-6 col-md-6 col-lg-6 text-center"
ng-class="{'col-md-12 col-lg-12':(plansGroup.plans.filter(filterDisabledPlans).length % 2 == 1 && key == plansGroup.plans.filter(filterDisabledPlans).length-1)}"
ng-repeat="(key, plan) in plansGroup.plans.filter(filterDisabledPlans) | orderBy:'interval'">
<plan-card plan="plan"
user="ctrl.member"
operator="currentUser"
on-select-plan="selectPlan"
is-selected="isSelected(plan)">
</plan-card>
<div ng-repeat="(key, plan) in plansGroup.plans.filter(filterDisabledPlans) | orderBy:'interval'"
ng-class-even="'row'">
<div class="pricing-panel col-xs-12 col-md-6 col-lg-6 text-center"
ng-class="{'col-md-12 col-lg-12':(plansGroup.plans.filter(filterDisabledPlans).length % 2 == 1 && key == plansGroup.plans.filter(filterDisabledPlans).length-1)}">
<!-- ng-class directive center the last item if the list length is odd -->
<plan-card plan="plan"
user-id="ctrl.member.id"
subscribed-plan-id="ctrl.member.subscribed_plan.id"
operator="currentUser"
on-select-plan="selectPlan"
is-selected="isSelected(plan)">
</plan-card>
</div>
</div>
<a class="m-t-lg btn btn-small btn-default pull-right" href="#" ng-click="doNotSubscribePlan($event)">{{ 'app.shared.plan_subscribe.do_not_subscribe' | translate }} <i class="fa fa-long-arrow-right"></i></a>

View File

@ -32,7 +32,8 @@
ng-repeat="(key, plan) in plansGroup.plans.filter(filterDisabledPlans) | orderBy: '-ui_weight'">
<plan-card plan="plan"
user="ctrl.member"
user-id="ctrl.member.id"
subscribed-plan-id="ctrl.member.subscribed_plan.id"
operator="currentUser"
on-select-plan="selectPlan"
is-selected="isSelected(plan)">

View File

@ -21,6 +21,7 @@ class Subscription < ApplicationRecord
# @param invoice if true then only the subscription is payed, without reservation
# if false then the subscription is payed with reservation
# @param payment_method is only used for schedules
def save_with_payment(operator_profile_id, invoice: true, coupon_code: nil, payment_intent_id: nil, schedule: nil, payment_method: nil)
return false unless valid?

View File

@ -15,7 +15,7 @@ class Subscriptions::Subscribe
# @param invoice {Boolean}
# @param payment_intent_id {String} from stripe
# @param schedule {Boolean}
# @param payment_method {String}
# @param payment_method {String} only for schedules
##
def pay_and_save(subscription, coupon: nil, invoice: false, payment_intent_id: nil, schedule: false, payment_method: nil)
return false if user_id.nil?