1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-17 06:52:27 +01:00

fix conflt of changelog

This commit is contained in:
Peng DU 2016-06-27 12:42:57 +02:00
commit df8dbfae8c
30 changed files with 107 additions and 135 deletions

View File

@ -1,5 +1,9 @@
# Changelog Fab Manager
- add json cache for machines, events, trainings
- optimise sql query, avoid to N+1
## v2.2.1 2016 June 22
- Fix a bug: field User.merged_at should not be allowed to be mapped in SSO
- Fix a bug: integration test "user reservation without plan"
@ -36,4 +40,4 @@
- Fix a bug: custom asset favicon-file favicon file is not set
- Fix a security issue: stripe card token is now checked on server side on new/renew subscription
- Translated notification e-mails into english language
- Subscription extension logic has been extracted into a microservice
- Subscription extension logic has been extracted into a microservice

View File

@ -16,7 +16,8 @@ gem 'therubyracer', '= 0.12.0', platforms: :ruby
# Use jquery as the JavaScript library
gem 'jquery-rails'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'
gem 'jbuilder', '~> 2.5'
gem 'jbuilder_cache_multi'
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0', group: :doc #TODO remove unused ?

View File

@ -179,9 +179,11 @@ GEM
multi_xml (>= 0.5.2)
i18n (0.7.0)
ice_nine (0.11.1)
jbuilder (2.2.12)
activesupport (>= 3.0.0, < 5)
jbuilder (2.5.0)
activesupport (>= 3.0.0, < 5.1)
multi_json (~> 1.2)
jbuilder_cache_multi (0.0.3)
jbuilder (>= 1.5.0, < 3)
jquery-rails (4.0.3)
rails-dom-testing (~> 1.0)
railties (>= 4.2.0)
@ -208,13 +210,13 @@ GEM
mime-types (2.99)
mini_magick (4.2.0)
mini_portile2 (2.0.0)
minitest (5.8.4)
minitest (5.9.0)
minitest-reporters (1.1.8)
ansi
builder
minitest (>= 5.0)
ruby-progressbar
multi_json (1.11.2)
multi_json (1.12.1)
multi_xml (0.5.5)
multipart-post (2.0.0)
naught (1.0.0)
@ -452,7 +454,8 @@ DEPENDENCIES
foreman
forgery
friendly_id (~> 5.1.0)
jbuilder (~> 2.0)
jbuilder (~> 2.5)
jbuilder_cache_multi
jquery-rails
kaminari
letter_opener
@ -497,4 +500,4 @@ DEPENDENCIES
webmock
BUNDLED WITH
1.11.2
1.12.5

View File

@ -175,8 +175,8 @@ Application.Controllers.controller 'NewPlanController', ['$scope', '$uibModal',
##
# Controller used in the plan edition form
##
Application.Controllers.controller 'EditPlanController', ['$scope', 'groups', 'plans', 'planPromise', 'machines', 'prices', 'partners', 'CSRF', '$state', '$stateParams', 'growl', '$filter', '_t', '$locale'
, ($scope, groups, plans, planPromise, machines, prices, partners, CSRF, $state, $stateParams, growl, $filter, _t, $locale) ->
Application.Controllers.controller 'EditPlanController', ['$scope', 'groups', 'plans', 'planPromise', 'machines', 'prices', 'partners', 'CSRF', '$state', '$stateParams', 'growl', '$filter', '_t', '$locale', 'Plan'
, ($scope, groups, plans, planPromise, machines, prices, partners, CSRF, $state, $stateParams, growl, $filter, _t, $locale, Plan) ->
@ -207,12 +207,13 @@ Application.Controllers.controller 'EditPlanController', ['$scope', 'groups', 'p
##
$scope.copyPricesFromPlan = ->
if $scope.plan.parent
parentPlan = $scope.getPlanFromId($scope.plan.parent)
for parentPrice in parentPlan.prices
for childKey, childPrice of $scope.plan.prices
if childPrice.priceable_type == parentPrice.priceable_type and childPrice.priceable_id == parentPrice.priceable_id
$scope.plan.prices[childKey].amount = parentPrice.amount
break
Plan.get {id: $scope.plan.parent}, (parentPlan) ->
for parentPrice in parentPlan.prices
for childKey, childPrice of $scope.plan.prices
if childPrice.priceable_type == parentPrice.priceable_type and childPrice.priceable_id == parentPrice.priceable_id
$scope.plan.prices[childKey].amount = parentPrice.amount
break
# if no plan were selected, unset every prices
else
for key, price of $scope.plan.prices
@ -257,4 +258,4 @@ Application.Controllers.controller 'EditPlanController', ['$scope', 'groups', 'p
## !!! MUST BE CALLED AT THE END of the controller
initialize()
]
]

View File

@ -8,7 +8,7 @@ Application.Controllers.controller "EditPricingController", ["$scope", "$state",
### PUBLIC SCOPE ###
## List of machines prices (not considering any plan)
$scope.machinesPrices = machinesPricesPromise.prices
$scope.machinesPrices = machinesPricesPromise
## List of trainings pricing
$scope.trainingsPricings = trainingsPricingsPromise

View File

@ -330,7 +330,7 @@ angular.module('application.router', ['ui.router']).
controller: 'ReserveMachineController'
resolve:
plansPromise: ['Plan', (Plan)->
Plan.query(attributes_requested: "['machines_credits']").$promise
Plan.query().$promise
]
groupsPromise: ['Group', (Group)->
Group.query().$promise
@ -375,7 +375,7 @@ angular.module('application.router', ['ui.router']).
Setting.get(name: 'training_explications_alert').$promise
]
plansPromise: ['Plan', (Plan)->
Plan.query(attributes_requested: "['trainings_credits']").$promise
Plan.query().$promise
]
groupsPromise: ['Group', (Group)->
Group.query().$promise
@ -423,7 +423,7 @@ angular.module('application.router', ['ui.router']).
Setting.get(name: 'subscription_explications_alert').$promise
]
plansPromise: ['Plan', (Plan)->
Plan.query(shallow: true).$promise
Plan.query().$promise
]
groupsPromise: ['Group', (Group)->
Group.query().$promise

View File

@ -4,7 +4,7 @@ Application.Services.factory 'Price', ["$resource", ($resource)->
$resource "/api/prices/:id",
{},
query:
isArray: false
isArray: true
update:
method: 'PUT'
compute:

View File

@ -3,7 +3,7 @@ class API::AdminsController < API::ApiController
def index
authorize :admin
@admins = User.admins
@admins = User.includes(profile: [:user_avatar]).admins
end
def create

View File

@ -49,21 +49,22 @@ class API::AvailabilitiesController < API::ApiController
else
@user = current_user
end
@current_user_role = current_user.is_admin? ? 'admin' : 'user'
@machine = Machine.find(params[:machine_id])
@slots = []
@reservations = Reservation.where('reservable_type = ? and reservable_id = ?', @machine.class.to_s, @machine.id).joins(:slots).where('slots.start_at > ?', Time.now)
@reservations = Reservation.where('reservable_type = ? and reservable_id = ?', @machine.class.to_s, @machine.id).includes(:slots, user: [:profile]).references(:slots, :user).where('slots.start_at > ?', Time.now)
if @user.is_admin?
@availabilities = @machine.availabilities.where("end_at > ? AND available_type = 'machines'", Time.now)
@availabilities = @machine.availabilities.includes(:tags).where("end_at > ? AND available_type = 'machines'", Time.now)
else
end_at = 1.month.since
end_at = 3.months.since if is_subscription_year(@user)
@availabilities = @machine.availabilities.includes(:availability_tags).where("end_at > ? AND end_at < ? AND available_type = 'machines'", Time.now, end_at).where('availability_tags.tag_id' => @user.tag_ids.concat([nil]))
@availabilities = @machine.availabilities.includes(:tags).where("end_at > ? AND end_at < ? AND available_type = 'machines'", Time.now, end_at).where('availability_tags.tag_id' => @user.tag_ids.concat([nil]))
end
@availabilities.each do |a|
((a.end_at - a.start_at)/SLOT_DURATION.minutes).to_i.times do |i|
if (a.start_at + (i * SLOT_DURATION).minutes) > Time.now
slot = Slot.new(start_at: a.start_at + (i*SLOT_DURATION).minutes, end_at: a.start_at + (i*SLOT_DURATION).minutes + SLOT_DURATION.minutes, availability_id: a.id, machine: @machine, title: '')
slot = verify_machine_is_reserved(slot, @reservations)
slot = Slot.new(start_at: a.start_at + (i*SLOT_DURATION).minutes, end_at: a.start_at + (i*SLOT_DURATION).minutes + SLOT_DURATION.minutes, availability_id: a.id, availability: a, machine: @machine, title: '')
slot = verify_machine_is_reserved(slot, @reservations, current_user, @current_user_role)
@slots << slot
end
end
@ -77,13 +78,13 @@ class API::AvailabilitiesController < API::ApiController
@user = current_user
end
@slots = []
@reservations = @user.reservations.where("reservable_type = 'Training'").joins(:slots).where('slots.start_at > ?', Time.now)
@reservations = @user.reservations.includes(:slots).references(:slots).where("reservable_type = 'Training' AND slots.start_at > ?", Time.now)
if @user.is_admin?
@availabilities = Availability.trainings.where('start_at > ?', Time.now)
@availabilities = Availability.includes(:tags, :slots, trainings: [:machines]).trainings.where('availabilities.start_at > ?', Time.now)
else
end_at = 1.month.since
end_at = 3.months.since if can_show_slot_plus_three_months(@user)
@availabilities = Availability.trainings.includes(:availability_tags).where('start_at > ? AND start_at < ?', Time.now, end_at).where('availability_tags.tag_id' => @user.tag_ids.concat([nil]))
@availabilities = Availability.includes(:tags, :slots, trainings: [:machines]).trainings.where('start_at > ? AND start_at < ?', Time.now, end_at).where('availability_tags.tag_id' => @user.tag_ids.concat([nil]))
end
@availabilities.each do |a|
a = verify_training_is_reserved(a, @reservations)
@ -115,15 +116,14 @@ class API::AvailabilitiesController < API::ApiController
is_reserved
end
def verify_machine_is_reserved(slot, reservations)
user = current_user
def verify_machine_is_reserved(slot, reservations, user, user_role)
reservations.each do |r|
r.slots.each do |s|
if s.start_at == slot.start_at and s.canceled_at == nil
slot.id = s.id
slot.is_reserved = true
slot.title = t('availabilities.not_available')
slot.can_modify = true if user.is_admin?
slot.can_modify = true if user_role === 'admin'
slot.reservation = r
end
if s.start_at == slot.start_at and r.user == user and s.canceled_at == nil

View File

@ -4,13 +4,14 @@ class API::EventsController < API::ApiController
def index
@events = policy_scope(Event)
@total = @events.count
@events = @events.page(params[:page]).per(12)
@page = params[:page]
@events = @events.page(@page).per(12)
end
# GET /events/upcoming/:limit
def upcoming
limit = params[:limit]
@events = Event.includes(:event_image, :event_files, :availability)
@events = Event.includes(:event_image, :event_files, :availability, :categories)
.where('availabilities.start_at >= ?', Time.now)
.order('availabilities.start_at ASC').references(:availabilities).limit(limit)
end

View File

@ -13,7 +13,7 @@ class API::MembersController < API::ApiController
end
def last_subscribed
@members = User.active.with_role(:member).includes(:profile).where('is_allow_contact = true AND confirmed_at IS NOT NULL').order('created_at desc').limit(params[:last])
@members = User.active.with_role(:member).includes(profile: [:user_avatar]).where('is_allow_contact = true AND confirmed_at IS NOT NULL').order('created_at desc').limit(params[:last])
@requested_attributes = ['profile']
render :index
end
@ -169,7 +169,7 @@ class API::MembersController < API::ApiController
order_key = 'users.id'
end
@members = User.includes(:profile, :group)
@members = User.includes(:profile, :group, :subscriptions)
.joins(:profile, :group, :roles, 'LEFT JOIN "subscriptions" ON "subscriptions"."user_id" = "users"."id" LEFT JOIN "plans" ON "plans"."id" = "subscriptions"."plan_id"')
.where("users.is_active = 'true' AND roles.name = 'member'")
.order("#{order_key} #{direction}")

View File

@ -2,14 +2,9 @@
before_action :authenticate_user!, except: [:index]
def index
@attributes_requested = params[:attributes_requested]
@plans = Plan.all
@plans = Plan.includes(:plan_file)
@plans = @plans.where(group_id: params[:group_id]) if params[:group_id]
if params[:shallow]
render :shallow_index
else
render :index
end
render :index
end
def show

View File

@ -2,7 +2,7 @@ class API::TrainingsPricingsController < API::ApiController
before_action :authenticate_user!
def index
@trainings_pricings = TrainingsPricing.includes(:training)
@trainings_pricings = TrainingsPricing.all
end
def update

View File

@ -16,7 +16,7 @@ class Availability < ActiveRecord::Base
accepts_nested_attributes_for :tags, allow_destroy: true
scope :machines, -> { where(available_type: 'machines') }
scope :trainings, -> { where(available_type: 'training') }
scope :trainings, -> { includes(:trainings).where(available_type: 'training') }
attr_accessor :is_reserved, :slot_id, :can_modify
@ -51,9 +51,10 @@ class Availability < ActiveRecord::Base
# if haven't defined a nb_total_places, places are unlimited
def is_completed
return false if nb_total_places.blank?
nb_total_places <= slots.where(canceled_at: nil).size
nb_total_places <= slots.to_a.select {|s| s.canceled_at == nil }.size
end
# TODO: refactoring this function for avoid N+1 query
def nb_total_places
if read_attribute(:nb_total_places).present?
read_attribute(:nb_total_places)

View File

@ -15,6 +15,8 @@ class Event < ActiveRecord::Base
after_create :event_recurrence
before_save :update_nb_free_places
# update event updated_at for index cache
after_save -> { self.touch }
def name
title

View File

@ -2,12 +2,12 @@ class EventPolicy < ApplicationPolicy
class Scope < Scope
def resolve
if user.nil? or (user and !user.is_admin?)
scope.includes(:event_image, :event_files, :availability)
scope.includes(:event_image, :event_files, :availability, :categories)
.where('availabilities.start_at >= ?', Time.now)
.order('availabilities.start_at ASC')
.references(:availabilities)
else
scope.includes(:event_image, :event_files, :availability)
scope.includes(:event_image, :event_files, :availability, :categories)
.order('availabilities.start_at DESC')
.references(:availabilities)
end

View File

@ -17,7 +17,7 @@ json.array!(@slots) do |slot|
json.user do
json.id slot.reservation.user.id
json.name slot.reservation.user.profile.full_name
end if slot.reservation # ... if the slot was reserved
end if @current_user_role == 'admin' and slot.reservation # ... if the slot was reserved
json.tag_ids slot.availability.tag_ids
json.tags slot.availability.tags do |t|
json.id t.id

View File

@ -2,26 +2,21 @@ json.array!(@availabilities) do |a|
json.id a.id
json.slot_id a.slot_id if a.slot_id
if a.is_reserved
json.is_reserved true
json.title "#{a.trainings[0].name}' - #{t('trainings.i_ve_reserved')}"
json.borderColor '#b2e774'
elsif a.is_completed
json.is_completed true
json.title "#{a.trainings[0].name} - #{t('trainings.completed')}"
json.borderColor '#eeeeee'
else
json.title a.trainings[0].name
json.borderColor '#bd7ae9'
end
json.start a.start_at.iso8601
json.end a.end_at.iso8601
json.is_reserved a.is_reserved
json.backgroundColor 'white'
json.borderColor a.is_reserved ? '#b2e774' : '#bd7ae9'
if a.is_reserved
json.borderColor '#b2e774'
elsif a.is_completed
json.borderColor '#eeeeee'
else
json.borderColor '#bd7ae9'
end
json.can_modify a.can_modify
json.is_completed a.is_completed
json.nb_total_places a.nb_total_places
json.training do
@ -32,7 +27,6 @@ json.array!(@availabilities) do |a|
json.id m.id
json.name m.name
end
json.amount a.trainings.first.amount_by_group(@user.group_id).amount_by_plan(nil)/100.0 if @user
end
json.tag_ids a.tag_ids
json.tags a.tags do |t|

View File

@ -1,7 +1,8 @@
json.array!(@events) do |event|
json.partial! 'api/events/event', event: event
json.event_image_small event.event_image.attachment.small.url if event.event_image
json.url event_url(event, format: :json)
json.nb_total_events @total
json.cache! [@events, @page] do
json.array!(@events) do |event|
json.partial! 'api/events/event', event: event
json.event_image_small event.event_image.attachment.small.url if event.event_image
json.url event_url(event, format: :json)
json.nb_total_events @total
end
end

View File

@ -1,6 +1,7 @@
json.array!(@events) do |event|
json.partial! 'api/events/event', event: event
json.event_image_medium event.event_image.attachment.medium.url if event.event_image
json.url event_url(event, format: :json)
json.cache! @events do
json.array!(@events) do |event|
json.partial! 'api/events/event', event: event
json.event_image_medium event.event_image.attachment.medium.url if event.event_image
json.url event_url(event, format: :json)
end
end

View File

@ -1 +1,3 @@
json.partial! 'api/groups/group', collection: @groups, as: :group
json.cache! @groups do
json.partial! 'api/groups/group', collection: @groups, as: :group
end

View File

@ -1,13 +1,7 @@
user_is_admin = (current_user and current_user.is_admin?)
json.array!(@machines) do |machine|
json.extract! machine, :id, :name, :description, :spec, :slug
json.url machine_url(machine, format: :json)
json.machine_image machine.machine_image.attachment.medium.url if machine.machine_image
json.current_user_is_training current_user.is_training_machine?(machine) if current_user
json.current_user_training_reservation do
json.partial! 'api/reservations/reservation', reservation: current_user.training_reservation_by_machine(machine)
end if current_user and !current_user.is_training_machine?(machine) and current_user.training_reservation_by_machine(machine)
json.plan_ids machine.plan_ids if user_is_admin
json.cache! @machines do
json.array!(@machines) do |machine|
json.extract! machine, :id, :name, :description, :spec, :slug
json.url machine_url(machine, format: :json)
json.machine_image machine.machine_image.attachment.medium.url if machine.machine_image
end
end

View File

@ -11,16 +11,6 @@ json.current_user_training_reservation do
json.partial! 'api/reservations/reservation', reservation: current_user.training_reservation_by_machine(@machine)
end if current_user and !current_user.is_training_machine?(@machine) and current_user.training_reservation_by_machine(@machine)
json.amount_by_group Group.all do |g|
json.id g.id
json.name g.name
json.not_subscribe_amount @machine.not_subscribe_price(g.id).amount/100.0
json.amount_by_plan @machine.prices_by_group(g.id) do |price|
json.plan_id price.plan_id
json.amount price.amount/100.0
end
end
json.machine_projects @machine.projects.published.last(10) do |p|
json.id p.id
json.name p.name

View File

@ -6,23 +6,8 @@ json.plan_file_attributes do
json.attachment_identifier plan.plan_file.attachment_identifier
end if plan.plan_file
json.prices plan.prices do |price|
json.extract! price, :id, :group_id, :plan_id, :priceable_type, :priceable_id
json.amount price.amount / 100.0
json.priceable_name price.priceable.name
end
json.partners plan.partners do |partner|
json.first_name partner.first_name
json.last_name partner.last_name
json.email partner.email
end if plan.respond_to?(:partners)
json.training_credits plan.training_credits do |tc|
json.training_id tc.creditable_id
end if attribute_requested?(@attributes_requested, 'trainings_credits')
json.machine_credits plan.machine_credits do |mc|
json.machine_id mc.creditable_id
json.hours mc.hours
end if attribute_requested?(@attributes_requested, 'machines_credits')

View File

@ -1 +1,5 @@
json.partial! 'api/plans/plan', collection: @plans, as: :plan
json.array!(@plans) do |plan|
json.extract! plan, :id, :base_name, :name, :interval, :interval_count, :group_id, :training_credit_nb, :description, :type, :ui_weight
json.amount (plan.amount / 100.00)
json.plan_file_url plan.plan_file.attachment_url if plan.plan_file
end

View File

@ -1 +1,3 @@
json.prices @prices, partial: 'api/prices/price', as: :price
json.cache! @prices do
json.partial! 'api/prices/price', collection: @prices, as: :price
end

View File

@ -1,19 +1,13 @@
json.array!(@trainings) do |training|
json.id training.id
json.name training.name
json.description training.description
json.machine_ids training.machine_ids
json.availabilities training.availabilities do |a|
json.id a.id
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.reservation.user.id
json.full_name slot.reservation.user.profile.full_name
json.is_valid slot.reservation.user.trainings.include?(training)
end
end if attribute_requested?(@requested_attributes, 'availabilities')
json.nb_total_places training.nb_total_places
role = (current_user and current_user.is_admin?) ? 'admin' : 'user'
json.plan_ids training.plan_ids if current_user and current_user.is_admin?
json.cache! [@trainings, role] do
json.array!(@trainings) do |training|
json.id training.id
json.name training.name
json.description training.description
json.machine_ids training.machine_ids
json.nb_total_places training.nb_total_places
json.plan_ids training.plan_ids if role === 'admin'
end
end

View File

@ -1,5 +1,5 @@
json.extract! @training, :id, :name, :machine_ids, :nb_total_places
json.availabilities @training.availabilities.order('start_at DESC') do |a|
json.availabilities @training.availabilities do |a|
json.id a.id
json.start_at a.start_at.iso8601
json.end_at a.end_at.iso8601

View File

@ -1,5 +1,2 @@
json.extract! trainings_pricing, :id, :group_id, :training_id
json.amount trainings_pricing.amount / 100.0
json.training do
json.name trainings_pricing.training.name
end

View File

@ -11,7 +11,7 @@ Rails.application.configure do
# Show full error reports and disable caching.
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
config.action_controller.perform_caching = true
# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false