Update a transaction by ID.
A movimentação é procurada DENTRO da empresa do header x-company-id: id de outra empresa responde 404. Numa compra no cartão de crédito, amount, competence, credit_card_account_id e due_date NÃO são editáveis (422): parcelas e faturas não são reprocessadas, e o due_date é derivado do vencimento da fatura — alterá-los deixaria o DRE, o dashboard e a fatura discordando. Reenviar os mesmos valores (o objeto que o GET devolveu) passa; para mudá-los, exclua o lançamento e registre-o de novo. Os demais campos — referência, contato, informações adicionais, url, tags, centro de custo e plano de contas — seguem editáveis.
Lançamento de conta bancária PAGO (F2): edição só descritiva (ou aumento de valor com pagamento parcial) grava sem mover dinheiro e preserva o status; edição com efeito financeiro — valor maior com pagamento integral, valor menor que o pago, troca de conta ou de tipo — gera estornos e pagamentos com data de hoje, numa operação atômica e auditada, e exige reason (422 reason_required, nada é gravado). Lançamento não pago: reason é opcional e ignorado. Conta, categoria, fornecedor, centro de custo ou cartão do corpo que não é da empresa: 422 reference_not_in_company com fields.
Authorizations
Token da sessão no cabeçalho Authorization, no formato Bearer (mesmo esquema ApiKeyAuth do contrato).
Headers
company uuid
Path Parameters
Transaction ID
Body
Transaction data (com reason opcional)
CostCenterID e BankAccountID seguem string (e não ponteiro): o corpo atual continua válido byte a byte, e ausência de conta deixou de ser erro por si só — passou a depender de haver, ou não, cartão no lugar dela.
CreditCardAccountID é a SEGUNDA origem possível (Decisão B). Aditivo: ausente, tudo se comporta exatamente como antes desta feature.
DueDate, Competence e PaymentDate são DateOnly (não time.Time): aceitam "AAAA-MM-DD" (Swagger) e RFC3339 (frontend web) — ver date_only.go.
Installments é PONTEIRO para distinguir "ausente" de "1". Os dois
significam à vista, mas só o ponteiro permite recusar installments
enviado junto com conta bancária — silenciar levaria o usuário a crer que
parcelou algo que não foi parcelado (mesma regra que a coluna Parcelas
do CSV tem na spec).
O TETO (24, decisão Q2) NÃO é validado aqui: quem o decide é creditcardrepo.validatePurchaseRequest, via ErrInstallmentsOutOfRange, e duplicar o número neste arquivo criaria duas fontes para o mesmo limite.
Reason é lido SÓ pelo PUT de lançamento de conta bancária (paid-transaction-reversal / T7): obrigatório quando a edição move dinheiro (valor, conta ou tipo de lançamento pago — RN7), ignorado quando não move. O POST de criação o ignora.
Response
OK