ETL de produção cooperativista com conectores de dados, apuração econômica e publicação contábil separados por contratos de integração. O perfil padrão preserva o modelo operacional da LibreCode com Kimai, Nextcloud Profile Fields e Akaunting. Perfis adicionais podem definir outras métricas e políticas sem reutilizar implicitamente as regras financeiras da LibreCode.
| Sistema | Descrição |
|---|---|
| Kimai | Registro de horas trabalhadas por projeto, emissão de relatório de horas trabalhadas para clientes |
| Akaunting | Gestão financeira |
| Nextcloud + Profile Fields | Diretório interno dos cooperados com os campos customizados weight, tax_number e dependents usados na produção |
Execute a apuração em uma instalação e bancos isolados dos produtivos. Os dados importados podem conter informações pessoais e financeiras: mantenha dumps, .env, CSVs e logs fora do Git, sob permissões privadas e uma política de retenção.
- Copie
.env.examplepara.enve configure somente credenciais de desenvolvimento; não use tokens de escrita, senhas nem chaves de produção para homologar. - Verifique que
DATABASE_URLaponta para um banco intermediário próprio da homologação,DATABASE_AKAUNTING_URLpara a cópia local do banco do Akaunting eAKAUNTING_API_BASE_URLpara uma API local, nunca para o serviço de produção. O bootstrap de testes recusa bancos remotos e URLs de API não locais. Chamadas HTTP reais sob APP_ENV=test também são bloqueadas fora de serviços locais; clientes HTTP simulados não acessam a rede. - Defina
APP_ENV=dev(outestpara PHPUnit). SelecioneCOOPERATIVE_PROFILE=librecodesomente para a política vigente; outros perfis exigem instância/banco próprios. - Evite publicar portas de banco no host e não conecte o ETL a redes externas quando estiver testando snapshots. Configure a infraestrutura de homologação existente em vez de reutilizar bancos de desenvolvimento compartilhados.
O projeto usa duas bases distintas: a do ETL (transformações, importações e auditoria) e a do Akaunting (documentos contábeis). Restaurar apenas uma delas não reproduz a execução histórica. O Kimai e as demais integrações exigem fontes autorizadas, ou um snapshot previamente importado.
- Emissão e consulta de NFS-e são responsabilidade do módulo fiscal do Akaunting e do Emissor Nacional. A importação da produção utiliza documentos financeiros do Akaunting, sem consultar portais municipais.
- Nextcloud + Profile Fields
- Criar no app
profile_fieldsos camposweight,tax_numberedependents. - Preencher estes campos para cada cooperado; eles passam a ser a fonte oficial do peso, do CPF/CNPJ e da quantidade de dependentes usados no cálculo.
- O Kimai fornece horas e uma referência de CPF/CNPJ para conciliação, mas não fornece mais dependentes: a importação exige o valor explícito no Profile Fields. Veja
docs/member-data-authority.md.
- Criar no app
- Akaunting
- Dados de clientes
- Definir número de identificação fiscal (cpf/cnpj) para todo fornecedor/cliente. Quando houver nota emitida para mais de um setor de um mesmo CNPJ e figurarem diferentes contas na LibreCode (conta = contrato), concatenar da seguinte forma:
<cpf/CNPJ>|<setor>
- Definir número de identificação fiscal (cpf/cnpj) para todo fornecedor/cliente. Quando houver nota emitida para mais de um setor de um mesmo CNPJ e figurarem diferentes contas na LibreCode (conta = contrato), concatenar da seguinte forma:
- Receitas
- Toda transação com nota fiscal emitida pela LibreCode deve conter o número da nota fiscal no campo
referência. - Sempre que for receita vinda de cliente deve possuir a categoria
RecorrênciaouServiço
- Toda transação com nota fiscal emitida pela LibreCode deve conter o número da nota fiscal no campo
- Divisão de sobras
- Criar uma fatura de venda com categoria
Cliente > Interno > Cooperado > Produção > Distribuição de sobras - Colocar o cliente como
LibreCode(é um cliente interno) - Inserir um item "Bruto produção" e remover a descrição padrão
- No valor do item, inserir o valor que será dividido
- Campo de anotações:
- Colocar o motivo da divisão de sobras bem detalhado
- Informar se é transaçâo para algum mês específico
- Criar a fatura
- Marcar fatura como enviada
- Cancelar fatura. Após cancelada, a fatura não será contabilizada no mês mas será considerado o valor dela para distribuição de sobras.
- Criar uma fatura de venda com categoria
- Custos
-
Categorizar transação de saída como
Cliente (custo)quando forem custos de clientes -
Sempre que for custo reembolsável pelo cliente, adicionar
<cpf/CNPJ>|<setor>na transação no campoReferênciapara que seja possível identificar qual cliente deverá reembolsar este custo de entrada. Lembrar de acrescentar o setor sempre que necessário. -
Todo custo que deve descontar do líquido da fatura do cooperado precisa estar abaixo da categoria pai
Cooperado > Produção > Desconto líquido- Exemplo:
Cooperado > Produção > Desconto líquido > Plano de saúde - Exemplo:
Cooperado > Produção > Desconto líquido > Telefonia
- Exemplo:
-
Configure o id da categoria pai em
AKAUNTING_PARENT_DESCONTO_LIQUIDO_CATEGORY_ID -
Categorias fora desta hierarquia são ignoradas.
-
No campo "nota" (descrição) de cada desconto líquido deve conter a divisão por cooperado. Exemplo:
Cooperado: Hedy Lamarr; CPF: 00000000000; Valor: 781,95 Cooperado: Grace Hopper; CPF: 11111111111; Valor: R$ 439,55 Cooperado: Ada Lovelace, CPF: 22222222222, Valor: 1.592,65 Cooperado: Radia Perlman, CPF: 33333333333, Valor: R$12.345,67
Validação monetária: use vírgula como separador decimal e ponto apenas entre grupos de três dígitos para milhares. São aceitos
781,95,R$ 781,95,1.592,65eR$12.345,67. Um valor como1592.65, com ponto decimal, interrompe o cálculo com uma mensagem de correção; não será interpretado como159265. O formato é obrigatório: confira as notas antes de apurar a produção. -
Customização da fatura (compra ou venda) ou transação deve ser inserida na descrição. Valores possíveis:
Nome Descrição Transação do mês Mês onde esta transação será contabilizada. Formato: 2023-09CNPJ cliente CNPJ do cliente de quem será cobrado o valor Setor Setor do cliente, quando é um CNPJ com mais de um contrato Arquivar sim= Arquivar transação e não utilizá-la.Percentual desconto fixo Ignora a taxa administrativa (somatório de todas as despesas do mês incluindo valor de NFSe e custos da coop do mês) e aplica apenas este perentual de desconto no valor da nota. Valores customizados precisam ter o nome da propriedade separado do valor com dois pointos, exemplo:
Transação do mês: 2023-05
-
- Dados de clientes
- Cada contato de cooperado no Akaunting deve ter identificação fiscal válida e verificável.
- Confira os IDs de categorias, itens e tributos no Akaunting e as variáveis correspondentes do
.env, sem copiar credenciais de produção. - Antes de uma publicação, valide pesos, dependentes e identificação no Profile Fields, apontamentos do Kimai, recebimentos efetivos, categorias e despesas no Akaunting e eventuais campos manuais de competência.
Primeiro clone o repositório e entre nele.
Copie o arquivo .env.example para .env
Edite o arquivo .env preenchendo os dados necessários.
Em um terminal:
docker compose upEm outro terminal:
docker compose exec php bash
composer install
php ./bin/console doctrine:migrations:migrate -nO banco de ETL de produção não é descartável: além dos dados importados, ele mantém o histórico de tentativas de publicação financeira. Em instalações novas, as migrations são executadas em ordem sobre um banco vazio; em ambientes existentes, aplique apenas as migrations pendentes após backup e conferência. A retirada da tabela nfse exige confirmação de que ela está vazia. Não apague tabelas ou reinicie o histórico de migrations da Conceição para simplificar o PR.
O comando make:producao calcula sem publicar por padrão. Para conferir valores, use --csv: a prévia inclui agora o número esperado do documento PDC_...-AAAA-MM, permitindo conciliação por identificador, e não por posição da linha.
php bin/console make:producao --ano-mes=2026-08 --baixar-dados=0 --as-of=2026-10-07 --csv--ano-mes=AAAA-MMidentifica o mês trabalhado; 2026-08 corresponde à competência de documentos 2026-09, com pagamento previsto no mês seguinte.--baixar-dados=1(padrão) importa novamente as fontes externas e altera o banco intermediário. Para importar separadamente, useetl:sync --ano-mes=AAAA-MM.--baixar-dados=0apenas reutiliza dados já importados: não garante, sozinho, uma fotografia histórica, nem corrige importação incompleta. Aceita exclusivamente0ou1.--as-of=AAAA-MM-DDfixa a data de referência em uma prévia e não pode ser combinado com publicação.--dias-uteis,--dia-util-pagamentoe--percentual-maximoafetam o cálculo; use somente parâmetros aprovados.--atualiza-producaopublica documentos e tributos no Akaunting configurado; use apenas após conferência e autorização, nunca conectado à produção durante homologação.--databasenão grava dados nem publica por conta própria e agora é recusado explicitamente.--odsfoi removido: não havia exportação ODS implementada.
Uma prévia recalculada pode divergir de uma fatura paga por mudanças posteriores nas fontes, descontos, adiantamentos ou critérios. Não altere o valor histórico automaticamente para fazer os relatórios coincidirem.
O comando principal é composto pela execução independente de cada um dos comandos abaixo que você provavelmente não precisará usar:
Available commands:
get
get:categories Get categories
get:customers Get customers
get:invoices Get invoices
get:projects Get projects
get:taxes Get taxes
get:timesheets Get timesheets
get:transactions Get transactions
get:users Get users- Conferir as origens: fechamento das horas no Kimai, campos cadastrais no Profile Fields, identificação dos cooperados, pagamentos de clientes, notas, custos e categorias corretas no Akaunting. Campos livres como
Transação do mês,Arquivar: sime descontos fixos exigem conferência humana. Não use essas marcações para contornar uma diferença não investigada. Receitas e despesas vinculadas a clientes devem ter identificador explícito; referências ausentes não serão mais presumidas como o CNPJ da própria cooperativa. - Importar e preservar o corte: execute
etl:sync --ano-mes=AAAA-MMcom acesso autorizado e gereaudit:inputs --ano-mes=AAAA-MM --revision="$(git rev-parse HEAD)". Preserve snapshot intermediário e manifesto em área confidencial. Importar outra competência pode mudar as bases da anterior. - Calcular sem publicar:
make:producao --ano-mes=AAAA-MM --baixar-dados=0 --csv; use--as-ofem auditoria histórica. Confira todos os númerosPDC_, bases, retenções, adiantamentos, descontos, FRRA, totais e datas. Guarde o CSV com acesso restrito. - Conciliar em leitura com o Akaunting: compare
document_number, situação (draft,paidoucancelled), competência, itens e notas. Não sobrescreva faturas finalizadas. Toda divergência exige explicação sobre dados de origem, data de corte, política e eventuais ajustes posteriores. - Aprovar ou bloquear: obtenha a revisão financeira/contábil aplicável antes de usar
--atualiza-producaono ambiente aprovado. Ausência de horas, custos sem receita, capital elegível insuficiente ou inconsistência cadastral bloqueiam a publicação. Após uma falha de publicação, confira os registros existentes antes de repetir a operação.
Para o procedimento seguro de reconciliação e retomada após publicação parcial, consulte docs/publication-recovery.md. O histórico de tentativas de emissão é consultável por php bin/console publication:pending --limit=100; exige a nova migration do banco intermediário, preservada pelo reset do ETL.
Publicações de cooperados pessoa física cuja previsão de pagamento atravesse o ano civil ficam bloqueadas até revisão do período de incidência do IRRF. Consulte docs/tax-period-boundary.md. A prévia continua disponível; isso não homologa pagamentos dentro do mesmo exercício.
O Monolog registra a execução em var/log/<APP_ENV>.log (por exemplo, var/log/dev.log) e os erros em var/log/calculation-errors.log, ambos com rotação. Acompanhe localmente com:
tail -f var/log/dev.log var/log/calculation-errors.logLogs, relatórios CSV e snapshots podem conter dados pessoais ou financeiros. Nunca os anexe a um PR ou issue públicos.
- PHP: imagem de execução declarada uma única vez em
ARG PHP_IMAGEde.docker/php/Dockerfile; os workflows leem esse valor automaticamente. Ocomposer.jsonmantém apenas a versão mínima compatível. - Node.js: versão de execução de testes declarada em
.nvmrc. O frontend usa JavaScript nativo, sem dependências npm instaladas. - Dependências:
composer update -Wno backend, com ferramentas de desenvolvimento isoladas emvendor-bin. O Dependabot acompanha Composer, GitHub Actions e Docker Compose; o Renovate acompanha o Dockerfile,.nvmrce a imagem MySQL usada pelo CI. As atualizações exigem revisão e CI aprovada. - Modernização de PHP:
composer run rector:checkverifica as refatorações, ecomposer run rector:fixaplica as alterações. - Verificação:
composer run test:unit,composer run cs:checkecomposer run psalm. Os testes de JavaScript usamnode --test tests/js/*.test.cjs. A CI executa esses testes em um workflow separado, com limites mínimos de cobertura (90% de linhas, 80% de ramos e 75% de funções). - Testabilidade do frontend: regras de domínio JavaScript (competência e conciliação de fontes, seleção e arredondamento de cooperados, elegibilidade de vínculos, interpretação de documentos financeiros, validação de IDs e processamento SSE) são funções puras ou adaptadores independentes de DOM/HTTP. Use casos parametrizados (
forcomtest()nomeado) emtests/js/*-rules.test.cjspara valores nulos, zero legítimo, identificadores inválidos, competência incorreta e operações concorrentes; mantenha testes de integração com DOM/HTTP simulados para validar efeitos e autorizações. Onode:testnativo é suficiente; não introduza bibliotecas de UI quando uma regra puder ser testada sem navegador.
O pipeline mantém quatro limites: conectores de origem (Kimai e Akaunting), banco de transformação, apuração econômica e publicação opcional no Akaunting. As etapas de origem implementam SourceStep e são orquestradas por SourcePipeline, preservando a ordem das dependências. ProductionDistributionPlanner calcula a distribuição sem acessar APIs ou saldo bancário. O capital social é consultado separadamente e não integra receitas de clientes.
A competência mensal é validada como YYYY-MM. A importação completa do Kimai reconcilia alterações e exclusões. Em casos não cobertos pela reconciliação de lançamentos financeiros, utilize a reconstrução do banco intermediário e importe novamente. A nova classificação contraditória de percentuais fixos e móveis do mesmo cliente interrompe o cálculo para análise, em vez de permitir uma distribuição incompleta.
Audite os dados intermediários sem qualquer escrita financeira:
php bin/console audit:inputs --ano-mes=2025-04 --revision="$(git rev-parse HEAD)"O relatório compacto mostra contagens e fingerprints SHA-256 de entradas, pesos e configurações (incluindo dependências e runtime), sem expor valores financeiros ou dados pessoais. Para preservar as entradas integrais de uma execução, adicione --save-bundle. O arquivo ficará em var/audit/ com permissão privada. Verifique posteriormente com php bin/console audit:verify --file=var/audit/AAAA-MM/NOME.json; a verificação detecta alterações no conteúdo em relação ao manifesto, mas não substitui armazenamento imutável externo nem uma assinatura digital independente. Contém dados pessoais e financeiros confidenciais: proteja o acesso, os backups e a retenção conforme a LGPD; não publique em Git ou PRs.
Simule o resultado de uma competência antiga com uma data de referência operacional definida:
php bin/console make:producao --ano-mes=2025-04 --baixar-dados=0 --as-of=2025-05-10--as-of é exclusivo de prévias e não pode ser combinado com --atualiza-producao.
Os relatórios e arquivos de auditoria permitem conferir os dados efetivamente disponíveis na execução indicada, seus parâmetros e a versão do código. A análise de qualquer competência deve considerar o conjunto de comprovantes, políticas aprovadas e dados de origem aplicáveis ao período; a geração de um relatório não equivale, por si só, à certificação contábil da competência.
- Ingestão: cada integração implementa
SourceStep.SourcePipelineseleciona somente as etapas declaradas pelo perfil, sem alterar os conectores existentes. - Perfil:
CooperativeProfiledeclara as origens e a política de distribuição.ProfileRegistryseleciona o perfil por instalação usandoCOOPERATIVE_PROFILE(padrão:librecode). Não existe isolamento de múltiplas cooperativas no mesmo banco; cada cooperativa precisa de uma instalação/banco independente. - Métricas:
MetricStrategypermite novas unidades de produção. As implementações de exemplo sãoelapsed-hours(horas registradas) ework-entries(quantidade de apontamentos faturáveis). Os dados importados do Kimai são normalizados porWorkMetricsReader; o perfil de exemplo usaBasicUsers, sem exigir CPF, Profile Fields ou vínculo prévio com o Akaunting. - Política de rateio:
AllocationPolicyrecebe valores elegíveis aprovados e medições normalizadas, sem depender do Akaunting.HoursProportionalPolicyé apenas um exemplo técnico de cálculo proporcional por cliente, não uma regra atribuída à Inovar ou a qualquer outra cooperativa. - Publicação:
ProductionPublisherePublicationRouterisolam a gravação. O único publicador homologado por padrão é o da LibreCode (produção, FRRA e tributos). Para outro perfil, a publicação fica bloqueada até que exista implementação e aprovação contábil específicas.
Configure COOPERATIVE_PROFILE=hours em uma instância de homologação própria, depois importe as origens desse perfil:
php bin/console etl:sync --ano-mes=2026-07Forneça um arquivo JSON de bases elegíveis aprovadas. O programa não presume que saldo bancário, faturamento bruto ou valor de nota seja distribuível:
[
{"customer_reference": "CLIENTE-EXEMPLO", "eligible_amount": 1200.00, "currency": "BRL"}
]Execute a prévia com uma métrica configurada:
php bin/console allocation:preview --ano-mes=2026-07 --receipts-file=/caminho/restrito/bases.json --metric=elapsed-hoursA prévia inclui valores por cliente/cooperado, total elegível, total distribuído e fingerprint do arquivo de bases, sem emissão de documentos. work-entries demonstra uma métrica alternativa. Para usar outra política econômica, implemente a interface de rateio, o perfil e, quando aprovado, um publicador financeiro próprio; não altere diretamente os conectores Kimai ou as regras da LibreCode.
O comando make:producao e a interface de produção contábil existente permanecem exclusivos do perfil librecode. O Akaunting armazena os documentos financeiros; a emissão e a validação fiscal das NFS-e pertencem ao módulo fiscal do Akaunting e ao Emissor Nacional, fora deste ETL.
A instalação produtiva usa o Compose versionado e o procedimento operacional. As configurações da aplicação, Nginx e PHP ficam no Git; credenciais, bancos de dados e hashes do HTTP Basic Auth ficam exclusivamente no servidor.
Edite os arquivos em resources/scss/, não os CSS gerados. Os arquivos compilados em public/css/ são versionados e servidos diretamente: Node.js/Sass não são exigidos na Conceição. Para desenvolver ou revisar os estilos, use:
npm ci --include=dev
npm run scss:format # formata o código-fonte
npm run scss:format:check # falha se o SCSS estiver fora do padrão
npm run scss:lint # verifica erros e construções SCSS
npm run css:build # atualiza os CSS versionados após editar o SCSS
npm run css:check # compila em memória e compara sem alterar arquivosO workflow Styles executa dois checks independentes em todo pull request: SCSS formatting and lint (Prettier + Stylelint) e Generated CSS matches SCSS (inclui testes para alterações manuais e CSS ausente/obsoleto). Se o segundo falhar, rode npm run css:build e inclua os CSS atualizados no commit. Não edite public/css/ manualmente; o verificador sempre recompila o SCSS em memória e compara byte a byte com o CSS versionado.
Nos SCSS, agrupe as regras de um componente sob seu seletor pai (por exemplo, .production-period-fields { .form-field { ... } label { ... } }) em vez de repetir o prefixo em cada regra. Para estados, use &:hover e &[data-state="..."]. Mantenha seletores compartilhados entre componentes fora desses blocos quando o agrupamento mudaria o escopo; evite hierarquias profundas que aumentem a especificidade. Formatação e compilação idêntica são verificadas pela CI, mas a decisão de aninhar deve preservar a semântica do CSS.
Para editar integrações e regras, configure CONFIG_ADMIN_USERS no .env com os nomes autorizados na autenticação HTTP Basic. Credenciais são exibidas somente sob demanda e alterações são gravadas em var/admin-config/settings.json (privado, não versionado). O arquivo sobrepõe os parâmetros na próxima requisição ou execução CLI; proteja-o nos backups. Valores incorretos podem impedir a apuração ou a conexão com serviços externos.
A competência é o mês das horas trabalhadas. Para a LibreCode, a regra
configurável é trabalhar em M, faturar/receber em M+1 e fechar em M+2
(PRODUCAO_FECHAMENTO_DEFASAGEM_MESES=2). O formulário sugere essa
competência, mas permite selecionar manualmente outros meses. Já os
relatórios, sem data na URL, mostram a última competência de horas
efetivamente importada, para evitar aparentar perda de dados após a virada
do mês. Mudar a data sugerida nunca limpa a base.
A página de limpeza exibe o ambiente real: APP_DEPLOYMENT_STAGE pode ser
production, staging ou development; na ausência desse parâmetro,
APP_ENV=prod identifica produção. Quando o Symfony local usa
APP_ENV=prod para cache e desempenho, configure explicitamente
APP_DEPLOYMENT_STAGE=development; na instalação de produção, configure
APP_DEPLOYMENT_STAGE=production. Ambiente de execução não é origem
dos dados. Apenas em instalações não produtivas um administrador pode
selecionar APP_DATA_SOURCE_PROFILE=production. Essa opção só aparece
quando as dez variáveis SOURCE_PRODUCTION_* do exemplo estiverem
configuradas separadamente. Configure o acesso SQL ao Akaunting de
produção com usuário somente leitura, sem permissão de gravação.
Não é permitido mudar de fonte enquanto qualquer tabela de importação
possuir dados. O seletor de origem não é apresentado em produção.
Ao utilizar fontes de produção em desenvolvimento/homologação, atualizações
de perfis Nextcloud e publicações no Akaunting são bloqueadas. Em desenvolvimento,
outras gravações externas também ficam bloqueadas por padrão, salvo
aprovação no servidor com APP_NONPROD_SOURCE_WRITES_ENABLED=1 e uso
de fontes de homologação. Essa opção
é para importação e conferência, não para alterar cadastros reais.
A meta PRODUCAO_META_LIQUIDA_MENSAL (R$ 50.000 por padrão), para
PRODUCAO_META_HORAS_REFERENCIA (165 h por padrão), é uma simulação
não vinculante. O cálculo estima a base necessária para uma pessoa
física atingir o líquido proporcional às horas usando as tabelas de
INSS/IRPF da competência. A comparação não desconta antecipações e
descontos individuais nem altera o rateio atual, os pagamentos ou as
sobras contábeis. Uma distribuição real limitada por teto e destinação
de excedente exige uma política formal adicional, não implementada aqui.