added subroles and dpi association fixed all pages and migration

This commit is contained in:
2026-06-04 12:17:17 +02:00
parent f7e97f55e9
commit b1f2bb60e3
20 changed files with 6125 additions and 638 deletions
@@ -0,0 +1,74 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreateJobSubRolesTable extends AbstractMigration
{
public function change(): void
{
$table = $this->table('job_sub_roles', [
'id' => false,
'primary_key' => ['id'],
'collation' => 'utf8mb4_unicode_ci',
'encoding' => 'utf8mb4',
]);
$table
->addColumn('id', 'integer', [
'identity' => true,
'signed' => false,
])
->addColumn('job_role_id', 'integer', [
'signed' => false,
'null' => false,
])
->addColumn('name', 'string', [
'limit' => 255,
'null' => false,
])
->addColumn('description', 'text', [
'null' => true,
'default' => null,
])
->addColumn('sort_order', 'integer', [
'signed' => false,
'null' => false,
'default' => 999,
])
->addColumn('is_active', 'boolean', [
'null' => false,
'default' => 1,
])
->addColumn('created_at', 'timestamp', [
'null' => true,
'default' => 'CURRENT_TIMESTAMP',
])
->addColumn('updated_at', 'timestamp', [
'null' => true,
'default' => 'CURRENT_TIMESTAMP',
'update' => 'CURRENT_TIMESTAMP',
])
->addIndex(['job_role_id'], [
'name' => 'idx_job_sub_roles_job_role_id',
])
->addIndex(['is_active'], [
'name' => 'idx_job_sub_roles_is_active',
])
->addIndex(['sort_order'], [
'name' => 'idx_job_sub_roles_sort_order',
])
->addForeignKey(
'job_role_id',
'job_roles',
'id',
[
'delete' => 'CASCADE',
'update' => 'CASCADE',
'constraint' => 'fk_job_sub_roles_job_role',
]
)
->create();
}
}
@@ -0,0 +1,84 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreatePpeItemsTable extends AbstractMigration
{
public function change(): void
{
$table = $this->table('ppe_items', [
'id' => false,
'primary_key' => ['id'],
'collation' => 'utf8mb4_unicode_ci',
'encoding' => 'utf8mb4',
]);
$table
->addColumn('id', 'integer', [
'identity' => true,
'signed' => false,
])
->addColumn('name', 'string', [
'limit' => 255,
'null' => false,
])
->addColumn('description', 'text', [
'null' => true,
'default' => null,
])
->addColumn('category', 'string', [
'limit' => 100,
'null' => true,
'default' => null,
'comment' => 'PPE category, for example Head, Hands, Eyes, Feet, Respiratory',
])
->addColumn('photo', 'string', [
'limit' => 255,
'null' => true,
'default' => null,
'comment' => 'PPE image path or filename',
])
->addColumn('standard_reference', 'string', [
'limit' => 255,
'null' => true,
'default' => null,
'comment' => 'Reference standard, for example EN ISO 20345',
])
->addColumn('validity_months', 'integer', [
'signed' => false,
'null' => true,
'default' => null,
'comment' => 'Default validity in months after assignment',
])
->addColumn('sort_order', 'integer', [
'signed' => false,
'null' => false,
'default' => 999,
])
->addColumn('is_active', 'boolean', [
'null' => false,
'default' => 1,
])
->addColumn('created_at', 'timestamp', [
'null' => true,
'default' => 'CURRENT_TIMESTAMP',
])
->addColumn('updated_at', 'timestamp', [
'null' => true,
'default' => 'CURRENT_TIMESTAMP',
'update' => 'CURRENT_TIMESTAMP',
])
->addIndex(['category'], [
'name' => 'idx_ppe_items_category',
])
->addIndex(['is_active'], [
'name' => 'idx_ppe_items_is_active',
])
->addIndex(['sort_order'], [
'name' => 'idx_ppe_items_sort_order',
])
->create();
}
}
@@ -0,0 +1,102 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreateEmployeePpeItemsTable extends AbstractMigration
{
public function change(): void
{
$table = $this->table('employee_ppe_items', [
'id' => false,
'primary_key' => ['id'],
'collation' => 'utf8mb4_unicode_ci',
'encoding' => 'utf8mb4',
]);
$table
->addColumn('id', 'integer', [
'identity' => true,
'signed' => false,
])
->addColumn('employee_id', 'integer', [
'signed' => false,
'null' => false,
])
->addColumn('ppe_item_id', 'integer', [
'signed' => false,
'null' => false,
])
->addColumn('assigned_date', 'date', [
'null' => true,
'default' => null,
])
->addColumn('expiry_date', 'date', [
'null' => true,
'default' => null,
])
->addColumn('quantity', 'integer', [
'signed' => false,
'null' => false,
'default' => 1,
])
->addColumn('status', 'enum', [
'values' => [
'assigned',
'returned',
'expired',
'lost',
'damaged',
],
'null' => false,
'default' => 'assigned',
])
->addColumn('notes', 'text', [
'null' => true,
'default' => null,
])
->addColumn('created_at', 'timestamp', [
'null' => true,
'default' => 'CURRENT_TIMESTAMP',
])
->addColumn('updated_at', 'timestamp', [
'null' => true,
'default' => 'CURRENT_TIMESTAMP',
'update' => 'CURRENT_TIMESTAMP',
])
->addIndex(['employee_id'], [
'name' => 'idx_employee_ppe_items_employee_id',
])
->addIndex(['ppe_item_id'], [
'name' => 'idx_employee_ppe_items_ppe_item_id',
])
->addIndex(['status'], [
'name' => 'idx_employee_ppe_items_status',
])
->addIndex(['expiry_date'], [
'name' => 'idx_employee_ppe_items_expiry_date',
])
->addForeignKey(
'employee_id',
'employees',
'id',
[
'delete' => 'CASCADE',
'update' => 'CASCADE',
'constraint' => 'fk_employee_ppe_items_employee',
]
)
->addForeignKey(
'ppe_item_id',
'ppe_items',
'id',
[
'delete' => 'RESTRICT',
'update' => 'CASCADE',
'constraint' => 'fk_employee_ppe_items_ppe_item',
]
)
->create();
}
}
@@ -0,0 +1,101 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreateJobSubRolePpeItemsTable extends AbstractMigration
{
public function change(): void
{
$table = $this->table('job_sub_role_ppe_items', [
'id' => false,
'primary_key' => ['id'],
'collation' => 'utf8mb4_unicode_ci',
'encoding' => 'utf8mb4',
]);
$table
->addColumn('id', 'integer', [
'identity' => true,
'signed' => false,
])
->addColumn('job_sub_role_id', 'integer', [
'signed' => false,
'null' => false,
])
->addColumn('ppe_item_id', 'integer', [
'signed' => false,
'null' => false,
])
->addColumn('requirement_type', 'enum', [
'values' => [
'mandatory',
'recommended',
'optional',
],
'null' => false,
'default' => 'mandatory',
'comment' => 'Defines if the PPE is mandatory, recommended or optional for the sub role',
])
->addColumn('notes', 'text', [
'null' => true,
'default' => null,
])
->addColumn('sort_order', 'integer', [
'signed' => false,
'null' => false,
'default' => 999,
])
->addColumn('is_active', 'boolean', [
'null' => false,
'default' => 1,
])
->addColumn('created_at', 'timestamp', [
'null' => true,
'default' => 'CURRENT_TIMESTAMP',
])
->addColumn('updated_at', 'timestamp', [
'null' => true,
'default' => 'CURRENT_TIMESTAMP',
'update' => 'CURRENT_TIMESTAMP',
])
->addIndex(['job_sub_role_id'], [
'name' => 'idx_job_sub_role_ppe_items_sub_role_id',
])
->addIndex(['ppe_item_id'], [
'name' => 'idx_job_sub_role_ppe_items_ppe_item_id',
])
->addIndex(['requirement_type'], [
'name' => 'idx_job_sub_role_ppe_items_requirement_type',
])
->addIndex(['is_active'], [
'name' => 'idx_job_sub_role_ppe_items_is_active',
])
->addIndex(['job_sub_role_id', 'ppe_item_id'], [
'unique' => true,
'name' => 'uq_job_sub_role_ppe_item',
])
->addForeignKey(
'job_sub_role_id',
'job_sub_roles',
'id',
[
'delete' => 'CASCADE',
'update' => 'CASCADE',
'constraint' => 'fk_job_sub_role_ppe_items_sub_role',
]
)
->addForeignKey(
'ppe_item_id',
'ppe_items',
'id',
[
'delete' => 'CASCADE',
'update' => 'CASCADE',
'constraint' => 'fk_job_sub_role_ppe_items_ppe_item',
]
)
->create();
}
}
@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class AddJobSubRoleIdToEmployeesTable extends AbstractMigration
{
public function change(): void
{
$table = $this->table('employees');
$table
->addColumn('job_sub_role_id', 'integer', [
'signed' => false,
'null' => true,
'default' => null,
'after' => 'job_role_id',
])
->addIndex(['job_sub_role_id'], [
'name' => 'idx_employees_job_sub_role_id',
])
->addForeignKey(
'job_sub_role_id',
'job_sub_roles',
'id',
[
'delete' => 'SET_NULL',
'update' => 'CASCADE',
'constraint' => 'fk_employees_job_sub_role',
]
)
->update();
}
}
@@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class AddDeliveryFieldsToEmployeePpeItemsTable extends AbstractMigration
{
public function change(): void
{
$table = $this->table('employee_ppe_items');
$table
->addColumn('delivered_by', 'string', [
'limit' => 255,
'null' => true,
'default' => null,
'after' => 'expiry_date',
])
->addColumn('created_by', 'integer', [
'signed' => false,
'null' => true,
'default' => null,
'after' => 'notes',
])
->addIndex(['created_by'], [
'name' => 'idx_employee_ppe_items_created_by',
])
->addForeignKey(
'created_by',
'auth_users',
'id',
[
'delete' => 'SET_NULL',
'update' => 'CASCADE',
'constraint' => 'fk_employee_ppe_items_created_by',
]
)
->update();
}
}
@@ -0,0 +1,96 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class CreateEmployeeJobSubRolesTable extends AbstractMigration
{
public function up(): void
{
if (!$this->hasTable('employee_job_sub_roles')) {
$table = $this->table('employee_job_sub_roles', [
'id' => false,
'primary_key' => ['id'],
'signed' => false,
'collation' => 'utf8mb4_general_ci',
'encoding' => 'utf8mb4',
]);
$table
->addColumn('id', 'integer', [
'identity' => true,
'signed' => false,
])
->addColumn('employee_id', 'integer', [
'signed' => false,
'null' => false,
])
->addColumn('job_sub_role_id', 'integer', [
'signed' => false,
'null' => false,
])
->addColumn('is_primary', 'boolean', [
'null' => false,
'default' => false,
])
->addColumn('created_at', 'timestamp', [
'null' => true,
'default' => 'CURRENT_TIMESTAMP',
])
->addIndex(['employee_id', 'job_sub_role_id'], [
'unique' => true,
'name' => 'uq_employee_subrole',
])
->addIndex(['employee_id'], [
'name' => 'idx_employee_job_sub_roles_employee',
])
->addIndex(['job_sub_role_id'], [
'name' => 'idx_employee_job_sub_roles_subrole',
])
->addForeignKey(
'employee_id',
'employees',
'id',
[
'delete' => 'CASCADE',
'update' => 'CASCADE',
'constraint' => 'fk_employee_job_sub_roles_employee',
]
)
->addForeignKey(
'job_sub_role_id',
'job_sub_roles',
'id',
[
'delete' => 'CASCADE',
'update' => 'CASCADE',
'constraint' => 'fk_employee_job_sub_roles_subrole',
]
)
->create();
}
// Import existing single sub-role assignments from employees.job_sub_role_id
// into the new bridge table.
$this->execute("
INSERT IGNORE INTO employee_job_sub_roles
(employee_id, job_sub_role_id, is_primary, created_at)
SELECT
e.id,
e.job_sub_role_id,
1,
NOW()
FROM employees e
WHERE e.job_sub_role_id IS NOT NULL
AND e.job_sub_role_id > 0
");
}
public function down(): void
{
if ($this->hasTable('employee_job_sub_roles')) {
$this->table('employee_job_sub_roles')->drop()->save();
}
}
}