First commit - backup RDOC
This commit is contained in:
399
documentation/RESUMO_ACOES_PRIORITARIAS.md
Normal file
399
documentation/RESUMO_ACOES_PRIORITARIAS.md
Normal file
@@ -0,0 +1,399 @@
|
||||
# 🎯 RESUMO DAS AÇÕES PRIORITÁRIAS - TRANSFORMAÇÃO SAAS MULTI-TENANT
|
||||
|
||||
## ✅ JÁ ESTÁ PRONTO (Não precisa implementar nada ainda!)
|
||||
|
||||
### 📦 Arquivos Criados:
|
||||
1. ✅ **4 Migrations SQL completas** em `supabase/migrations/`
|
||||
2. ✅ **Scripts de verificação** (`check-supabase-status.js`)
|
||||
3. ✅ **Scripts de deploy** (`apply-migrations.js`)
|
||||
4. ✅ **Documentação completa** (3 arquivos .md)
|
||||
|
||||
### 🗄️ Schema do Banco de Dados:
|
||||
- ✅ Tabela `organizacoes` (tenants) com slug, planos e limites
|
||||
- ✅ Sistema de roles e permissões por organização
|
||||
- ✅ Sistema de convites para onboarding
|
||||
- ✅ Todas as tabelas adaptadas com `organizacao_id`
|
||||
- ✅ RLS (Row Level Security) completo
|
||||
- ✅ Triggers automáticos para propagação de dados
|
||||
- ✅ Validação de quotas por plano
|
||||
- ✅ Funções auxiliares para permissões
|
||||
|
||||
---
|
||||
|
||||
## 🚀 PRÓXIMAS AÇÕES (Em ordem de prioridade)
|
||||
|
||||
### **1️⃣ APLICAR MIGRATIONS NO SUPABASE** ⚡ URGENTE
|
||||
|
||||
**Por que fazer primeiro?**
|
||||
Sem o banco de dados configurado, nada mais funciona.
|
||||
|
||||
**Como fazer:**
|
||||
|
||||
#### Opção A: Via Supabase CLI (Recomendado)
|
||||
```bash
|
||||
# Passo 1: Linkar projeto
|
||||
supabase link --project-ref bbyzrywmgjiufqtnkslu
|
||||
|
||||
# Passo 2: Aplicar migrations
|
||||
supabase db push
|
||||
|
||||
# Passo 3: Verificar
|
||||
node check-supabase-status.js
|
||||
```
|
||||
|
||||
#### Opção B: Via Dashboard
|
||||
1. Acesse: https://supabase.com/dashboard/project/bbyzrywmgjiufqtnkslu/editor
|
||||
2. Abra SQL Editor
|
||||
3. Execute cada migration manualmente (na ordem)
|
||||
|
||||
**Tempo estimado:** 30 minutos
|
||||
|
||||
**Resultado esperado:**
|
||||
- ✅ 16 tabelas criadas
|
||||
- ✅ RLS habilitado em todas
|
||||
- ✅ 1 organização demo criada
|
||||
- ✅ Funções e triggers funcionando
|
||||
|
||||
---
|
||||
|
||||
### **2️⃣ ATUALIZAR TIPOS TYPESCRIPT**
|
||||
|
||||
**Arquivo:** `src/types/database.types.ts`
|
||||
|
||||
**O que fazer:**
|
||||
```bash
|
||||
# Gerar tipos atualizados do Supabase
|
||||
supabase gen types typescript --project-id bbyzrywmgjiufqtnkslu > src/types/database.types.ts
|
||||
```
|
||||
|
||||
**Ou manualmente:**
|
||||
- Adicionar tipo `Organization`
|
||||
- Adicionar tipo `OrganizacaoUsuario`
|
||||
- Adicionar tipo `Convite`
|
||||
- Atualizar tipos existentes com `organizacao_id`
|
||||
|
||||
**Tempo estimado:** 1 hora
|
||||
|
||||
---
|
||||
|
||||
### **3️⃣ CRIAR CONTEXTO DE ORGANIZAÇÃO**
|
||||
|
||||
**Arquivo novo:** `src/contexts/OrganizationContext.tsx`
|
||||
|
||||
**O que criar:**
|
||||
```typescript
|
||||
interface OrganizationContextType {
|
||||
organization: Organization | null;
|
||||
loading: boolean;
|
||||
isOwner: boolean;
|
||||
isAdmin: boolean;
|
||||
userRole: string | null;
|
||||
switchOrganization: (slug: string) => Promise<void>;
|
||||
}
|
||||
|
||||
export const OrganizationProvider: React.FC<{children}> = ({children}) => {
|
||||
// Implementação
|
||||
};
|
||||
|
||||
export const useOrganization = () => useContext(OrganizationContext);
|
||||
```
|
||||
|
||||
**Integrar em:** `src/App.tsx`
|
||||
|
||||
**Tempo estimado:** 2 horas
|
||||
|
||||
---
|
||||
|
||||
### **4️⃣ IMPLEMENTAR ROTEAMENTO COM SLUG**
|
||||
|
||||
**Arquivos a modificar:**
|
||||
- `src/config/routes.tsx`
|
||||
- `src/App.tsx`
|
||||
|
||||
**Mudança:**
|
||||
```typescript
|
||||
// Antes
|
||||
{ path: '/dashboard', component: Dashboard }
|
||||
|
||||
// Depois
|
||||
{ path: '/:orgSlug/dashboard', component: Dashboard }
|
||||
```
|
||||
|
||||
**Criar componente:** `ProtectedOrgRoute`
|
||||
- Extrair slug da URL
|
||||
- Validar acesso do usuário
|
||||
- Carregar organização
|
||||
- Redirecionar se não tiver acesso
|
||||
|
||||
**Tempo estimado:** 3 horas
|
||||
|
||||
---
|
||||
|
||||
### **5️⃣ ATUALIZAR QUERIES DO SUPABASE**
|
||||
|
||||
**Criar helper:** `src/lib/supabase-tenant.ts`
|
||||
|
||||
```typescript
|
||||
export const useTenantQuery = <T>(table: string) => {
|
||||
const { organization } = useOrganization();
|
||||
|
||||
return useQuery({
|
||||
queryKey: [table, organization?.id],
|
||||
queryFn: async () => {
|
||||
const { data, error } = await supabase
|
||||
.from(table)
|
||||
.select('*')
|
||||
.eq('organizacao_id', organization?.id);
|
||||
|
||||
if (error) throw error;
|
||||
return data as T[];
|
||||
},
|
||||
enabled: !!organization?.id
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
**Atualizar TODAS as queries em:**
|
||||
- `src/hooks/useSupabaseData.ts`
|
||||
- `src/hooks/queries/*`
|
||||
- `src/stores/*`
|
||||
- `src/pages/*`
|
||||
|
||||
**Tempo estimado:** 1 dia
|
||||
|
||||
---
|
||||
|
||||
### **6️⃣ CRIAR FLUXO DE SIGNUP**
|
||||
|
||||
**Arquivo novo:** `src/pages/SignupOrganization.tsx`
|
||||
|
||||
**Fluxo:**
|
||||
1. Formulário com:
|
||||
- Nome da organização
|
||||
- Slug (validar unicidade)
|
||||
- Email do usuário
|
||||
- Nome do usuário
|
||||
- Senha
|
||||
|
||||
2. Ao submeter:
|
||||
```typescript
|
||||
// 1. Criar usuário no Auth
|
||||
const { data: authData } = await supabase.auth.signUp({
|
||||
email,
|
||||
password,
|
||||
options: {
|
||||
data: { nome, organizacao_id: null }
|
||||
}
|
||||
});
|
||||
|
||||
// 2. Criar organização e vincular usuário
|
||||
const { data: orgData } = await supabase.rpc('criar_organizacao_com_owner', {
|
||||
p_slug: slug,
|
||||
p_nome: nomeOrg,
|
||||
p_email_usuario: email,
|
||||
p_nome_usuario: nome,
|
||||
p_user_id: authData.user.id
|
||||
});
|
||||
|
||||
// 3. Redirecionar
|
||||
navigate(`/${slug}/dashboard`);
|
||||
```
|
||||
|
||||
**Tempo estimado:** 4 horas
|
||||
|
||||
---
|
||||
|
||||
### **7️⃣ CRIAR SISTEMA DE CONVITES**
|
||||
|
||||
**Arquivo novo:** `src/pages/TeamManagement.tsx`
|
||||
|
||||
**Funcionalidades:**
|
||||
- Listar membros da equipe
|
||||
- Botão "Convidar Membro"
|
||||
- Modal com formulário (email + role)
|
||||
- Gerar link de convite
|
||||
- Copiar link ou enviar por email
|
||||
|
||||
**Arquivo novo:** `src/pages/AcceptInvite.tsx`
|
||||
- Rota: `/convite/:token`
|
||||
- Validar token
|
||||
- Formulário de cadastro
|
||||
- Aceitar convite e criar conta
|
||||
|
||||
**Tempo estimado:** 6 horas
|
||||
|
||||
---
|
||||
|
||||
### **8️⃣ CRIAR DASHBOARD DE ADMIN**
|
||||
|
||||
**Arquivo novo:** `src/pages/OrganizationSettings.tsx`
|
||||
|
||||
**Abas:**
|
||||
1. **Geral** - Nome, logo, cores
|
||||
2. **Equipe** - Membros, convites, roles
|
||||
3. **Plano** - Plano atual, uso, limites
|
||||
4. **Personalização** - Tipos de atividade, funções, etc.
|
||||
|
||||
**Tempo estimado:** 1 dia
|
||||
|
||||
---
|
||||
|
||||
### **9️⃣ IMPLEMENTAR VALIDAÇÃO DE QUOTAS**
|
||||
|
||||
**Criar:** `src/lib/quota-checker.ts`
|
||||
|
||||
```typescript
|
||||
export async function checkQuota(
|
||||
resource: 'usuarios' | 'obras' | 'rdos'
|
||||
): Promise<{ allowed: boolean; message?: string }> {
|
||||
const { organization } = useOrganization();
|
||||
|
||||
const { data: metricas } = await supabase
|
||||
.from('organizacao_metricas')
|
||||
.select('*')
|
||||
.eq('organizacao_id', organization.id)
|
||||
.single();
|
||||
|
||||
// Verificar limites
|
||||
// Retornar resultado
|
||||
}
|
||||
```
|
||||
|
||||
**Integrar em:**
|
||||
- Criação de obras
|
||||
- Criação de RDOs
|
||||
- Convite de usuários
|
||||
|
||||
**Mostrar modal quando atingir limite**
|
||||
|
||||
**Tempo estimado:** 4 horas
|
||||
|
||||
---
|
||||
|
||||
### **🔟 APLICAR PERSONALIZAÇÃO**
|
||||
|
||||
**Criar:** `src/hooks/useTheme.ts`
|
||||
|
||||
```typescript
|
||||
export const useTheme = () => {
|
||||
const { organization } = useOrganization();
|
||||
|
||||
useEffect(() => {
|
||||
if (organization) {
|
||||
document.documentElement.style.setProperty(
|
||||
'--color-primary',
|
||||
organization.cor_primaria
|
||||
);
|
||||
document.documentElement.style.setProperty(
|
||||
'--color-secondary',
|
||||
organization.cor_secundaria
|
||||
);
|
||||
}
|
||||
}, [organization]);
|
||||
};
|
||||
```
|
||||
|
||||
**Carregar configurações dinâmicas:**
|
||||
- Tipos de atividade
|
||||
- Funções de mão de obra
|
||||
- Tipos de equipamento
|
||||
- Condições climáticas
|
||||
|
||||
**Tempo estimado:** 3 horas
|
||||
|
||||
---
|
||||
|
||||
## 📊 CRONOGRAMA SUGERIDO
|
||||
|
||||
### **Semana 1: Fundação**
|
||||
- ✅ Dia 1: Aplicar migrations + Atualizar tipos
|
||||
- ✅ Dia 2: Criar OrganizationContext
|
||||
- ✅ Dia 3: Implementar roteamento com slug
|
||||
- ✅ Dia 4-5: Atualizar todas as queries
|
||||
|
||||
### **Semana 2: Onboarding**
|
||||
- ✅ Dia 1: Criar signup de organização
|
||||
- ✅ Dia 2-3: Sistema de convites completo
|
||||
- ✅ Dia 4-5: Dashboard de admin
|
||||
|
||||
### **Semana 3: Refinamento**
|
||||
- ✅ Dia 1: Validação de quotas
|
||||
- ✅ Dia 2: Personalização
|
||||
- ✅ Dia 3-5: Testes e ajustes
|
||||
|
||||
**Total: 15 dias úteis (3 semanas)**
|
||||
|
||||
---
|
||||
|
||||
## 🎯 MÉTRICAS DE SUCESSO
|
||||
|
||||
### Técnicas:
|
||||
- [ ] Todas as migrations aplicadas sem erros
|
||||
- [ ] RLS funcionando (usuários não veem dados de outras orgs)
|
||||
- [ ] Quotas sendo validadas
|
||||
- [ ] Sem queries sem `organizacao_id`
|
||||
|
||||
### Funcionais:
|
||||
- [ ] Usuário consegue criar organização
|
||||
- [ ] Usuário consegue convidar membros
|
||||
- [ ] Convidado consegue aceitar e criar conta
|
||||
- [ ] Cada organização vê apenas seus dados
|
||||
- [ ] Personalização aplicada corretamente
|
||||
|
||||
### Performance:
|
||||
- [ ] Queries com índices otimizados
|
||||
- [ ] Tempo de carregamento < 2s
|
||||
- [ ] Sem N+1 queries
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ PONTOS DE ATENÇÃO
|
||||
|
||||
### Segurança:
|
||||
- ⚠️ **NUNCA** confiar apenas no frontend
|
||||
- ⚠️ **SEMPRE** validar `organizacao_id` no backend (RLS)
|
||||
- ⚠️ **NUNCA** expor service_role_key no frontend
|
||||
- ⚠️ Validar permissões em TODAS as operações
|
||||
|
||||
### Performance:
|
||||
- ⚠️ Usar índices compostos `(organizacao_id, id)`
|
||||
- ⚠️ Cachear configurações da organização
|
||||
- ⚠️ Lazy loading de recursos pesados
|
||||
|
||||
### UX:
|
||||
- ⚠️ Indicador visual da organização atual
|
||||
- ⚠️ Transição suave entre organizações
|
||||
- ⚠️ Mensagens claras quando atingir limites
|
||||
- ⚠️ Onboarding guiado para novos usuários
|
||||
|
||||
---
|
||||
|
||||
## 🆘 PRECISA DE AJUDA?
|
||||
|
||||
### Durante a implementação:
|
||||
1. **Erro nas migrations?** → Me envie a mensagem de erro
|
||||
2. **Dúvida sobre alguma fase?** → Posso detalhar qualquer parte
|
||||
3. **Problema de performance?** → Posso otimizar queries
|
||||
4. **Questão de segurança?** → Posso revisar políticas RLS
|
||||
|
||||
### Documentação de referência:
|
||||
- `INSTRUCOES_DEPLOY_SUPABASE.md` - Como aplicar migrations
|
||||
- `PLANO_SAAS_MULTI_TENANT.md` - Plano completo detalhado
|
||||
- Migrations em `supabase/migrations/` - Schema do banco
|
||||
|
||||
---
|
||||
|
||||
## 🎉 CONCLUSÃO
|
||||
|
||||
**Você tem tudo pronto para começar!**
|
||||
|
||||
O trabalho mais complexo (schema do banco de dados) já está feito.
|
||||
Agora é seguir o passo a passo acima para integrar no frontend.
|
||||
|
||||
**Próximo passo imediato:**
|
||||
```bash
|
||||
supabase link --project-ref bbyzrywmgjiufqtnkslu
|
||||
supabase db push
|
||||
```
|
||||
|
||||
**Boa sorte! 🚀**
|
||||
Reference in New Issue
Block a user