Overview
Uma Cooperative representa a organização administradora. Uma Company representa a empresa de transporte que opera frota, rotas, viagens, vendas e billing.
A relação é 1:N:
- Uma
Cooperative pode administrar zero ou mais Company.
- Uma
Company pertence obrigatoriamente a uma única Cooperative.
- O vínculo é persistido em
Company.cooperativeId.
Responsabilidades
| Entidade | Responsabilidade |
|---|
Cooperative | Agrupa e administra empresas afiliadas. É o escopo de coordenação e governança. |
Company | Opera transporte. É dona de frota, motoristas vinculados, rotas, viagens, vendas e billing. |
Organization | Fornece identidade de tenant, dados cadastrais, roles, memberships e convites. |
Mesmo vinculada a uma cooperativa, a Company continua sendo a unidade operacional e financeira. Dados como Vehicle, Route, Trip, Order, Payment, Receivable, Transfer, BankAccount e CompanyPaymentSettings pertencem à empresa.
Lifecycle
- A cooperativa nasce como uma
Organization com type=COOPERATIVE e extensão Cooperative.
- A empresa nasce como uma
Organization com type=COMPANY e extensão Company.
- A criação da empresa exige uma
Cooperative ativa.
- O
cooperativeId da empresa define a afiliação administrativa.
- O owner da cooperativa recebe
Membership na organização da cooperativa.
- O owner da empresa recebe
Membership na organização da empresa.
Regras de negócio
| Regra | Descrição |
|---|
| Cardinalidade | Uma cooperativa pode ter N empresas. Uma empresa tem exatamente uma cooperativa. |
| Obrigatoriedade | Company.cooperativeId é obrigatório. Não existe Company órfã. |
| Tenant próprio | Cooperative e Company têm Organization próprias. Elas não compartilham organizationId. |
| Escopo operacional | Frota, motoristas, rotas, viagens, tickets e pedidos são sempre filtrados por companyId. |
| Escopo financeiro | Billing pertence à Company. Cooperative não recebe pagamentos, recebíveis ou transferências diretamente. |
| Administração | Usuários da Cooperative podem administrar empresas afiliadas apenas por capacidades explicitamente permitidas. |
| Auditoria | Criação, troca de afiliação, bloqueio ou remoção de Company deve registrar ator, data e motivo quando aplicável. |
Escopo de acesso
Memberships continuam sendo avaliadas no contexto da Organization ativa do usuário.
| Contexto ativo | Pode acessar |
|---|
Organization da Cooperative | Dados administrativos da cooperativa e empresas afiliadas conforme permissions disponíveis. |
Organization da Company | Operação da própria empresa: frota, rotas, viagens, vendas e billing. |
| Sem Membership no contexto | Nenhum dado privado da cooperativa ou da empresa. |
Quando uma tela de cooperativa lista empresas afiliadas, a consulta deve filtrar por:
Company.cooperativeId = Cooperative.cooperativeId do contexto ativo
Quando uma tela operacional da empresa busca recursos, a consulta deve filtrar por:
resource.companyId = Company.companyId do contexto ativo
Mudança de afiliação
A troca de Company.cooperativeId é uma operação sensível. O comportamento recomendado é tratar a troca como rotina administrativa controlada, não como edição comum de cadastro.
| Ponto | Regra |
|---|
| Autorização | Exigir permission administrativa compatível com BackOffice ou Cooperative. |
| Integridade | A nova Cooperative deve existir, estar ativa e não estar removida. |
| Dados históricos | Registros já criados continuam apontando para a mesma Company. Não reescrever companyId histórico. |
| Billing | Não alterar ownership financeiro. Billing continua pertencendo à Company. |
| Auditoria | Registrar oldCooperativeId, newCooperativeId, ator, data e motivo. |
Padrões de consulta
Listar empresas da cooperativa
SELECT Company
WHERE Company.cooperativeId = :activeCooperativeId
AND Company.deletedAt IS NULL
ORDER BY Company.createdAt DESC
Resolver cooperativa de uma empresa
SELECT Cooperative
JOIN Company ON Company.cooperativeId = Cooperative.cooperativeId
WHERE Company.companyId = :companyId
Validar se uma empresa pertence à cooperativa ativa
EXISTS Company
WHERE Company.companyId = :companyId
AND Company.cooperativeId = :activeCooperativeId
AND Company.deletedAt IS NULL
Modelagem relacionada