diff --git a/app/controllers/api/availabilities_controller.rb b/app/controllers/api/availabilities_controller.rb index 51d32dca0..d8bf5425d 100644 --- a/app/controllers/api/availabilities_controller.rb +++ b/app/controllers/api/availabilities_controller.rb @@ -260,11 +260,9 @@ class API::AvailabilitiesController < API::ApiController def verify_space_is_reserved(slot, reservations, user, user_role) reservations.each do |r| r.slots.each do |s| - if slot.availability.spaces.first.id == r.reservable_id + if slot.space.id == r.reservable_id 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_role === 'admin' slot.reservations.push r end diff --git a/app/models/reservation.rb b/app/models/reservation.rb index ac24b34b6..903c7edef 100644 --- a/app/models/reservation.rb +++ b/app/models/reservation.rb @@ -2,7 +2,10 @@ class Reservation < ActiveRecord::Base include NotifyWith::NotificationAttachedObject belongs_to :user - has_many :slots, dependent: :destroy + + has_many :slots_reservations, dependent: :destroy + has_many :slots, through: :slots_reservations + accepts_nested_attributes_for :slots, allow_destroy: true belongs_to :reservable, polymorphic: true @@ -375,7 +378,7 @@ class Reservation < ActiveRecord::Base def machine_not_already_reserved already_reserved = false self.slots.each do |slot| - same_hour_slots = Slot.joins(:reservation).where( + same_hour_slots = Slot.joins(:reservations).where( reservations: { reservable_type: self.reservable_type, reservable_id: self.reservable_id }, diff --git a/app/models/slot.rb b/app/models/slot.rb index b29b8ddb7..29f902a65 100644 --- a/app/models/slot.rb +++ b/app/models/slot.rb @@ -1,16 +1,27 @@ class Slot < ActiveRecord::Base include NotifyWith::NotificationAttachedObject - belongs_to :reservation + has_many :slots_reservations, dependent: :destroy + has_many :reservations, through: :slots_reservations belongs_to :availability - attr_accessor :is_reserved, :machine, :title, :can_modify, :is_reserved_by_current_user + attr_accessor :is_reserved, :machine, :space, :title, :can_modify, :is_reserved_by_current_user after_update :set_ex_start_end_dates_attrs, if: :dates_were_modified? after_update :notify_member_and_admin_slot_is_modified, if: :dates_were_modified? after_update :notify_member_and_admin_slot_is_canceled, if: :canceled? + # for backward compatibility + def reservation + reservations.first + end + + def destroy + update_column(:destroying, true) + super + end + def is_complete? reservations.length >= availability.nb_total_places end diff --git a/app/models/slots_reservation.rb b/app/models/slots_reservation.rb new file mode 100644 index 000000000..fdac26e2d --- /dev/null +++ b/app/models/slots_reservation.rb @@ -0,0 +1,13 @@ +class SlotsReservation < ActiveRecord::Base + belongs_to :slot + belongs_to :reservation + after_destroy :cleanup_slots + + # when the SlotsReservation is deleted (from Reservation destroy cascade), we delete the + # corresponding slot + def cleanup_slots + unless slot.destroying + slot.destroy + end + end +end diff --git a/app/views/api/availabilities/spaces.json.jbuilder b/app/views/api/availabilities/spaces.json.jbuilder index 9ee3f25a7..2286f4d9d 100644 --- a/app/views/api/availabilities/spaces.json.jbuilder +++ b/app/views/api/availabilities/spaces.json.jbuilder @@ -11,8 +11,8 @@ json.array!(@slots) do |slot| json.availability_id slot.availability_id json.space do - json.id slot.availability.spaces.first.id - json.name slot.availability.spaces.first.name + json.id slot.space.id + json.name slot.space.name end # the user who booked the slot ... json.user do diff --git a/db/migrate/20170227104736_create_slots_reservations.rb b/db/migrate/20170227104736_create_slots_reservations.rb new file mode 100644 index 000000000..772de952b --- /dev/null +++ b/db/migrate/20170227104736_create_slots_reservations.rb @@ -0,0 +1,8 @@ +class CreateSlotsReservations < ActiveRecord::Migration + def change + create_table :slots_reservations do |t| + t.belongs_to :slot, index: true, foreign_key: true + t.belongs_to :reservation, index: true, foreign_key: true + end + end +end diff --git a/db/migrate/20170227104934_migrate_slots_reservations.rb b/db/migrate/20170227104934_migrate_slots_reservations.rb new file mode 100644 index 000000000..b376f54c8 --- /dev/null +++ b/db/migrate/20170227104934_migrate_slots_reservations.rb @@ -0,0 +1,13 @@ +class MigrateSlotsReservations < ActiveRecord::Migration + def up + Slot.all.each do |slot| + SlotsReservation.create!({slot_id: slot.id, reservation_id: slot.reservation_id}) + end + end + + def down + SlotsReservation.all.each do |sr| + Slot.find(sr.slot_id).update_attributes(:reservation_id => sr.reservation_id) + end + end +end diff --git a/db/migrate/20170227113718_remove_reservation_id_from_slots.rb b/db/migrate/20170227113718_remove_reservation_id_from_slots.rb new file mode 100644 index 000000000..c9e59c02a --- /dev/null +++ b/db/migrate/20170227113718_remove_reservation_id_from_slots.rb @@ -0,0 +1,5 @@ +class RemoveReservationIdFromSlots < ActiveRecord::Migration + def change + remove_column :slots, :reservation_id, :integer + end +end diff --git a/db/migrate/20170227114634_add_destroying_to_slot.rb b/db/migrate/20170227114634_add_destroying_to_slot.rb new file mode 100644 index 000000000..b46a9915a --- /dev/null +++ b/db/migrate/20170227114634_add_destroying_to_slot.rb @@ -0,0 +1,7 @@ +class AddDestroyingToSlot < ActiveRecord::Migration + def change + # this allow to prevent conflicts of 'delete cascade' by marking a slot + # as 'currently being destroyed' + add_column :slots, :destroying, :boolean, default: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 33a09cd11..4a276470d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -15,8 +15,8 @@ ActiveRecord::Schema.define(version: 20170213142543) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" - enable_extension "unaccent" enable_extension "pg_trgm" + enable_extension "unaccent" create_table "abuses", force: :cascade do |t| t.integer "signaled_id" @@ -32,14 +32,14 @@ ActiveRecord::Schema.define(version: 20170213142543) do add_index "abuses", ["signaled_type", "signaled_id"], name: "index_abuses_on_signaled_type_and_signaled_id", using: :btree create_table "addresses", force: :cascade do |t| - t.string "address" - t.string "street_number" - t.string "route" - t.string "locality" - t.string "country" - t.string "postal_code" + t.string "address", limit: 255 + t.string "street_number", limit: 255 + t.string "route", limit: 255 + t.string "locality", limit: 255 + t.string "country", limit: 255 + t.string "postal_code", limit: 255 t.integer "placeable_id" - t.string "placeable_type" + t.string "placeable_type", limit: 255 t.datetime "created_at" t.datetime "updated_at" end @@ -55,9 +55,9 @@ ActiveRecord::Schema.define(version: 20170213142543) do create_table "assets", force: :cascade do |t| t.integer "viewable_id" - t.string "viewable_type" - t.string "attachment" - t.string "type" + t.string "viewable_type", limit: 255 + t.string "attachment", limit: 255 + t.string "type", limit: 255 t.datetime "created_at" t.datetime "updated_at" end @@ -74,11 +74,11 @@ ActiveRecord::Schema.define(version: 20170213142543) do create_table "availabilities", force: :cascade do |t| t.datetime "start_at" t.datetime "end_at" - t.string "available_type" + t.string "available_type", limit: 255 t.datetime "created_at" t.datetime "updated_at" t.integer "nb_total_places" - t.boolean "destroying", default: false + t.boolean "destroying", default: false end create_table "availability_tags", force: :cascade do |t| @@ -92,7 +92,7 @@ ActiveRecord::Schema.define(version: 20170213142543) do add_index "availability_tags", ["tag_id"], name: "index_availability_tags_on_tag_id", using: :btree create_table "categories", force: :cascade do |t| - t.string "name" + t.string "name", limit: 255 t.datetime "created_at" t.datetime "updated_at" t.string "slug" @@ -101,7 +101,7 @@ ActiveRecord::Schema.define(version: 20170213142543) do add_index "categories", ["slug"], name: "index_categories_on_slug", unique: true, using: :btree create_table "components", force: :cascade do |t| - t.string "name", null: false + t.string "name", limit: 255, null: false end create_table "coupons", force: :cascade do |t| @@ -119,7 +119,7 @@ ActiveRecord::Schema.define(version: 20170213142543) do create_table "credits", force: :cascade do |t| t.integer "creditable_id" - t.string "creditable_type" + t.string "creditable_type", limit: 255 t.integer "plan_id" t.integer "hours" t.datetime "created_at" @@ -160,7 +160,7 @@ ActiveRecord::Schema.define(version: 20170213142543) do add_index "event_themes", ["slug"], name: "index_event_themes_on_slug", unique: true, using: :btree create_table "events", force: :cascade do |t| - t.string "title" + t.string "title", limit: 255 t.text "description" t.datetime "created_at" t.datetime "updated_at" @@ -198,10 +198,10 @@ ActiveRecord::Schema.define(version: 20170213142543) do add_index "exports", ["user_id"], name: "index_exports_on_user_id", using: :btree create_table "friendly_id_slugs", force: :cascade do |t| - t.string "slug", null: false - t.integer "sluggable_id", null: false + t.string "slug", limit: 255, null: false + t.integer "sluggable_id", null: false t.string "sluggable_type", limit: 50 - t.string "scope" + t.string "scope", limit: 255 t.datetime "created_at" end @@ -211,17 +211,17 @@ ActiveRecord::Schema.define(version: 20170213142543) do add_index "friendly_id_slugs", ["sluggable_type"], name: "index_friendly_id_slugs_on_sluggable_type", using: :btree create_table "groups", force: :cascade do |t| - t.string "name" + t.string "name", limit: 255 t.datetime "created_at" t.datetime "updated_at" - t.string "slug" + t.string "slug", limit: 255 end add_index "groups", ["slug"], name: "index_groups_on_slug", unique: true, using: :btree create_table "invoice_items", force: :cascade do |t| t.integer "invoice_id" - t.string "stp_invoice_item_id" + t.string "stp_invoice_item_id", limit: 255 t.integer "amount" t.datetime "created_at" t.datetime "updated_at" @@ -234,17 +234,17 @@ ActiveRecord::Schema.define(version: 20170213142543) do create_table "invoices", force: :cascade do |t| t.integer "invoiced_id" - t.string "invoiced_type" - t.string "stp_invoice_id" + t.string "invoiced_type", limit: 255 + t.string "stp_invoice_id", limit: 255 t.integer "total" t.datetime "created_at" t.datetime "updated_at" t.integer "user_id" - t.string "reference" - t.string "avoir_mode" + t.string "reference", limit: 255 + t.string "avoir_mode", limit: 255 t.datetime "avoir_date" t.integer "invoice_id" - t.string "type" + t.string "type", limit: 255 t.boolean "subscription_to_expire" t.text "description" t.integer "wallet_amount" @@ -258,17 +258,17 @@ ActiveRecord::Schema.define(version: 20170213142543) do add_index "invoices", ["wallet_transaction_id"], name: "index_invoices_on_wallet_transaction_id", using: :btree create_table "licences", force: :cascade do |t| - t.string "name", null: false + t.string "name", limit: 255, null: false t.text "description" end create_table "machines", force: :cascade do |t| - t.string "name", null: false + t.string "name", limit: 255, null: false t.text "description" t.text "spec" t.datetime "created_at" t.datetime "updated_at" - t.string "slug" + t.string "slug", limit: 255 end add_index "machines", ["slug"], name: "index_machines_on_slug", unique: true, using: :btree @@ -284,14 +284,14 @@ ActiveRecord::Schema.define(version: 20170213142543) do create_table "notifications", force: :cascade do |t| t.integer "receiver_id" t.integer "attached_object_id" - t.string "attached_object_type" + t.string "attached_object_type", limit: 255 t.integer "notification_type_id" - t.boolean "is_read", default: false + t.boolean "is_read", default: false t.datetime "created_at" t.datetime "updated_at" t.string "receiver_type" - t.boolean "is_send", default: false - t.jsonb "meta_data", default: {} + t.boolean "is_send", default: false + t.jsonb "meta_data", default: {} end add_index "notifications", ["notification_type_id"], name: "index_notifications_on_notification_type_id", using: :btree @@ -360,20 +360,20 @@ ActiveRecord::Schema.define(version: 20170213142543) do add_index "organizations", ["profile_id"], name: "index_organizations_on_profile_id", using: :btree create_table "plans", force: :cascade do |t| - t.string "name" + t.string "name", limit: 255 t.integer "amount" - t.string "interval" + t.string "interval", limit: 255 t.integer "group_id" - t.string "stp_plan_id" + t.string "stp_plan_id", limit: 255 t.datetime "created_at" t.datetime "updated_at" - t.integer "training_credit_nb", default: 0 - t.boolean "is_rolling", default: true + t.integer "training_credit_nb", default: 0 + t.boolean "is_rolling", default: true t.text "description" t.string "type" t.string "base_name" - t.integer "ui_weight", default: 0 - t.integer "interval_count", default: 1 + t.integer "ui_weight", default: 0 + t.integer "interval_count", default: 1 t.string "slug" end @@ -402,11 +402,11 @@ ActiveRecord::Schema.define(version: 20170213142543) do create_table "profiles", force: :cascade do |t| t.integer "user_id" - t.string "first_name" - t.string "last_name" + t.string "first_name", limit: 255 + t.string "last_name", limit: 255 t.boolean "gender" t.date "birthday" - t.string "phone" + t.string "phone", limit: 255 t.text "interest" t.text "software_mastered" t.datetime "created_at" @@ -436,7 +436,7 @@ ActiveRecord::Schema.define(version: 20170213142543) do t.integer "project_id" t.datetime "created_at" t.datetime "updated_at" - t.string "title" + t.string "title", limit: 255 t.integer "step_nb" end @@ -447,27 +447,27 @@ ActiveRecord::Schema.define(version: 20170213142543) do t.integer "user_id" t.datetime "created_at" t.datetime "updated_at" - t.boolean "is_valid", default: false - t.string "valid_token" + t.boolean "is_valid", default: false + t.string "valid_token", limit: 255 end add_index "project_users", ["project_id"], name: "index_project_users_on_project_id", using: :btree 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" + 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" - t.string "slug" + t.string "state", limit: 255 + t.string "slug", limit: 255 t.datetime "published_at" end - add_index "projects", ["slug"], name: "index_projects_on_slug", unique: true, using: :btree + add_index "projects", ["slug"], name: "index_projects_on_slug", using: :btree create_table "projects_components", force: :cascade do |t| t.integer "project_id" @@ -507,19 +507,19 @@ ActiveRecord::Schema.define(version: 20170213142543) do t.datetime "created_at" t.datetime "updated_at" t.integer "reservable_id" - t.string "reservable_type" - t.string "stp_invoice_id" + t.string "reservable_type", limit: 255 + t.string "stp_invoice_id", limit: 255 t.integer "nb_reserve_places" end - add_index "reservations", ["reservable_type", "reservable_id"], name: "index_reservations_on_reservable_type_and_reservable_id", using: :btree + add_index "reservations", ["reservable_id", "reservable_type"], name: "index_reservations_on_reservable_id_and_reservable_type", using: :btree add_index "reservations", ["stp_invoice_id"], name: "index_reservations_on_stp_invoice_id", using: :btree add_index "reservations", ["user_id"], name: "index_reservations_on_user_id", using: :btree create_table "roles", force: :cascade do |t| - t.string "name" + t.string "name", limit: 255 t.integer "resource_id" - t.string "resource_type" + t.string "resource_type", limit: 255 t.datetime "created_at" t.datetime "updated_at" end @@ -539,7 +539,6 @@ ActiveRecord::Schema.define(version: 20170213142543) do create_table "slots", force: :cascade do |t| t.datetime "start_at" t.datetime "end_at" - t.integer "reservation_id" t.datetime "created_at" t.datetime "updated_at" t.integer "availability_id" @@ -551,7 +550,6 @@ ActiveRecord::Schema.define(version: 20170213142543) do end add_index "slots", ["availability_id"], name: "index_slots_on_availability_id", using: :btree - add_index "slots", ["reservation_id"], name: "index_slots_on_reservation_id", using: :btree create_table "spaces", force: :cascade do |t| t.string "name" @@ -577,18 +575,18 @@ ActiveRecord::Schema.define(version: 20170213142543) do create_table "statistic_fields", force: :cascade do |t| t.integer "statistic_index_id" - t.string "key" - t.string "label" + t.string "key", limit: 255 + t.string "label", limit: 255 t.datetime "created_at" t.datetime "updated_at" - t.string "data_type" + t.string "data_type", limit: 255 end add_index "statistic_fields", ["statistic_index_id"], name: "index_statistic_fields_on_statistic_index_id", using: :btree create_table "statistic_graphs", force: :cascade do |t| t.integer "statistic_index_id" - t.string "chart_type" + t.string "chart_type", limit: 255 t.integer "limit" t.datetime "created_at" t.datetime "updated_at" @@ -597,17 +595,17 @@ ActiveRecord::Schema.define(version: 20170213142543) do add_index "statistic_graphs", ["statistic_index_id"], name: "index_statistic_graphs_on_statistic_index_id", using: :btree create_table "statistic_indices", force: :cascade do |t| - t.string "es_type_key" - t.string "label" + t.string "es_type_key", limit: 255 + t.string "label", limit: 255 t.datetime "created_at" t.datetime "updated_at" - t.boolean "table", default: true - t.boolean "ca", default: true + t.boolean "table", default: true + t.boolean "ca", default: true end create_table "statistic_sub_types", force: :cascade do |t| - t.string "key" - t.string "label" + t.string "key", limit: 255 + t.string "label", limit: 255 t.datetime "created_at" t.datetime "updated_at" end @@ -624,8 +622,8 @@ ActiveRecord::Schema.define(version: 20170213142543) do create_table "statistic_types", force: :cascade do |t| t.integer "statistic_index_id" - t.string "key" - t.string "label" + t.string "key", limit: 255 + t.string "label", limit: 255 t.boolean "graph" t.datetime "created_at" t.datetime "updated_at" @@ -643,7 +641,7 @@ ActiveRecord::Schema.define(version: 20170213142543) do create_table "subscriptions", force: :cascade do |t| t.integer "plan_id" t.integer "user_id" - t.string "stp_subscription_id" + t.string "stp_subscription_id", limit: 255 t.datetime "created_at" t.datetime "updated_at" t.datetime "expired_at" @@ -662,7 +660,7 @@ ActiveRecord::Schema.define(version: 20170213142543) do add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree create_table "themes", force: :cascade do |t| - t.string "name", null: false + t.string "name", limit: 255, null: false end create_table "tickets", force: :cascade do |t| @@ -677,13 +675,13 @@ ActiveRecord::Schema.define(version: 20170213142543) do add_index "tickets", ["reservation_id"], name: "index_tickets_on_reservation_id", using: :btree create_table "trainings", force: :cascade do |t| - t.string "name" + t.string "name", limit: 255 t.datetime "created_at" t.datetime "updated_at" t.integer "nb_total_places" - t.string "slug" + t.string "slug", limit: 255 t.text "description" - t.boolean "public_page", default: true + t.boolean "public_page", default: true end add_index "trainings", ["slug"], name: "index_trainings_on_slug", unique: true, using: :btree @@ -738,32 +736,32 @@ ActiveRecord::Schema.define(version: 20170213142543) do 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", default: "", null: false - t.string "encrypted_password", default: "", null: false - t.string "reset_password_token" + t.string "email", limit: 255, default: "", null: false + t.string "encrypted_password", limit: 255, default: "", null: false + t.string "reset_password_token", limit: 255 t.datetime "reset_password_sent_at" t.datetime "remember_created_at" - t.integer "sign_in_count", default: 0, null: false + t.integer "sign_in_count", default: 0, null: false t.datetime "current_sign_in_at" t.datetime "last_sign_in_at" - t.string "current_sign_in_ip" - t.string "last_sign_in_ip" - t.string "confirmation_token" + t.string "current_sign_in_ip", limit: 255 + t.string "last_sign_in_ip", limit: 255 + t.string "confirmation_token", limit: 255 t.datetime "confirmed_at" t.datetime "confirmation_sent_at" - t.string "unconfirmed_email" - t.integer "failed_attempts", default: 0, null: false - t.string "unlock_token" + t.string "unconfirmed_email", limit: 255 + t.integer "failed_attempts", default: 0, null: false + t.string "unlock_token", limit: 255 t.datetime "locked_at" t.datetime "created_at" t.datetime "updated_at" - t.boolean "is_allow_contact", default: true + t.boolean "is_allow_contact", default: true t.integer "group_id" - t.string "stp_customer_id" - t.string "username" - t.string "slug" - t.boolean "is_active", default: true - t.boolean "invoicing_disabled", default: false + t.string "stp_customer_id", limit: 255 + t.string "username", limit: 255 + t.string "slug", limit: 255 + t.boolean "is_active", default: true + t.boolean "invoicing_disabled", default: false t.string "provider" t.string "uid" t.string "auth_token" @@ -841,8 +839,6 @@ ActiveRecord::Schema.define(version: 20170213142543) do add_foreign_key "prices", "plans" add_foreign_key "projects_spaces", "projects" add_foreign_key "projects_spaces", "spaces" - add_foreign_key "spaces_availabilities", "availabilities" - add_foreign_key "spaces_availabilities", "spaces" add_foreign_key "statistic_custom_aggregations", "statistic_types" add_foreign_key "tickets", "event_price_categories" add_foreign_key "tickets", "reservations" diff --git a/test/fixtures/slots.yml b/test/fixtures/slots.yml index 10141ae73..9453d6352 100644 --- a/test/fixtures/slots.yml +++ b/test/fixtures/slots.yml @@ -3,7 +3,6 @@ slot_1: id: 1 start_at: 2012-04-11 06:00:00.000000000 Z end_at: 2012-04-11 10:00:00.000000000 Z - reservation_id: 1 created_at: 2012-03-12 13:40:22.342717000 Z updated_at: 2012-03-12 13:40:22.342717000 Z availability_id: 12 diff --git a/test/fixtures/slots_reservations.yml b/test/fixtures/slots_reservations.yml new file mode 100644 index 000000000..0809b31ae --- /dev/null +++ b/test/fixtures/slots_reservations.yml @@ -0,0 +1,5 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + slot_id: 1 + reservation_id: 1 \ No newline at end of file