d1516c3f5d
First business module of Phase 2 (LST-64, rodage). Strangler-style, additive move — no behavioural change to the public API or MCP tools. - New module App\Module\TimeTracking (TimeTrackingModule, id "time-tracking", declares time-tracking.entries.view/export permissions in the RBAC catalog; operation security left on ROLE_USER, not re-wired here). - Move TimeEntry entity, repository (now interface + Doctrine impl bound in services.yaml), ActiveTimeEntryProvider, export service/controller and the 4 MCP TimeEntry tools into the module. #[ApiResource] (operations, security, uriTemplates /time_entries/*), filters and serialization groups preserved. - Doctrine mapping "TimeTracking" added; table time_entry unchanged. - Sidebar item gated with module "time-tracking" (SidebarFilter disables the route when the module is inactive). - Timestampable/Blamable adopted (first adopter): additive migration adds created_at/updated_at/created_by/updated_by (nullable, FK SET NULL) + COMMENT ON COLUMN. Functional test confirms created_at on persist and updated_at refresh on update — the suspected preUpdate recompute issue does not occur (Doctrine ORM 3.6.2 recomputes change sets after preUpdate). 159 tests green, schema mapping valid, php-cs-fixer clean.
53 lines
2.8 KiB
PHP
53 lines
2.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace DoctrineMigrations;
|
|
|
|
use Doctrine\DBAL\Schema\Schema;
|
|
use Doctrine\Migrations\AbstractMigration;
|
|
|
|
/**
|
|
* TimeTracking module (2.1): add Timestampable/Blamable columns to time_entry.
|
|
*
|
|
* TimeEntry is the first adopter of TimestampableBlamableTrait. This migration
|
|
* is purely additive — nullable columns + nullable FK to "user" with
|
|
* ON DELETE SET NULL. No DROP/ALTER on existing data. Columns are lowercase
|
|
* snake_case. Hand-written to guarantee zero destructive instruction.
|
|
*/
|
|
final class Version20260620161036 extends AbstractMigration
|
|
{
|
|
public function getDescription(): string
|
|
{
|
|
return 'TimeTracking: add timestampable/blamable columns to time_entry (additive)';
|
|
}
|
|
|
|
public function up(Schema $schema): void
|
|
{
|
|
$this->addSql('ALTER TABLE time_entry ADD created_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
|
|
$this->addSql('ALTER TABLE time_entry ADD updated_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
|
|
$this->addSql('ALTER TABLE time_entry ADD created_by INT DEFAULT NULL');
|
|
$this->addSql('ALTER TABLE time_entry ADD updated_by INT DEFAULT NULL');
|
|
$this->addSql('ALTER TABLE time_entry ADD CONSTRAINT FK_6E537C0CDE12AB56 FOREIGN KEY (created_by) REFERENCES "user" (id) ON DELETE SET NULL NOT DEFERRABLE');
|
|
$this->addSql('ALTER TABLE time_entry ADD CONSTRAINT FK_6E537C0C16FE72E1 FOREIGN KEY (updated_by) REFERENCES "user" (id) ON DELETE SET NULL NOT DEFERRABLE');
|
|
$this->addSql('CREATE INDEX IDX_6E537C0CDE12AB56 ON time_entry (created_by)');
|
|
$this->addSql('CREATE INDEX IDX_6E537C0C16FE72E1 ON time_entry (updated_by)');
|
|
$this->addSql("COMMENT ON COLUMN time_entry.created_at IS 'Creation timestamp (Timestampable, set on prePersist)'");
|
|
$this->addSql("COMMENT ON COLUMN time_entry.updated_at IS 'Last update timestamp (Timestampable, set on prePersist/preUpdate)'");
|
|
$this->addSql("COMMENT ON COLUMN time_entry.created_by IS 'User who created the entry (Blamable, FK user.id, SET NULL on delete)'");
|
|
$this->addSql("COMMENT ON COLUMN time_entry.updated_by IS 'User who last updated the entry (Blamable, FK user.id, SET NULL on delete)'");
|
|
}
|
|
|
|
public function down(Schema $schema): void
|
|
{
|
|
$this->addSql('ALTER TABLE time_entry DROP CONSTRAINT FK_6E537C0CDE12AB56');
|
|
$this->addSql('ALTER TABLE time_entry DROP CONSTRAINT FK_6E537C0C16FE72E1');
|
|
$this->addSql('DROP INDEX IDX_6E537C0CDE12AB56');
|
|
$this->addSql('DROP INDEX IDX_6E537C0C16FE72E1');
|
|
$this->addSql('ALTER TABLE time_entry DROP created_at');
|
|
$this->addSql('ALTER TABLE time_entry DROP updated_at');
|
|
$this->addSql('ALTER TABLE time_entry DROP created_by');
|
|
$this->addSql('ALTER TABLE time_entry DROP updated_by');
|
|
}
|
|
}
|