56 lines
3.7 KiB
PHP
56 lines
3.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace DoctrineMigrations;
|
|
|
|
use Doctrine\DBAL\Schema\Schema;
|
|
use Doctrine\Migrations\AbstractMigration;
|
|
|
|
/**
|
|
* Auto-generated Migration: Please modify to your needs!
|
|
*/
|
|
final class Version20260913133131 extends AbstractMigration
|
|
{
|
|
public function getDescription(): string
|
|
{
|
|
return 'Adds time ranges and recurring series to bookings, and drops the unique (resource, date) guard';
|
|
}
|
|
|
|
public function up(Schema $schema): void
|
|
{
|
|
$this->addSql('CREATE TABLE booking_series (id INT AUTO_INCREMENT NOT NULL, rule VARCHAR(255) NOT NULL, weekdays JSON NOT NULL, start_date DATE NOT NULL, end_date DATE NOT NULL, start_minute INT NOT NULL, end_minute INT NOT NULL, created_at DATETIME NOT NULL, user_id INT NOT NULL, resource_id INT NOT NULL, INDEX IDX_818A3AD3A76ED395 (user_id), INDEX IDX_818A3AD389329D25 (resource_id), PRIMARY KEY (id)) DEFAULT CHARACTER SET utf8mb4');
|
|
$this->addSql('ALTER TABLE booking_series ADD CONSTRAINT FK_818A3AD3A76ED395 FOREIGN KEY (user_id) REFERENCES `user` (id) ON DELETE CASCADE');
|
|
$this->addSql('ALTER TABLE booking_series ADD CONSTRAINT FK_818A3AD389329D25 FOREIGN KEY (resource_id) REFERENCES resource (id) ON DELETE RESTRICT');
|
|
// The unique index cannot express "no overlapping time range" -- and MariaDB has no
|
|
// exclusion constraints -- so the guard moves into BookingManager, which serialises on a
|
|
// SELECT ... FOR UPDATE of the resource row. This index makes that check cheap.
|
|
$this->addSql('ALTER TABLE booking DROP INDEX uniq_booking_resource_date, ADD INDEX idx_booking_resource_date (resource_id, date)');
|
|
// The defaults are what backfills existing rows: every booking made so far was a whole
|
|
// day, which is exactly 0..1440. They are dropped again immediately so the application
|
|
// stays the only thing that decides a booking's span.
|
|
$this->addSql('ALTER TABLE booking ADD start_minute INT NOT NULL DEFAULT 0, ADD end_minute INT NOT NULL DEFAULT 1440, ADD overridden TINYINT(1) NOT NULL DEFAULT 0, ADD series_id INT DEFAULT NULL');
|
|
$this->addSql('ALTER TABLE booking ALTER COLUMN start_minute DROP DEFAULT');
|
|
$this->addSql('ALTER TABLE booking ALTER COLUMN end_minute DROP DEFAULT');
|
|
$this->addSql('ALTER TABLE booking ALTER COLUMN overridden DROP DEFAULT');
|
|
$this->addSql('ALTER TABLE booking ADD CONSTRAINT FK_E00CEDDE5278319C FOREIGN KEY (series_id) REFERENCES booking_series (id) ON DELETE SET NULL');
|
|
$this->addSql('CREATE INDEX idx_booking_user_date ON booking (user_id, date)');
|
|
$this->addSql('CREATE INDEX IDX_E00CEDDE5278319C ON booking (series_id)');
|
|
}
|
|
|
|
public function down(Schema $schema): void
|
|
{
|
|
// Note the down() is lossy by nature: restoring UNIQUE(resource_id, date) fails if any
|
|
// day holds two part-day bookings of the same resource, which is the whole point of this
|
|
// migration. Release those first if you really need to roll back.
|
|
$this->addSql('ALTER TABLE booking_series DROP FOREIGN KEY FK_818A3AD3A76ED395');
|
|
$this->addSql('ALTER TABLE booking_series DROP FOREIGN KEY FK_818A3AD389329D25');
|
|
$this->addSql('DROP TABLE booking_series');
|
|
$this->addSql('ALTER TABLE booking DROP INDEX idx_booking_resource_date, ADD UNIQUE INDEX uniq_booking_resource_date (resource_id, date)');
|
|
$this->addSql('ALTER TABLE booking DROP FOREIGN KEY FK_E00CEDDE5278319C');
|
|
$this->addSql('DROP INDEX idx_booking_user_date ON booking');
|
|
$this->addSql('DROP INDEX IDX_E00CEDDE5278319C ON booking');
|
|
$this->addSql('ALTER TABLE booking DROP start_minute, DROP end_minute, DROP overridden, DROP series_id');
|
|
}
|
|
}
|