Lorsqu'un super-admin crée un établissement via l'interface, le système doit automatiquement créer la base tenant, exécuter les migrations, créer le premier utilisateur admin et envoyer l'invitation — le tout de manière asynchrone pour ne pas bloquer la réponse HTTP. Ce mécanisme rend chaque établissement opérationnel dès sa création sans intervention manuelle sur l'infrastructure.
124 lines
3.5 KiB
PHP
124 lines
3.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\SuperAdmin\Domain\Model\Establishment;
|
|
|
|
use App\Shared\Domain\AggregateRoot;
|
|
use App\Shared\Domain\Tenant\TenantId;
|
|
use App\SuperAdmin\Domain\Event\EtablissementCree;
|
|
use App\SuperAdmin\Domain\Event\EtablissementDesactive;
|
|
use App\SuperAdmin\Domain\Exception\EstablishmentDejaInactifException;
|
|
use App\SuperAdmin\Domain\Model\SuperAdmin\SuperAdminId;
|
|
use DateTimeImmutable;
|
|
|
|
use function sprintf;
|
|
|
|
/**
|
|
* Aggregate Root for an Establishment (tenant) — lives in master database.
|
|
*
|
|
* Each Establishment maps to a tenant with its own database.
|
|
*/
|
|
final class Establishment extends AggregateRoot
|
|
{
|
|
public private(set) ?DateTimeImmutable $lastActivityAt = null;
|
|
|
|
private function __construct(
|
|
public private(set) EstablishmentId $id,
|
|
public private(set) TenantId $tenantId,
|
|
public private(set) string $name,
|
|
public private(set) string $subdomain,
|
|
public private(set) string $databaseName,
|
|
public private(set) EstablishmentStatus $status,
|
|
public private(set) DateTimeImmutable $createdAt,
|
|
public private(set) ?SuperAdminId $createdBy,
|
|
) {
|
|
}
|
|
|
|
public static function creer(
|
|
string $name,
|
|
string $subdomain,
|
|
string $adminEmail,
|
|
SuperAdminId $createdBy,
|
|
DateTimeImmutable $createdAt,
|
|
): self {
|
|
$tenantId = TenantId::generate();
|
|
|
|
$establishment = new self(
|
|
id: EstablishmentId::generate(),
|
|
tenantId: $tenantId,
|
|
name: $name,
|
|
subdomain: $subdomain,
|
|
databaseName: sprintf('classeo_tenant_%s', str_replace('-', '', (string) $tenantId)),
|
|
status: EstablishmentStatus::PROVISIONING,
|
|
createdAt: $createdAt,
|
|
createdBy: $createdBy,
|
|
);
|
|
|
|
$establishment->recordEvent(new EtablissementCree(
|
|
establishmentId: $establishment->id,
|
|
tenantId: $establishment->tenantId,
|
|
name: $name,
|
|
subdomain: $subdomain,
|
|
adminEmail: $adminEmail,
|
|
occurredOn: $createdAt,
|
|
));
|
|
|
|
return $establishment;
|
|
}
|
|
|
|
public function activer(): void
|
|
{
|
|
$this->status = EstablishmentStatus::ACTIF;
|
|
}
|
|
|
|
public function desactiver(DateTimeImmutable $at): void
|
|
{
|
|
if ($this->status !== EstablishmentStatus::ACTIF) {
|
|
throw EstablishmentDejaInactifException::pour($this->id);
|
|
}
|
|
|
|
$this->status = EstablishmentStatus::INACTIF;
|
|
|
|
$this->recordEvent(new EtablissementDesactive(
|
|
establishmentId: $this->id,
|
|
occurredOn: $at,
|
|
));
|
|
}
|
|
|
|
public function enregistrerActivite(DateTimeImmutable $at): void
|
|
{
|
|
$this->lastActivityAt = $at;
|
|
}
|
|
|
|
/**
|
|
* @internal For Infrastructure use only
|
|
*/
|
|
public static function reconstitute(
|
|
EstablishmentId $id,
|
|
TenantId $tenantId,
|
|
string $name,
|
|
string $subdomain,
|
|
string $databaseName,
|
|
EstablishmentStatus $status,
|
|
DateTimeImmutable $createdAt,
|
|
?SuperAdminId $createdBy = null,
|
|
?DateTimeImmutable $lastActivityAt = null,
|
|
): self {
|
|
$establishment = new self(
|
|
id: $id,
|
|
tenantId: $tenantId,
|
|
name: $name,
|
|
subdomain: $subdomain,
|
|
databaseName: $databaseName,
|
|
status: $status,
|
|
createdAt: $createdAt,
|
|
createdBy: $createdBy,
|
|
);
|
|
|
|
$establishment->lastActivityAt = $lastActivityAt;
|
|
|
|
return $establishment;
|
|
}
|
|
}
|