mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-20 14:54:15 +01:00
Merge branch 'statisticprofile' into dev
This commit is contained in:
commit
02a4660a76
2
Procfile
2
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
|
||||
|
@ -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 */
|
||||
|
@ -14,11 +14,11 @@
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" translate>{{ 'trainings' }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="hidden" name="user[training_ids][]" value="" />
|
||||
<input type="hidden" name="user[statistic_profile_attributes][training_ids][]" value="" />
|
||||
<ui-select multiple ng-model="user.training_ids" class="form-control">
|
||||
<ui-select-match>
|
||||
<span ng-bind="$item.name"></span>
|
||||
<input type="hidden" name="user[training_ids][]" value="{{$item.id}}" />
|
||||
<input type="hidden" name="user[statistic_profile_attributes][training_ids][]" value="{{$item.id}}" />
|
||||
</ui-select-match>
|
||||
<ui-select-choices ui-disable-choice="t.disabled" repeat="t.id as t in (trainings | filter: $select.search)">
|
||||
<span ng-bind-html="t.name | highlight: $select.search"></span>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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?,
|
||||
|
@ -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],
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
||||
|
@ -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?
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
18
app/views/api/projects/_indexed.json.jbuilder
Normal file
18
app/views/api/projects/_indexed.json.jbuilder
Normal file
@ -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
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
@ -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
|
@ -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)
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
@ -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
|
5
db/migrate/20190606074801_delete_user_trainings.rb
Normal file
5
db/migrate/20190606074801_delete_user_trainings.rb
Normal file
@ -0,0 +1,5 @@
|
||||
class DeleteUserTrainings < ActiveRecord::Migration
|
||||
def change
|
||||
drop_table :user_trainings
|
||||
end
|
||||
end
|
49
db/schema.rb
49
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"
|
||||
|
15
test/fixtures/invoices.yml
vendored
15
test/fixtures/invoices.yml
vendored
@ -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:
|
||||
|
2
test/fixtures/projects.yml
vendored
2
test/fixtures/projects.yml
vendored
@ -6,7 +6,7 @@ project_1:
|
||||
pommes de terre ou d'outres légumes afin de confectionner de la purée.<br></p>"
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user