{
  "id": "recorrencias",
  "title": "Recorrências",
  "description": "Moldes que geram receitas e despesas ao longo do tempo.",
  "type": "feature",
  "status": "observed",
  "visibility": "public",
  "tags": [
    "finanças",
    "recorrências",
    "scheduler"
  ],
  "related": [
    "financas",
    "transacoes",
    "automacoes",
    "relatorios"
  ],
  "sourceRefs": [
    "https://github.com/james-suite/james/blob/master/app/Models/FinancialRecurrence.php",
    "https://github.com/james-suite/james/blob/master/app/Console/Commands/ProcessFinancialRecurrences.php"
  ],
  "authors": [],
  "updated": null,
  "diagram": null,
  "body": "## Visão Geral\n\nAs **Recorrências** (`FinancialRecurrence`) permitem a automação do fluxo de caixa agendando despesas ou receitas recorrentes (ex: assinaturas, mensalidades, salários). Diferente de compras parceladas, onde as parcelas nascem limitadas e já instanciadas no banco de dados, as recorrências são um \"molde\" dinâmico que gera transações à medida que o tempo passa, permitindo projeções de longo prazo sem inchar o banco de dados.\n\n## Tabelas\n\n### `financial_recurrences`\n\n| Coluna | Tipo | Descrição |\n| --- | --- | --- |\n| `id` | bigint | Chave primária. |\n| `financial_account_id` | foreignId | (Opcional) Conta bancária vinculada. |\n| `financial_credit_card_id` | foreignId | (Opcional) Cartão de Crédito vinculado. |\n| `title` | string | Descrição/Título da recorrência. |\n| `type` | enum | `income` (receita) ou `expense` (despesa). |\n| `amount` | decimal | Valor base da transação a ser gerada. |\n| `frequency` | string | `weekly`, `monthly`, ou `yearly`. |\n| `start_date` | date | Data de início da recorrência. O dia desta data serve como base (Ex: dia 15). |\n| `end_date` | date | (Opcional) Data em que a recorrência deixa de vigorar. |\n| `next_processing_date` | date | Próxima data em que uma transação deverá ser materializada. |\n| `is_active` | boolean | Liga/desliga o motor de geração para esta recorrência. |\n\n## Diagrama Relacional (ER)\n\n{{diagram:recurrences-model}}\n\n## Regras de Negócio e Comportamento\n\n### Vínculo Exclusivo (Validação XOR)\nUma recorrência sempre movimenta fundos. Portanto, ela exige um vínculo de origem/destino.\nA regra de negócio determina que deve haver um **Ou Exclusivo (XOR)** na validação e na estrutura de dados:\n- Ou a recorrência está vinculada a uma Conta Bancária (`financial_account_id`).\n- Ou a recorrência está vinculada a um Cartão de Crédito (`financial_credit_card_id`).\nAs duas colunas não podem estar nulas simultaneamente, nem preenchidas ao mesmo tempo.\n\n### Frequência e Dia Base\nO dia em que a transação acontece é definido pelo dia extraído da coluna `start_date` via o método `dayOfMonth()`.\nO processamento irá somar +1 semana, +1 mês ou +1 ano a depender da `frequency`, gerando o `next_processing_date`.\n\n### Transações Virtuais vs. Materialização\nPara evitar criação massiva de registros no banco de dados para os próximos 10 anos, as recorrências operam sob o conceito de **Transações Virtuais**.\n- Ao consultar projeções financeiras, o sistema \"extrapola\" as datas calculando instâncias virtuais em tempo real na memória.\n- Uma recorrência só vira uma `FinancialTransaction` real (materialização) quando:\n  1. A data da `next_processing_date` se aproxima de hoje e o motor de automação (Cron) roda para criar a despesa real.\n  2. O usuário interage com o sistema para efetivar/pagar manualmente.\n  3. Quando vinculada a cartão de crédito, ao chegar próximo ao fechamento da fatura.\n\nEssa abordagem híbrida garante relatórios performáticos enquanto mantém os dados estritamente fiéis à realidade consolidada.",
  "sections": [
    {
      "id": "visao-geral",
      "level": 2,
      "title": "Visão Geral",
      "text": "As **Recorrências** (`FinancialRecurrence`) permitem a automação do fluxo de caixa agendando despesas ou receitas recorrentes (ex: assinaturas, mensalidades, salários). Diferente de compras parceladas, onde as parcelas nascem limitadas e já instanciadas no banco de dados, as recorrências são um \"molde\" dinâmico que gera transações à medida que o tempo passa, permitindo projeções de longo prazo sem inchar o banco de dados.",
      "line": 1
    },
    {
      "id": "tabelas",
      "level": 2,
      "title": "Tabelas",
      "text": "",
      "line": 5
    },
    {
      "id": "financial-recurrences",
      "level": 3,
      "title": "financial_recurrences",
      "text": "| Coluna | Tipo | Descrição | | --- | --- | --- | | `id` | bigint | Chave primária. | | `financial_account_id` | foreignId | (Opcional) Conta bancária vinculada. | | `financial_credit_card_id` | foreignId | (Opcional) Cartão de Crédito vinculado. | | `title` | string | Descrição/Título da recorrência. | | `type` | enum | `income` (receita) ou `expense` (despesa). | | `amount` | decimal | Valor base da transação a ser gerada. | | `frequency` | string | `weekly`, `monthly`, ou `yearly`. | | `start_date` | date | Data de início da recorrência. O dia desta data serve como base (Ex: dia 15). | | `end_date` | date | (Opcional) Data em que a recorrência deixa de vigorar. | | `next_processing_date` | date | Próxima data em que uma transação deverá ser materializada. | | `is_active` | boolean | Liga/desliga o motor de geração para esta recorrência. |",
      "line": 7
    },
    {
      "id": "diagrama-relacional-er",
      "level": 2,
      "title": "Diagrama Relacional (ER)",
      "text": "",
      "line": 23
    },
    {
      "id": "regras-de-negocio-e-comportamento",
      "level": 2,
      "title": "Regras de Negócio e Comportamento",
      "text": "",
      "line": 27
    },
    {
      "id": "vinculo-exclusivo-validacao-xor",
      "level": 3,
      "title": "Vínculo Exclusivo (Validação XOR)",
      "text": "Uma recorrência sempre movimenta fundos. Portanto, ela exige um vínculo de origem/destino. A regra de negócio determina que deve haver um **Ou Exclusivo (XOR)** na validação e na estrutura de dados: - Ou a recorrência está vinculada a uma Conta Bancária (`financial_account_id`). - Ou a recorrência está vinculada a um Cartão de Crédito (`financial_credit_card_id`). As duas colunas não podem estar nulas simultaneamente, nem preenchidas ao mesmo tempo.",
      "line": 29
    },
    {
      "id": "frequencia-e-dia-base",
      "level": 3,
      "title": "Frequência e Dia Base",
      "text": "O dia em que a transação acontece é definido pelo dia extraído da coluna `start_date` via o método `dayOfMonth()`. O processamento irá somar +1 semana, +1 mês ou +1 ano a depender da `frequency`, gerando o `next_processing_date`.",
      "line": 36
    },
    {
      "id": "transacoes-virtuais-vs-materializacao",
      "level": 3,
      "title": "Transações Virtuais vs. Materialização",
      "text": "Para evitar criação massiva de registros no banco de dados para os próximos 10 anos, as recorrências operam sob o conceito de **Transações Virtuais**. - Ao consultar projeções financeiras, o sistema \"extrapola\" as datas calculando instâncias virtuais em tempo real na memória. - Uma recorrência só vira uma `FinancialTransaction` real (materialização) quando: 1. A data da `next_processing_date` se aproxima de hoje e o motor de automação (Cron) roda para criar a despesa real. 2. O usuário interage com o sistema para efetivar/pagar manualmente. 3. Quando vinculada a cartão de crédito, ao chegar próximo ao fechamento da fatura.  Essa abordagem híbrida garante relatórios performáticos enquanto mantém os dados estritamente fiéis à realidade consolidada.",
      "line": 40
    }
  ],
  "sourcePath": "content/recorrencias.md",
  "visuals": [
    {
      "id": "recurrences-model",
      "kind": "er",
      "title": "Modelo relacional de recorrências",
      "description": "Recorrências se vinculam a uma conta ou cartão e materializam transações históricas.",
      "summary": "Uma recorrência tem vínculo exclusivo com uma conta financeira ou cartão de crédito e pode materializar várias transações ao longo do tempo.",
      "renderMode": "mermaid",
      "api": "api/diagrams/recurrences-model.json",
      "human": "diagrams/recurrences-model.html"
    }
  ],
  "apiVersion": 1
}
