Faturamento + Contabilidade para PMEs
Uma mensagem confusa → fatura, registro de despesas e o próximo rascunho de lembrete. Sem conta, sem assinatura, sem dependência — seu dinheiro, em arquivos que você possui.
Pequenas empresas não fracassam no trabalho. Elas fracassam na espera: cerca de 55% das faturas B2B na América do Norte são pagas com atraso (Atradius, via Crestmont Capital, atualizado em 2026), pequenas empresas nos EUA esperaram em média 29,3 dias para receber pagamento no 2º trimestre de 2026, ~9 dias após o vencimento (Xero Small Business Insights, via Foundrly, ago. 2026), e 82% dos fracassos de pequenas empresas são atribuíveis a problemas de fluxo de caixa (Câmara de Comércio dos EUA, via Crestmont, 2026). A chance de receber cai rapidamente com a idade — mais de 95% nos primeiros 30 dias com acompanhamento proativo, caindo para 20–30% após 120 dias (Crestmont, 2026). A fatura é a parte fácil. A cobrança é o produto — e em todos os outros lugares a cobrança é paga: lembretes automáticos são apenas Pro no Wave ($19/mês) e Invoice Ninja ($14/mês) (páginas de preços dos fornecedores, nov. 2026), o Wave não pode enviar faturas fora dos EUA/Canadá (suporte Wave, 8 set. 2026), e o plano gratuito do Zoho Invoice limita a 500 faturas/ano e apaga dados inativos após 180 dias (zoho.com/invoice/pricing, lido em 2026-11-11). Esta skill redige a cobrança gratuitamente.
Versão 0.2.0. Reconstruída a partir da revisão adversarial v0.1.0 (20 lacunas, todas corrigidas ou registradas em
MEASUREMENTS.md§11) e das correções de pesquisa aprofundada (research-notes-v2.md§1). O que mudou está emCHANGELOG.md. Os números abaixo são execuções reais nos dados de amostra incluídos, não estimativas.
Não é aconselhamento jurídico, fiscal ou financeiro. Esta skill ajuda você a criar faturas e monitorar dinheiro. Alíquotas de impostos, limites de registro e requisitos de fatura diferem por país e mudam ao longo do tempo. Defina sua própria alíquota de imposto e confirme as regras para o seu negócio com a autoridade fiscal local (em Bangladesh: a Junta Nacional de Receitas, nbr.gov.bd) ou um contador qualificado. Este aviso também é impresso no rodapé de cada fatura e recibo gerado — em bengali nos documentos em bengali. Para as regras de manutenção de registros por trás disso (o que manter, TIN/BIN nas faturas, formulários Mushak, retenção), consulte o guia de referência complementar: a skill
bd-bookkeepingdo OpenAccountants (openaccountants/openaccountants, 484★, atualizado em 2026-11-11) — um guia de referência em inglês, explicitamente "apenas referência geral… não revisado para os fatos de qualquer pessoa específica". Ele não gera faturas. Esta skill gera.
Execute
python3 scripts/bookkeeper.py <comando>
Python ≥ 3.9, apenas biblioteca padrão. Sem etapa de instalação, sem dependências, sem chamada de rede, sem chave de API, sem conta. Os dados residem em arquivos JSON simples que você pode abrir, copiar e levar para qualquer lugar.
Regras financeiras — leia antes de confiar em qualquer número
Estas são as regras que tornam os totais confiáveis, e aquelas que a revisão v0.1.0 pego esta skill quebrando:
- O dinheiro arredonda half-up (
ROUND_HALF_UP), da forma que um lojista arredonda com uma calculadora — nunca arredondamento bancário. ৳2,345 é ৳2,35. - As quantidades são exatas, nunca arredondadas como dinheiro. Uma qtd. de 1,005 é 1,005; apenas o total da linha arredonda. As quantidades são impressas sem zeros à direita (3, nunca 3,00).
- O imposto é por linha, sobre o valor da linha com desconto — o imposto de cada linha arredonda half-up nessa linha, depois soma (da forma que Wave / Xero / FreshBooks fazem). 3 linhas de ৳0,35 com imposto de 15% ৳0,15, não ৳0,16.
- O status de pago vem do saldo, nunca da string de status. Uma fatura marcada como "paga" com ৳4.000 ainda devidos relata ৳4.000 devidos, e o relatório diz que o status está errado. Status é uma dica; o estado de vencimento é derivado da data de vencimento e do saldo.
- O dinheiro nunca é somado entre moedas. Um livro-razão com moedas mistas relata totais por moeda (৳5.000 + $100) e recusa um total mesclado e um líquido mesclado — a skill não possui câmbio e informa isso.
- Um problema no livro-razão é alto e custa saída 2.
overdueecashflowsaem com código 2 quando uma linha é pulada (dados inválidos), um número é duplicado, uma fatura "paga" ainda tem saldo, um pagamento paga a mais, ou um pagamento não tempaid_date. O relatório ainda é impresso; o código de saída diz para corrigir o livro-razão antes de confiar nele. - Dinheiro negativo imprime o menos primeiro: −৳4.100 — uma convenção, em todos os lugares.
O fluxo de trabalho: uma entrada → fatura → recibo → lembrete → fluxo de caixa
1. Fatura, orçamento ou recibo a partir de uma entrada JSON
python3 scripts/bookkeeper.py invoice --input samples/invoice-input.json --out out/invoice.html --config config/bd.json
python3 scripts/bookkeeper.py invoice --input samples/invoice-input-bn.json --out out/invoice-bn.html --config config/bd.json --lang bn
python3 scripts/bookkeeper.py invoice --input my-quote.json --out out/quote.html --format md
python3 scripts/bookkeeper.py receipt --input samples/invoice-input.json --out out/receipt.html --paid-date 2026-11-05 --amount-paid 4500
- A entrada é um pequeno arquivo JSON: negócio + cliente + itens de linha
(descrição, quantidade, preço unitário) + número da fatura + data de emissão +
data de vencimento. Consulte
samples/invoice-input.jsonpara o formato exato. - Orçamento → fatura → recibo é um ciclo de vida, um modelo de dados.
type: "quote"precisa devalid_untilem vez de uma data de vencimento; uma fatura precisa de uma data de vencimento real no calendário, não apenas "Net 30"; um recibo é gerado a partir de uma fatura paga com--paid-datee--amount-paide mostra o বাকি (saldo devedor) restante se o pagamento foi parcial. Um recibo com um valor de 0 é recusado — um recibo confirma dinheiro recebido. Um orçamento nunca mostra linhas de pago/saldo (nada é devido em uma proposta), em HTML ou Markdown, e seu número é rotulado como "Número do orçamento", não "Número da fatura". - A fatura contém os campos que toda fatura precisa (notas de pesquisa §3.1): a palavra "Fatura", um número sequencial único, data de emissão, data de vencimento, detalhes do vendedor, detalhes do comprador, descrições específicas, itens de linha, imposto como sua própria linha, instruções de pagamento + total devido. Um número de orçamento é referenciado na fatura quando existe; o número PO do cliente e o número de registro fiscal do vendedor (tax_id — em Bangladesh, o BIN de 13 dígitos) são impressos na fatura quando fornecidos.
- A numeração é sequencial (
INV-2026-001,INV-2026-002, …). Nunca pule ou reuse um número — uma lacuna ou duplicata parece falta de receita ou despesa inventada na época do imposto. Os comandos do livro-razão avisam alto e saem com código 2 em caso de número duplicado. Onumbering_prefixda configuração é verificado em relação ao número da fatura (um aviso, não um erro);default_termspreenche a linha de Termos quando a entrada não tem nenhum. - A saída é HTML limpo imprimível (abra em um navegador, imprima para PDF) ou
Markdown (
--format md). Sem recursos externos no HTML, para que imprima exatamente como aparece — as amostras enviadas foram renderizadas no Chromium sem cabeça e impressas para PDF uma vez (consulteMEASUREMENTS.md§11.6, capturas de tela emdocs/). - O dinheiro é calculado com
Decimal, nunca float. O desconto é uma porcentagem do subtotal, aplicado por linha; o imposto é por linha sobre o valor com desconto (consulte "Regras financeiras"). - A validação é rigorosa e o código de saída é 2 em caso de entrada ruim: data de vencimento ausente, quantidade ou preço negativo, alíquota de imposto fora de 0–100%, datas ruins, JSON malformado, arquivo ausente, data de vencimento antes da data de emissão, pagamento datado antes da data de emissão. Uma fatura com zero itens é permitida (total ৳0) mas imprime um aviso — é um rascunho, não um erro a ser escondido. Pagar a mais em um documento imprime um aviso em ambos os comandos de documento (um recibo nunca deve mostrar "Saldo devedor: ৳-825").
2. Imposto — uma configuração que você digita, nunca uma alíquota fixa
# Na entrada da fatura (este é o ÚNICO lugar onde uma alíquota existe):
"tax": {"name": "IVA", "rate_percent": 15}
- Nenhuma ferramenta fixa uma alíquota e esta skill também não. Toda ferramenta de faturamento (Zoho, FreshBooks, Wave, Xero — notas de pesquisa §5.1) permite que o usuário defina um imposto nomeado + porcentagem, aplica-o por linha, e o mostra como uma linha separada. Esta skill copia exatamente isso: imposto é um imposto nomeado + taxa % na entrada, padrão 0% / sem imposto.
- Predefinições de país em
config/fornecem o rótulo do imposto, a moeda, os métodos de pagamento, os termos padrão e o prefixo de numeração — nunca uma alíquota.config/bd.json(Bangladesh: ৳, "IVA", bKash / Nagad / Rocket / transferência bancária / dinheiro) econfig/us.json(EUA: $, "Imposto sobre vendas", Net 30).tax_rate_percentem ambas as configurações énullde propósito. Umtax_idna configuração (seu BIN) preenche a fatura quando a entrada não tem nenhum. - A fatura de exemplo usa 15% de IVA porque a entrada de exemplo diz isso — a alíquota padrão de IVA de Bangladesh é 15% sob a Lei de IVA e Imposto Suplementar de 2012 (ArthiKalap, atualizado em 25 jul. 2026; TRW, AF 2026-27; TaxDo, 2026; SDTT Academy, início de 2026) — mas a skill não sabe disso e nunca deve ser citada como sabendo. As declarações de IVA são mensais novamente (vencimento em 15 dias): a Lei Financeira 2026 as tornou trimestrais a partir de 1º jul. 2026, mas uma portaria de emenda publicada em 14 out. 2026 restaurou as declarações mensais (TRW "Fazendo Negócios em Bangladesh 2026", lei em 24 out. 2026; entrepreneurs.bd, 2026). Qualquer linha "trimestral" em notas mais antigas está agora errada.
- Os limites de registro NÃO são fixados nesta skill. Três guias independentes de out.–nov. 2026 agora convergem para os mesmos números — registro obrigatório acima de Tk 50 lakh de faturamento anual; alistamento para Tk 30–50 lakh a 4% de imposto sobre o faturamento; algumas atividades registram independentemente do faturamento (TRW "IVA em Bangladesh 2026", posição em 18 out. 2026; TRW "Registro de IVA"; entrepreneurs.bd, 2026; Aniday, verificado em set. 2026). Mas a verificação direta junto à NBR não foi alcançada: a página inicial da NBR (carregada em 2026-11-11) não contém texto de limite, e vat.gov.bd estava inacessível naquele dia. Portanto, esses números são relatados aqui como fontes secundárias convergentes, não fato verificado pela NBR — a skill nunca declara um limite como próprio e aponta os usuários para nbr.gov.bd. O BIN tem 13 dígitos (listagem de serviços da página inicial da NBR, 2026-11-11 — um rótulo, não um diário oficial; confirme a contagem de dígitos no guia de registro de IVA da NBR ao verificar os limites).
- Preços com imposto incluído são suportados:
"tax": {"name": "IVA", "rate_percent": 15, "inclusive": true}extrai o imposto do preço bruto (IVA = bruto × 15 ÷ 115). Medido emMEASUREMENTS.md§5: ৳1.150 brutos → ৳150 de IVA, total permanece ৳1.150.
3. Registro de despesas — linguagem simples, arquivos simples
python3 scripts/bookkeeper.py expense add --ledger expenses.json --date 2026-11-11 --category Materials --amount 1200 --note "fio de cobre, 20 m"
python3 scripts/bookkeeper.py expense list --ledger expenses.json --month 2026-11
python3 scripts/bookkeeper.py expense export --ledger expenses.json --out expenses.csv
- Uma despesa = data, categoria, valor, nota. O livro-razão é uma lista
JSON;
exportescreve um CSV que abre em qualquer planilha. - As categorias são em linguagem simples, não um plano de contas: Materiais,
Transporte, Ferramentas, Celular/internet, Refeições, Aluguel, Mão de obra,
Embalagem, Outros. Uma categoria desconhecida é um erro, nunca aceita
silenciosamente. Valores negativos são rejeitados.
--monthdeve ser umYYYY-MMreal (2026-1é rejeitado — uma correspondência de prefixo bruta mesclaria silenciosamente outubro e novembro). - Uma linha do livro-razão que não é um objeto é pulada alto com um aviso
e saída 2 — nunca um traceback, nunca silenciosa.
expense addrecusa-se a reescrever um livro-razão que contém uma linha quebrada (corrija-a primeiro).
4. Rastreador de vencimentos + rascunhos de lembretes — o centro da skill
python3 scripts/bookkeeper.py overdue --invoices samples/invoices.json --as-of 2026-11-11
python3 scripts/bookkeeper.py overdue --invoices samples/invoices.json --as-of 2026-11-11 --lang bn --json
- Escaneia o livro-razão de faturas, lista cada fatura aberta por faixa de idade (atual / 1–30 / 31–60 / 61–90 / 90+ dias vencida) e redige o próximo lembrete no estágio certo para cada uma.
- A sequência de 6 estágios (o consenso de 5 toques em Raoura, verificado em jul. 2026; InvoiceCub, 31 out. 2026; InvoiceFly, ~nov. 2026; HeroThemes, ~ago. 2026; FreelanceDesk, ~jun. 2026 — antes do vencimento, data de vencimento, 7, 14, 30 dias — mais o lembrete amigável precoce para 1–6 dias vencido da versão de 7 toques; o toque extra de 21 dias da versão de 7 toques não é um estágio separado, seu terreno é coberto pelo rascunho de 14 dias com o próximo toque no dia 30): 3 dias antes do vencimento, na data de vencimento, 7 dias vencido, 14 dias vencido, 30 dias aviso final, mais o lembrete de 1–6 dias. Escalonamento gradual, nunca acusação primeiro: assuma boa intenção no início (esqueceu / enterrado / em fila de aprovação); mencione uma taxa de atraso apenas quando o acordo fornecer uma e a fatura estiver ~2 semanas vencida. Cada rascunho reafirma número da fatura, valor, a data de vencimento original — e os dias reais de atraso (uma fatura de 8 dias recebe "8 dias vencida", nunca o número do estágio).
- Apenas rascunhos — a skill nunca envia nada. Você envia o
lembrete. O relatório também imprime a próxima data de contato, para que a
escalada não dependa de lembrar. Um próximo contato que já passou imprime como
"enviar agora (vencimento era …)", nunca como uma data passada simples. O aviso
final dá um prazo de 7 dias a partir de hoje no mínimo (
max(vencimento + 37 dias, as-of + 7 dias)) — uma cobrança cujo prazo já passou é pior do que nenhuma cobrança. - Medido nas amostras (em 2026-11-11): 6 faturas abertas, ৳48.650
devidos a você (বাকি), 4 vencidas totalizando ৳28.250 — uma em cada
estágio, do lembrete ao aviso final. Consulte
MEASUREMENTS.md§3. - Faturas de rascunho são excluídas de "devidos a você" — uma fatura não enviada não é dinheiro devido ainda. Faturas pagas (saldo 0) também são excluídas. (Empresas que acompanham 100% das faturas vencidas têm 76% mais probabilidade de receber o pagamento dentro de uma semana — Relatório Anual Chaser 2026 AR, via Raoura, indiretamente.)
5. Visão simples de fluxo de caixa — os números que o proprietário realmente verifica
python3 scripts/bookkeeper.py cashflow --invoices samples/invoices.json --expenses expenses.json --as-of 2026-11-11 --month 2026-11
- Mostra em uma tela: dinheiro recebido no mês (pagamentos de faturas), dinheiro gasto (despesas), e dinheiro pendente (faturas abertas — não enviadas e vencidas separadas). Calcula o fluxo de caixa líquido do mês (recebido − gasto) e o total de dinheiro pendente.
- A saída em JSON (
--json) produz um objeto que pode ser analisado por outros scripts. - Datas de ordenação: pagamentos são ordenados por
paid_date; despesas pordate; faturas abertas por data de vencimento. Itens sem a data esperada são avisados e a saída é código 2. - Uma fatura marcada como "paga" mas sem
paid_dateé tratada como uma fatura em aberto (saldo calculado a partir do valor) — o aviso é impresso, e a saída é código 2 se o valor não for zero. "Pagamentos" no livro-razão são ignorados para faturas marcadas como "não paga" — um cliente não pode ter pago uma fatura não paga.
6. Calculadora embutida — quando você digitou errado
python3 scripts/bookkeeper.py calc 6*9 # → 54
python3 scripts/bookkeeper.py calc '5*(2+3)' # → 25
- Útil quando você está escrevendo a descrição de um item de linha e não quer
abrir uma calculadora separada.
calcaceita+,-,*,/,//,%,**, parênteses e espaços. Saída de erro em 2.
Amostras e medições
- Amostras: um cliente (Ana Silva, Floricultura Silva), um fornecedor (João
Pereira), 6 faturas — paga, não enviada, não paga, 3, 8, 15, 29 e 33
dias vencida — em
samples/invoices.json. Uma despesa de exemplo:samples/expenses.json. ConsulteMEASUREMENTS.md§2–4 para valores e diagnósticos. - Estrutura de saída:
out/contém todos os arquivos gerados — HTML, PDF, Markdown, JSON, CSV. Consultedocs/para capturas de tela do HTML renderizado versus saída marcada como aceita. - Cobertura de testes:
tests/contém 43+ testes unitários (pytest). Executepython3 -m pytest tests/ -v.
Configuração
config/bd.json:
{
"currency": "BDT",
"currency_symbol": "৳",
"locale": "bn_BD",
"tax_label": "VAT",
"tax_rate_percent": null,
"numbering_prefix": "INV-",
"default_terms": "Pagamento devido em 30 dias",
"payment_methods": ["bKash", "Nagad", "Rocket", "Transferência bancária", "Dinheiro"],
"tax_id": null
}
config/us.json:
{
"currency": "USD",
"currency_symbol": "$",
"locale": "en_US",
"tax_label": "Imposto sobre vendas",
"tax_rate_percent": null,
"numbering_prefix": "INV-",
"default_terms": "Net 30",
"payment_methods": ["Cheque", "Transferência ACH", "Cartão de crédito", "PayPal", "Dinheiro"],
"tax_id": null
}
Estrutura completa do comando
python3 scripts/bookkeeper.py invoice --input ARQUIVO [--out ARQUIVO] [--config ARQUIVO] [--lang en|bn]
python3 scripts/bookkeeper.py quote --input ARQUIVO [--out ARQUIVO] [--config ARQUIVO] [--lang en|bn]
python3 scripts/bookkeeper.py receipt --input ARQUIVO --paid-date DATA --amount-paid VALOR [--out ARQUIVO] [--config ARQUIVO] [--lang en|bn]
python3 scripts/bookkeeper.py expense add --ledger ARQUIVO --date DATA --category CATEGORIA --amount VALOR --note TEXTO
python3 scripts/bookkeeper.py expense list --ledger ARQUIVO [--month YYYY-MM] [--category CATEGORIA] [--json]
python3 scripts/bookkeeper.py expense export --ledger ARQUIVO --out ARQUIVO.csv
python3 scripts/bookkeeper.py overdue --invoices ARQUIVO --as-of DATA [--lang en|bn] [--json]
python3 scripts/bookkeeper.py cashflow --invoices ARQUIVO [--expenses ARQUIVO] --as-of DATA --month YYYY-MM [--json]
python3 scripts/bookkeeper.py calc EXPRESSÃO
Changelog v0.2.0
- Arredondamento
ROUND_HALF_UPcorrigido em todos os lugares - Imposto calculado por linha, não sobre o subtotal
- Livro-razão de moeda mista recusa total mesclado
- Saída de dinheiro negativo: −৳4.100
- Saída de JSON adicionada a
overdueecashflow - Validação de data de vencimento e data de emissão
- Tipos de documento: orçamento, fatura, recibo — ciclo de vida único
- Interface de linha de comando unificada (
bookkeeper.py) - Cobertura de testes: 43+ testes
- Veja
CHANGELOG.mdpara detalhes completos.
Licença
MIT