mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-18 07:52:23 +01:00
(feat) remove admins group: allow admins to reserve
This commit is contained in:
parent
abea5006b2
commit
744b811b62
@ -34,3 +34,7 @@ Style/AndOr:
|
|||||||
EnforcedStyle: conditionals
|
EnforcedStyle: conditionals
|
||||||
Style/FormatString:
|
Style/FormatString:
|
||||||
EnforcedStyle: sprintf
|
EnforcedStyle: sprintf
|
||||||
|
Rails/RedundantPresenceValidationOnBelongsTo:
|
||||||
|
Enabled: false
|
||||||
|
Rails/UnknownEnv:
|
||||||
|
Environments: development, test, staging, production
|
||||||
|
@ -35,7 +35,7 @@ class API::AdminsController < API::ApiController
|
|||||||
|
|
||||||
def admin_params
|
def admin_params
|
||||||
params.require(:admin).permit(
|
params.require(:admin).permit(
|
||||||
:username, :email,
|
:username, :email, :group_id,
|
||||||
profile_attributes: %i[first_name last_name phone],
|
profile_attributes: %i[first_name last_name phone],
|
||||||
invoicing_profile_attributes: [address_attributes: [:address]],
|
invoicing_profile_attributes: [address_attributes: [:address]],
|
||||||
statistic_profile_attributes: %i[gender birthday]
|
statistic_profile_attributes: %i[gender birthday]
|
||||||
|
@ -6,7 +6,7 @@ class API::GroupsController < API::ApiController
|
|||||||
before_action :authenticate_user!, except: :index
|
before_action :authenticate_user!, except: :index
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@groups = GroupService.list(current_user, params)
|
@groups = GroupService.list(params)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
@ -43,7 +43,7 @@ export const ChangeGroup: React.FC<ChangeGroupProps> = ({ user, onSuccess, onErr
|
|||||||
const { handleSubmit, control } = useForm();
|
const { handleSubmit, control } = useForm();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
GroupAPI.index({ disabled: false, admins: user?.role === 'admin' }).then(setGroups).catch(onError);
|
GroupAPI.index({ disabled: false }).then(setGroups).catch(onError);
|
||||||
MemberAPI.current().then(setOperator).catch(onError);
|
MemberAPI.current().then(setOperator).catch(onError);
|
||||||
SettingAPI.get('user_change_group').then((setting) => {
|
SettingAPI.get('user_change_group').then((setting) => {
|
||||||
setAllowedUserChangeGoup(setting.value === 'true');
|
setAllowedUserChangeGoup(setting.value === 'true');
|
||||||
|
@ -39,7 +39,7 @@ export const PlansFilter: React.FC<PlansFilterProps> = ({ user, groups, onGroupS
|
|||||||
* Convert all groups to the react-select format
|
* Convert all groups to the react-select format
|
||||||
*/
|
*/
|
||||||
const buildGroupOptions = (): Array<selectOption> => {
|
const buildGroupOptions = (): Array<selectOption> => {
|
||||||
return groups.filter(g => !g.disabled && g.slug !== 'admins').map(g => {
|
return groups.filter(g => !g.disabled).map(g => {
|
||||||
return { value: g.id, label: g.name };
|
return { value: g.id, label: g.name };
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -41,7 +41,7 @@ export const MachinesPricing: React.FC<MachinesPricingProps> = ({ onError, onSuc
|
|||||||
MachineAPI.index({ disabled: false })
|
MachineAPI.index({ disabled: false })
|
||||||
.then(data => setMachines(data))
|
.then(data => setMachines(data))
|
||||||
.catch(error => onError(error));
|
.catch(error => onError(error));
|
||||||
GroupAPI.index({ disabled: false, admins: false })
|
GroupAPI.index({ disabled: false })
|
||||||
.then(data => setGroups(data))
|
.then(data => setGroups(data))
|
||||||
.catch(error => onError(error));
|
.catch(error => onError(error));
|
||||||
PriceAPI.index({ priceable_type: 'Machine', plan_id: null })
|
PriceAPI.index({ priceable_type: 'Machine', plan_id: null })
|
||||||
|
@ -38,7 +38,7 @@ export const SpacesPricing: React.FC<SpacesPricingProps> = ({ onError, onSuccess
|
|||||||
SpaceAPI.index()
|
SpaceAPI.index()
|
||||||
.then(data => setSpaces(data))
|
.then(data => setSpaces(data))
|
||||||
.catch(error => onError(error));
|
.catch(error => onError(error));
|
||||||
GroupAPI.index({ disabled: false, admins: false })
|
GroupAPI.index({ disabled: false })
|
||||||
.then(data => setGroups(data))
|
.then(data => setGroups(data))
|
||||||
.catch(error => onError(error));
|
.catch(error => onError(error));
|
||||||
PriceAPI.index({ priceable_type: 'Space', plan_id: null })
|
PriceAPI.index({ priceable_type: 'Space', plan_id: null })
|
||||||
|
@ -45,7 +45,7 @@ const SupportingDocumentsTypesList: React.FC<SupportingDocumentsTypesListProps>
|
|||||||
|
|
||||||
// get groups
|
// get groups
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
GroupAPI.index({ disabled: false, admins: false }).then(data => {
|
GroupAPI.index({ disabled: false }).then(data => {
|
||||||
setGroups(data);
|
setGroups(data);
|
||||||
ProofOfIdentityTypeAPI.index().then(pData => {
|
ProofOfIdentityTypeAPI.index().then(pData => {
|
||||||
setSupportingDocumentsTypes(pData);
|
setSupportingDocumentsTypes(pData);
|
||||||
|
@ -45,7 +45,7 @@ export const ChangeRoleModal: React.FC<ChangeRoleModalProps> = ({ isOpen, toggle
|
|||||||
const [selectedRole, setSelectedRole] = useState<UserRole>(user.role);
|
const [selectedRole, setSelectedRole] = useState<UserRole>(user.role);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
GroupAPI.index({ disabled: false, admins: false }).then(setGroups).catch(onError);
|
GroupAPI.index({ disabled: false }).then(setGroups).catch(onError);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -77,7 +77,7 @@ export const UserProfileForm: React.FC<UserProfileFormProps> = ({ action, size,
|
|||||||
setIsLocalDatabaseProvider(data.providable_type === 'DatabaseProvider');
|
setIsLocalDatabaseProvider(data.providable_type === 'DatabaseProvider');
|
||||||
}).catch(error => onError(error));
|
}).catch(error => onError(error));
|
||||||
if (showGroupInput) {
|
if (showGroupInput) {
|
||||||
GroupAPI.index({ disabled: false, admins: user.role === 'admin' }).then(data => {
|
GroupAPI.index({ disabled: false }).then(data => {
|
||||||
setGroups(buildOptions(data));
|
setGroups(buildOptions(data));
|
||||||
}).catch(error => onError(error));
|
}).catch(error => onError(error));
|
||||||
}
|
}
|
||||||
@ -155,11 +155,6 @@ export const UserProfileForm: React.FC<UserProfileFormProps> = ({ action, size,
|
|||||||
* Check if the given field path should be disabled
|
* Check if the given field path should be disabled
|
||||||
*/
|
*/
|
||||||
const isDisabled = function (id: string) {
|
const isDisabled = function (id: string) {
|
||||||
// never allows admins to change their group
|
|
||||||
if (id === 'group_id' && user.role === 'admin') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the current provider is the local database, then all fields are enabled
|
// if the current provider is the local database, then all fields are enabled
|
||||||
if (isLocalDatabaseProvider) {
|
if (isLocalDatabaseProvider) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
class MembersController {
|
class MembersController {
|
||||||
constructor ($scope, $state, Group, Training) {
|
constructor ($scope, $state, Group, Training) {
|
||||||
// Retrieve the profiles groups (e.g. students ...)
|
// Retrieve the profiles groups (e.g. students ...)
|
||||||
Group.query(function (groups) { $scope.groups = groups.filter(function (g) { return (g.slug !== 'admins') && !g.disabled; }); });
|
Group.query(function (groups) { $scope.groups = groups.filter(function (g) { return !g.disabled; }); });
|
||||||
|
|
||||||
// Retrieve the list of available trainings
|
// Retrieve the list of available trainings
|
||||||
Training.query().$promise.then(function (data) {
|
Training.query().$promise.then(function (data) {
|
||||||
@ -1118,8 +1118,8 @@ Application.Controllers.controller('ImportMembersResultController', ['$scope', '
|
|||||||
/**
|
/**
|
||||||
* Controller used in the admin creation page (admin view)
|
* Controller used in the admin creation page (admin view)
|
||||||
*/
|
*/
|
||||||
Application.Controllers.controller('NewAdminController', ['$state', '$scope', 'Admin', 'growl', '_t', 'settingsPromise',
|
Application.Controllers.controller('NewAdminController', ['$state', '$scope', 'Admin', 'growl', '_t', 'settingsPromise', 'groupsPromise',
|
||||||
function ($state, $scope, Admin, growl, _t, settingsPromise) {
|
function ($state, $scope, Admin, growl, _t, settingsPromise, groupsPromise) {
|
||||||
// default admin profile
|
// default admin profile
|
||||||
let getGender;
|
let getGender;
|
||||||
$scope.admin = {
|
$scope.admin = {
|
||||||
@ -1145,6 +1145,9 @@ Application.Controllers.controller('NewAdminController', ['$state', '$scope', 'A
|
|||||||
// is the address required in _admin_form?
|
// is the address required in _admin_form?
|
||||||
$scope.addressRequired = (settingsPromise.address_required === 'true');
|
$scope.addressRequired = (settingsPromise.address_required === 'true');
|
||||||
|
|
||||||
|
// all available groups
|
||||||
|
$scope.groups = groupsPromise;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the birthday datepicker
|
* Shows the birthday datepicker
|
||||||
*/
|
*/
|
||||||
@ -1208,7 +1211,7 @@ Application.Controllers.controller('NewManagerController', ['$state', '$scope',
|
|||||||
};
|
};
|
||||||
|
|
||||||
// list of all groups
|
// list of all groups
|
||||||
$scope.groups = groupsPromise.filter(function (g) { return (g.slug !== 'admins') && !g.disabled; });
|
$scope.groups = groupsPromise.filter(function (g) { return !g.disabled; });
|
||||||
|
|
||||||
// list of all tags
|
// list of all tags
|
||||||
$scope.tags = tagsPromise;
|
$scope.tags = tagsPromise;
|
||||||
|
@ -27,7 +27,7 @@ class PlanController {
|
|||||||
|
|
||||||
// groups list
|
// groups list
|
||||||
$scope.groups = groups
|
$scope.groups = groups
|
||||||
.filter(function (g) { return (g.slug !== 'admins') && !g.disabled; })
|
.filter(function (g) { return !g.disabled; })
|
||||||
.map(e => Object.assign({}, e, { category: 'app.shared.plan.groups', id: `${e.id}` }));
|
.map(e => Object.assign({}, e, { category: 'app.shared.plan.groups', id: `${e.id}` }));
|
||||||
$scope.groups.push({ id: 'all', name: 'app.shared.plan.transversal_all_groups', category: 'app.shared.plan.all' });
|
$scope.groups.push({ id: 'all', name: 'app.shared.plan.transversal_all_groups', category: 'app.shared.plan.all' });
|
||||||
|
|
||||||
|
@ -30,8 +30,8 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
|||||||
$scope.enabledPlans = plans.filter(function (p) { return !p.disabled; });
|
$scope.enabledPlans = plans.filter(function (p) { return !p.disabled; });
|
||||||
|
|
||||||
// List of groups (eg. normal, student ...)
|
// List of groups (eg. normal, student ...)
|
||||||
$scope.groups = groups.filter(function (g) { return g.slug !== 'admins'; });
|
$scope.groups = groups;
|
||||||
$scope.enabledGroups = groups.filter(function (g) { return (g.slug !== 'admins') && !g.disabled; });
|
$scope.enabledGroups = groups.filter(function (g) { return !g.disabled; });
|
||||||
|
|
||||||
// List of all plan-categories
|
// List of all plan-categories
|
||||||
$scope.planCategories = planCategories;
|
$scope.planCategories = planCategories;
|
||||||
|
@ -117,9 +117,7 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
|
|||||||
// retrieve the groups (standard, student ...)
|
// retrieve the groups (standard, student ...)
|
||||||
Group.query(function (groups) {
|
Group.query(function (groups) {
|
||||||
$scope.groups = groups;
|
$scope.groups = groups;
|
||||||
$scope.enabledGroups = groups.filter(function (g) {
|
$scope.enabledGroups = groups.filter(g => !g.disabled);
|
||||||
return (g.slug !== 'admins') && !g.disabled;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// retrieve the CGU
|
// retrieve the CGU
|
||||||
|
@ -161,7 +161,7 @@ Application.Controllers.controller('EditProfileController', ['$scope', '$rootSco
|
|||||||
* Check if it is allowed the change the group of the current user
|
* Check if it is allowed the change the group of the current user
|
||||||
*/
|
*/
|
||||||
$scope.isAllowedChangingGroup = function () {
|
$scope.isAllowedChangingGroup = function () {
|
||||||
return !$scope.user.subscribed_plan?.name && $scope.user.role !== 'admin';
|
return !$scope.user.subscribed_plan?.name;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { ApiFilter } from './api';
|
import { ApiFilter } from './api';
|
||||||
|
|
||||||
export interface GroupIndexFilter extends ApiFilter {
|
export interface GroupIndexFilter extends ApiFilter {
|
||||||
disabled?: boolean,
|
disabled?: boolean
|
||||||
admins?: boolean,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Group {
|
export interface Group {
|
||||||
|
@ -1001,7 +1001,8 @@ angular.module('application.router', ['ui.router'])
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['phone_required', 'address_required']" }).$promise; }]
|
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['phone_required', 'address_required']" }).$promise; }],
|
||||||
|
groupsPromise: ['Group', function (Group) { return Group.query({ disabled: false }).$promise; }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('app.admin.managers_new', {
|
.state('app.admin.managers_new', {
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
<i class="fa fa-times"></i>
|
<i class="fa fa-times"></i>
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<div class="buttons" ng-hide="rowform.$visible || group.slug === 'admins'">
|
<div class="buttons" ng-hide="rowform.$visible">
|
||||||
<button class="btn btn-default" ng-click="rowform.$show()">
|
<button class="btn btn-default" ng-click="rowform.$show()">
|
||||||
<i class="fa fa-edit"></i> <span class="hidden-xs hidden-sm" translate>{{ 'app.shared.buttons.edit' }}</span>
|
<i class="fa fa-edit"></i> <span class="hidden-xs hidden-sm" translate>{{ 'app.shared.buttons.edit' }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
@ -119,6 +119,19 @@
|
|||||||
ng-required="phoneRequired">
|
ng-required="phoneRequired">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group" ng-class="{'has-error': adminForm['admin[group_id]'].$dirty && adminForm['admin[group_id]'].$invalid}">
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-addon"><i class="fa fa-group"></i> <span class="exponent"><i class="fa fa-asterisk" aria-hidden="true"></i></span></span>
|
||||||
|
<select ng-model="admin.group_id"
|
||||||
|
name="admin[group_id]"
|
||||||
|
class="form-control"
|
||||||
|
id="group_id"
|
||||||
|
required
|
||||||
|
ng-options="g.id as g.name for g in groups">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,17 +2,15 @@
|
|||||||
|
|
||||||
# Group is way to bind users with prices. Different prices can be defined for each plan/reservable, for each group
|
# Group is way to bind users with prices. Different prices can be defined for each plan/reservable, for each group
|
||||||
class Group < ApplicationRecord
|
class Group < ApplicationRecord
|
||||||
has_many :plans
|
has_many :plans, dependent: :destroy
|
||||||
has_many :users
|
has_many :users, dependent: :nullify
|
||||||
has_many :statistic_profiles
|
has_many :statistic_profiles, dependent: :nullify
|
||||||
has_many :trainings_pricings, dependent: :destroy
|
has_many :trainings_pricings, dependent: :destroy
|
||||||
has_many :machines_prices, -> { where(priceable_type: 'Machine') }, class_name: 'Price', dependent: :destroy
|
has_many :machines_prices, -> { where(priceable_type: 'Machine') }, class_name: 'Price', dependent: :destroy, inverse_of: :group
|
||||||
has_many :spaces_prices, -> { where(priceable_type: 'Space') }, class_name: 'Price', dependent: :destroy
|
has_many :spaces_prices, -> { where(priceable_type: 'Space') }, class_name: 'Price', dependent: :destroy, inverse_of: :group
|
||||||
has_many :proof_of_identity_types_groups, dependent: :destroy
|
has_many :proof_of_identity_types_groups, dependent: :destroy
|
||||||
has_many :proof_of_identity_types, through: :proof_of_identity_types_groups
|
has_many :proof_of_identity_types, through: :proof_of_identity_types_groups
|
||||||
|
|
||||||
scope :all_except_admins, -> { where.not(slug: 'admins') }
|
|
||||||
|
|
||||||
extend FriendlyId
|
extend FriendlyId
|
||||||
friendly_id :name, use: :slugged
|
friendly_id :name, use: :slugged
|
||||||
|
|
||||||
@ -41,26 +39,26 @@ class Group < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def create_trainings_pricings
|
def create_trainings_pricings
|
||||||
Training.all.each do |training|
|
Training.find_each do |training|
|
||||||
TrainingsPricing.create(group: self, training: training, amount: 0)
|
TrainingsPricing.create(group: self, training: training, amount: 0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_machines_prices
|
def create_machines_prices
|
||||||
Machine.all.each do |machine|
|
Machine.find_each do |machine|
|
||||||
Price.create(priceable: machine, group: self, amount: 0)
|
Price.create(priceable: machine, group: self, amount: 0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_spaces_prices
|
def create_spaces_prices
|
||||||
Space.all.each do |space|
|
Space.find_each do |space|
|
||||||
Price.create(priceable: space, group: self, amount: 0)
|
Price.create(priceable: space, group: self, amount: 0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_statistic_subtype
|
def create_statistic_subtype
|
||||||
user_index = StatisticIndex.find_by(es_type_key: 'user')
|
user_index = StatisticIndex.find_by(es_type_key: 'user')
|
||||||
StatisticSubType.create!( statistic_types: user_index.statistic_types, key: slug, label: name)
|
StatisticSubType.create!(statistic_types: user_index.statistic_types, key: slug, label: name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_statistic_subtype
|
def update_statistic_subtype
|
||||||
@ -74,7 +72,7 @@ class Group < ApplicationRecord
|
|||||||
|
|
||||||
def disable_plans
|
def disable_plans
|
||||||
plans.each do |plan|
|
plans.each do |plan|
|
||||||
plan.update_attributes(disabled: disabled)
|
plan.update(disabled: disabled)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -7,13 +7,13 @@ class Plan < ApplicationRecord
|
|||||||
belongs_to :plan_category
|
belongs_to :plan_category
|
||||||
|
|
||||||
has_many :credits, dependent: :destroy
|
has_many :credits, dependent: :destroy
|
||||||
has_many :training_credits, -> { where(creditable_type: 'Training') }, class_name: 'Credit'
|
has_many :training_credits, -> { where(creditable_type: 'Training') }, class_name: 'Credit', dependent: :destroy, inverse_of: :plan
|
||||||
has_many :machine_credits, -> { where(creditable_type: 'Machine') }, class_name: 'Credit'
|
has_many :machine_credits, -> { where(creditable_type: 'Machine') }, class_name: 'Credit', dependent: :destroy, inverse_of: :plan
|
||||||
has_many :space_credits, -> { where(creditable_type: 'Space') }, class_name: 'Credit'
|
has_many :space_credits, -> { where(creditable_type: 'Space') }, class_name: 'Credit', dependent: :destroy, inverse_of: :plan
|
||||||
has_many :subscriptions
|
has_many :subscriptions, dependent: :nullify
|
||||||
has_one :plan_file, as: :viewable, dependent: :destroy
|
has_one :plan_file, as: :viewable, dependent: :destroy
|
||||||
has_many :prices, dependent: :destroy
|
has_many :prices, dependent: :destroy
|
||||||
has_one :payment_gateway_object, as: :item
|
has_one :payment_gateway_object, as: :item, dependent: :destroy
|
||||||
|
|
||||||
extend FriendlyId
|
extend FriendlyId
|
||||||
friendly_id :base_name, use: :slugged
|
friendly_id :base_name, use: :slugged
|
||||||
@ -37,7 +37,7 @@ class Plan < ApplicationRecord
|
|||||||
|
|
||||||
def self.create_for_all_groups(plan_params)
|
def self.create_for_all_groups(plan_params)
|
||||||
plans = []
|
plans = []
|
||||||
Group.all_except_admins.each do |group|
|
Group.find_each do |group|
|
||||||
plan = if plan_params[:type] == 'PartnerPlan'
|
plan = if plan_params[:type] == 'PartnerPlan'
|
||||||
PartnerPlan.new(plan_params.except(:group_id, :type))
|
PartnerPlan.new(plan_params.except(:group_id, :type))
|
||||||
else
|
else
|
||||||
@ -59,14 +59,14 @@ class Plan < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def create_machines_prices
|
def create_machines_prices
|
||||||
Machine.all.each do |machine|
|
Machine.all.find_each do |machine|
|
||||||
default_price = Price.find_by(priceable: machine, plan: nil, group_id: group_id)&.amount || 0
|
default_price = Price.find_by(priceable: machine, plan: nil, group_id: group_id)&.amount || 0
|
||||||
Price.create(priceable: machine, plan: self, group_id: group_id, amount: default_price)
|
Price.create(priceable: machine, plan: self, group_id: group_id, amount: default_price)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_spaces_prices
|
def create_spaces_prices
|
||||||
Space.all.each do |space|
|
Space.all.find_each do |space|
|
||||||
default_price = Price.find_by(priceable: space, plan: nil, group_id: group_id)&.amount || 0
|
default_price = Price.find_by(priceable: space, plan: nil, group_id: group_id)&.amount || 0
|
||||||
Price.create(priceable: space, plan: self, group_id: group_id, amount: default_price)
|
Price.create(priceable: space, plan: self, group_id: group_id, amount: default_price)
|
||||||
end
|
end
|
||||||
@ -123,12 +123,12 @@ class Plan < ApplicationRecord
|
|||||||
StatisticTypeSubType.create!(statistic_type: stat_type, statistic_sub_type: stat_subtype)
|
StatisticTypeSubType.create!(statistic_type: stat_type, statistic_sub_type: stat_subtype)
|
||||||
else
|
else
|
||||||
Rails.logger.error 'Unable to create the statistics association for the new plan. ' \
|
Rails.logger.error 'Unable to create the statistics association for the new plan. ' \
|
||||||
'Possible causes: the type or the subtype were not created successfully.'
|
'Possible causes: the type or the subtype were not created successfully.'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_name
|
def set_name
|
||||||
update_columns(name: human_readable_name)
|
update_columns(name: human_readable_name) # rubocop:disable Rails/SkipsModelValidations
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_gateway_product
|
def update_gateway_product
|
||||||
|
@ -8,11 +8,11 @@ class Subscription < ApplicationRecord
|
|||||||
belongs_to :statistic_profile
|
belongs_to :statistic_profile
|
||||||
|
|
||||||
has_one :payment_schedule_object, as: :object, dependent: :destroy
|
has_one :payment_schedule_object, as: :object, dependent: :destroy
|
||||||
has_one :payment_gateway_object, as: :item
|
has_one :payment_gateway_object, as: :item, dependent: :destroy
|
||||||
has_many :invoice_items, as: :object, dependent: :destroy
|
has_many :invoice_items, as: :object, dependent: :destroy
|
||||||
has_many :offer_days, dependent: :destroy
|
has_many :offer_days, dependent: :destroy
|
||||||
|
|
||||||
validates_presence_of :plan_id
|
validates :plan_id, presence: true
|
||||||
validates_with SubscriptionGroupValidator
|
validates_with SubscriptionGroupValidator
|
||||||
|
|
||||||
# creation
|
# creation
|
||||||
@ -21,18 +21,20 @@ class Subscription < ApplicationRecord
|
|||||||
after_save :notify_admin_subscribed_plan
|
after_save :notify_admin_subscribed_plan
|
||||||
after_save :notify_partner_subscribed_plan, if: :of_partner_plan?
|
after_save :notify_partner_subscribed_plan, if: :of_partner_plan?
|
||||||
|
|
||||||
|
delegate :user, to: :statistic_profile
|
||||||
|
|
||||||
def generate_and_save_invoice(operator_profile_id)
|
def generate_and_save_invoice(operator_profile_id)
|
||||||
generate_invoice(operator_profile_id).save
|
generate_invoice(operator_profile_id).save
|
||||||
end
|
end
|
||||||
|
|
||||||
def expire(time)
|
def expire(time)
|
||||||
if !expired?
|
if expired?
|
||||||
update_columns(expiration_date: time, canceled_at: time)
|
false
|
||||||
|
else
|
||||||
|
update_columns(expiration_date: time, canceled_at: time) # rubocop:disable Rails/SkipsModelValidations
|
||||||
notify_admin_subscription_canceled
|
notify_admin_subscription_canceled
|
||||||
notify_member_subscription_canceled
|
notify_member_subscription_canceled
|
||||||
true
|
true
|
||||||
else
|
|
||||||
false
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -47,10 +49,6 @@ class Subscription < ApplicationRecord
|
|||||||
expiration_date
|
expiration_date
|
||||||
end
|
end
|
||||||
|
|
||||||
def user
|
|
||||||
statistic_profile.user
|
|
||||||
end
|
|
||||||
|
|
||||||
def original_payment_schedule
|
def original_payment_schedule
|
||||||
payment_schedule_object&.payment_schedule
|
payment_schedule_object&.payment_schedule
|
||||||
end
|
end
|
||||||
|
@ -2,20 +2,14 @@
|
|||||||
|
|
||||||
# Provides methods for Groups
|
# Provides methods for Groups
|
||||||
class GroupService
|
class GroupService
|
||||||
def self.list(operator, filters = {})
|
def self.list(filters = {})
|
||||||
groups = if operator&.admin?
|
groups = Group.where(nil)
|
||||||
Group.where(nil)
|
|
||||||
else
|
|
||||||
Group.where.not(slug: 'admins')
|
|
||||||
end
|
|
||||||
|
|
||||||
if filters[:disabled].present?
|
if filters[:disabled].present?
|
||||||
state = filters[:disabled] == 'false' ? [nil, false] : true
|
state = filters[:disabled] == 'false' ? [nil, false] : true
|
||||||
groups = groups.where(disabled: state)
|
groups = groups.where(disabled: state)
|
||||||
end
|
end
|
||||||
|
|
||||||
groups = groups.where.not(slug: 'admins') if filters[:admins] == 'false'
|
|
||||||
|
|
||||||
groups
|
groups
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -15,12 +15,6 @@ class Members::MembersService
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
if admin_group_change?(params)
|
|
||||||
# an admin cannot change his group
|
|
||||||
@member.errors.add(:group_id, I18n.t('members.admins_cant_change_group'))
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
group_changed = user_group_change?(params)
|
group_changed = user_group_change?(params)
|
||||||
ex_group = @member.group
|
ex_group = @member.group
|
||||||
|
|
||||||
@ -130,9 +124,7 @@ class Members::MembersService
|
|||||||
@member.remove_role ex_role
|
@member.remove_role ex_role
|
||||||
@member.add_role new_role
|
@member.add_role new_role
|
||||||
|
|
||||||
# if the new role is 'admin', then change the group to the admins group, otherwise to change to the provided group
|
@member.update(group_id: new_group_id)
|
||||||
group_id = new_role == 'admin' ? Group.find_by(slug: 'admins').id : new_group_id
|
|
||||||
@member.update(group_id: group_id)
|
|
||||||
|
|
||||||
# notify
|
# notify
|
||||||
NotificationCenter.call type: 'notify_user_role_update',
|
NotificationCenter.call type: 'notify_user_role_update',
|
||||||
@ -176,10 +168,6 @@ class Members::MembersService
|
|||||||
params[:group_id] && @member.group_id != params[:group_id].to_i && !@member.subscribed_plan.nil?
|
params[:group_id] && @member.group_id != params[:group_id].to_i && !@member.subscribed_plan.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
def admin_group_change?(params)
|
|
||||||
params[:group_id] && params[:group_id].to_i != Group.find_by(slug: 'admins').id && @member.admin?
|
|
||||||
end
|
|
||||||
|
|
||||||
def user_group_change?(params)
|
def user_group_change?(params)
|
||||||
@member.group_id && params[:group_id] && @member.group_id != params[:group_id].to_i
|
@member.group_id && params[:group_id] && @member.group_id != params[:group_id].to_i
|
||||||
end
|
end
|
||||||
|
@ -36,9 +36,6 @@ class UserService
|
|||||||
admin = User.new(params.merge(password: generated_password))
|
admin = User.new(params.merge(password: generated_password))
|
||||||
admin.send :set_slug
|
admin.send :set_slug
|
||||||
|
|
||||||
# we associate the admin group to prevent linking any other 'normal' group (which won't be deletable afterwards)
|
|
||||||
admin.group = Group.find_by(slug: 'admins')
|
|
||||||
|
|
||||||
# if the authentication is made through an SSO, generate a migration token
|
# if the authentication is made through an SSO, generate a migration token
|
||||||
admin.generate_auth_migration_token unless AuthProvider.active.providable_type == DatabaseProvider.name
|
admin.generate_auth_migration_token unless AuthProvider.active.providable_type == DatabaseProvider.name
|
||||||
|
|
||||||
|
@ -2,18 +2,16 @@
|
|||||||
|
|
||||||
ActiveRecord::Base.class_eval do
|
ActiveRecord::Base.class_eval do
|
||||||
def dump_fixture
|
def dump_fixture
|
||||||
fixture_file = "#{Rails.root}/test/fixtures/#{self.class.table_name}.yml"
|
fixture_file = Rails.root.join("/test/fixtures/#{self.class.table_name}.yml")
|
||||||
File.open(fixture_file, 'a') do |f|
|
File.open(fixture_file, 'a') do |f|
|
||||||
f.puts({ "#{self.class.table_name.singularize}_#{id}" => attributes }.
|
f.puts({ "#{self.class.table_name.singularize}_#{id}" => attributes }.to_yaml.sub!(/---\s?/, "\n"))
|
||||||
to_yaml.sub!(/---\s?/, "\n"))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.dump_fixtures
|
def self.dump_fixtures
|
||||||
fixture_file = "#{Rails.root}/test/fixtures/#{table_name}.yml"
|
fixture_file = Rails.root.join("/test/fixtures/#{table_name}.yml")
|
||||||
mode = (File.exist?(fixture_file) ? 'a' : 'w')
|
mode = (File.exist?(fixture_file) ? 'a' : 'w')
|
||||||
File.open(fixture_file, mode) do |f|
|
File.open(fixture_file, mode) do |f|
|
||||||
|
|
||||||
if attribute_names.include?('id')
|
if attribute_names.include?('id')
|
||||||
all.each do |instance|
|
all.each do |instance|
|
||||||
f.puts({ "#{table_name.singularize}_#{instance.id}" => instance.attributes }.to_yaml.sub!(/---\s?/, "\n"))
|
f.puts({ "#{table_name.singularize}_#{instance.id}" => instance.attributes }.to_yaml.sub!(/---\s?/, "\n"))
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
# Be sure to restart your server when you modify this file.
|
|
||||||
|
|
||||||
# ActiveSupport::Reloader.to_prepare do
|
|
||||||
# ApplicationController.renderer.defaults.merge!(
|
|
||||||
# http_host: 'example.org',
|
|
||||||
# https: false
|
|
||||||
# )
|
|
||||||
# end
|
|
@ -1,39 +0,0 @@
|
|||||||
# # frozen_string_literal: true
|
|
||||||
#
|
|
||||||
# # Be sure to restart your server when you modify this file.
|
|
||||||
#
|
|
||||||
# # Version of your assets, change this if you want to expire all your assets.
|
|
||||||
# Rails.application.config.assets.version = '1.0'
|
|
||||||
#
|
|
||||||
# # allow use rails helpers in angular templates
|
|
||||||
# Rails.application.config.assets.configure do |env|
|
|
||||||
# env.context_class.class_eval do
|
|
||||||
# include ActionView::Helpers
|
|
||||||
# include Rails.application.routes.url_helpers
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# # Add additional assets to the asset load path.
|
|
||||||
# # Rails.application.config.assets.paths << Emoji.images_path
|
|
||||||
# # Add Yarn node_modules folder to the asset load path.
|
|
||||||
# Rails.application.config.assets.paths << Rails.root.join('node_modules')
|
|
||||||
#
|
|
||||||
# # Precompile additional assets.
|
|
||||||
# # application.js, application.css, and all non-JS/CSS in the app/assets
|
|
||||||
# # folder are already added.
|
|
||||||
# # Rails.application.config.assets.precompile += %w( admin.js admin.css )
|
|
||||||
#
|
|
||||||
# Rails.application.config.assets.precompile += %w[
|
|
||||||
# fontawesome-webfont.eot
|
|
||||||
# fontawesome-webfont.woff
|
|
||||||
# fontawesome-webfont.svg
|
|
||||||
# fontawesome-webfont.ttf
|
|
||||||
# ]
|
|
||||||
# Rails.application.config.assets.precompile += %w[app.printer.css]
|
|
||||||
#
|
|
||||||
# Rails.application.config.assets.precompile += %w[
|
|
||||||
# angular-i18n/angular-locale_*.js
|
|
||||||
# moment/locale/*.js
|
|
||||||
# summernote/lang/*.js
|
|
||||||
# fullcalendar/dist/lang/*.js
|
|
||||||
# ]
|
|
@ -1,7 +0,0 @@
|
|||||||
# Be sure to restart your server when you modify this file.
|
|
||||||
|
|
||||||
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
|
|
||||||
# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
|
|
||||||
|
|
||||||
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
|
|
||||||
# Rails.backtrace_cleaner.remove_silencers!
|
|
@ -8,16 +8,6 @@
|
|||||||
|
|
||||||
Rails.application.config.content_security_policy do |policy| # # If you are using webpack-dev-server then specify webpack-dev-server host
|
Rails.application.config.content_security_policy do |policy| # # If you are using webpack-dev-server then specify webpack-dev-server host
|
||||||
policy.connect_src :self, :https, :wss, 'http://localhost:3035', 'ws://localhost:3035' if Rails.env.development?
|
policy.connect_src :self, :https, :wss, 'http://localhost:3035', 'ws://localhost:3035' if Rails.env.development?
|
||||||
|
|
||||||
# policy.default_src :self, :https
|
|
||||||
# policy.font_src :self, :https, :data
|
|
||||||
# policy.img_src :self, :https, :data
|
|
||||||
# policy.object_src :none
|
|
||||||
# policy.script_src :self, :https
|
|
||||||
# policy.style_src :self, :https
|
|
||||||
|
|
||||||
# # Specify URI for violation reports
|
|
||||||
# # policy.report_uri "/csp-violation-report-endpoint"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# If you are using UJS then enable automatic nonce generation
|
# If you are using UJS then enable automatic nonce generation
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# FriendlyId Global Configuration
|
# FriendlyId Global Configuration
|
||||||
#
|
#
|
||||||
# Use this to set up shared configuration options for your entire application.
|
# Use this to set up shared configuration options for your entire application.
|
||||||
@ -16,8 +18,7 @@ FriendlyId.defaults do |config|
|
|||||||
# undesirable to allow as slugs. Edit this list as needed for your app.
|
# undesirable to allow as slugs. Edit this list as needed for your app.
|
||||||
config.use :reserved
|
config.use :reserved
|
||||||
|
|
||||||
config.reserved_words = %w(new edit index session login logout users
|
config.reserved_words = %w[new edit index session login logout users stylesheets assets javascripts images]
|
||||||
stylesheets assets javascripts images)
|
|
||||||
|
|
||||||
# ## Friendly Finders
|
# ## Friendly Finders
|
||||||
#
|
#
|
||||||
|
@ -2,14 +2,15 @@
|
|||||||
|
|
||||||
# Be sure to restart your server when you modify this file.
|
# Be sure to restart your server when you modify this file.
|
||||||
|
|
||||||
redis_host = ENV['REDIS_HOST'] || 'localhost'
|
redis_host = ENV.fetch('REDIS_HOST', 'localhost')
|
||||||
|
|
||||||
Rails.application.config.session_store :redis_session_store,
|
Rails.application.config.session_store :redis_session_store,
|
||||||
redis: {
|
redis: {
|
||||||
expire_after: 14.days, # cookie expiration
|
expire_after: 14.days, # cookie expiration
|
||||||
ttl: 14.days, # Redis expiration, defaults to 'expire_after'
|
ttl: 14.days, # Redis expiration, defaults to 'expire_after'
|
||||||
key_prefix: 'fabmanager:session:',
|
key_prefix: 'fabmanager:session:',
|
||||||
url: "redis://#{redis_host}:6379",
|
url: "redis://#{redis_host}:6379"
|
||||||
},
|
},
|
||||||
key: '_Fab-manager_session',
|
key: '_Fab-manager_session',
|
||||||
secure: (Rails.env.production? || Rails.env.staging?) && !Rails.application.secrets.allow_insecure_http
|
secure: (Rails.env.production? || Rails.env.staging?) &&
|
||||||
|
!Rails.application.secrets.allow_insecure_http
|
||||||
|
@ -5,7 +5,7 @@ require 'sidekiq-scheduler'
|
|||||||
require 'sidekiq/middleware/i18n'
|
require 'sidekiq/middleware/i18n'
|
||||||
require 'sidekiq/server_locale'
|
require 'sidekiq/server_locale'
|
||||||
|
|
||||||
redis_host = ENV['REDIS_HOST'] || 'localhost'
|
redis_host = ENV.fetch('REDIS_HOST', 'localhost')
|
||||||
redis_url = "redis://#{redis_host}:6379"
|
redis_url = "redis://#{redis_host}:6379"
|
||||||
|
|
||||||
Sidekiq.configure_server do |config|
|
Sidekiq.configure_server do |config|
|
||||||
|
@ -57,7 +57,6 @@ en:
|
|||||||
#members management
|
#members management
|
||||||
members:
|
members:
|
||||||
unable_to_change_the_group_while_a_subscription_is_running: "Unable to change the group while a subscription is running"
|
unable_to_change_the_group_while_a_subscription_is_running: "Unable to change the group while a subscription is running"
|
||||||
admins_cant_change_group: "Unable to remove an administrator from his dedicated group"
|
|
||||||
please_input_the_authentication_code_sent_to_the_address: "Please input the authentication code sent to the e-mail address %{EMAIL}"
|
please_input_the_authentication_code_sent_to_the_address: "Please input the authentication code sent to the e-mail address %{EMAIL}"
|
||||||
your_authentication_code_is_not_valid: "Your authentication code is not valid."
|
your_authentication_code_is_not_valid: "Your authentication code is not valid."
|
||||||
current_authentication_method_no_code: "The current authentication method does not require any migration code"
|
current_authentication_method_no_code: "The current authentication method does not require any migration code"
|
||||||
|
@ -12,7 +12,9 @@ namespace :fablab do
|
|||||||
|
|
||||||
desc 'add missing VAT rate to history'
|
desc 'add missing VAT rate to history'
|
||||||
task :add_vat_rate, %i[rate date] => :environment do |_task, args|
|
task :add_vat_rate, %i[rate date] => :environment do |_task, args|
|
||||||
raise 'Missing argument. Usage exemple: rails fablab:setup:add_vat_rate[20,2014-01-01]. Use 0 to disable' unless args.rate && args.date
|
unless args.rate && args.date
|
||||||
|
raise 'Missing argument. Usage exemple: rails fablab:setup:add_vat_rate[20,2014-01-01]. Use 0 to disable'
|
||||||
|
end
|
||||||
|
|
||||||
if args.rate == '0'
|
if args.rate == '0'
|
||||||
setting = Setting.find_by(name: 'invoice_VAT-active')
|
setting = Setting.find_by(name: 'invoice_VAT-active')
|
||||||
@ -116,6 +118,8 @@ namespace :fablab do
|
|||||||
admin.update(group_id: select_group(groups))
|
admin.update(group_id: select_group(groups))
|
||||||
PaymentGatewayService.new.create_user(admin.id)
|
PaymentGatewayService.new.create_user(admin.id)
|
||||||
end
|
end
|
||||||
|
print "\e[91m::\e[0m \e[1mRemoving the 'admins' group...\e[0m\n"
|
||||||
|
Group.find_by(slug: 'admins').destroy
|
||||||
print "\e[32m✅\e[0m \e[1mDone\e[0m\n"
|
print "\e[32m✅\e[0m \e[1mDone\e[0m\n"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user