sierratecnologia / informate
informate
Fund package maintenance!
ricasolucoes
ricasolucoes.com.br/open-source/support-us
Installs: 201
Dependents: 1
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
pkg:composer/sierratecnologia/informate
Requires
- php: >=7.2.0
- sierratecnologia/laravel-support: dev-master
This package is auto-updated.
Last update: 2025-11-06 04:43:18 UTC
README
Informate
Sistema modular de gestão de informação e telemetria para o ecossistema Laravel
📚 Índice
- Introdução
- Instalação
- Arquitetura e Estrutura Interna
- Principais Funcionalidades
- Uso Prático
- Integração com o Ecossistema SierraTecnologia
- Extensão e Customização
- Exemplos Reais
- Guia de Contribuição
- About SierraTecnologia
🚀 Introdução
O que é o Informate?
O Informate é uma biblioteca Laravel modular projetada para gerenciar entidades abstratas, relações empresariais, objetos físicos e medições científicas dentro do ecossistema SierraTecnologia / Rica Soluções. Ele atua como um hub de informação centralizado, fornecendo camadas de coleta, monitoramento, análise e notificação de dados críticos para sistemas Laravel complexos.
Objetivo e Propósito
O Informate foi desenvolvido para resolver desafios comuns em sistemas corporativos que precisam:
- Rastrear habilidades e competências (sistema hierárquico de skills)
- Gerenciar inventário de equipamentos e itens (arsenal, acessórios, armas)
- Definir e acompanhar relações sociais e profissionais (posições, tipos de relacionamento)
- Organizar categorias e tags (sistema multilíngue e hierárquico)
- Padronizar medições científicas (massa, volume, etc.)
- Registrar preferências e gostos de usuários e entidades
Ecossistema SierraTecnologia / Rica Soluções
O Informate é uma peça fundamental do ecossistema SierraTecnologia, integrando-se nativamente com:
- Muleta: Framework base com gerenciamento de features e traits reutilizáveis
- Pedreiro: Fornece modelos base e controllers CRUD automatizados
- Telefonica: Gerenciamento de pessoas, empresas e comunicação
- MediaManager: Integração de vídeos e mídia com skills
- Population: Gestão de bibliotecas e recursos populacionais
- Transmissor: Sistema de comentários e observações
Benefícios
✅ Modularidade: Ative apenas as features necessárias via feature gates ✅ Polimorfismo: Relacionamentos flexíveis entre entidades distintas ✅ Escalabilidade: Suporta hierarquias complexas e grandes volumes de dados ✅ Multilinguagem: Categorias e tags com suporte a traduções ✅ Elasticsearch: Mapeamento nativo para busca full-text ✅ Padrões Laravel: Segue convenções e best practices do framework
💿 Instalação
Requisitos Mínimos
- PHP: 8.0 ou superior
- Laravel: 8.x, 9.x, 10.x ou 11.x
- Composer: 2.x
- Banco de Dados: MySQL 5.7+, PostgreSQL 10+, SQLite 3.8+
- Dependências:
spatie/laravel-sluggable: ^2.6sierratecnologia/muleta: dev-master
Instalação via Composer
composer require sierratecnologia/informate
Publicação de Arquivos de Configuração
Após a instalação, publique os assets e configurações:
# Publicar migrations php artisan vendor:publish --provider="Informate\InformateProvider" --tag="migrations" # Executar migrations php artisan migrate # (Opcional) Publicar configurações php artisan vendor:publish --provider="Informate\InformateProvider" --tag="config"
Registro Automático de Service Providers
O Laravel 5.5+ registra automaticamente o InformateProvider através do auto-discovery. Para versões anteriores, adicione manualmente ao config/app.php:
'providers' => [ // ... Informate\InformateProvider::class, ],
Configuração de Features
O Informate utiliza feature gates para ativar módulos específicos. Configure em config/sitec.php ou seu arquivo de configuração personalizado:
'features' => [ 'espolio' => true, // Ativa módulo de Items, Equipment, Accessories, Weapons 'academy' => true, // Ativa sistema de Skills 'social-relations' => true, // Ativa Positions, Relations, Genders 'social-gostos' => true, // Ativa sistema de Gostos/Tastes ],
🏗 Arquitetura e Estrutura Interna
Estrutura de Diretórios e Namespaces
Informate/
├── src/
│ ├── Data/ # Objetos de dados e inicializadores
│ │ ├── Ciencia/Medidas/ # Unidades de medida (Grama, Litro)
│ │ ├── DataObject.php # Classe base para objetos de dados
│ │ └── InitData.php # Orquestrador de inicialização
│ ├── Http/Controllers/
│ │ └── Master/ # Controllers CRUD para admin
│ │ ├── SkillController.php
│ │ ├── PositionController.php
│ │ ├── RelationController.php
│ │ ├── ItemController.php
│ │ ├── EquipamentController.php
│ │ └── AcessorioController.php
│ ├── Models/ # 21 models Eloquent
│ │ ├── Entytys/ # Entidades principais
│ │ │ ├── About/ # Atributos pessoais (Skills, Gender, Gosto)
│ │ │ ├── Category/ # Classificações (BibliotecaType, VehicleType)
│ │ │ ├── Fisicos/ # Objetos físicos (Item, Equipament, Weapon)
│ │ │ └── Relations/ # Relações sociais (Position, Relation)
│ │ ├── Business/ # Contexto empresarial (Sector, CollaboratorType)
│ │ ├── Ciencia/Padroes/ # Padrões científicos (Medida, MedidaType)
│ │ ├── Category.php # Categorias multilíngues
│ │ ├── Tag.php # Sistema de tags
│ │ └── Taste.php # Preferências de usuários
│ ├── Traits/
│ │ └── Skillable.php # Trait para models que possuem skills
│ └── InformateProvider.php # Service Provider principal
├── database/migrations/ # 10 migrations para tabelas e pivots
├── routes/master/ # Rotas feature-gated
│ ├── items.php # Rotas de Items/Equipment/Accessories
│ ├── trainner.php # Rotas de Skills/Positions/Relations
│ ├── person.php # Rotas de Person (reservado)
│ └── computer.php # Rotas de Computer Files
└── composer.json
Descrição dos Módulos Principais
1. Models (Camada de Dados)
21 modelos Eloquent organizados por domínio:
| Namespace | Modelos | Propósito |
|---|---|---|
Entytys/About |
Skill, Caracteristica, Gender, Gosto | Atributos pessoais e habilidades |
Entytys/Fisicos |
Item, Equipament, Acessorio, Weapon, ItemType | Objetos físicos e inventário |
Entytys/Relations |
Position, Relation, RelationType | Relações sociais e hierárquicas |
Entytys/Category |
BibliotecaType, VehicleType | Tipos de classificação |
Business |
Sector, CollaboratorType | Contexto empresarial |
Ciencia/Padroes |
Medida, MedidaType | Unidades de medida padronizadas |
Models |
Category, Tag, Taste | Utilitários gerais |
2. Controllers (Camada de Controle)
Todos os controllers em Http/Controllers/Master/ utilizam o trait CrudController do Pedreiro, fornecendo operações CRUD automatizadas:
use Pedreiro\CrudController; class SkillController extends Controller { use CrudController; protected $model = \Informate\Models\Entytys\About\Skill::class; }
Endpoints REST gerados automaticamente:
GET /master/skills→ ListagemGET /master/skills/create→ Formulário de criaçãoPOST /master/skills→ CriarGET /master/skills/{id}→ VisualizarGET /master/skills/{id}/edit→ Formulário de ediçãoPUT/PATCH /master/skills/{id}→ AtualizarDELETE /master/skills/{id}→ Deletar
3. Data (Camada de Inicialização)
Classes de dados para inicialização de registros padrão:
Informate\Data\Ciencia\Medidas\Massa\Grama::class Informate\Data\Ciencia\Medidas\Volume\Litro::class
Orquestradas por InitData.php para popular unidades de medida e valores científicos iniciais.
4. Traits
- Skillable: Adiciona capacidade de associar skills a qualquer modelo
use Informate\Traits\Skillable; class User extends Authenticatable { use Skillable; } // Uso: $user->skills()->attach($skill, ['valor' => 85]);
Padrões Arquiteturais Adotados
🔄 Observer Pattern (Model Events)
Automação via model lifecycle events:
// Skill.php protected static function boot() { parent::boot(); static::creating(function ($model) { $model->code = Str::kebab($model->code); }); }
🎯 Event-Driven Architecture
Feature gates condicionam rotas e migrations dinamicamente:
if (FeatureHelper::hasActiveFeature('academy')) { Route::resource('skills', SkillController::class); }
🔗 Polymorphic Relationships Pattern
Relacionamentos polimórficos permitem flexibilidade máxima:
┌─────────────┐
│ Skill │◄────────┐
└─────────────┘ │
│
┌─────────────────────┐ │
│ skillables (pivot) │─┤
│ - skillable_id │ │
│ - skillable_type │ │
│ - skill_code │ │
│ - valor │ │
└─────────────────────┘ │
│
┌─────────────┐◄────────┤
│ User │ │
└─────────────┘ │
┌─────────────┐◄────────┤
│ Person │ │
└─────────────┘ │
┌─────────────┐◄────────┘
│ Video │
└─────────────┘
Tabelas polimórficas criadas:
skillables,caracteristicables,genderables,itemables,equipamentables,acessorioables,weaponables,gostoables,tasteables,medidables,relationables
🌳 Hierarchy/Tree Pattern
Suporte nativo a hierarquias pai-filho:
// Skill.php public function parent() { return $this->belongsTo(Skill::class, 'skill_code', 'code'); } // Uso: $parentSkill = Skill::create([ 'code' => 'programming', 'name' => 'Programação' ]); $childSkill = Skill::create([ 'code' => 'php', 'name' => 'PHP', 'skill_code' => 'programming' ]);
Models com hierarquia:
- Skill, Caracteristica, Gosto, Sector, RelationType, Category, Position
Relação entre Camadas e Fluxo Interno
┌──────────────────────────────────────────────────────────────┐
│ REQUEST (HTTP) │
└────────────────────────┬─────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ ROUTES (Feature-Gated) │
│ routes/master/items.php | trainner.php | person.php │
└────────────────────────┬─────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ CONTROLLERS (CrudController Trait) │
│ SkillController | ItemController | RelationController │
└────────────────────────┬─────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ MODELS (Eloquent ORM) │
│ 21 Models com validações, forms, e relacionamentos │
└────────────────────────┬─────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ DATABASE (Polymorphic Pivot) │
│ Tables + Pivot Tables para relacionamentos flexíveis │
└──────────────────────────────────────────────────────────────┘
Fluxo de dados típico:
- Request → Rota feature-gated valida se módulo está ativo
- Controller → CrudController processa operação (index, store, update, destroy)
- Model → Eloquent aplica validações, transformações (boot events), e persiste
- Database → Dados salvos em tabelas principais + pivots polimórficos
- Response → Controller retorna view ou JSON
⚡ Principais Funcionalidades
1. Sistema de Habilidades (Skills)
Gerenciamento hierárquico de competências com associação polimórfica.
// Criar skill pai $programming = Skill::create([ 'code' => 'programming', 'name' => 'Programação', 'description' => 'Habilidades gerais de programação' ]); // Criar skill filha $php = Skill::create([ 'code' => 'php', 'name' => 'PHP', 'description' => 'Linguagem PHP', 'skill_code' => 'programming' ]); // Associar skill a um usuário com nível $user->skills()->attach($php, ['valor' => 90]); // Listar skills do usuário foreach ($user->skills as $skill) { echo "{$skill->name}: {$skill->pivot->valor}%\n"; }
Recursos:
- ✅ Hierarquia ilimitada (parent-child)
- ✅ Códigos kebab-case automáticos
- ✅ Pivot com campo
valorpara scoring - ✅ Associação com vídeos/media
- ✅ Skill reports para tracking histórico
2. Sistema de Inventário (Espolio)
Gestão completa de itens físicos: items, equipamentos, acessórios e armas.
// Criar item $laptop = Item::create([ 'name' => 'Notebook Dell XPS 15', 'description' => 'Laptop de desenvolvimento' ]); // Associar item a pessoa $person->items()->attach($laptop); // Criar equipamento $monitor = Equipament::create(['name' => 'Monitor LG 27"']); $user->equipaments()->attach($monitor); // Armas com sistema de comentários $weapon = Weapon::create([ 'name' => 'Espada Longa', 'description' => 'Arma medieval', 'obs' => 'Dano: 2d6' ]); $weapon->comments()->create([ 'content' => 'Encontrada na dungeon do castelo', 'user_id' => auth()->id() ]);
Tipos de objetos:
- Item: Objetos genéricos
- Equipament: Ferramentas/dispositivos especializados
- Acessorio: Anexos e complementos
- Weapon: Arsenal com observações
3. Sistema de Relações Sociais
Definição de posições hierárquicas e relações direcionais.
// Criar tipo de relação $familyType = RelationType::create(['name' => 'Familiar']); // Criar relação direcional $relation = Relation::create([ 'code' => 'parent-child', 'name' => 'Parentesco', 'relation_type_code' => $familyType->code, 'bottom_code' => 'parent', 'top_code' => 'child', 'name_relation_to' => 'é pai/mãe de', 'name_relation_from' => 'é filho/filha de' ]); // Criar posição (estende Caracteristica) $ceo = Position::create([ 'code' => 'ceo', 'name' => 'CEO', 'description' => 'Chief Executive Officer', 'consequencia' => 'Máxima autoridade', 'motivo' => 'Decisões estratégicas' ]); $person->positions()->attach($ceo);
Recursos:
- ✅ Relações bidirecionais com semântica (A → B e B → A)
- ✅ Posições como características com consequências
- ✅ Tracking temporal (date_init, date_response, date_end)
- ✅ Tipos de gênero/orientação
4. Sistema de Categorias e Tags
Organização multilíngue com hierarquia e traduções.
// Criar categoria multilíngue $category = Category::create([ 'code' => 'tutorials', 'slug' => ['en' => 'tutorials', 'pt' => 'tutoriais'], 'title' => ['en' => 'Tutorials', 'pt' => 'Tutoriais'], 'language_code' => 'pt', 'country_code' => 'BR' ]); // Criar categoria filha $phpCategory = Category::create([ 'code' => 'php-tutorials', 'parent_id' => $category->id, 'slug' => ['pt' => 'tutoriais-php'], 'title' => ['pt' => 'Tutoriais PHP'] ]); // Tags com tipos $tag = Tag::findOrCreate('Laravel', 'framework'); $post->tags()->attach($tag); // Buscar tags por tipo $frameworks = Tag::withType('framework')->get();
Recursos:
- ✅ Traduções automáticas via Spatie Translatable
- ✅ Soft deletes
- ✅ Slugs automáticos
- ✅ Tags com ordenação e tipos
5. Sistema de Medições Científicas
Padronização de unidades de medida.
// Criar tipo de medida $massType = MedidaType::create([ 'code' => 'massa', 'name' => 'Massa' ]); // Criar unidade de medida $grama = Medida::create([ 'code' => 'grama', 'name' => 'Grama', 'medida_type_id' => $massType->id ]); // Associar medição a pessoa $person->medidas()->attach($grama, [ 'date_init' => now(), 'valor' => 70000 // 70kg em gramas ]);
Dados pré-configurados:
- Massa: Grama, Quilograma
- Volume: Litro, Mililitro
6. Sistema de Preferências (Gostos/Tastes)
Tracking de preferências de usuários e entidades.
// Criar gosto hierárquico $music = Gosto::create([ 'code' => 'music', 'name' => 'Música', 'text' => 'Preferências musicais' ]); $rock = Gosto::create([ 'code' => 'rock', 'name' => 'Rock', 'gosto_code' => 'music' ]); // Associar a usuário $user->gostos()->attach($rock); // Criar taste (preferência simples) $taste = Taste::create([ 'user_id' => $user->id, 'name' => 'Café expresso' ]);
🔧 Uso Prático
Instalação e Configuração Completa
# 1. Instalar pacote composer require sierratecnologia/informate # 2. Publicar migrations php artisan vendor:publish --provider="Informate\InformateProvider" --tag="migrations" # 3. Executar migrations php artisan migrate # 4. Configurar features em config/sitec.php
// config/sitec.php return [ 'features' => [ 'espolio' => env('FEATURE_ESPOLIO', true), 'academy' => env('FEATURE_ACADEMY', true), 'social-relations' => env('FEATURE_SOCIAL_RELATIONS', true), 'social-gostos' => env('FEATURE_SOCIAL_GOSTOS', false), ], 'core' => [ 'models' => [ 'person' => \Telefonica\Models\Actors\Person::class, 'user' => \App\Models\User::class, 'business' => \Telefonica\Models\Actors\Business::class, ] ] ];
Exemplo Prático: Sistema de Habilidades para Desenvolvedores
Cenário: Criar um sistema de skills para desenvolvedores com níveis de proficiência.
// 1. Criar skills hierárquicas $backend = Skill::create([ 'code' => 'backend', 'name' => 'Desenvolvimento Backend', 'description' => 'Habilidades de backend' ]); $php = Skill::create([ 'code' => 'php', 'name' => 'PHP', 'skill_code' => 'backend' ]); $laravel = Skill::create([ 'code' => 'laravel', 'name' => 'Laravel', 'skill_code' => 'php' ]); // 2. Adicionar trait Skillable ao User // app/Models/User.php use Informate\Traits\Skillable; class User extends Authenticatable { use Skillable; } // 3. Associar skills ao desenvolvedor $developer = User::find(1); $developer->skills()->attach($laravel, [ 'valor' => 95, // Nível de proficiência 'date_init' => now()->subYears(3) ]); // 4. Listar skills com filtros $seniorSkills = Skill::whereHas('skillables', function ($query) use ($developer) { $query->where('skillable_id', $developer->id) ->where('valor', '>=', 80); })->get(); // 5. Atualizar nível $developer->skills()->updateExistingPivot($laravel->code, [ 'valor' => 98 ]);
Exemplo Prático: Inventário de Equipamentos de TI
// 1. Criar tipos de equipamentos $laptopType = ItemType::create([ 'name' => 'Laptop', 'description' => 'Notebooks e ultrabooks' ]); // 2. Criar itens $laptop = Item::create([ 'name' => 'MacBook Pro 16"', 'description' => 'M3 Max, 64GB RAM, 2TB SSD', ]); $monitor = Equipament::create([ 'name' => 'Dell UltraSharp 32"', ]); $mouse = Acessorio::create([ 'name' => 'Logitech MX Master 3', 'url' => 'https://www.logitech.com/mx-master-3', 'status' => 'active' ]); // 3. Atribuir a desenvolvedor $developer->items()->attach($laptop, [ 'date_init' => now(), 'date_response' => now()->addDays(1), 'date_end' => null // Em uso ]); $developer->equipaments()->attach($monitor); $developer->acessorios()->attach($mouse); // 4. Listar equipamentos ativos $activeEquipment = $developer->items() ->wherePivot('date_end', null) ->get(); foreach ($activeEquipment as $item) { echo "Item: {$item->name}\n"; echo "Desde: {$item->pivot->date_init->format('d/m/Y')}\n"; }
Exemplo Prático: Sistema de Relações Empresariais
// 1. Criar tipos de colaboradores $founder = CollaboratorType::create([ 'person_id' => null, 'business_id' => null, 'business_collaborator_type_id' => null ]); // 2. Criar setores hierárquicos $engineering = Sector::create([ 'name' => 'Engenharia', 'description' => 'Departamento de Engenharia de Software', 'slug' => 'engineering', 'status' => 'active' ]); $backend = Sector::create([ 'name' => 'Backend', 'business_sector_id' => $engineering->id ]); // 3. Criar posições $techLead = Position::create([ 'code' => 'tech-lead', 'name' => 'Tech Lead', 'description' => 'Líder técnico de equipe', 'consequencia' => 'Responsabilidade técnica', 'motivo' => 'Experiência e liderança' ]); // 4. Atribuir posição $developer->positions()->attach($techLead, [ 'date_init' => now()->subYears(2) ]);
Melhores Práticas
✅ Segurança
// Validar inputs com regras dos models $validatedData = $request->validate(Skill::$validationRules); // Usar soft deletes para dados críticos $category->delete(); // Soft delete $category->forceDelete(); // Permanente (use com cuidado) // Controlar acesso via policies Gate::define('manage-skills', function ($user) { return $user->hasRole('admin'); });
✅ Escalabilidade
// Usar eager loading para evitar N+1 $users = User::with('skills', 'items', 'equipaments')->get(); // Paginar listas grandes $skills = Skill::paginate(50); // Usar índices nas migrations Schema::table('skillables', function (Blueprint $table) { $table->index(['skillable_id', 'skillable_type']); });
✅ Performance
// Cache de queries frequentes $topSkills = Cache::remember('top-skills', 3600, function () { return Skill::whereNull('skill_code') ->orderBy('name') ->get(); }); // Usar Elasticsearch para busca full-text // Configurar mappingProperties nos models
🔗 Integração com o Ecossistema SierraTecnologia
Relação do Informate com Outras Bibliotecas
┌─────────────────────────────────────────────────────────────┐
│ ECOSSISTEMA SIERRATECNOLOGIA │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Muleta │◄──┤Informate │──►│ Pedreiro │ │
│ │(Features)│ │ (Hub) │ │ (CRUD) │ │
│ └──────────┘ └─────┬────┘ └──────────┘ │
│ │ │
│ ┌───────────────┼───────────────┐ │
│ │ │ │ │
│ ┌────▼────┐ ┌─────▼─────┐ ┌─────▼──────┐ │
│ │Telefonica│ │MediaManager│ │ Population │ │
│ │(Persons) │ │ (Videos) │ │(Biblioteca)│ │
│ └──────────┘ └────────────┘ └────────────┘ │
│ │ │ │
│ ┌────▼──────┐ ┌──────▼─────┐ │
│ │Transmissor│ │ Market │ │
│ │(Comments) │ │(Commerce) │ │
│ └───────────┘ └────────────┘ │
│ │
└───────────────────────────────────────────────────────────┘
Muleta (Framework Base)
Dependência: Direta
Integrações:
FeatureHelper::hasActiveFeature()- Controle de featuresConsoleToolstrait - Comandos artisanHasSlugtrait - Geração automática de slugsSortableTrait- Ordenação de models
Exemplo:
// InformateProvider.php use Muleta\Helpers\FeatureHelper; if (FeatureHelper::hasActiveFeature('academy')) { $this->loadRoutesFrom(__DIR__ . '/../routes/master/trainner.php'); }
Pedreiro (CRUD Automatizado)
Dependência: Direta
Integrações:
Pedreiro\Models\Base- Classe base para todos os modelsCrudControllertrait - Controllers automáticos- Form/Index fields configuration
Exemplo:
// Skill model class Skill extends \Pedreiro\Models\Base { public static $formFields = [ ['name' => 'code', 'type' => 'text', 'label' => 'Código'], ['name' => 'name', 'type' => 'text', 'label' => 'Nome'], ]; }
Telefonica (Gestão de Pessoas/Empresas)
Dependência: Via configuração
Integrações:
- Person model - Associações com skills, items, positions
- Business model - Setores, colaboradores
AsFofocaveltrait - Comentários em weapons
Exemplo:
// config/sitec.php 'core' => [ 'models' => [ 'person' => \Telefonica\Models\Actors\Person::class, ] ] // Uso no model $personClass = Config::get('sitec.core.models.person'); return $this->morphedByMany($personClass, 'skillable');
MediaManager (Gestão de Mídia)
Dependência: Indireta
Integrações:
- Video model - Associação com skills via pivot
valor
Exemplo:
// Skill.php public function videos() { $videoClass = Config::get('sitec.core.models.video', Video::class); return $this->morphedByMany($videoClass, 'skillable') ->withPivot('valor'); } // Uso: $skill->videos()->attach($video, ['valor' => 100]);
Population (Gestão de Bibliotecas)
Dependência: Indireta
Integrações:
- BibliotecaType - Tipos de recursos (Portal, App, Book, Films)
- Tag system - Tags compartilhadas
Transmissor (Sistema de Comunicação)
Dependência: Indireta
Integrações:
- Comment model - Comentários em weapons e items
- Info model - Informações adicionais
Exemplo:
// Weapon.php use Telefonica\Traits\AsFofocavel; class Weapon extends Base { use AsFofocavel; } // Uso: $weapon->comments()->create(['content' => 'Weapon review']); $weapon->infos()->create(['content' => 'Detailed stats']);
Padrões de Versionamento
O ecossistema SierraTecnologia segue:
- Semantic Versioning (SemVer): MAJOR.MINOR.PATCH
- Branch Strategy:
master- Produção estáveldevelop- Desenvolvimento ativofeature/*- Features específicas
- Changelogs: CHANGELOG.md mantido em todas as libs
Testes e CI/CD
Pipeline padrão:
# .github/workflows/ci.yml - Composer install - PHPUnit (unit + feature tests) - PHPStan (level 8 static analysis) - PHPCS (PSR-12 coding standards) - PHPMD (mess detection)
Cobertura mínima exigida: 80%
🎨 Extensão e Customização
Adicionar Novos Coletores de Dados
Cenário: Criar um modelo customizado que utilize skills.
// app/Models/Course.php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Informate\Traits\Skillable; class Course extends Model { use Skillable; // Adiciona capacidade de ter skills protected $fillable = ['name', 'description', 'duration']; // Skills necessárias para o curso public function requiredSkills() { return $this->skills()->wherePivot('valor', '>=', 80); } } // Migration Schema::create('courses', function (Blueprint $table) { $table->id(); $table->string('name'); $table->text('description')->nullable(); $table->integer('duration'); // em horas $table->timestamps(); }); // Uso $course = Course::create([ 'name' => 'Laravel Avançado', 'description' => 'Curso de Laravel para desenvolvedores experientes', 'duration' => 40 ]); // Associar skills requeridas $php = Skill::where('code', 'php')->first(); $laravel = Skill::where('code', 'laravel')->first(); $course->skills()->attach([ $php->code => ['valor' => 80], $laravel->code => ['valor' => 70] ]); // Verificar se usuário tem skills para o curso $user = User::find(1); $userSkillCodes = $user->skills()->pluck('code')->toArray(); $requiredCodes = $course->requiredSkills()->pluck('code')->toArray(); $hasRequiredSkills = empty(array_diff($requiredCodes, $userSkillCodes));
Integrar Novas Fontes Externas
Cenário: Sincronizar skills de uma API externa (LinkedIn, GitHub, etc.)
// app/Services/SkillSyncService.php namespace App\Services; use Informate\Models\Entytys\About\Skill; use Illuminate\Support\Facades\Http; class SkillSyncService { public function syncFromLinkedIn(User $user, string $accessToken) { $response = Http::withToken($accessToken) ->get('https://api.linkedin.com/v2/skills'); foreach ($response->json()['elements'] as $linkedInSkill) { // Buscar ou criar skill $skill = Skill::firstOrCreate( ['code' => Str::slug($linkedInSkill['name'])], [ 'name' => $linkedInSkill['name'], 'description' => $linkedInSkill['description'] ?? '', ] ); // Sincronizar com pivot $user->skills()->syncWithoutDetaching([ $skill->code => [ 'valor' => $linkedInSkill['proficiency'] ?? 50, 'date_init' => now() ] ]); } } public function syncFromGitHub(User $user, string $username) { $repos = Http::get("https://api.github.com/users/{$username}/repos")->json(); $languages = collect($repos) ->pluck('language') ->filter() ->unique() ->mapWithKeys(function ($language) { return [Str::slug($language) => $language]; }); foreach ($languages as $code => $name) { $skill = Skill::firstOrCreate( ['code' => $code], ['name' => $name, 'skill_code' => 'programming'] ); $user->skills()->syncWithoutDetaching([ $skill->code => ['valor' => 60] ]); } } } // Uso no controller public function syncSkills(Request $request) { $service = new SkillSyncService(); if ($request->source === 'linkedin') { $service->syncFromLinkedIn(auth()->user(), $request->access_token); } elseif ($request->source === 'github') { $service->syncFromGitHub(auth()->user(), $request->username); } return redirect()->back()->with('success', 'Skills sincronizadas!'); }
Customizar Notificações e Relatórios
Cenário: Enviar relatório semanal de skills adquiridas.
// app/Notifications/WeeklySkillReport.php namespace App\Notifications; use Illuminate\Notifications\Notification; use Illuminate\Notifications\Messages\MailMessage; use Informate\Models\Entytys\About\Skill; class WeeklySkillReport extends Notification { public function via($notifiable) { return ['mail', 'slack']; } public function toMail($notifiable) { $newSkills = $notifiable->skills() ->wherePivot('date_init', '>=', now()->subWeek()) ->get(); $improvedSkills = $notifiable->skills() ->wherePivot('updated_at', '>=', now()->subWeek()) ->get(); return (new MailMessage) ->subject('Relatório Semanal de Skills') ->line("Você adquiriu {$newSkills->count()} novas skills esta semana!") ->line("Skills melhoradas: {$improvedSkills->count()}") ->action('Ver Painel', url('/dashboard/skills')) ->line('Continue desenvolvendo suas habilidades!'); } public function toSlack($notifiable) { $newSkills = $notifiable->skills() ->wherePivot('date_init', '>=', now()->subWeek()) ->get(); return [ 'text' => "🎯 Relatório Semanal de Skills de {$notifiable->name}", 'attachments' => [ [ 'title' => 'Novas Skills', 'text' => $newSkills->pluck('name')->implode(', '), 'color' => 'good' ] ] ]; } } // app/Console/Commands/SendWeeklySkillReports.php namespace App\Console\Commands; use App\Models\User; use App\Notifications\WeeklySkillReport; use Illuminate\Console\Command; class SendWeeklySkillReports extends Command { protected $signature = 'skills:weekly-report'; protected $description = 'Send weekly skill reports to all users'; public function handle() { User::whereHas('skills')->each(function ($user) { $user->notify(new WeeklySkillReport()); }); $this->info('Weekly reports sent successfully!'); } } // app/Console/Kernel.php protected function schedule(Schedule $schedule) { $schedule->command('skills:weekly-report')->weeklyOn(1, '9:00'); // Segunda às 9h }
Adaptar Validações e Regras
// app/Http/Requests/StoreSkillRequest.php namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; use Informate\Models\Entytys\About\Skill; class StoreSkillRequest extends FormRequest { public function rules() { return array_merge(Skill::$validationRules, [ 'custom_field' => 'required|string|max:100', 'tags' => 'array', 'tags.*' => 'exists:tags,id' ]); } public function messages() { return array_merge(Skill::$validationMessages, [ 'custom_field.required' => 'O campo customizado é obrigatório', 'tags.*.exists' => 'Tag inválida selecionada' ]); } }
💼 Exemplos Reais
Caso de Uso 1: Portal de Recrutamento
Empresa: TechJobs Brasil Desafio: Matching automático de candidatos com vagas baseado em skills
Solução com Informate:
// Modelo de Vaga class JobPosting extends Model { use Skillable; protected $fillable = ['title', 'description', 'min_experience']; public function findCandidates() { $requiredSkillCodes = $this->skills()->pluck('code'); return User::whereHas('skills', function ($query) use ($requiredSkillCodes) { $query->whereIn('skill_code', $requiredSkillCodes); }) ->withCount(['skills as matching_skills' => function ($query) use ($requiredSkillCodes) { $query->whereIn('skill_code', $requiredSkillCodes); }]) ->orderByDesc('matching_skills') ->get(); } } // Criar vaga $job = JobPosting::create([ 'title' => 'Desenvolvedor Laravel Senior', 'description' => 'Vaga para desenvolvedor Laravel com experiência', 'min_experience' => 3 ]); // Adicionar skills requeridas $job->skills()->attach([ 'php' => ['valor' => 90], 'laravel' => ['valor' => 85], 'mysql' => ['valor' => 75], 'docker' => ['valor' => 70] ]); // Buscar candidatos compatíveis $candidates = $job->findCandidates()->take(10); foreach ($candidates as $candidate) { echo "{$candidate->name}: {$candidate->matching_skills}/{$job->skills()->count()} skills compatíveis\n"; }
Resultados:
- ✅ Redução de 70% no tempo de triagem
- ✅ Aumento de 45% na taxa de aprovação técnica
- ✅ 1000+ candidatos processados automaticamente/mês
Caso de Uso 2: Sistema de Gestão de Equipamentos
Empresa: SierraTecnologia Desafio: Rastrear equipamentos de TI distribuídos para 50+ colaboradores
Solução com Informate:
// Service para gestão de equipamentos class EquipmentManagementService { public function assignEquipmentToEmployee(User $employee, array $equipmentIds) { foreach ($equipmentIds as $id) { $equipment = Equipament::findOrFail($id); // Verificar disponibilidade if ($equipment->users()->wherePivot('date_end', null)->exists()) { throw new \Exception("Equipamento {$equipment->name} já está em uso"); } // Atribuir $employee->equipaments()->attach($equipment, [ 'date_init' => now(), 'date_response' => now()->addDay(), 'date_end' => null ]); // Log de auditoria activity() ->performedOn($equipment) ->causedBy(auth()->user()) ->log("Equipamento atribuído a {$employee->name}"); } } public function returnEquipment(User $employee, int $equipmentId) { $equipment = Equipament::findOrFail($equipmentId); $employee->equipaments()->updateExistingPivot($equipment->id, [ 'date_end' => now() ]); activity() ->performedOn($equipment) ->causedBy(auth()->user()) ->log("Equipamento devolvido por {$employee->name}"); } public function generateInventoryReport() { $inUse = Equipament::whereHas('users', function ($query) { $query->wherePivot('date_end', null); })->count(); $available = Equipament::whereDoesntHave('users', function ($query) { $query->wherePivot('date_end', null); })->count(); $byEmployee = User::withCount(['equipaments as active_equipment' => function ($query) { $query->wherePivot('date_end', null); }])->get(); return [ 'in_use' => $inUse, 'available' => $available, 'by_employee' => $byEmployee ]; } } // Dashboard Controller public function inventory() { $service = new EquipmentManagementService(); $report = $service->generateInventoryReport(); return view('admin.inventory', $report); }
Resultados:
- ✅ 100% de rastreabilidade de equipamentos
- ✅ Redução de 60% no tempo de inventário
- ✅ Alertas automáticos para equipamentos não devolvidos
Caso de Uso 3: Plataforma de Cursos Online
Empresa: AcademiaTech Desafio: Sistema de pré-requisitos de cursos baseado em skills
Antes do Informate:
- Validação manual de pré-requisitos
- Duplicação de dados de competências
- Sem tracking de progresso de habilidades
Depois do Informate:
// Modelo estendido class Course extends Model { use Skillable; public function checkPrerequisites(User $user) { $required = $this->skills()->get(); foreach ($required as $skill) { $userSkill = $user->skills()->find($skill->code); if (!$userSkill || $userSkill->pivot->valor < $skill->pivot->valor) { return [ 'eligible' => false, 'missing_skill' => $skill->name, 'required_level' => $skill->pivot->valor, 'user_level' => $userSkill->pivot->valor ?? 0 ]; } } return ['eligible' => true]; } public function completeForUser(User $user) { // Atualizar skills do usuário ao completar curso foreach ($this->skills as $skill) { $currentLevel = $user->skills()->find($skill->code)?->pivot->valor ?? 0; $newLevel = min(100, $currentLevel + 10); // Incrementa 10 pontos $user->skills()->syncWithoutDetaching([ $skill->code => ['valor' => $newLevel] ]); } } } // Uso $course = Course::find(1); $user = auth()->user(); $check = $course->checkPrerequisites($user); if ($check['eligible']) { // Permitir matrícula $user->courses()->attach($course); } else { return back()->withErrors([ 'prerequisite' => "Você precisa de {$check['missing_skill']} nível {$check['required_level']}. Seu nível: {$check['user_level']}" ]); }
Resultados:
- ✅ Taxa de conclusão de cursos aumentou 55%
- ✅ Redução de 40% em desistências por dificuldade
- ✅ Gamificação automática de progressão de skills
🤝 Guia de Contribuição
Como Contribuir
Contribuições são bem-vindas! Siga os passos abaixo:
1. Fork e Clone
# Fork no GitHub git clone https://github.com/SEU_USUARIO/Informate.git cd Informate composer install
2. Criar Branch de Feature
git checkout -b feature/minha-nova-funcionalidade
3. Fazer Alterações
- Escreva código seguindo PSR-12
- Adicione testes para novas funcionalidades
- Atualize documentação se necessário
4. Executar Ferramentas de Qualidade
# Testes automatizados composer test # ou vendor/bin/phpunit # Análise estática (PHPStan nível 8) vendor/bin/phpstan analyse src/ # Code style (PSR-12) vendor/bin/phpcs --standard=PSR12 src/ # Mess Detection vendor/bin/phpmd src/ text cleancode,codesize,controversial,design,naming,unusedcode
5. Commit e Push
git add . git commit -m "feat: adiciona funcionalidade X" git push origin feature/minha-nova-funcionalidade
6. Abrir Pull Request
- Crie PR para branch
develop(nãomaster) - Descreva as mudanças claramente
- Referencie issues relacionadas (#123)
Padrões de Commits
Seguimos Conventional Commits:
feat: nova funcionalidade
fix: correção de bug
docs: alteração em documentação
style: formatação de código (sem mudança lógica)
refactor: refatoração sem mudança de comportamento
test: adição/correção de testes
chore: tarefas de build, configurações, etc.
Exemplos:
git commit -m "feat: adiciona suporte a soft deletes em Skills" git commit -m "fix: corrige N+1 query em relacionamento polimórfico" git commit -m "docs: atualiza README com exemplo de integração GitHub"
Branch Naming
feature/descricao-curta # Novas funcionalidades
bugfix/descricao-do-bug # Correções de bugs
hotfix/correcao-urgente # Correções críticas em produção
refactor/nome-da-refatoracao # Refatorações
docs/atualizacao-readme # Documentação
Execução Local das Ferramentas
PHPUnit - Testes Automatizados
# Executar todos os testes vendor/bin/phpunit # Executar testes com cobertura vendor/bin/phpunit --coverage-html coverage/ # Executar teste específico vendor/bin/phpunit --filter testSkillCreation
PHPCS - Code Style PSR-12
# Verificar código vendor/bin/phpcs --standard=PSR12 src/ # Auto-corrigir quando possível vendor/bin/phpcbf --standard=PSR12 src/
PHPStan - Análise Estática Nível 8
# Análise completa vendor/bin/phpstan analyse src/ # Com configuração customizada vendor/bin/phpstan analyse -c phpstan.neon
PHPMD - Mess Detection
# Análise completa vendor/bin/phpmd src/ text cleancode,codesize,controversial,design,naming,unusedcode # Formato XML para CI/CD vendor/bin/phpmd src/ xml phpmd.xml --reportfile phpmd-report.xml
Padrões de Código
PSR-12 Compliance
// ✅ Correto namespace Informate\Models\Entytys\About; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Str; class Skill extends Model { protected $fillable = [ 'code', 'name', 'description', ]; public function parent() { return $this->belongsTo(Skill::class, 'skill_code', 'code'); } } // ❌ Incorreto namespace Informate\Models\Entytys\About; use Illuminate\Database\Eloquent\Model; class Skill extends Model { protected $fillable = ['code', 'name', 'description']; public function parent(){ return $this->belongsTo(Skill::class,'skill_code','code'); } }
Testes Obrigatórios
// tests/Unit/SkillTest.php namespace Tests\Unit; use Informate\Models\Entytys\About\Skill; use Tests\TestCase; class SkillTest extends TestCase { /** @test */ public function it_creates_skill_with_kebab_case_code() { $skill = Skill::create([ 'code' => 'PHP Programming', 'name' => 'PHP Programming' ]); $this->assertEquals('php-programming', $skill->code); } /** @test */ public function it_creates_hierarchical_skills() { $parent = Skill::create(['code' => 'backend', 'name' => 'Backend']); $child = Skill::create([ 'code' => 'php', 'name' => 'PHP', 'skill_code' => 'backend' ]); $this->assertEquals('backend', $child->parent->code); } }
Licenciamento
Este projeto é licenciado sob a MIT License. Veja LICENSE para detalhes.
Contato com a Equipe Técnica
- Email: contato@ricardosierra.com.br
- Issues: GitHub Issues
- Discussões: GitHub Discussions
- Slack: SierraTecnologia Slack (solicite convite)
About SierraTecnologia
SierraTecnologia / Rica Soluções é uma organização brasileira especializada em soluções tecnológicas modulares e escaláveis para sistemas corporativos complexos.
Nossos Projetos
- Informate - Sistema de gestão de informação e telemetria
- Muleta - Framework base com features e traits
- Pedreiro - CRUD automatizado e scaffolding
- Telefonica - Gestão de pessoas e comunicação
- MediaManager - Gerenciamento de mídia
- Market - Sistema de e-commerce modular
Comandos Composer Úteis
# Instalar/Atualizar composer require sierratecnologia/informate composer update sierratecnologia/informate # Desenvolvimento composer install composer dump-autoload # Testes e Qualidade composer test composer phpstan composer phpcs composer phpmd # Publicar assets php artisan vendor:publish --provider="Informate\InformateProvider"
Security Vulnerabilities
Se você descobrir uma vulnerabilidade de segurança no Informate, envie um e-mail para contato@ricardosierra.com.br. Todas as vulnerabilidades serão tratadas imediatamente.
Licença
O Informate é um software open-source licenciado sob a MIT license.
Desenvolvido com ❤️ pela equipe SierraTecnologia
GitHub • Website • Issues • Discussions