diff --git a/Procfile b/Procfile index 62285c3ed..f8a9f7b3c 100644 --- a/Procfile +++ b/Procfile @@ -1,3 +1,3 @@ -#web: bundle exec rails server puma -p $PORT -b0.0.0.0 +web: bundle exec rails server puma -p $PORT -b0.0.0.0 worker: bundle exec sidekiq -C ./config/sidekiq.yml mail: bundle exec mailcatcher --foreground diff --git a/app/assets/javascripts/controllers/projects.js.erb b/app/assets/javascripts/controllers/projects.js.erb index 3de0fa16d..c8e78be77 100644 --- a/app/assets/javascripts/controllers/projects.js.erb +++ b/app/assets/javascripts/controllers/projects.js.erb @@ -257,6 +257,7 @@ Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'P /* PRIVATE STATIC CONSTANTS */ // Number of projects added to the page when the user clicks on 'load more projects' + // -- dependency in app/models/project.rb const PROJECTS_PER_PAGE = 16; /* PUBLIC SCOPE */ diff --git a/app/assets/templates/admin/members/_form.html.erb b/app/assets/templates/admin/members/_form.html.erb index 9d81a9a60..a6d9fc7d6 100644 --- a/app/assets/templates/admin/members/_form.html.erb +++ b/app/assets/templates/admin/members/_form.html.erb @@ -14,11 +14,11 @@
- + - + diff --git a/app/controllers/api/availabilities_controller.rb b/app/controllers/api/availabilities_controller.rb index b3e6aa8fa..f9e98f5c1 100644 --- a/app/controllers/api/availabilities_controller.rb +++ b/app/controllers/api/availabilities_controller.rb @@ -23,8 +23,8 @@ class API::AvailabilitiesController < API::ApiController def public start_date = ActiveSupport::TimeZone[params[:timezone]].parse(params[:start]) end_date = ActiveSupport::TimeZone[params[:timezone]].parse(params[:end]).end_of_day - @reservations = Reservation.includes(:slots, user: [:profile]) - .references(:slots, :user) + @reservations = Reservation.includes(:slots, :statistic_profile) + .references(:slots) .where('slots.start_at >= ? AND slots.end_at <= ?', start_date, end_date) machine_ids = params[:m] || [] @@ -93,7 +93,7 @@ class API::AvailabilitiesController < API::ApiController def reservations authorize Availability - @reservation_slots = @availability.slots.includes(reservations: [user: [:profile]]).order('slots.start_at ASC') + @reservation_slots = @availability.slots.includes(reservations: [statistic_profile: [user: [:profile]]]).order('slots.start_at ASC') end def export_availabilities diff --git a/app/controllers/api/members_controller.rb b/app/controllers/api/members_controller.rb index 7b0a19a8c..47c32369a 100644 --- a/app/controllers/api/members_controller.rb +++ b/app/controllers/api/members_controller.rb @@ -203,7 +203,7 @@ class API::MembersController < API::ApiController elsif current_user.admin? params.require(:user).permit(:username, :email, :password, :password_confirmation, :is_allow_contact, :is_allow_newsletter, :group_id, - training_ids: [], tag_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, :dailymotion, :github, :echosciences, :pinterest, :lastfm, :flickr, @@ -213,7 +213,7 @@ class API::MembersController < API::ApiController address_attributes: %i[id address], organization_attributes: [:id, :name, address_attributes: %i[id address]] ], - statistic_profile_attributes: %i[id gender birthday]) + statistic_profile_attributes: [:id, :gender, :birthday, training_ids: []]) end end diff --git a/app/controllers/api/prices_controller.rb b/app/controllers/api/prices_controller.rb index fc9e4384d..d23f0624d 100644 --- a/app/controllers/api/prices_controller.rb +++ b/app/controllers/api/prices_controller.rb @@ -41,8 +41,8 @@ class API::PricesController < API::ApiController # user user = User.find(price_parameters[:user_id]) # reservable - if price_parameters[:reservable_id].nil? - @amount = {elements: nil, total: 0, before_coupon: 0} + if [nil, ''].include? price_parameters[:reservable_id] + @amount = { elements: nil, total: 0, before_coupon: 0 } else reservable = price_parameters[:reservable_type].constantize.find(price_parameters[:reservable_id]) @amount = Price.compute(current_user.admin?, diff --git a/app/controllers/api/projects_controller.rb b/app/controllers/api/projects_controller.rb index 126bb382c..adf27a948 100644 --- a/app/controllers/api/projects_controller.rb +++ b/app/controllers/api/projects_controller.rb @@ -20,7 +20,7 @@ class API::ProjectsController < API::ApiController end def create - @project = Project.new(project_params.merge(author_id: current_user.id)) + @project = Project.new(project_params.merge(author_statistic_profile_id: current_user.statistic_profile.id)) if @project.save render :show, status: :created, location: @project else @@ -71,8 +71,7 @@ class API::ProjectsController < API::ApiController end def project_params - params.require(:project).permit(:name, :description, :tags, :machine_ids, :component_ids, :theme_ids, :licence_id, - :author_id, :licence_id, :state, + params.require(:project).permit(:name, :description, :tags, :machine_ids, :component_ids, :theme_ids, :licence_id, :licence_id, :state, user_ids: [], machine_ids: [], component_ids: [], theme_ids: [], project_image_attributes: [:attachment], project_caos_attributes: %i[id attachment _destroy], diff --git a/app/controllers/api/trainings_controller.rb b/app/controllers/api/trainings_controller.rb index 36cc7b96d..e7ef567f9 100644 --- a/app/controllers/api/trainings_controller.rb +++ b/app/controllers/api/trainings_controller.rb @@ -58,7 +58,7 @@ class API::TrainingsController < API::ApiController authorize Training @training = Training.find(params[:id]) @availabilities = @training.availabilities - .includes(slots: { reservations: { user: %i[profile trainings] } }) + .includes(slots: { reservations: { statistic_profile: [:trainings, user: [:profile]] } }) .order('start_at DESC') end diff --git a/app/models/availability.rb b/app/models/availability.rb index fe3b28f46..54881fa8f 100644 --- a/app/models/availability.rb +++ b/app/models/availability.rb @@ -1,3 +1,8 @@ +# frozen_string_literal: true + +# Availability stores time slots that are available to reservation for an associated reservable +# Eg. a 3D printer will be reservable on thursday from 9 to 11 pm +# Availabilities may be subdivided into Slots (of 1h), for some types of reservables (eg. Machine) class Availability < ActiveRecord::Base # elastic initialisations @@ -87,9 +92,7 @@ class Availability < ActiveRecord::Base def title(filter = {}) case available_type when 'machines' - if filter[:machine_ids] - return machines.to_ary.delete_if { |m| !filter[:machine_ids].include?(m.id) }.map(&:name).join(' - ') - end + return machines.to_ary.delete_if { |m| !filter[:machine_ids].include?(m.id) }.map(&:name).join(' - ') if filter[:machine_ids] machines.map(&:name).join(' - ') when 'event' @@ -134,13 +137,13 @@ class Availability < ActiveRecord::Base json['hours_duration'] = (end_at - start_at) / (60 * 60) json['subType'] = case available_type when 'machines' - machines_availabilities.map{ |ma| ma.machine.friendly_id } + machines_availabilities.map { |ma| ma.machine.friendly_id } when 'training' - trainings_availabilities.map{ |ta| ta.training.friendly_id } + trainings_availabilities.map { |ta| ta.training.friendly_id } when 'event' [event.category.friendly_id] when 'space' - spaces_availabilities.map{ |sa| sa.space.friendly_id } + spaces_availabilities.map { |sa| sa.space.friendly_id } else [] end @@ -156,7 +159,9 @@ class Availability < ActiveRecord::Base end def should_be_associated - errors.add(:machine_ids, I18n.t('availabilities.must_be_associated_with_at_least_1_machine')) if available_type == 'machines' && machine_ids.count == 0 + return unless available_type == 'machines' && machine_ids.count.zero? + + errors.add(:machine_ids, I18n.t('availabilities.must_be_associated_with_at_least_1_machine')) end end diff --git a/app/models/invoice.rb b/app/models/invoice.rb index 44fbf9ddf..3395536a9 100644 --- a/app/models/invoice.rb +++ b/app/models/invoice.rb @@ -13,6 +13,7 @@ class Invoice < ActiveRecord::Base has_many :invoice_items, dependent: :destroy accepts_nested_attributes_for :invoice_items belongs_to :invoicing_profile + belongs_to :statistic_profile belongs_to :wallet_transaction belongs_to :coupon diff --git a/app/models/partner_plan.rb b/app/models/partner_plan.rb index d6ee3a3f4..ef461be90 100644 --- a/app/models/partner_plan.rb +++ b/app/models/partner_plan.rb @@ -1,13 +1,18 @@ +# frozen_string_literal: true + +# A special plan associated which can be associated with some users (with role 'partner') +# These partners will be notified when the subscribers to this plan are realizing some actions class PartnerPlan < Plan resourcify before_create :assign_default_values def partners - User.joins(:roles).where(roles: { name: 'partner', resource_type: 'PartnerPlan', resource_id: self.id }) + User.joins(:roles).where(roles: { name: 'partner', resource_type: 'PartnerPlan', resource_id: id }) end private + def assign_default_values assign_attributes(is_rolling: false) end diff --git a/app/models/project.rb b/app/models/project.rb index 351cdcca3..056a86775 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1,3 +1,7 @@ +# frozen_string_literal: true + +# Project is the documentation about an object built by a fab-user +# It can describe the steps taken by the fab-user to build his object, provide photos, description, attached CAO files, etc. class Project < ActiveRecord::Base include AASM include NotifyWith::NotificationAttachedObject @@ -9,7 +13,8 @@ class Project < ActiveRecord::Base document_type 'projects' # kaminari - paginates_per 12 # dependency in projects.coffee + # -- dependency in app/assets/javascripts/controllers/projects.js.erb + paginates_per 16 # friendlyId extend FriendlyId @@ -20,15 +25,15 @@ class Project < ActiveRecord::Base has_many :project_caos, as: :viewable, dependent: :destroy accepts_nested_attributes_for :project_caos, allow_destroy: true, reject_if: :all_blank - has_and_belongs_to_many :machines, join_table: :projects_machines - has_and_belongs_to_many :spaces, join_table: :projects_spaces - has_and_belongs_to_many :components, join_table: :projects_components - has_and_belongs_to_many :themes, join_table: :projects_themes + has_and_belongs_to_many :machines, join_table: 'projects_machines' + has_and_belongs_to_many :spaces, join_table: 'projects_spaces' + has_and_belongs_to_many :components, join_table: 'projects_components' + has_and_belongs_to_many :themes, join_table: 'projects_themes' has_many :project_users, dependent: :destroy has_many :users, through: :project_users - belongs_to :author, foreign_key: :author_id, class_name: 'User' + belongs_to :author, foreign_key: :author_statistic_profile_id, class_name: 'StatisticProfile' belongs_to :licence, foreign_key: :licence_id has_many :project_steps, dependent: :destroy @@ -39,22 +44,22 @@ class Project < ActiveRecord::Base after_save :after_save_and_publish - aasm :column => 'state' do + aasm column: 'state' do state :draft, initial: true state :published - event :publish, :after => :notify_admin_when_project_published do - transitions from: :draft, :to => :published + event :publish, after: :notify_admin_when_project_published do + transitions from: :draft, to: :published end end - #scopes + # scopes scope :published, -> { where("state = 'published'") } ## elastic # callbacks - after_save { ProjectIndexerWorker.perform_async(:index, self.id) } - after_destroy { ProjectIndexerWorker.perform_async(:delete, self.id) } + after_save { ProjectIndexerWorker.perform_async(:index, id) } + after_destroy { ProjectIndexerWorker.perform_async(:delete, id) } # mapping settings index: { number_of_replicas: 0 } do @@ -64,31 +69,19 @@ class Project < ActiveRecord::Base indexes 'name', analyzer: Rails.application.secrets.elasticsearch_language_analyzer indexes 'description', analyzer: Rails.application.secrets.elasticsearch_language_analyzer indexes 'project_steps' do - indexes 'title', analyzer: Rails.application.secrets.elasticsearch_language_analyzer - indexes 'description', analyzer: Rails.application.secrets.elasticsearch_language_analyzer + indexes 'title', analyzer: Rails.application.secrets.elasticsearch_language_analyzer + indexes 'description', analyzer: Rails.application.secrets.elasticsearch_language_analyzer end end end def as_indexed_json - Jbuilder.new do |json| - json.id id - json.state state - json.author_id author_id - json.user_ids user_ids - json.machine_ids machine_ids - json.theme_ids theme_ids - json.component_ids component_ids - json.tags tags - json.name name - json.description description - json.project_steps project_steps do |project_step| - json.title project_step.title - json.description project_step.description - end - json.created_at created_at - json.updated_at updated_at - end.target! + ApplicationController.new.view_context.render( + partial: 'api/projects/indexed', + locals: { project: self }, + formats: [:json], + handlers: [:jbuilder] + ) end def self.search(params, current_user) @@ -101,43 +94,45 @@ class Project < ActiveRecord::Base bool: { must: [], should: [], - filter: [], + filter: [] } } } - if params['q'].blank? # we sort by created_at if there isn't a query + # we sort by created_at if there isn't a query + if params['q'].blank? search[:sort] = { created_at: { order: :desc } } - else # otherwise we search for the word (q) in various fields + else + # otherwise we search for the word (q) in various fields search[:query][:bool][:must] << { multi_match: { query: params['q'], type: 'most_fields', - fields: %w(tags^4 name^5 description^3 project_steps.title^2 project_steps.description) + fields: %w[tags^4 name^5 description^3 project_steps.title^2 project_steps.description] } } end - params.each do |name, value| # we filter by themes, components, machines + # we filter by themes, components, machines + params.each do |name, value| if name =~ /(.+_id$)/ search[:query][:bool][:filter] << { term: { "#{name}s" => value } } if value end end - if current_user and params.key?('from') # if use select filter 'my project' or 'my collaborations' - if params['from'] == 'mine' - search[:query][:bool][:filter] << { term: { author_id: current_user.id } } - end - if params['from'] == 'collaboration' - search[:query][:bool][:filter] << { term: { user_ids: current_user.id } } - end + # if use select filter 'my project' or 'my collaborations' + if current_user && params.key?('from') + search[:query][:bool][:filter] << { term: { author_id: current_user.id } } if params['from'] == 'mine' + search[:query][:bool][:filter] << { term: { user_ids: current_user.id } } if params['from'] == 'collaboration' end - if current_user # if user is connected, also display his draft projects + # if user is connected, also display his draft projects + if current_user search[:query][:bool][:should] << { term: { state: 'published' } } search[:query][:bool][:should] << { term: { author_id: current_user.id } } search[:query][:bool][:should] << { term: { user_ids: current_user.id } } - else # otherwise display only published projects + else + # otherwise display only published projects search[:query][:bool][:must] << { term: { state: 'published' } } end @@ -145,6 +140,7 @@ class Project < ActiveRecord::Base end private + def notify_admin_when_project_published NotificationCenter.call type: 'notify_admin_when_project_published', receiver: User.admins, @@ -152,9 +148,9 @@ class Project < ActiveRecord::Base end def after_save_and_publish - if state_changed? and published? - update_columns(published_at: Time.now) - notify_admin_when_project_published - end + return unless state_changed? && published? + + update_columns(published_at: Time.now) + notify_admin_when_project_published end end diff --git a/app/models/role.rb b/app/models/role.rb index ce3605cc4..d82c7e694 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -1,6 +1,6 @@ class Role < ActiveRecord::Base - has_and_belongs_to_many :users, :join_table => :users_roles - belongs_to :resource, :polymorphic => true + has_and_belongs_to_many :users, join_table: 'users_roles' + belongs_to :resource, polymorphic: true scopify end diff --git a/app/models/statistic_profile.rb b/app/models/statistic_profile.rb index acc6cd495..4d1c9b023 100644 --- a/app/models/statistic_profile.rb +++ b/app/models/statistic_profile.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +AVG_DAYS_PER_YEAR = 365.2425 + # This table will save the user's profile data needed for statistical purposes. # GDPR requires that an user can delete his account at any time but we need to keep the statistics original data to being able to # rebuild them at any time. @@ -7,14 +9,21 @@ class StatisticProfile < ActiveRecord::Base belongs_to :user belongs_to :group + belongs_to :role - # relations to reservations, trainings, subscriptions has_many :subscriptions, dependent: :destroy accepts_nested_attributes_for :subscriptions, allow_destroy: false has_many :reservations, dependent: :destroy accepts_nested_attributes_for :reservations, allow_destroy: false + # Trainings that were validated by an admin + has_many :statistic_profile_trainings, dependent: :destroy + has_many :trainings, through: :statistic_profile_trainings + + # Projects that the current user is the author + has_many :my_projects, foreign_key: :author_statistic_profile_id, class_name: 'Project', dependent: :destroy + def str_gender gender ? 'male' : 'female' end @@ -22,7 +31,7 @@ class StatisticProfile < ActiveRecord::Base def age if birthday.present? now = Time.now.utc.to_date - (now - birthday).to_f / 365.2425 + (now - birthday).to_f / AVG_DAYS_PER_YEAR else '' end diff --git a/app/models/user_training.rb b/app/models/statistic_profile_training.rb similarity index 51% rename from app/models/user_training.rb rename to app/models/statistic_profile_training.rb index cbf27131e..167c42cc7 100644 --- a/app/models/user_training.rb +++ b/app/models/statistic_profile_training.rb @@ -1,15 +1,19 @@ -class UserTraining < ActiveRecord::Base +# frozen_string_literal: true + +# Stores trainings validated per user (non validated trainings are only recorded in reservations) +class StatisticProfileTraining < ActiveRecord::Base include NotifyWith::NotificationAttachedObject - belongs_to :user + belongs_to :statistic_profile belongs_to :training after_commit :notify_user_training_valid, on: :create private + def notify_user_training_valid NotificationCenter.call type: 'notify_user_training_valid', - receiver: user, + receiver: statistic_profile.user, attached_object: self end end diff --git a/app/models/training.rb b/app/models/training.rb index c7ae28f5e..682204239 100644 --- a/app/models/training.rb +++ b/app/models/training.rb @@ -12,9 +12,9 @@ class Training < ActiveRecord::Base has_many :reservations, as: :reservable, dependent: :destroy - # members who DID the training - has_many :user_trainings, dependent: :destroy - has_many :users, through: :user_trainings + # members who has validated the trainings + has_many :statistic_profile_trainings, dependent: :destroy + has_many :statistic_profiles, through: :statistic_profile_trainings has_many :trainings_pricings, dependent: :destroy diff --git a/app/models/user.rb b/app/models/user.rb index 2b4c0b808..64d75a29c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -27,14 +27,9 @@ class User < ActiveRecord::Base has_one :statistic_profile, dependent: :nullify accepts_nested_attributes_for :statistic_profile - has_many :my_projects, foreign_key: :author_id, class_name: 'Project', dependent: :destroy has_many :project_users, dependent: :destroy has_many :projects, through: :project_users - # Trainings that were already passed - has_many :user_trainings, dependent: :destroy - has_many :trainings, through: :user_trainings - belongs_to :group has_many :users_credits, dependent: :destroy @@ -69,6 +64,8 @@ class User < ActiveRecord::Base delegate :last_name, to: :profile delegate :subscriptions, to: :statistic_profile delegate :reservations, to: :statistic_profile + delegate :trainings, to: :statistic_profile + delegate :my_projects, to: :statistic_profile delegate :wallet, to: :invoicing_profile delegate :wallet_transactions, to: :invoicing_profile delegate :invoices, to: :invoicing_profile @@ -376,7 +373,8 @@ class User < ActiveRecord::Base if statistic_profile.nil? StatisticProfile.create!( user: self, - group_id: group_id + group_id: group_id, + role_id: roles.first.id ) else update_statistic_profile @@ -391,6 +389,7 @@ class User < ActiveRecord::Base ) end + # will update the statistic_profile after a group switch. Updating the role is not supported def update_statistic_profile raise NoProfileError if statistic_profile.nil? diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index 79b15c0ff..514295bf9 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -2,23 +2,24 @@ class ProjectPolicy < ApplicationPolicy class Scope < Scope def resolve if user + statistic_profile = StatisticProfile.find_by(user_id: user.id) scope.includes(:project_image, :machines, :users) - .where("state = 'published' OR (state = 'draft' AND (author_id = ? OR users.id = ?))", user.id, user.id) - .references(:users) - .order(created_at: :desc) + .where("state = 'published' OR (state = 'draft' AND (author_statistic_profile_id = ? OR users.id = ?))", statistic_profile.id, user.id) + .references(:users) + .order(created_at: :desc) else scope.includes(:project_image, :machines, :users) - .where("state = 'published'") - .order(created_at: :desc) + .where("state = 'published'") + .order(created_at: :desc) end end end def update? - user.admin? or record.author == user or record.users.include?(user) + user.admin? or record.author.user_id == user.id or record.users.include?(user) end def destroy? - user.admin? or record.author == user + user.admin? or record.author.user_id == user end end diff --git a/app/services/availabilities/status_service.rb b/app/services/availabilities/status_service.rb index 9079e2748..438be1d0b 100644 --- a/app/services/availabilities/status_service.rb +++ b/app/services/availabilities/status_service.rb @@ -4,11 +4,12 @@ class Availabilities::StatusService def initialize(current_user_role) @current_user_role = current_user_role + @show_name = (@current_user_role == 'admin' || Setting.find_by(name: 'display_name_enable').value == 'true') end # check that the provided machine slot is reserved or not and modify it accordingly def machine_reserved_status(slot, reservations, user) - show_name = (@current_user_role == 'admin' || Setting.find_by(name: 'display_name_enable').value == 'true') + statistic_profile_id = user&.statistic_profile&.id reservations.each do |r| r.slots.each do |s| next unless slot.machine.id == r.reservable_id @@ -17,11 +18,11 @@ class Availabilities::StatusService slot.id = s.id slot.is_reserved = true - slot.title = "#{slot.machine.name} - #{show_name ? r.user.profile.full_name : I18n.t('availabilities.not_available')}" + slot.title = "#{slot.machine.name} - #{@show_name ? r.user.profile.full_name : I18n.t('availabilities.not_available')}" slot.can_modify = true if @current_user_role == 'admin' slot.reservations.push r - next unless r.user == user + next unless r.statistic_profile_id == statistic_profile_id slot.title = "#{slot.machine.name} - #{I18n.t('availabilities.i_ve_reserved')}" slot.can_modify = true @@ -33,6 +34,7 @@ class Availabilities::StatusService # check that the provided space slot is reserved or not and modify it accordingly def space_reserved_status(slot, reservations, user) + statistic_profile_id = user&.statistic_profile&.id reservations.each do |r| r.slots.each do |s| next unless slot.space.id == r.reservable_id @@ -42,7 +44,7 @@ class Availabilities::StatusService slot.can_modify = true if @current_user_role == 'admin' slot.reservations.push r - next unless r.user == user + next unless r.statistic_profile_id == statistic_profile_id slot.id = s.id slot.title = I18n.t('availabilities.i_ve_reserved') @@ -55,6 +57,7 @@ class Availabilities::StatusService # check that the provided availability (training or event) is reserved or not and modify it accordingly def training_event_reserved_status(availability, reservations, user) + statistic_profile_id = user&.statistic_profile&.id reservations.each do |r| r.slots.each do |s| next unless ( @@ -63,7 +66,7 @@ class Availabilities::StatusService ) && s.start_at == availability.start_at && s.canceled_at.nil? availability.slot_id = s.id - if r.user == user + if r.statistic_profile_id == statistic_profile_id availability.is_reserved = true availability.can_modify = true end diff --git a/app/services/reservations/reserve.rb b/app/services/reservations/reserve.rb index 128262b63..d55a376c7 100644 --- a/app/services/reservations/reserve.rb +++ b/app/services/reservations/reserve.rb @@ -10,7 +10,7 @@ class Reservations::Reserve end def pay_and_save(reservation, payment_method, coupon) - reservation.statistic_profile_id = User.find(user_id).statistic_profile.id + reservation.statistic_profile_id = StatisticProfile.find_by(user_id: user_id).id if payment_method == :local reservation.save_with_local_payment(operator_id, coupon) elsif payment_method == :stripe diff --git a/app/services/statistic_service.rb b/app/services/statistic_service.rb index 95bafb739..ed304c2b5 100644 --- a/app/services/statistic_service.rb +++ b/app/services/statistic_service.rb @@ -127,7 +127,7 @@ class StatisticService def subscriptions_list(options = default_options) result = [] InvoiceItem.where('invoice_items.created_at >= :start_date AND invoice_items.created_at <= :end_date', options) - .eager_load(invoice: [:coupon], subscription: [:plan, user: %i[profile group]]).each do |i| + .eager_load(invoice: [:coupon], subscription: [:plan, statistic_profile: [:group]]).each do |i| next if i.invoice.is_a?(Avoir) sub = i.subscription @@ -135,7 +135,7 @@ class StatisticService ca = i.amount.to_i / 100.0 ca = CouponService.new.ventilate(get_invoice_total_no_coupon(i.invoice), ca, i.invoice.coupon) unless i.invoice.coupon_id.nil? - u = sub.user + profile = sub.statistic_profile p = sub.plan result.push OpenStruct.new({ date: options[:start_date].to_date, @@ -149,7 +149,7 @@ class StatisticService subscription_id: sub.id, invoice_item_id: i.id, ca: ca - }.merge(user_info(u))) + }.merge(user_info(profile))) end result end @@ -158,11 +158,11 @@ class StatisticService result = [] Reservation .where("reservable_type = 'Machine' AND reservations.created_at >= :start_date AND reservations.created_at <= :end_date", options) - .eager_load(:slots, user: %i[profile group], invoice: [:invoice_items]) + .eager_load(:slots, statistic_profile: [:group], invoice: [:invoice_items]) .each do |r| next unless r.reservable - u = r.user + profile = r.statistic_profile result.push OpenStruct.new({ date: options[:start_date].to_date, reservation_id: r.id, @@ -171,7 +171,7 @@ class StatisticService machine_name: r.reservable.name, nb_hours: r.slots.size, ca: calcul_ca(r.invoice) - }.merge(user_info(u))) + }.merge(user_info(profile))) end result end @@ -180,11 +180,11 @@ class StatisticService result = [] Reservation .where("reservable_type = 'Space' AND reservations.created_at >= :start_date AND reservations.created_at <= :end_date", options) - .eager_load(:slots, user: %i[profile group], invoice: [:invoice_items]) + .eager_load(:slots, statistic_profile: [:group], invoice: [:invoice_items]) .each do |r| next unless r.reservable - u = r.user + profile = r.statistic_profile result.push OpenStruct.new({ date: options[:start_date].to_date, reservation_id: r.id, @@ -193,7 +193,7 @@ class StatisticService space_type: r.reservable.slug, nb_hours: r.slots.size, ca: calcul_ca(r.invoice) - }.merge(user_info(u))) + }.merge(user_info(profile))) end result end @@ -202,11 +202,11 @@ class StatisticService result = [] Reservation .where("reservable_type = 'Training' AND reservations.created_at >= :start_date AND reservations.created_at <= :end_date", options) - .eager_load(:slots, user: %i[profile group], invoice: [:invoice_items]) + .eager_load(:slots, statistic_profile: [:group], invoice: [:invoice_items]) .each do |r| next unless r.reservable - u = r.user + profile = r.statistic_profile slot = r.slots.first result.push OpenStruct.new({ date: options[:start_date].to_date, @@ -217,7 +217,7 @@ class StatisticService training_date: slot.start_at.to_date, nb_hours: difference_in_hours(slot.start_at, slot.end_at), ca: calcul_ca(r.invoice) - }.merge(user_info(u))) + }.merge(user_info(profile))) end result end @@ -226,11 +226,11 @@ class StatisticService result = [] Reservation .where("reservable_type = 'Event' AND reservations.created_at >= :start_date AND reservations.created_at <= :end_date", options) - .eager_load(:slots, user: %i[profile group], invoice: [:invoice_items]) + .eager_load(:slots, statistic_profile: [:group], invoice: [:invoice_items]) .each do |r| next unless r.reservable - u = r.user + profile = r.statistic_profile slot = r.slots.first result.push OpenStruct.new({ date: options[:start_date].to_date, @@ -244,7 +244,7 @@ class StatisticService nb_places: r.total_booked_seats, nb_hours: difference_in_hours(slot.start_at, slot.end_at), ca: calcul_ca(r.invoice) - }.merge(user_info(u))) + }.merge(user_info(profile))) end result end @@ -254,21 +254,27 @@ class StatisticService reservations_ca_list = [] avoirs_ca_list = [] result = [] - Reservation .where('reservations.created_at >= :start_date AND reservations.created_at <= :end_date', options) - .eager_load(:slots, user: %i[profile group], invoice: [:invoice_items]) - .each do |r| + Reservation.where('reservations.created_at >= :start_date AND reservations.created_at <= :end_date', options) + .eager_load(:slots, statistic_profile: [:group], invoice: [:invoice_items]) + .each do |r| next unless r.reservable - reservations_ca_list.push OpenStruct.new({ date: options[:start_date].to_date, ca: calcul_ca(r.invoice) }.merge(user_info(r.user))) + reservations_ca_list.push OpenStruct.new({ + date: options[:start_date].to_date, + ca: calcul_ca(r.invoice) + }.merge(user_info(r.statistic_profile))) end Avoir.where('invoices.created_at >= :start_date AND invoices.created_at <= :end_date', options) - .eager_load(:invoice_items, user: %i[profile group]) + .eager_load(:invoice_items, statistic_profile: [:group]) .each do |i| - avoirs_ca_list.push OpenStruct.new({ date: options[:start_date].to_date, ca: calcul_avoir_ca(i) }.merge(user_info(i.user))) + avoirs_ca_list.push OpenStruct.new({ + date: options[:start_date].to_date, + ca: calcul_avoir_ca(i) + }.merge(user_info(i.statistic_profile))) end reservations_ca_list.concat(subscriptions_ca_list).concat(avoirs_ca_list).each do |e| - user = User.find(e.user_id) - u = find_or_create_user_info_info_list(user, result) + profile = StatisticProfile.find(e.statistic_profile_id) + u = find_or_create_user_info_info_list(profile, result) u.date = options[:start_date].to_date e.ca = 0 unless e.ca if u.ca @@ -284,15 +290,14 @@ class StatisticService def members_list(options = default_options) result = [] - User.with_role(:member) - .includes(:profile) - .where('users.created_at >= :start_date AND users.created_at <= :end_date', options) - .each do |u| - next if u.need_completion? + member = Role.find_by(name: 'member') + StatisticProfile.where('role_id = :member AND created_at >= :start_date AND created_at <= :end_date', options.merge(member: member.id)) + .each do |sp| + next if sp.user&.need_completion? result.push OpenStruct.new({ date: options[:start_date].to_date - }.merge(user_info(u))) + }.merge(user_info(sp))) end result end @@ -300,7 +305,7 @@ class StatisticService def projects_list(options = default_options) result = [] Project.where('projects.published_at >= :start_date AND projects.published_at <= :end_date', options) - .eager_load(:licence, :themes, :components, :machines, :project_users, author: %i[profile group]) + .eager_load(:licence, :themes, :components, :machines, :project_users, author: [:group]) .each do |p| result.push OpenStruct.new({ date: options[:start_date].to_date @@ -310,18 +315,18 @@ class StatisticService end # return always yesterday's sum of comment of each project - def projects_comment_nb_list - result = [] - Project.where(state: 'published') - .eager_load(:licence, :themes, :components, :machines, :project_users, author: %i[profile group]) - .each do |p| - result.push OpenStruct.new({ - date: 1.day.ago.to_date, - project_comments: get_project_comment_nb(p) - }.merge(user_info(p.author)).merge(project_info(p))) - end - result - end + # def projects_comment_nb_list + # result = [] + # Project.where(state: 'published') + # .eager_load(:licence, :themes, :components, :machines, :project_users, author: %i[profile group]) + # .each do |p| + # result.push OpenStruct.new({ + # date: 1.day.ago.to_date, + # project_comments: get_project_comment_nb(p) + # }.merge(user_info(p.author)).merge(project_info(p))) + # end + # result + # end def clean_stat(options = default_options) client = Elasticsearch::Model.client @@ -353,13 +358,13 @@ class StatisticService end end - def user_info(user) + def user_info(statistic_profile) { - user_id: user.id, - gender: user.statistic_profile.str_gender, - age: user.statistic_profile.age, - group: user.group ? user.group.slug : nil, - email: user.email + statistic_profile_id: statistic_profile.id, + user_id: statistic_profile.user_id, + gender: statistic_profile.str_gender, + age: statistic_profile.age, + group: statistic_profile.group ? statistic_profile.group.slug : nil } end @@ -439,12 +444,12 @@ class StatisticService sum end - def get_project_comment_nb(project) - project_comment_info = @projects_comment_info.select do |p| - p['identifiers'].first == "project_#{project.id}" - end.first - project_comment_info ? project_comment_info['posts'] : 0 - end + # def get_project_comment_nb(project) + # project_comment_info = @projects_comment_info.select do |p| + # p['identifiers'].first == "project_#{project.id}" + # end.first + # project_comment_info ? project_comment_info['posts'] : 0 + # end def project_info(project) { @@ -472,22 +477,22 @@ class StatisticService } end - def get_user_subscription_ca(user, subscriptions_ca_list) - user_subscription_ca = subscriptions_ca_list.select do |ca| - ca.user_id == user.id - end - user_subscription_ca.inject {|sum,x| sum.ca + x.ca } || 0 - end + # def get_user_subscription_ca(user, subscriptions_ca_list) + # user_subscription_ca = subscriptions_ca_list.select do |ca| + # ca.user_id == user.id + # end + # user_subscription_ca.inject {|sum,x| sum.ca + x.ca } || 0 + # end def get_invoice_total_no_coupon(invoice) total = (invoice.invoice_items.map(&:amount).map(&:to_i).reduce(:+) or 0) total / 100.0 end - def find_or_create_user_info_info_list(user, list) + def find_or_create_user_info_info_list(profile, list) found = list.select do |l| - l.user_id == user.id + l.statistic_profile_id == profile.id end.first - found || OpenStruct.new(user_info(user)) + found || OpenStruct.new(user_info(profile)) end end diff --git a/app/services/subscriptions/subscribe.rb b/app/services/subscriptions/subscribe.rb index 74ea491f7..dd5b5a065 100644 --- a/app/services/subscriptions/subscribe.rb +++ b/app/services/subscriptions/subscribe.rb @@ -12,7 +12,7 @@ class Subscriptions::Subscribe def pay_and_save(subscription, payment_method, coupon, invoice) return false if user_id.nil? - subscription.statistic_profile_id = User.find(user_id).statistic_profile.id + subscription.statistic_profile_id = StatisticProfile.find_by(user_id: user_id).id if payment_method == :local subscription.save_with_local_payment(operator_id, invoice, coupon) elsif payment_method == :stripe diff --git a/app/views/api/availabilities/reservations.json.jbuilder b/app/views/api/availabilities/reservations.json.jbuilder index 86b3e56b8..c34226e2a 100644 --- a/app/views/api/availabilities/reservations.json.jbuilder +++ b/app/views/api/availabilities/reservations.json.jbuilder @@ -7,8 +7,8 @@ json.array!(@reservation_slots) do |slot| json.reservable_id slot.reservation.reservable_id json.reservable_type slot.reservation.reservable_type json.user do - json.id slot.reservation.user.id - json.name slot.reservation.user.profile.full_name + json.id slot.reservation.statistic_profile&.user_id + json.name slot.reservation.statistic_profile&.user&.profile&.full_name end json.canceled_at slot.canceled_at end diff --git a/app/views/api/members/show.json.jbuilder b/app/views/api/members/show.json.jbuilder index 9aa41c8db..335136632 100644 --- a/app/views/api/members/show.json.jbuilder +++ b/app/views/api/members/show.json.jbuilder @@ -1,9 +1,11 @@ +# frozen_string_literal: true + requested_current = (current_user and current_user.id == @member.id) json.partial! 'api/members/member', member: @member json.extract! @member, :uid, :slug, :is_allow_contact, :is_allow_newsletter -json.training_ids @member.training_ids +json.training_ids @member.statistic_profile.training_ids json.trainings @member.trainings do |t| json.id t.id json.name t.name @@ -13,13 +15,14 @@ json.training_reservations @member.reservations.where(reservable_type: 'Training json.start_at r.slots.first.start_at json.end_at r.slots.first.end_at json.reservable r.reservable - json.is_valid @member.training_ids.include?(r.reservable_id) + json.is_valid @member.statistic_profile.training_ids.include?(r.reservable_id) json.canceled_at r.slots.first.canceled_at end json.all_projects @member.all_projects do |project| if requested_current || project.state == 'published' - json.extract! project, :id, :name, :description, :author_id, :licence_id, :slug, :state + json.extract! project, :id, :name, :description, :licence_id, :slug, :state + json.author_id project.author.user_id json.url project_url(project, format: :json) json.project_image project.project_image.attachment.large.url if project.project_image json.machine_ids project.machine_ids @@ -27,7 +30,6 @@ json.all_projects @member.all_projects do |project| json.id m.id json.name m.name end - json.author_id project.author_id json.user_ids project.user_ids json.component_ids project.component_ids json.components project.components do |c| @@ -69,7 +71,7 @@ json.invoices @member.invoices.order('reference DESC') do |i| json.reference i.reference json.type i.invoiced_type json.invoiced_id i.invoiced_id - json.total (i.total / 100.00) + json.total i.total / 100.00 json.is_avoir i.is_a?(Avoir) json.date i.is_a?(Avoir) ? i.avoir_date : i.created_at end diff --git a/app/views/api/projects/_indexed.json.jbuilder b/app/views/api/projects/_indexed.json.jbuilder new file mode 100644 index 000000000..afdfa520d --- /dev/null +++ b/app/views/api/projects/_indexed.json.jbuilder @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +json.id project.id +json.state project.state +json.author_id project.author.user_id +json.user_ids project.user_ids +json.machine_ids project.machine_ids +json.theme_ids project.theme_ids +json.component_ids project.component_ids +json.tags project.tags +json.name project.name +json.description project.description +json.project_steps project.project_steps do |project_step| + json.title project_step.title + json.description project_step.description +end +json.created_at project.created_at +json.updated_at project.updated_at diff --git a/app/views/api/projects/index.json.jbuilder b/app/views/api/projects/index.json.jbuilder index d9bfd00ed..6be508e95 100644 --- a/app/views/api/projects/index.json.jbuilder +++ b/app/views/api/projects/index.json.jbuilder @@ -1,8 +1,10 @@ +# frozen_string_literal: true + json.projects @projects do |project| - json.extract! project, :id, :name, :description, :author_id, :licence_id, :slug, :state + json.extract! project, :id, :name, :description, :licence_id, :slug, :state + json.author_id project.author.user_id json.url project_url(project, format: :json) json.project_image project.project_image.attachment.medium.url if project.project_image - json.author_id project.author_id json.user_ids project.user_ids end diff --git a/app/views/api/projects/last_published.json.jbuilder b/app/views/api/projects/last_published.json.jbuilder index 608448810..97199d440 100644 --- a/app/views/api/projects/last_published.json.jbuilder +++ b/app/views/api/projects/last_published.json.jbuilder @@ -1,3 +1,5 @@ +# frozen_string_literal: true + json.array!(@projects) do |project| json.extract! project, :id, :name, :description, :slug json.url project_url(project, format: :json) diff --git a/app/views/api/projects/show.json.jbuilder b/app/views/api/projects/show.json.jbuilder index a5fe8fe8f..5f79f3e98 100644 --- a/app/views/api/projects/show.json.jbuilder +++ b/app/views/api/projects/show.json.jbuilder @@ -1,17 +1,22 @@ -json.extract! @project, :id, :name, :description, :tags, :created_at, :updated_at, :author_id, :licence_id, :slug +# frozen_string_literal: true + +json.extract! @project, :id, :name, :description, :tags, :created_at, :updated_at, :licence_id, :slug +json.author_id @project.author.user_id json.project_image @project.project_image.attachment.large.url if @project.project_image json.project_full_image @project.project_image.attachment.url if @project.project_image json.author do - json.id @project.author_id - json.first_name @project.author.profile.first_name - json.last_name @project.author.profile.last_name - json.full_name @project.author.profile.full_name - json.user_avatar do - json.id @project.author.profile.user_avatar.id - json.attachment_url @project.author.profile.user_avatar.attachment_url - end if @project.author.profile.user_avatar - json.username @project.author.username - json.slug @project.author.slug + json.id @project.author.user_id + json.first_name @project.author&.user&.profile&.first_name + json.last_name @project.author&.user&.profile&.last_name + json.full_name @project.author&.user&.profile&.full_name + if @project.author&.user&.profile&.user_avatar + json.user_avatar do + json.id @project.author&.user&.profile&.user_avatar&.id + json.attachment_url @project.author&.user&.profile&.user_avatar&.attachment_url + end + end + json.username @project.author&.user&.username + json.slug @project.author&.user&.slug end json.project_caos_attributes @project.project_caos do |f| json.id f.id @@ -39,10 +44,12 @@ json.project_users @project.project_users do |pu| json.first_name pu.user.profile.first_name json.last_name pu.user.profile.last_name json.full_name pu.user.profile.full_name - json.user_avatar do - json.id pu.user.profile.user_avatar.id - json.attachment_url pu.user.profile.user_avatar.attachment_url - end if pu.user.profile.user_avatar + if pu.user.profile.user_avatar + json.user_avatar do + json.id pu.user.profile.user_avatar.id + json.attachment_url pu.user.profile.user_avatar.attachment_url + end + end json.username pu.user.username json.slug pu.user.slug json.is_valid pu.is_valid @@ -60,9 +67,8 @@ json.project_steps_attributes @project.project_steps.order('project_steps.step_n json.step_nb s.step_nb end json.state @project.state -json.licence do - json.name @project.licence.name -end if @project.licence.present? -#json.project_steps_attributes @project.project_steps do |s| - #json.set! s.id, {id: s.id, description: s.description} -#end +if @project.licence.present? + json.licence do + json.name @project.licence.name + end +end diff --git a/app/views/api/trainings/availabilities.json.jbuilder b/app/views/api/trainings/availabilities.json.jbuilder index d65a5a1c8..b3701a28e 100644 --- a/app/views/api/trainings/availabilities.json.jbuilder +++ b/app/views/api/trainings/availabilities.json.jbuilder @@ -4,8 +4,8 @@ json.availabilities @availabilities do |a| json.start_at a.start_at.iso8601 json.end_at a.end_at.iso8601 json.reservation_users a.slots.map do |slot| - json.id slot.reservations.first.user_id - json.full_name slot.reservations.first.user.profile.full_name - json.is_valid slot.reservations.first.user.trainings.include?(@training) + json.id slot.reservations.first.statistic_profile.user_id + json.full_name slot.reservations.first.statistic_profile&.user&.profile&.full_name + json.is_valid slot.reservations.first.statistic_profile.trainings.include?(@training) end end diff --git a/app/workers/availability_indexer_worker.rb b/app/workers/availability_indexer_worker.rb index c26acadad..7466904a9 100644 --- a/app/workers/availability_indexer_worker.rb +++ b/app/workers/availability_indexer_worker.rb @@ -9,20 +9,20 @@ class AvailabilityIndexerWorker logger.debug [operation, "ID: #{record_id}"] case operation.to_s - when /index/ - begin - record = Availability.find(record_id) - Client.index index: Availability.index_name, type: Availability.document_type, id: record.id, body: record.as_indexed_json - rescue ActiveRecord::RecordNotFound - STDERR.puts "Availability id(#{record_id}) will not be indexed in ElasticSearch as it does not exists anymore in database" - end - when /delete/ - begin - Client.delete index: Availability.index_name, type: Availability.document_type, id: record_id - rescue Elasticsearch::Transport::Transport::Errors::NotFound - STDERR.puts "Availability id(#{record_id}) will not be deleted form ElasticSearch as it has not been already indexed" - end - else raise ArgumentError, "Unknown operation '#{operation}'" + when /index/ + begin + record = Availability.find(record_id) + Client.index index: Availability.index_name, type: Availability.document_type, id: record.id, body: record.as_indexed_json + rescue ActiveRecord::RecordNotFound + STDERR.puts "Availability id(#{record_id}) will not be indexed in ElasticSearch as it does not exists anymore in database" + end + when /delete/ + begin + Client.delete index: Availability.index_name, type: Availability.document_type, id: record_id + rescue Elasticsearch::Transport::Transport::Errors::NotFound + STDERR.puts "Availability id(#{record_id}) will not be deleted form ElasticSearch as it has not been already indexed" + end + else raise ArgumentError, "Unknown operation '#{operation}'" end end end diff --git a/config/initializers/activerecord.rb b/config/initializers/activerecord.rb index c1f4bf43b..38fb8526f 100644 --- a/config/initializers/activerecord.rb +++ b/config/initializers/activerecord.rb @@ -1,6 +1,8 @@ +# frozen_string_literal: true + # https://github.com/ruckus/active-record-query-trace # traces the origin of active record queries, useful for optimisation purposes if Rails.env.development? - ActiveRecordQueryTrace.enabled = false # set to true to enable + ActiveRecordQueryTrace.enabled = false # set to true to enable ActiveRecordQueryTrace.level = :app end diff --git a/config/locales/devise.fr.yml b/config/locales/devise.fr.yml index a1477eb79..344dcf26d 100644 --- a/config/locales/devise.fr.yml +++ b/config/locales/devise.fr.yml @@ -3,7 +3,7 @@ fr: devise: confirmations: - confirmed: "Votre compte a été confirmé avec succès. Vous êtes désormais connecté(e)." + confirmed: "Votre compte a été confirmé avec succès." send_instructions: "Vous allez recevoir sous quelques minutes un e-mail comportant des instructions pour confirmer votre compte." send_paranoid_instructions: "Si votre e-mail existe sur notre base de données, vous recevrez sous quelques minutes un message avec des instructions pour confirmer votre compte." failure: diff --git a/db/migrate/20190603150642_create_statistic_profile.rb b/db/migrate/20190521123642_create_statistic_profile.rb similarity index 58% rename from db/migrate/20190603150642_create_statistic_profile.rb rename to db/migrate/20190521123642_create_statistic_profile.rb index 5dce99692..f2fa55f0a 100644 --- a/db/migrate/20190603150642_create_statistic_profile.rb +++ b/db/migrate/20190521123642_create_statistic_profile.rb @@ -5,9 +5,16 @@ class CreateStatisticProfile < ActiveRecord::Migration t.date :birthday t.belongs_to :group, index: true, foreign_key: true t.belongs_to :user, index: true, foreign_key: true + t.belongs_to :role, index: true, foreign_key: true + + t.timestamps end add_reference :reservations, :statistic_profile, index: true, foreign_key: true add_reference :subscriptions, :statistic_profile, index: true, foreign_key: true + add_reference :invoices, :statistic_profile, index: true, foreign_key: true + + add_column :projects, :author_statistic_profile_id, :integer, index: true + add_foreign_key :projects, :statistic_profiles, column: :author_statistic_profile_id end end diff --git a/db/migrate/20190603151142_migrate_profile_to_statistic_profile.rb b/db/migrate/20190521151142_migrate_profile_to_statistic_profile.rb similarity index 86% rename from db/migrate/20190603151142_migrate_profile_to_statistic_profile.rb rename to db/migrate/20190521151142_migrate_profile_to_statistic_profile.rb index f08cb22be..02f3bef2f 100644 --- a/db/migrate/20190603151142_migrate_profile_to_statistic_profile.rb +++ b/db/migrate/20190521151142_migrate_profile_to_statistic_profile.rb @@ -7,8 +7,10 @@ class MigrateProfileToStatisticProfile < ActiveRecord::Migration StatisticProfile.create!( user: u, group: u.group, + role: u.roles.first, gender: p.gender, - birthday: p.birthday + birthday: p.birthday, + created_at: u.created_at ) end end diff --git a/db/migrate/20190522115230_migrate_user_to_invoicing_profile.rb b/db/migrate/20190522115230_migrate_user_to_invoicing_profile.rb index b1d863e44..3688ebfb5 100644 --- a/db/migrate/20190522115230_migrate_user_to_invoicing_profile.rb +++ b/db/migrate/20190522115230_migrate_user_to_invoicing_profile.rb @@ -14,6 +14,7 @@ class MigrateUserToInvoicingProfile < ActiveRecord::Migration Invoice.order(:id).all.each do |i| user = User.find(i.user_id) i.update_column('invoicing_profile_id', user.invoicing_profile.id) + i.update_column('statistic_profile_id', user.statistic_profile.id) i.update_column('user_id', nil) end # chain all records @@ -32,6 +33,7 @@ class MigrateUserToInvoicingProfile < ActiveRecord::Migration Invoice.order(:created_at).all.each do |i| i.update_column('user_id', i.invoicing_profile.user_id) i.update_column('invoicing_profile_id', nil) + i.update_column('statistic_profile_id', nil) end # chain all records InvoiceItem.order(:id).all.each(&:chain_record) diff --git a/db/migrate/20190604070903_migrate_projet_to_statistic_profile.rb b/db/migrate/20190604070903_migrate_projet_to_statistic_profile.rb new file mode 100644 index 000000000..945ea2610 --- /dev/null +++ b/db/migrate/20190604070903_migrate_projet_to_statistic_profile.rb @@ -0,0 +1,19 @@ +class MigrateProjetToStatisticProfile < ActiveRecord::Migration + def up + Project.all.each do |p| + author = User.find(p.author_id) + p.update_column( + 'author_statistic_profile_id', author.statistic_profile.id + ) + end + end + + def down + Project.all.each do |p| + statistic_profile = User.find(p.author_statistic_profile_id) + p.update_column( + 'author_id', statistic_profile.user_id + ) + end + end +end diff --git a/db/migrate/20190604075717_remove_statistic_columns.rb b/db/migrate/20190604075717_remove_statistic_columns.rb index 20c64033a..edd95b978 100644 --- a/db/migrate/20190604075717_remove_statistic_columns.rb +++ b/db/migrate/20190604075717_remove_statistic_columns.rb @@ -4,5 +4,6 @@ class RemoveStatisticColumns < ActiveRecord::Migration remove_column :profiles, :birthday, :date remove_column :reservations, :user_id remove_column :subscriptions, :user_id + remove_column :projects, :author_id end end diff --git a/db/migrate/20190605141322_create_statistic_profile_trainings.rb b/db/migrate/20190605141322_create_statistic_profile_trainings.rb new file mode 100644 index 000000000..f6db78b50 --- /dev/null +++ b/db/migrate/20190605141322_create_statistic_profile_trainings.rb @@ -0,0 +1,10 @@ +class CreateStatisticProfileTrainings < ActiveRecord::Migration + def change + create_table :statistic_profile_trainings do |t| + t.belongs_to :statistic_profile, index: true, foreign_key: true + t.belongs_to :training, index: true, foreign_key: true + + t.timestamps null: false + end + end +end diff --git a/db/migrate/20190606074050_migrate_user_trainings_to_statistic_profile_trainings.rb b/db/migrate/20190606074050_migrate_user_trainings_to_statistic_profile_trainings.rb new file mode 100644 index 000000000..b500142d0 --- /dev/null +++ b/db/migrate/20190606074050_migrate_user_trainings_to_statistic_profile_trainings.rb @@ -0,0 +1,32 @@ +class MigrateUserTrainingsToStatisticProfileTrainings < ActiveRecord::Migration + def up + user_trainings = execute('SELECT * FROM user_trainings') + + user_trainings.each do |ut| + user = User.find(ut['user_id']) + # here we use raw sql to prevent the notify_user callback the email the whole DB + spt_id = insert("INSERT INTO statistic_profile_trainings (statistic_profile_id, training_id, created_at, updated_at) + VALUES (#{user.statistic_profile.id}, #{ut['training_id']}, '#{ut['created_at']}', '#{DateTime.now.utc}')") + + # update notifications + execute("UPDATE notifications SET + attached_object_type = 'StatisticProfileTraining', + attached_object_id = #{spt_id}, + updated_at = '#{DateTime.now.utc}' + WHERE attached_object_id = #{ut['id']} AND attached_object_type = 'UserTraining'") + end + end + + def down + StatisticProfileTraining.all.each do |spt| + statistic_profile = StatisticProfile.find(spt.statistic_profile_id) + ut_id = execute("INSERT INTO user_trainings (user_id, training_id, created_at, updated_at) + VALUES (#{statistic_profile.user_id}, #{spt.training_id}, '#{spt.created_at.utc}', '#{DateTime.now.utc}')") + execute("UPDATE notifications SET + attached_object_type = 'UserTraining', + attached_object_id = #{ut_id}, + updated_at = '#{DateTime.now.utc}' + WHERE attached_object_id = #{spt.id} AND attached_object_type = 'StatisticProfileTraining'") + end + end +end diff --git a/db/migrate/20190606074801_delete_user_trainings.rb b/db/migrate/20190606074801_delete_user_trainings.rb new file mode 100644 index 000000000..acb3648a6 --- /dev/null +++ b/db/migrate/20190606074801_delete_user_trainings.rb @@ -0,0 +1,5 @@ +class DeleteUserTrainings < ActiveRecord::Migration + def change + drop_table :user_trainings + end +end diff --git a/db/schema.rb b/db/schema.rb index 4e99a8f1a..c29be35d2 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20190604075717) do +ActiveRecord::Schema.define(version: 20190606074801) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -280,11 +280,13 @@ ActiveRecord::Schema.define(version: 20190604075717) do t.string "environment" t.integer "operator_id" t.integer "invoicing_profile_id" + t.integer "statistic_profile_id" end add_index "invoices", ["coupon_id"], name: "index_invoices_on_coupon_id", using: :btree add_index "invoices", ["invoice_id"], name: "index_invoices_on_invoice_id", using: :btree add_index "invoices", ["invoicing_profile_id"], name: "index_invoices_on_invoicing_profile_id", using: :btree + add_index "invoices", ["statistic_profile_id"], name: "index_invoices_on_statistic_profile_id", using: :btree add_index "invoices", ["wallet_transaction_id"], name: "index_invoices_on_wallet_transaction_id", using: :btree create_table "invoicing_profiles", force: :cascade do |t| @@ -496,16 +498,16 @@ ActiveRecord::Schema.define(version: 20190604075717) do add_index "project_users", ["user_id"], name: "index_project_users_on_user_id", using: :btree create_table "projects", force: :cascade do |t| - t.string "name", limit: 255 + t.string "name", limit: 255 t.text "description" t.datetime "created_at" t.datetime "updated_at" - t.integer "author_id" t.text "tags" t.integer "licence_id" - t.string "state", limit: 255 - t.string "slug", limit: 255 + t.string "state", limit: 255 + t.string "slug", limit: 255 t.datetime "published_at" + t.integer "author_statistic_profile_id" end add_index "projects", ["slug"], name: "index_projects_on_slug", using: :btree @@ -662,14 +664,28 @@ ActiveRecord::Schema.define(version: 20190604075717) do t.boolean "ca", default: true end + create_table "statistic_profile_trainings", force: :cascade do |t| + t.integer "statistic_profile_id" + t.integer "training_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + add_index "statistic_profile_trainings", ["statistic_profile_id"], name: "index_statistic_profile_trainings_on_statistic_profile_id", using: :btree + add_index "statistic_profile_trainings", ["training_id"], name: "index_statistic_profile_trainings_on_training_id", using: :btree + create_table "statistic_profiles", force: :cascade do |t| - t.boolean "gender" - t.date "birthday" - t.integer "group_id" - t.integer "user_id" + t.boolean "gender" + t.date "birthday" + t.integer "group_id" + t.integer "user_id" + t.integer "role_id" + t.datetime "created_at" + t.datetime "updated_at" end add_index "statistic_profiles", ["group_id"], name: "index_statistic_profiles_on_group_id", using: :btree + add_index "statistic_profiles", ["role_id"], name: "index_statistic_profiles_on_role_id", using: :btree add_index "statistic_profiles", ["user_id"], name: "index_statistic_profiles_on_user_id", using: :btree create_table "statistic_sub_types", force: :cascade do |t| @@ -795,16 +811,6 @@ ActiveRecord::Schema.define(version: 20190604075717) do add_index "user_tags", ["tag_id"], name: "index_user_tags_on_tag_id", using: :btree add_index "user_tags", ["user_id"], name: "index_user_tags_on_user_id", using: :btree - create_table "user_trainings", force: :cascade do |t| - t.integer "user_id" - t.datetime "created_at" - t.datetime "updated_at" - t.integer "training_id" - end - - add_index "user_trainings", ["training_id"], name: "index_user_trainings_on_training_id", using: :btree - add_index "user_trainings", ["user_id"], name: "index_user_trainings_on_user_id", using: :btree - create_table "users", force: :cascade do |t| t.string "email", limit: 255, default: "", null: false t.string "encrypted_password", limit: 255, default: "", null: false @@ -904,6 +910,7 @@ ActiveRecord::Schema.define(version: 20190604075717) do add_foreign_key "history_values", "settings" add_foreign_key "invoices", "coupons" add_foreign_key "invoices", "invoicing_profiles" + add_foreign_key "invoices", "statistic_profiles" add_foreign_key "invoices", "users", column: "operator_id" add_foreign_key "invoices", "wallet_transactions" add_foreign_key "invoicing_profiles", "users" @@ -912,6 +919,7 @@ ActiveRecord::Schema.define(version: 20190604075717) do add_foreign_key "organizations", "invoicing_profiles" add_foreign_key "prices", "groups" add_foreign_key "prices", "plans" + add_foreign_key "projects", "statistic_profiles", column: "author_statistic_profile_id" add_foreign_key "projects_spaces", "projects" add_foreign_key "projects_spaces", "spaces" add_foreign_key "reservations", "statistic_profiles" @@ -920,7 +928,10 @@ ActiveRecord::Schema.define(version: 20190604075717) do add_foreign_key "spaces_availabilities", "availabilities" add_foreign_key "spaces_availabilities", "spaces" add_foreign_key "statistic_custom_aggregations", "statistic_types" + add_foreign_key "statistic_profile_trainings", "statistic_profiles" + add_foreign_key "statistic_profile_trainings", "trainings" add_foreign_key "statistic_profiles", "groups" + add_foreign_key "statistic_profiles", "roles" add_foreign_key "statistic_profiles", "users" add_foreign_key "subscriptions", "statistic_profiles" add_foreign_key "tickets", "event_price_categories" diff --git a/test/fixtures/invoices.yml b/test/fixtures/invoices.yml index 71c588753..d1dc69c78 100644 --- a/test/fixtures/invoices.yml +++ b/test/fixtures/invoices.yml @@ -8,6 +8,7 @@ invoice_1: created_at: 2012-03-12 11:03:31.651441000 Z updated_at: 2012-03-12 11:03:31.651441000 Z invoicing_profile_id: 3 + statistic_profile_id: 3 reference: 1604001/VL avoir_mode: avoir_date: @@ -15,7 +16,7 @@ invoice_1: type: subscription_to_expire: description: - footprint: d477d23a473c565e2c379263d4c86c9cc80cdd88adc9a3ff7246afccec0e2a18 + footprint: e7fffd325cacbb76218626ea2a35a7a9f052c208c41aac13f70c31eae9f81bc7 environment: test operator_id: @@ -28,6 +29,7 @@ invoice_2: created_at: 2012-03-12 13:40:22.342717000 Z updated_at: 2012-03-12 13:40:22.342717000 Z invoicing_profile_id: 4 + statistic_profile_id: 4 reference: '1604002' avoir_mode: avoir_date: @@ -35,7 +37,7 @@ invoice_2: type: subscription_to_expire: description: - footprint: 4cef4ec78543075af4d782ef919ca95ccbdfbd3bad91f2dfe01fe9b5113eb4d4 + footprint: bd0b739c211b40abed7ddb07bc054281513acab4a0adde6c416dc1715dd9f005 environment: test operator_id: @@ -48,6 +50,7 @@ invoice_3: created_at: 2015-06-10 11:20:01.341130000 Z updated_at: 2015-06-10 11:20:01.341130000 Z invoicing_profile_id: 7 + statistic_profile_id: 7 reference: '1203001' avoir_mode: avoir_date: @@ -55,7 +58,7 @@ invoice_3: type: subscription_to_expire: description: - footprint: 295f687cfc1df1c9dfe6759f0c3a4d7e92bc8959ee909d944537dffa6b8a0a5e + footprint: ab00a9318314b75d29ec220e00c96e738d608d64423b1c5abb25786551f12f8b environment: test operator_id: @@ -69,6 +72,7 @@ invoice_4: created_at: 2016-04-05 08:35:52.931187000 Z updated_at: 2016-04-05 08:35:52.931187000 Z invoicing_profile_id: 7 + statistic_profile_id: 7 reference: '1203002' avoir_mode: avoir_date: @@ -76,7 +80,7 @@ invoice_4: type: subscription_to_expire: description: - footprint: 18a80a204730011d5c5b753bf9ff86bda49acf7acbdcf31cf37d67df9ae6e53e + footprint: 6c70f2bbbb3fd02a1ad7437ccd14456d1281d5a1f8666cce2e9d0b64701a837d environment: test operator_id: @@ -89,6 +93,7 @@ invoice_5: created_at: 2016-04-05 08:36:46.853368000 Z updated_at: 2016-04-05 08:36:46.853368000 Z invoicing_profile_id: 3 + statistic_profile_id: 3 reference: '1506031' avoir_mode: avoir_date: @@ -96,6 +101,6 @@ invoice_5: type: subscription_to_expire: description: - footprint: c94afc0e5054da75522d438e8f33e6fcadc94c960ce7bdcf4cb4d83e7ca2a8e9 + footprint: cccd4f290d900cb7004baa63896191a6938305e75589d137655cb91a0e7dede2 environment: test operator_id: diff --git a/test/fixtures/projects.yml b/test/fixtures/projects.yml index d371acfd9..07e635e93 100644 --- a/test/fixtures/projects.yml +++ b/test/fixtures/projects.yml @@ -6,7 +6,7 @@ project_1: pommes de terre ou d'outres légumes afin de confectionner de la purée.

" created_at: 2016-04-04 15:39:08.224918000 Z updated_at: 2016-04-04 15:39:08.224918000 Z - author_id: 5 + author_statistic_profile_id: 5 tags: cuisine licence_id: 1 state: published diff --git a/test/fixtures/user_trainings.yml b/test/fixtures/statistic_profile_trainings.yml similarity index 100% rename from test/fixtures/user_trainings.yml rename to test/fixtures/statistic_profile_trainings.yml