mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-19 13:54:25 +01:00
[bug] subscription page shows the groups without any active plans
[bug] cart price inconsistently updated after a subscription [feature] plans page for managers
This commit is contained in:
parent
05479e043c
commit
35ce577651
@ -8,6 +8,8 @@
|
||||
- Fix a bug: "Free entry" label for events without reservation
|
||||
- Fix a bug: updating a setting without any changes triggers an error
|
||||
- Fix a bug: plan edition does not show the associated group
|
||||
- Fix a bug: subscription page shows the groups without any active plans
|
||||
- Fix a bug: cart price inconsistently updated after a subscription
|
||||
|
||||
## v4.3.4 2020 April 14
|
||||
|
||||
|
@ -64,8 +64,6 @@ angular.module('application', ['ngCookies', 'ngResource', 'ngSanitize', 'ui.rout
|
||||
$translateProvider.useMessageFormatInterpolation();
|
||||
// Set the language of the instance (from ruby configuration)
|
||||
$translateProvider.preferredLanguage(Fablab.locale);
|
||||
// In any cases, fallback to english
|
||||
$translateProvider.fallbackLanguage('en');
|
||||
// End the tour when the user clicks the forward or back buttons of the browser
|
||||
TourConfigProvider.enableNavigationInterceptors();
|
||||
}]).run(['$rootScope', '$log', 'AuthService', 'Auth', 'amMoment', '$state', 'editableOptions', 'Analytics',
|
||||
|
@ -12,8 +12,8 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScope', '$state', '$uibModal', 'Auth', 'dialogs', 'growl', 'plansPromise', 'groupsPromise', 'Subscription', 'Member', 'subscriptionExplicationsPromise', '_t', 'Wallet', 'helpers',
|
||||
function ($scope, $rootScope, $state, $uibModal, Auth, dialogs, growl, plansPromise, groupsPromise, Subscription, Member, subscriptionExplicationsPromise, _t, Wallet, helpers) {
|
||||
Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScope', '$state', '$uibModal', 'Auth', 'AuthService', 'dialogs', 'growl', 'plansPromise', 'groupsPromise', 'Subscription', 'Member', 'subscriptionExplicationsPromise', '_t', 'Wallet', 'helpers',
|
||||
function ($scope, $rootScope, $state, $uibModal, Auth, AuthService, dialogs, growl, plansPromise, groupsPromise, Subscription, Member, subscriptionExplicationsPromise, _t, Wallet, helpers) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// list of groups
|
||||
@ -28,13 +28,6 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
|
||||
// list of plans, classified by group
|
||||
$scope.plansClassifiedByGroup = [];
|
||||
for (const group of Array.from($scope.groups)) {
|
||||
const groupObj = { id: group.id, name: group.name, plans: [] };
|
||||
for (let plan of Array.from(plansPromise)) {
|
||||
if (plan.group_id === group.id) { groupObj.plans.push(plan); }
|
||||
}
|
||||
$scope.plansClassifiedByGroup.push(groupObj);
|
||||
}
|
||||
|
||||
// user to deal with
|
||||
$scope.ctrl = {
|
||||
@ -62,7 +55,7 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
|
||||
/**
|
||||
* Callback to deal with the subscription of the user selected in the dropdown list instead of the current user's
|
||||
* subscription. (admins only)
|
||||
* subscription. (admins and managers only)
|
||||
*/
|
||||
$scope.updateMember = function () {
|
||||
$scope.selectedPlan = null;
|
||||
@ -97,14 +90,17 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
$scope.openSubscribePlanModal = function () {
|
||||
Wallet.getWalletByUser({ user_id: $scope.ctrl.member.id }, function (wallet) {
|
||||
const amountToPay = helpers.getAmountToPay($scope.cart.total, wallet.amount);
|
||||
if (($scope.currentUser.role !== 'admin') && (amountToPay > 0)) {
|
||||
if ((AuthService.isAuthorized('member') && amountToPay > 0)
|
||||
|| (AuthService.isAuthorized('manager') && $scope.ctrl.member.id === $rootScope.currentUser.id && amountToPay > 0)) {
|
||||
if ($rootScope.fablabWithoutOnlinePayment) {
|
||||
growl.error(_t('app.public.plans.online_payment_disabled'));
|
||||
} else {
|
||||
return payByStripe();
|
||||
}
|
||||
} else {
|
||||
if (($scope.currentUser.role === 'admin') || (amountToPay === 0)) {
|
||||
if (AuthService.isAuthorized('admin')
|
||||
|| (AuthService.isAuthorized('manager') && $scope.ctrl.member.id !== $rootScope.currentUser.id)
|
||||
|| amountToPay === 0) {
|
||||
return payOnSite();
|
||||
}
|
||||
}
|
||||
@ -130,7 +126,8 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
$scope.ctrl.member = user;
|
||||
$scope.group.change = false;
|
||||
$scope.selectedPlan = null;
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
if (AuthService.isAuthorized('member') ||
|
||||
(AuthService.isAuthorized('manager') && $scope.currentUser.id !== $scope.ctrl.member.id)) {
|
||||
$rootScope.currentUser = user;
|
||||
Auth._currentUser.group_id = user.group_id;
|
||||
growl.success(_t('app.public.plans.your_group_was_successfully_changed'));
|
||||
@ -139,7 +136,8 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
}
|
||||
}
|
||||
, function (err) {
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
if (AuthService.isAuthorized('member') ||
|
||||
(AuthService.isAuthorized('manager') && $scope.currentUser.id !== $scope.ctrl.member.id)) {
|
||||
growl.error(_t('app.public.plans.an_error_prevented_your_group_from_being_changed'));
|
||||
} else {
|
||||
growl.error(_t('app.public.plans.an_error_prevented_to_change_the_user_s_group'));
|
||||
@ -179,8 +177,20 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
// group all plans by Group
|
||||
for (const group of $scope.groups) {
|
||||
const groupObj = { id: group.id, name: group.name, plans: [], actives: 0 };
|
||||
for (let plan of plansPromise) {
|
||||
if (plan.group_id === group.id) {
|
||||
groupObj.plans.push(plan);
|
||||
if (!plan.disabled) { groupObj.actives++; }
|
||||
}
|
||||
}
|
||||
$scope.plansClassifiedByGroup.push(groupObj);
|
||||
}
|
||||
|
||||
if ($scope.currentUser) {
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
if (!AuthService.isAuthorized('admin')) {
|
||||
$scope.ctrl.member = $scope.currentUser;
|
||||
$scope.paid.plan = $scope.currentUser.subscribed_plan;
|
||||
$scope.group.id = $scope.currentUser.group_id;
|
||||
@ -201,9 +211,9 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
* Compute the total amount for the current reservation according to the previously set parameters
|
||||
* and assign the result in $scope.reserve.amountTotal
|
||||
*/
|
||||
var updateCartPrice = function () {
|
||||
// first we check that a user was selected
|
||||
if (Object.keys($scope.ctrl.member).length > 0) {
|
||||
const updateCartPrice = function () {
|
||||
// first we check the selection of a user
|
||||
if (Object.keys($scope.ctrl.member).length > 0 && $scope.selectedPlan) {
|
||||
$scope.cart.total = $scope.selectedPlan.amount;
|
||||
// apply the coupon if any
|
||||
if ($scope.coupon.applied) {
|
||||
@ -262,7 +272,7 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
CustomAsset.get({ name: 'cgv-file' }, function (cgv) { $scope.cgv = cgv.custom_asset; });
|
||||
|
||||
/**
|
||||
* Callback for click on the 'proceed' button.
|
||||
* Callback for a click on the 'proceed' button.
|
||||
* Handle the stripe's card tokenization process response and save the subscription to the API with the
|
||||
* card token just created.
|
||||
*/
|
||||
@ -301,7 +311,7 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
// user wallet amount
|
||||
$scope.walletAmount = wallet.amount;
|
||||
|
||||
// subcription price, coupon subtracted if any
|
||||
// subscription price, coupon subtracted if any
|
||||
$scope.price = price;
|
||||
|
||||
// price to pay
|
||||
|
@ -17,7 +17,7 @@
|
||||
<div class="row no-gutter">
|
||||
<div class="col-sm-12 col-md-9 b-r">
|
||||
|
||||
<div class="row m-t m-b padder" ng-repeat="plansGroup in plansClassifiedByGroup | groupFilter:ctrl.member">
|
||||
<div class="row m-t m-b padder" ng-repeat="plansGroup in plansClassifiedByGroup | groupFilter:ctrl.member" ng-show="plansGroup.actives > 0">
|
||||
|
||||
<div class="col-md-12 text-center">
|
||||
<h2 class="text-u-c">{{plansGroup.name}}</h2>
|
||||
@ -41,7 +41,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cta-button" ng-if="!ctrl.member || ctrl.member.role == 'member'">
|
||||
<div class="cta-button" ng-if="!ctrl.member || ctrl.member.role == 'member' || (ctrl.member.role == 'manager' && ctrl.member.id === currentUser.id)">
|
||||
<button class="btn btn-default rounded" ng-click="selectPlan(plan)" ng-if="ctrl.member.subscribed_plan.id != plan.id" ng-disabled="ctrl.member.subscribed_plan" ng-class="{ 'bg-yellow': selectedPlan==plan }">
|
||||
<span ng-if="ctrl.member" translate>{{ 'app.public.plans.i_choose_that_plan' }}</span>
|
||||
<span ng-if="!ctrl.member" translate>{{ 'app.public.plans.i_subscribe_online' }}</span>
|
||||
@ -53,7 +53,7 @@
|
||||
|
||||
</div>
|
||||
|
||||
<div class="cta-button" ng-if="isAuthorized(['admin', 'manager'])">
|
||||
<div class="cta-button" ng-if="isAuthorized('admin') || (ctrl.member.role == 'manager' && ctrl.member.id != currentUser.id)">
|
||||
<button class="btn btn-default rounded" ng-click="selectPlan(plan)" ng-class="{ 'bg-yellow': selectedPlan==plan }" ng-disabled="!ctrl.member">
|
||||
<span translate>{{ 'app.public.plans.i_choose_that_plan' }}</span>
|
||||
</button>
|
||||
|
@ -10,12 +10,13 @@ class API::SubscriptionsController < API::ApiController
|
||||
end
|
||||
|
||||
# Admins can create any subscriptions. Members can directly create subscriptions if total = 0,
|
||||
# otherwise, they must use payments_controller#confirm_payment
|
||||
# otherwise, they must use payments_controller#confirm_payment.
|
||||
# Managers can create subscriptions for other users
|
||||
def create
|
||||
user_id = current_user.admin? ? params[:subscription][:user_id] : current_user.id
|
||||
user_id = current_user.admin? || current_user.manager? ? params[:subscription][:user_id] : current_user.id
|
||||
amount = transaction_amount(current_user.admin?, user_id)
|
||||
|
||||
authorize SubscriptionContext.new(Subscription, amount)
|
||||
authorize SubscriptionContext.new(Subscription, amount, user_id)
|
||||
|
||||
@subscription = Subscription.new(subscription_params)
|
||||
is_subscribe = Subscriptions::Subscribe.new(current_user.invoicing_profile.id, user_id)
|
||||
|
@ -105,6 +105,10 @@ class User < ApplicationRecord
|
||||
User.with_role(:manager)
|
||||
end
|
||||
|
||||
def self.online_payers
|
||||
User.with_any_role(:manager, :member)
|
||||
end
|
||||
|
||||
def self.superadmin
|
||||
return unless Rails.application.secrets.superadmin_email.present?
|
||||
|
||||
|
@ -2,11 +2,12 @@
|
||||
|
||||
# Pundit Additional context to validate the price of a subscription
|
||||
class SubscriptionContext
|
||||
attr_reader :subscription, :price
|
||||
attr_reader :subscription, :price, :user_id
|
||||
|
||||
def initialize(subscription, price)
|
||||
def initialize(subscription, price, user_id)
|
||||
@subscription = subscription
|
||||
@price = price
|
||||
@user_id = user_id
|
||||
end
|
||||
|
||||
def policy_class
|
||||
|
@ -4,7 +4,7 @@
|
||||
class SubscriptionPolicy < ApplicationPolicy
|
||||
include FablabConfiguration
|
||||
def create?
|
||||
!fablab_plans_deactivated? && (user.admin? || record.price.zero?)
|
||||
!fablab_plans_deactivated? && (user.admin? || (user.manager? && record.user_id != user.id) || record.price.zero?)
|
||||
end
|
||||
|
||||
def show?
|
||||
|
@ -29,6 +29,7 @@ fr:
|
||||
#left menu
|
||||
notifications: "Notifications"
|
||||
admin: "Admin"
|
||||
manager: "Gestionnaire"
|
||||
reduce_panel: "Réduire le volet"
|
||||
#left menu (public)
|
||||
home: "Accueil"
|
||||
|
@ -48,7 +48,10 @@ namespace :fablab do
|
||||
|
||||
desc 'sync users to the stripe database'
|
||||
task sync_members: :environment do
|
||||
User.members.each do |member|
|
||||
puts 'We create all non-existing customers on stripe. This may take a while, please wait...'
|
||||
total = User.online_payers.count
|
||||
User.online_payers.each_with_index do |member, index|
|
||||
print_on_line "#{index} / #{total}"
|
||||
begin
|
||||
stp_customer = Stripe::Customer.retrieve member.stp_customer_id
|
||||
StripeWorker.perform_async(:create_stripe_customer, member.id) if stp_customer.nil? || stp_customer[:deleted]
|
||||
@ -56,6 +59,12 @@ namespace :fablab do
|
||||
StripeWorker.perform_async(:create_stripe_customer, member.id)
|
||||
end
|
||||
end
|
||||
puts 'Done'
|
||||
end
|
||||
|
||||
def print_on_line(str)
|
||||
print "#{str}\r"
|
||||
$stdout.flush
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user