Skip to content

feat(squads): fundar Squad com ciclo de vida#382

Open
guisaliba wants to merge 4 commits into
he4rt:feat/squadsfrom
guisaliba:feat/354-squads-lifecycle
Open

feat(squads): fundar Squad com ciclo de vida#382
guisaliba wants to merge 4 commits into
he4rt:feat/squadsfrom
guisaliba:feat/354-squads-lifecycle

Conversation

@guisaliba

Copy link
Copy Markdown

Closes #354

O que foi feito

Funda o primeiro slice runtime do módulo squads, criando o agregado Squad com persistência, status tipado, criação autorizada por super-admin e transições básicas de ciclo de vida.

  • ServiceProvider movido para src/SquadsServiceProvider.php e referência atualizada no composer.json
  • Migration squads via módulo, com datas Tz:
    • tenant_id
    • name
    • slug
    • objective nullable
    • status default draft
    • UNIQUE (tenant_id, slug)
    • INDEX (tenant_id, status)
  • Model Squad com @property PHPDoc, #[Table], #[UseFactory], HasUuids e cast de status
  • Factory SquadFactory
  • Enum backed string SquadStatus: draft, active, inactive, archived
  • Actions:
    • CreateSquad — cria squad como draft, apenas por super-admin, com slug único por tenant
    • ActivateSquad — muda status para active
    • DeactivateSquad — muda status para inactive
    • ArchiveSquad — muda status para archived

Critérios de aceite

  • Migration via módulo, datas Tz, UNIQUE (tenant_id, slug) e INDEX (tenant_id, status)
  • Model Squad com PHPDoc sincronizado
  • SquadStatus cast no model
  • CreateSquad só por super-admin
  • Squad nasce com status draft
  • Slug é único por tenant
  • Transições draft → active → inactive → archived
  • Testes de criação, autorização e transições

Cenários BDD → testes

  • "Super-admin cria um squad" → CreateSquadTest
  • "Usuário comum não cria squad" → CreateSquadTest
  • "Slug é único no tenant" → CreateSquadTest
  • "Ativar e arquivar" → SquadLifecycleTest
  • "Usuário comum não transiciona squad" → SquadLifecycleTest

Validação local

Rodado contra Postgres real via Docker Compose:

  • ✅ Pest focado em app-modules/squads/tests/Feature — 10 testes / 21 assertions
  • ✅ Pint — repo inteiro
  • ✅ PHPStan — 0 erros

Observação: o Pest completo da aplicação executou 845 testes, com 837 passando e 8 falhando por ausência de public/build/manifest.json em testes de UI/Filament. As falhas não passam pelo módulo squads.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Funda o primeiro slice runtime do módulo squads, introduzindo o agregado Squad com persistência (migration), SquadStatus como enum/cast no model, actions para criação e transições de status, e testes de criação/autorização/ciclo de vida.

Changes:

  • Move/ajusta o SquadsServiceProvider para src/ e atualiza referências do provider no módulo e no lockfile.
  • Adiciona migration/model/factory/enum para o agregado Squad com status tipado e unicidade de slug por tenant.
  • Implementa actions (CreateSquad, ActivateSquad, DeactivateSquad, ArchiveSquad) e testes de criação e transições.

Reviewed changes

Copilot reviewed 12 out of 13 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
composer.lock Atualiza o provider auto-discovered para o novo namespace/classe.
app-modules/squads/composer.json Atualiza o provider do módulo para He4rt\\Squads\\SquadsServiceProvider.
app-modules/squads/src/SquadsServiceProvider.php Ajusta namespace do provider para He4rt\\Squads.
app-modules/squads/database/migrations/2026_07_01_015630_create_squads_table.php Cria tabela squads com constraints/índices e timestamps Tz.
app-modules/squads/src/Models/Squad.php Define model Squad com casts e relação com Tenant.
app-modules/squads/src/Enums/SquadStatus.php Introduz enum backed string para status do squad.
app-modules/squads/database/factories/SquadFactory.php Cria factory para gerar squads válidos em testes.
app-modules/squads/src/Actions/CreateSquad.php Action de criação com autorização de super-admin e slug único por tenant.
app-modules/squads/src/Actions/ActivateSquad.php Action para transicionar status para active.
app-modules/squads/src/Actions/DeactivateSquad.php Action para transicionar status para inactive.
app-modules/squads/src/Actions/ArchiveSquad.php Action para transicionar status para archived.
app-modules/squads/tests/Feature/CreateSquadTest.php Testa criação, autorização e unicidade de slug.
app-modules/squads/tests/Feature/SquadLifecycleTest.php Testa transições e bloqueio por autorização.
Comments suppressed due to low confidence (1)

app-modules/squads/src/SquadsServiceProvider.php:7

  • O provider do módulo não carrega as migrations. Sem loadMigrationsFrom(__DIR__.'/../database/migrations'), a migration create_squads_table pode não ser descoberta quando o pacote é carregado, impedindo a criação da tabela squads em ambientes que dependem do ServiceProvider.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +5 to +22
namespace He4rt\Squads\Actions;

use He4rt\Identity\User\Models\User;
use He4rt\Squads\Enums\SquadStatus;
use He4rt\Squads\Models\Squad;
use Illuminate\Auth\Access\AuthorizationException;

final class ActivateSquad
{
public function handle(User $actor, Squad $squad): Squad
{
if (!$actor->isAdmin()) {
throw new AuthorizationException();
}

$squad->update([
'status' => SquadStatus::Active,
]);
Comment on lines +5 to +22
namespace He4rt\Squads\Actions;

use He4rt\Identity\User\Models\User;
use He4rt\Squads\Enums\SquadStatus;
use He4rt\Squads\Models\Squad;
use Illuminate\Auth\Access\AuthorizationException;

final class DeactivateSquad
{
public function handle(User $actor, Squad $squad): Squad
{
if (!$actor->isAdmin()) {
throw new AuthorizationException();
}

$squad->update([
'status' => SquadStatus::Inactive,
]);
Comment on lines +5 to +22
namespace He4rt\Squads\Actions;

use He4rt\Identity\User\Models\User;
use He4rt\Squads\Enums\SquadStatus;
use He4rt\Squads\Models\Squad;
use Illuminate\Auth\Access\AuthorizationException;

final class ArchiveSquad
{
public function handle(User $actor, Squad $squad): Squad
{
if (!$actor->isAdmin()) {
throw new AuthorizationException();
}

$squad->update([
'status' => SquadStatus::Archived,
]);
actor: $actor,
squad: $squad,
);
})->throws(AuthorizationException::class);
@stherzada stherzada linked an issue Jul 1, 2026 that may be closed by this pull request
5 tasks
@stherzada stherzada added this to the Squads milestone Jul 1, 2026
@stherzada

stherzada commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

@Clintonrocha98 @gvieira18

Meninos se puderem dar prioridade, essa task é necessária para poder liberar as outras

@stherzada stherzada added difficulty:easy 1-2 days mod:squads Squad lifecycle, membership and governance labels Jul 1, 2026
$table->string('name');
$table->string('slug');
$table->text('objective')->nullable();
$table->string('status', 30)->default(SquadStatus::Draft->value);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a good code practice to reference enum class with a value in a table column even when it will store enum values

use Illuminate\Auth\Access\AuthorizationException;

test('super-admin creates a squad as draft', function (): void {
config(['he4rt.admins' => 'guisaliba']);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its weird to see this, but while this project doesnt have a rbac module then it is what it is

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

difficulty:easy 1-2 days mod:squads Squad lifecycle, membership and governance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(squads): fundar módulo + Squad com ciclo de vida (CreateSquad)

4 participants