Sistema de gerenciamento de manufatura com rastreamento de fases, clientes, produtos e kanagatas (combinações de produção).
Um aplicativo móvel e desktop (iOS, Android, macOS, Windows, Web) desenvolvido em Flutter que funciona como um ERP leve para gerenciar:
- Fases: Etapas de produção (com código de barras CODE39)
- Clientes: Cadastro de clientes
- Produtos: Catálogo de produtos
- Kanagatas: Combinações de fase + cliente + produto (rastreamento de produção)
O projeto segue Clean Architecture com separação clara de camadas:
lib/
├── core/ # Código compartilhado
│ ├── contracts/ # Interfaces e contratos
│ ├── entities/ # Entidades do domínio (Worker, Success, etc)
│ ├── injection/ # Dependency Injection (GetIt)
│ └── utils/ # Utilitários gerais
│
├── features/ # Features da aplicação
│ ├── phases/ # Gerenciamento de Fases
│ ├── clients/ # Gerenciamento de Clientes
│ ├── products/ # Gerenciamento de Produtos
│ ├── kanagatas/ # Gerenciamento de Kanagatas
│ └── authentication/ # Autenticação com Firebase
│
└── pages/ # Páginas de alto nível
├── splash_page.dart
└── home_page.dart
features/{feature}/
├── domain/ # Lógica de negócio (independente de framework)
│ ├── entities/ # Modelos de dados do domínio
│ ├── repository/ # Interfaces de repositório
│ └── usecases/ # Casos de uso (AddPhase, RemovePhase, etc)
│
├── data/ # Acesso a dados (Firebase, APIs)
│ ├── datasources/ # Conexão com Firebase/APIs
│ ├── models/ # Modelos para serialização
│ └── repositories/ # Implementação de repositórios
│
└── presentation/ # UI e gerenciamento de estado (BLoC)
├── bloc/ # BLoCs (Business Logic Component)
├── pages/ # Páginas Flutter
└── widgets/ # Widgets reutilizáveis
O app usa flutter_bloc para gerenciamento de estado:
1. Usuário clica no botão "Deletar"
↓
2. BLoC recebe evento: RemoveClient(clientId)
↓
3. BLoC emite: ClientOperationInProgress()
↓
4. Repository checa se cliente está em uma Kanagata
├─ SIM → ClientOperationError("Cliente em uso")
└─ NÃO → Delete no Firebase → ClientOperationSuccess("Deletado!")
↓
5. BLoC dispara: LoadClients() (recarrega lista)
↓
6. UI BlocListener mostra SnackBar (vermelho ou verde)
↓
7. Lista volta ao estado: ClientsLoaded
abstract class ClientsState {}
class ClientsInitial extends ClientsState {} // Inicial
class ClientsLoading extends ClientsState {} // Carregando lista
class ClientsLoaded extends ClientsState {} // Lista carregada
class ClientsError extends ClientsState {} // Erro ao carregar
class ClientOperationInProgress extends ClientsState {} // Operação em andamento
class ClientOperationError extends ClientsState {} // Erro na operação (com mensagem)
class ClientOperationSuccess extends ClientsState {} // Sucesso na operaçãoO sistema previne referências órfãs:
Antes de deletar, o sistema verifica:
// phases_repo.dart
Future<Result<PhaseFailure, Success>> removePhase(params) async {
// 1. Verifica se existe Kanagata referenciando esta fase
final hasReferences = await _kanagataSource.hasKanagatasWithPhase(params.phaseId);
if (hasReferences) {
// 2. Se existir referência, retorna erro
return Left(PhaseFailure(msg: 'Não é possível remover fase em uso'));
}
// 3. Se não tiver referência, deleta
await _phaseSource.removePhase(params.phaseId);
return Right(Success(msg: 'Fase removida com sucesso'));
}Mesma validação para:
- ✅ Fases (não pode deletar se está em uma Kanagata)
- ✅ Clientes (não pode deletar se está em uma Kanagata)
- ✅ Produtos (não pode deletar se está em uma Kanagata)
O sistema gera códigos de barras CODE39, um padrão comercial reconhecido:
// Padrão CODE39
// - Barras largas (3px) e estreitas (1.5px)
// - Altura fixa 50px
// - Começa e termina com '*'
// - Suporta: 0-9, A-Z, -, ., espaço
Exemplo: "ABC123" → *ABC123* (visualizado como barras)Padrão consistente em todas as features:
Estado Inicial: Loaded (mostra lista)
↓
Usuário: Clica em adicionar/editar/deletar
↓
BLoC: emit(OperationInProgress)
↓
Repository: Valida e executa
↓
Resultado:
├─ ERRO → emit(OperationError) → SnackBar vermelho → emit(LoadEvent) → Loaded
└─ OK → emit(OperationSuccess) → SnackBar verde → emit(LoadEvent) → Loaded
- Firebase Authentication
- Login com email/senha
- Controle de permissões por usuário
- Criar, editar, deletar fases de produção
- Cada fase tem um código de barras CODE39 único
- Busca por nome/código
- Criar, editar, deletar clientes
- Busca por nome
- Validação de referências
- Criar, editar, deletar produtos
- Busca por nome/código
- Validação de referências
- Registra combinações: Fase + Cliente + Produto
- Rastreia produção e histórico
- Impede deleção de componentes em uso
- Backend: Firebase Firestore
- Realtime: Sync automático entre dispositivos
- Offline: Cache local (planned)
- Flutter 3.38.0
- Dart 3.10.0
- iOS 12+ / Android 7+
# Clone o projeto
git clone https://github.com/Hiraokii/itou_manager.git
cd itou_manager
# Instale dependências
flutter pub get
# Configure Firebase (gere seu próprio google-services.json)
# Copie: lib/firebase_options.dart.example → lib/firebase_options.dart
# Rode em macOS (recomendado para desenvolvimento)
flutter run
# Ou em iOS (wireless, sem debugger para melhor performance)
flutter run --profile -d <device-id>Para desenvolvimento no iPhone wireless:
# Profile mode: hot reload SEM debugger (RECOMENDADO)
flutter run --profile -d <device-id>
# Debug mode normal (pode pausar em wireless)
flutter run -d <device-id>
# Release (sem hot reload, mais rápido)
flutter run --release -d <device-id>Debug → Hot reload + Debug completo + Mais lento
Profile → Hot reload + Performance real + Sem debugger (IDEAL para wireless)
Release → Sem hot reload + Mais rápido + Sem debug
- ✅ iOS 12+
- ✅ Android 7+
- ✅ macOS 10.11+
- ✅ Windows 10+
- ✅ Web (Chrome/Firefox)
O app nunca fica em estado desconhecido:
- Erro ao carregar lista →
ClientsError→ Tela de erro com retry - Erro em operação →
ClientOperationError→ SnackBar + volta ao normal - Tela branca/travamento → Debugger pausa (no modo debug)
Solução: Use --profile para wireless evitando pausas do debugger!
- ✅ Clean Architecture: Separação de responsabilidades
- ✅ BLoC Pattern: Gerenciamento de estado
- ✅ Repository Pattern: Abstração de dados
- ✅ Dependency Injection: GetIt para injeção
- ✅ Either Pattern: Tratamento de erros com dartz
Branch atual: feature/manutencao
Ao fazer commit, use mensagens descritivas:
feat: adiciona nova feature
fix: corrige bug
docs: atualiza documentação
refactor: melhora código
Proprietary - Hiraokii