diff --git a/app/assets/javascripts/controllers/admin/members.js.erb b/app/assets/javascripts/controllers/admin/members.js.erb index fad467431..babdcf8b7 100644 --- a/app/assets/javascripts/controllers/admin/members.js.erb +++ b/app/assets/javascripts/controllers/admin/members.js.erb @@ -579,7 +579,11 @@ Application.Controllers.controller('NewMemberController', ['$scope', '$state', ' $scope.password = { change: false }; // Default member's profile parameters - $scope.user = { plan_interval: '' }; + $scope.user = { + plan_interval: '', + invoicing_profile: {}, + statistic_profile: {} + }; // Callback when the admin check/uncheck the box telling that the new user is an organization. // Disable or enable the organization fields in the form, accordingly diff --git a/app/assets/templates/shared/_member_form.html.erb b/app/assets/templates/shared/_member_form.html.erb index f83b1a50f..c9649a271 100644 --- a/app/assets/templates/shared/_member_form.html.erb +++ b/app/assets/templates/shared/_member_form.html.erb @@ -3,6 +3,7 @@ +
@@ -44,7 +45,7 @@ name="user[statistic_profile_attributes][gender]" ng-model="user.statistic_profile.gender" value="true" - ng-disabled="preventField['profile.gender'] && user.profile.gender && !userForm['user[statistic_profile_attributes][gender]'].$dirty" + ng-disabled="preventField['profile.gender'] && user.statistic_profile.gender && !userForm['user[statistic_profile_attributes][gender]'].$dirty" required/> {{ 'man' | translate }} @@ -53,7 +54,7 @@ name="user[statistic_profile_attributes][gender]" ng-model="user.statistic_profile.gender" value="false" - ng-disabled="preventField['profile.gender'] && user.profile.gender && !userForm['user[statistic_profile_attributes][gender]'].$dirty"/> + ng-disabled="preventField['profile.gender'] && user.statistic_profile.gender && !userForm['user[statistic_profile_attributes][gender]'].$dirty"/> {{ 'woman' | translate }} diff --git a/app/controllers/api/members_controller.rb b/app/controllers/api/members_controller.rb index ba659ff74..7b0a19a8c 100644 --- a/app/controllers/api/members_controller.rb +++ b/app/controllers/api/members_controller.rb @@ -189,21 +189,20 @@ class API::MembersController < API::ApiController def user_params if current_user.id == params[:id].to_i - params.require(:user).permit(:username, :email, :password, :password_confirmation, :group_id, :is_allow_contact, - :is_allow_newsletter, + params.require(:user).permit(:username, :email, :password, :password_confirmation, :group_id, :is_allow_contact, :is_allow_newsletter, profile_attributes: [:id, :first_name, :last_name, :phone, :interest, :software_mastered, :website, :job, :facebook, :twitter, :google_plus, :viadeo, :linkedin, :instagram, :youtube, :vimeo, :dailymotion, :github, :echosciences, :pinterest, :lastfm, :flickr, user_avatar_attributes: %i[id attachment destroy]], invoicing_profile_attributes: [ + :id, address_attributes: %i[id address], organization_attributes: [:id, :name, address_attributes: %i[id address]] ], statistic_profile_attributes: %i[id gender birthday]) elsif current_user.admin? - params.require(:user).permit(:username, :email, :password, :password_confirmation, - :is_allow_contact, :is_allow_newsletter, :group_id, + params.require(:user).permit(:username, :email, :password, :password_confirmation, :is_allow_contact, :is_allow_newsletter, :group_id, training_ids: [], tag_ids: [], profile_attributes: [:id, :first_name, :last_name, :phone, :interest, :software_mastered, :website, :job, :facebook, :twitter, :google_plus, :viadeo, :linkedin, :instagram, :youtube, :vimeo, diff --git a/app/models/user.rb b/app/models/user.rb index f64407028..52766483b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -61,8 +61,8 @@ class User < ActiveRecord::Base after_commit :notify_admin_when_user_is_created, on: :create after_create :init_dependencies after_update :notify_group_changed, if: :group_id_changed? - after_commit :update_invoicing_profile, if: :invoicing_data_was_modified?, on: [:update] - after_commit :update_statistic_profile, if: :statistic_data_was_modified?, on: [:update] + after_update :update_invoicing_profile, if: :invoicing_data_was_modified? + after_update :update_statistic_profile, if: :statistic_data_was_modified? attr_accessor :cgu delegate :first_name, to: :profile @@ -359,15 +359,22 @@ class User < ActiveRecord::Base end def init_dependencies - ip = InvoicingProfile.create!( - user: self, - email: email, - first_name: first_name, - last_name: last_name - ) - Wallet.create!( - invoicing_profile: ip - ) + if invoicing_profile.nil? + ip = InvoicingProfile.create!( + user: self, + email: email, + first_name: first_name, + last_name: last_name + ) + end + if wallet.nil? + ip ||= invoicing_profile + Wallet.create!( + invoicing_profile: ip + ) + end + return unless statistic_profile.nil? + StatisticProfile.create!( user: self, group_id: group_id @@ -375,7 +382,7 @@ class User < ActiveRecord::Base end def update_invoicing_profile - raise NoProfileError if user.invoicing_profile.nil? + raise NoProfileError if invoicing_profile.nil? invoicing_profile.update_attributes( email: email @@ -383,7 +390,7 @@ class User < ActiveRecord::Base end def update_statistic_profile - raise NoProfileError if user.statistic_profile.nil? + raise NoProfileError if statistic_profile.nil? statistic_profile.update_attributes( group_id: group_id diff --git a/app/policies/user_policy.rb b/app/policies/user_policy.rb index ede29d76c..0b6145d3b 100644 --- a/app/policies/user_policy.rb +++ b/app/policies/user_policy.rb @@ -2,7 +2,7 @@ class UserPolicy < ApplicationPolicy class Scope < Scope def resolve if user.admin? - scope.includes(:group, :training_credits, :machine_credits, subscriptions: [plan: [:credits]], profile: [:user_avatar]) + scope.includes(:group, :training_credits, :machine_credits, statistic_profile: [subscriptions: [plan: [:credits]]], profile: [:user_avatar]) .joins(:roles).where("users.is_active = 'true' AND roles.name = 'member'").order('users.created_at desc') else scope.includes(profile: [:user_avatar]).joins(:roles).where("users.is_active = 'true' AND roles.name = 'member'") diff --git a/app/services/members/list_service.rb b/app/services/members/list_service.rb index 24013efdf..3e67b8c60 100644 --- a/app/services/members/list_service.rb +++ b/app/services/members/list_service.rb @@ -4,17 +4,25 @@ class Members::ListService class << self def list(params) - @query = User.includes(:profile, :group, :subscriptions) + @query = User.includes(:profile, :group, :statistic_profile) .joins(:profile, :statistic_profile, :group, :roles, - 'LEFT JOIN "subscriptions" ON "subscriptions"."statistic_profile_id" = "statistic_profiles"."id" ' \ + 'LEFT JOIN ( + SELECT * + FROM "subscriptions" AS s1 + INNER JOIN ( + SELECT MAX("created_at") AS "s2_created_at", "statistic_profile_id" AS "s2_statistic_profile_id" + FROM "subscriptions" + GROUP BY "statistic_profile_id" + ) As s2 + ON "s1"."statistic_profile_id" = "s2"."s2_statistic_profile_id" + WHERE "s1"."expiration_date" > now()::date + ) AS "subscriptions" ON "subscriptions"."statistic_profile_id" = "statistic_profiles"."id" ' \ 'LEFT JOIN "plans" ON "plans"."id" = "subscriptions"."plan_id"') .where("users.is_active = 'true' AND roles.name = 'member'") .order(list_order(params)) - .page(params[:page]) - .per(params[:size]) # ILIKE => PostgreSQL case-insensitive LIKE if params[:search].size.positive? @@ -66,6 +74,8 @@ class Members::ListService def list_order(params) direction = (params[:order_by][0] == '-' ? 'DESC' : 'ASC') order_key = (params[:order_by][0] == '-' ? params[:order_by][1, params[:order_by].size] : params[:order_by]) + limit = params[:size] + offset = (params[:page]&.to_i || 1) - 1 order_key = case order_key when 'last_name' @@ -84,7 +94,7 @@ class Members::ListService 'users.id' end - "#{order_key} #{direction}" + "#{order_key} #{direction} LIMIT #{limit} OFFSET #{offset}" end end end diff --git a/app/views/api/members/_member.json.jbuilder b/app/views/api/members/_member.json.jbuilder index f3970073a..408957f45 100644 --- a/app/views/api/members/_member.json.jbuilder +++ b/app/views/api/members/_member.json.jbuilder @@ -47,6 +47,7 @@ json.invoicing_profile do end json.statistic_profile do + json.id member.statistic_profile.id json.gender member.statistic_profile.gender.to_s json.birthday member.statistic_profile&.birthday&.to_date&.iso8601 end diff --git a/app/views/api/members/index.json.jbuilder b/app/views/api/members/index.json.jbuilder index 86fedaa75..d6ea24324 100644 --- a/app/views/api/members/index.json.jbuilder +++ b/app/views/api/members/index.json.jbuilder @@ -25,11 +25,11 @@ json.array!(@members) do |member| end json.first_name member.profile.first_name json.last_name member.profile.last_name - json.gender member.statistic_profile.gender.to_s + json.phone member.profile.phone end if user_is_admin json.statistic_profile do - json.phone member.statistic_profile.phone + json.gender member.statistic_profile.gender.to_s json.birthday member.statistic_profile&.birthday&.iso8601 end end diff --git a/app/views/api/notifications/_notify_admin_user_group_changed.json.jbuilder b/app/views/api/notifications/_notify_admin_user_group_changed.json.jbuilder index 179eaeae4..30093c2c5 100644 --- a/app/views/api/notifications/_notify_admin_user_group_changed.json.jbuilder +++ b/app/views/api/notifications/_notify_admin_user_group_changed.json.jbuilder @@ -2,6 +2,6 @@ json.title notification.notification_type json.description _t('.user_NAME_changed_his_group_html', { NAME: notification.attached_object.profile.full_name, - GENDER: bool_to_sym(notification.attached_object.profile.gender) + GENDER: bool_to_sym(notification.attached_object.statistic_profile.gender) }) # messageFormat json.url notification_url(notification, format: :json) diff --git a/app/views/api/notifications/_notify_admin_user_merged.json.jbuilder b/app/views/api/notifications/_notify_admin_user_merged.json.jbuilder index 62433d938..9409ec4ec 100644 --- a/app/views/api/notifications/_notify_admin_user_merged.json.jbuilder +++ b/app/views/api/notifications/_notify_admin_user_merged.json.jbuilder @@ -2,7 +2,7 @@ json.title notification.notification_type json.description _t('.user_NAME_has_merged_his_account_with_the_one_imported_from_PROVIDER_UID_html', { NAME: notification.attached_object.profile.full_name, - GENDER: bool_to_sym(notification.attached_object.profile.gender), + GENDER: bool_to_sym(notification.attached_object.statistic_profile.gender), PROVIDER: notification.attached_object.provider, UID: notification.attached_object.uid }) # messageFormat diff --git a/app/views/exports/users_members.xlsx.axlsx b/app/views/exports/users_members.xlsx.axlsx index 2686e18b3..d07315c7d 100644 --- a/app/views/exports/users_members.xlsx.axlsx +++ b/app/views/exports/users_members.xlsx.axlsx @@ -42,7 +42,7 @@ wb.add_worksheet(name: t('export_members.members')) do |sheet| member.profile.first_name, member.email, member.is_allow_newsletter, - member.profile.gender ? t('export_members.man') : t('export_members.woman'), + member.statistic_profile.gender ? t('export_members.man') : t('export_members.woman'), member.profile.age, member.invoicing_profile.address ? member.invoicing_profile.address.address : '', member.profile.phone, diff --git a/doc/postgresql_readme.md b/doc/postgresql_readme.md index aa593bfaf..751980ed6 100644 --- a/doc/postgresql_readme.md +++ b/doc/postgresql_readme.md @@ -42,12 +42,12 @@ This can be achieved doing the following: ## Using another DBMS Some users may want to use another DBMS than PostgreSQL. This is currently not supported, because of some PostgreSQL specific instructions that cannot be efficiently handled with the ActiveRecord ORM: - - `app/controllers/api/members_controllers.rb@list` is using `ILIKE` - - `app/controllers/api/invoices_controllers.rb@list` is using `ILIKE` and `date_trunc()` + - `app/services/members/list_service.rb@list` is using `ILIKE`, `now()::date` and `OFFSET`. + - `app/services/invoices_service.rb@list` is using `ILIKE` and `date_trunc()` - `db/migrate/20160613093842_create_unaccent_function.rb` is using [unaccent](https://www.postgresql.org/docs/current/static/unaccent.html) and [trigram](https://www.postgresql.org/docs/current/static/pgtrgm.html) modules and defines a PL/pgSQL function (`f_unaccent()`) - `app/controllers/api/members_controllers.rb@search` is using `f_unaccent()` (see above) and `regexp_replace()` - `db/migrate/20150604131525_add_meta_data_to_notifications.rb` is using [jsonb](https://www.postgresql.org/docs/9.4/static/datatype-json.html), a PostgreSQL 9.4+ datatype. - `db/migrate/20160915105234_add_transformation_to_o_auth2_mapping.rb` is using [jsonb](https://www.postgresql.org/docs/9.4/static/datatype-json.html), a PostgreSQL 9.4+ datatype. - `db/migrate/20181217103441_migrate_settings_value_to_history_values.rb` is using `SELECT DISTINCT ON`. - `db/migrate/20190107111749_protect_accounting_periods.rb` is using `CREATE RULE` and `DROP RULE`. - - `db/migrate/20190522115230_migrate_user_to_invoicing_profile.rb` is using `CREATE RULE` and `DROP RULE`. \ No newline at end of file + - `db/migrate/20190522115230_migrate_user_to_invoicing_profile.rb` is using `CREATE RULE` and `DROP RULE`.