@fayz-ai/plugin-financial 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/FinancialContext.d.ts +44 -0
- package/dist/FinancialContext.d.ts.map +1 -0
- package/dist/FinancialPage.d.ts +18 -0
- package/dist/FinancialPage.d.ts.map +1 -0
- package/dist/components/FinancialGeneralSettings.d.ts +3 -0
- package/dist/components/FinancialGeneralSettings.d.ts.map +1 -0
- package/dist/components/FinancialOnboarding.d.ts +5 -0
- package/dist/components/FinancialOnboarding.d.ts.map +1 -0
- package/dist/components/FinancialSettings.d.ts +8 -0
- package/dist/components/FinancialSettings.d.ts.map +1 -0
- package/dist/components/PaymentModal.d.ts +8 -0
- package/dist/components/PaymentModal.d.ts.map +1 -0
- package/dist/data/index.d.ts +3 -0
- package/dist/data/index.d.ts.map +1 -0
- package/dist/data/mock.d.ts +9 -0
- package/dist/data/mock.d.ts.map +1 -0
- package/dist/data/supabase.d.ts +3 -0
- package/dist/data/supabase.d.ts.map +1 -0
- package/dist/data/types.d.ts +27 -0
- package/dist/data/types.d.ts.map +1 -0
- package/dist/index.cjs +4937 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +91 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4930 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/tenant.d.ts +3 -0
- package/dist/lib/tenant.d.ts.map +1 -0
- package/dist/locales/en.d.ts +2 -0
- package/dist/locales/en.d.ts.map +1 -0
- package/dist/locales/index.d.ts +2 -0
- package/dist/locales/index.d.ts.map +1 -0
- package/dist/locales/pt-BR.d.ts +2 -0
- package/dist/locales/pt-BR.d.ts.map +1 -0
- package/dist/registries.d.ts +3 -0
- package/dist/registries.d.ts.map +1 -0
- package/dist/store.d.ts +38 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/types.d.ts +302 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/views/CardsView.d.ts +3 -0
- package/dist/views/CardsView.d.ts.map +1 -0
- package/dist/views/CashRegistersView.d.ts +3 -0
- package/dist/views/CashRegistersView.d.ts.map +1 -0
- package/dist/views/CommissionsView.d.ts +3 -0
- package/dist/views/CommissionsView.d.ts.map +1 -0
- package/dist/views/InvoiceDetailView.d.ts +9 -0
- package/dist/views/InvoiceDetailView.d.ts.map +1 -0
- package/dist/views/InvoiceFormView.d.ts +13 -0
- package/dist/views/InvoiceFormView.d.ts.map +1 -0
- package/dist/views/InvoiceListView.d.ts +8 -0
- package/dist/views/InvoiceListView.d.ts.map +1 -0
- package/dist/views/PayablesView.d.ts +7 -0
- package/dist/views/PayablesView.d.ts.map +1 -0
- package/dist/views/ReceivablesView.d.ts +7 -0
- package/dist/views/ReceivablesView.d.ts.map +1 -0
- package/dist/views/StatementsView.d.ts +3 -0
- package/dist/views/StatementsView.d.ts.map +1 -0
- package/dist/views/SummaryView.d.ts +9 -0
- package/dist/views/SummaryView.d.ts.map +1 -0
- package/dist/views/dashboardWidgets.d.ts +11 -0
- package/dist/views/dashboardWidgets.d.ts.map +1 -0
- package/package.json +55 -0
- package/src/FinancialContext.tsx +47 -0
- package/src/FinancialPage.tsx +261 -0
- package/src/README.md +155 -0
- package/src/components/FinancialGeneralSettings.tsx +26 -0
- package/src/components/FinancialOnboarding.tsx +87 -0
- package/src/components/FinancialSettings.tsx +31 -0
- package/src/components/PaymentModal.tsx +322 -0
- package/src/data/index.ts +2 -0
- package/src/data/mock.ts +520 -0
- package/src/data/supabase.ts +509 -0
- package/src/data/types.ts +53 -0
- package/src/index.ts +307 -0
- package/src/lib/tenant.ts +3 -0
- package/src/locales/en.ts +331 -0
- package/src/locales/index.ts +7 -0
- package/src/locales/pt-BR.ts +331 -0
- package/src/migrations/001_financial_base.sql +109 -0
- package/src/migrations/002_chart_of_accounts.sql +28 -0
- package/src/migrations/003_card_brands.sql +12 -0
- package/src/migrations/004_order_to_cash.sql +164 -0
- package/src/migrations/005_seed_defaults.sql +38 -0
- package/src/registries.ts +305 -0
- package/src/store.ts +221 -0
- package/src/types.ts +359 -0
- package/src/views/CardsView.tsx +74 -0
- package/src/views/CashRegistersView.tsx +597 -0
- package/src/views/CommissionsView.tsx +18 -0
- package/src/views/InvoiceDetailView.tsx +595 -0
- package/src/views/InvoiceFormView.tsx +900 -0
- package/src/views/InvoiceListView.tsx +177 -0
- package/src/views/PayablesView.tsx +37 -0
- package/src/views/ReceivablesView.tsx +37 -0
- package/src/views/StatementsView.tsx +123 -0
- package/src/views/SummaryView.tsx +12 -0
- package/src/views/dashboardWidgets.tsx +191 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
// financial.* — merged plugin-own + saas-core central i18n
|
|
2
|
+
export const ptBR: Record<string, string> = {
|
|
3
|
+
"financial.cards.installment": "Parcela {{current}}/{{total}}",
|
|
4
|
+
"financial.cards.noTransactions": "Nenhuma transação com cartão",
|
|
5
|
+
"financial.cards.pending": "Pendente",
|
|
6
|
+
"financial.cards.received": "Recebido",
|
|
7
|
+
"financial.cards.subtitle": "Transações de cartão de crédito e débito",
|
|
8
|
+
"financial.cards.title": "Cartões",
|
|
9
|
+
"financial.cards.transactions": "({{count}} transações)",
|
|
10
|
+
"financial.cards.transactionsAppear": "As transações com cartão aparecerão aqui quando pagamentos forem feitos via cartão de crédito/débito",
|
|
11
|
+
"financial.cashRegisters.addNotes": "Adicionar observações",
|
|
12
|
+
"financial.cashRegisters.back": "Voltar",
|
|
13
|
+
"financial.cashRegisters.bills": "Notas",
|
|
14
|
+
"financial.cashRegisters.closeSession": "Fechar Sessão",
|
|
15
|
+
"financial.cashRegisters.closeThisSession": "Fechar esta sessão",
|
|
16
|
+
"financial.cashRegisters.closing": "Fechando...",
|
|
17
|
+
"financial.cashRegisters.closingBalance": "Saldo de Fechamento",
|
|
18
|
+
"financial.cashRegisters.closingNotes": "Observações de Fechamento",
|
|
19
|
+
"financial.cashRegisters.coins": "Moedas",
|
|
20
|
+
"financial.cashRegisters.confirmOpen": "Confirmar e Abrir",
|
|
21
|
+
"financial.cashRegisters.confirmOpening": "Confirmar Abertura do Caixa",
|
|
22
|
+
"financial.cashRegisters.count": "Contagem",
|
|
23
|
+
"financial.cashRegisters.countBills": "Contar Notas e Moedas",
|
|
24
|
+
"financial.cashRegisters.countedTotal": "Total Contado",
|
|
25
|
+
"financial.cashRegisters.denominationCount": "Contagem por denominação",
|
|
26
|
+
"financial.cashRegisters.differenceFromOpening": "Diferença em relação à abertura",
|
|
27
|
+
"financial.cashRegisters.method": "Método",
|
|
28
|
+
"financial.cashRegisters.noCashAccounts": "Nenhuma conta de caixa encontrada. Crie uma conta bancária do tipo \"Caixa Registradora\" primeiro.",
|
|
29
|
+
"financial.cashRegisters.noClosedSessions": "Nenhuma sessão encerrada ainda",
|
|
30
|
+
"financial.cashRegisters.openAnother": "Abrir outro caixa",
|
|
31
|
+
"financial.cashRegisters.openSession": "Abrir Sessão",
|
|
32
|
+
"financial.cashRegisters.openSessions": "Sessões Abertas",
|
|
33
|
+
"financial.cashRegisters.opened": "Aberto",
|
|
34
|
+
"financial.cashRegisters.opening": "Abrindo...",
|
|
35
|
+
"financial.cashRegisters.openingBalance": "Saldo de Abertura",
|
|
36
|
+
"financial.cashRegisters.quickAmount": "Valor Rápido",
|
|
37
|
+
"financial.cashRegisters.register": "Caixa",
|
|
38
|
+
"financial.cashRegisters.sessionHistory": "Histórico de Sessões",
|
|
39
|
+
"financial.cashRegisters.subtitle": "Abrir, contar e fechar sessões de caixa",
|
|
40
|
+
"financial.commissions.comingSoon": "Em breve",
|
|
41
|
+
"financial.commissions.subtitle": "Comissões da equipe",
|
|
42
|
+
"financial.invoice.accountsPayable": "Contas a Pagar",
|
|
43
|
+
"financial.invoice.accountsReceivable": "Contas a Receber",
|
|
44
|
+
"financial.invoice.cancelConfirm": "Esta ação não pode ser desfeita.",
|
|
45
|
+
"financial.invoice.cancelDesc": "A fatura será marcada como cancelada. Todas as parcelas pendentes também serão canceladas. Esta fatura não contará mais nos totais.",
|
|
46
|
+
"financial.invoice.cancelInvoice": "Cancelar Fatura",
|
|
47
|
+
"financial.invoice.cancelling": "Cancelando...",
|
|
48
|
+
"financial.invoice.contact": "Contato",
|
|
49
|
+
"financial.invoice.createFirst": "Crie sua primeira fatura",
|
|
50
|
+
"financial.invoice.date": "Data",
|
|
51
|
+
"financial.invoice.booking": "Agendamento",
|
|
52
|
+
"financial.invoice.discount": "Desconto",
|
|
53
|
+
"financial.invoice.due": "Vencimento:",
|
|
54
|
+
"financial.invoice.edit": "Editar Fatura",
|
|
55
|
+
"financial.invoice.fullyPaid": "Totalmente pago",
|
|
56
|
+
"financial.invoice.installments": "Parcelas",
|
|
57
|
+
"financial.invoice.invoices": "{{count}} faturas",
|
|
58
|
+
"financial.invoice.items": "Itens",
|
|
59
|
+
"financial.invoice.keepInvoice": "Manter Fatura",
|
|
60
|
+
"financial.invoice.new": "Nova",
|
|
61
|
+
"financial.invoice.noDetails": "Nenhum detalhe adicional registrado",
|
|
62
|
+
"financial.invoice.noInstallments": "Sem parcelas",
|
|
63
|
+
"financial.invoice.noInvoices": "Nenhuma fatura ainda",
|
|
64
|
+
"financial.invoice.summaryTotal": "Total",
|
|
65
|
+
"financial.invoice.summaryReceived": "Recebido",
|
|
66
|
+
"financial.invoice.summaryReceivable": "A Receber",
|
|
67
|
+
"financial.invoice.summaryPaid": "Pago",
|
|
68
|
+
"financial.invoice.summaryPayable": "A Pagar",
|
|
69
|
+
"financial.invoice.notFound": "Fatura não encontrada",
|
|
70
|
+
"financial.invoice.notFoundDesc": "Esta fatura não pôde ser carregada.",
|
|
71
|
+
"financial.invoice.notes": "Observações",
|
|
72
|
+
"financial.invoice.paidLabel": "Pago:",
|
|
73
|
+
"financial.invoice.paidOn": "Pago em:",
|
|
74
|
+
"financial.invoice.pay": "Pagar",
|
|
75
|
+
"financial.invoice.paymentSchedule": "Cronograma de Pagamento",
|
|
76
|
+
"financial.invoice.remaining": "Restante:",
|
|
77
|
+
"financial.invoice.searchPlaceholder": "Buscar por contato ou descrição...",
|
|
78
|
+
"financial.invoice.showing": "Exibindo {{shown}} de {{total}}",
|
|
79
|
+
"financial.invoice.subtotal": "Subtotal",
|
|
80
|
+
"financial.invoice.surcharge": "Acréscimo",
|
|
81
|
+
"financial.invoice.total": "Total",
|
|
82
|
+
"financial.invoice.yesCancel": "Sim, Cancelar",
|
|
83
|
+
"financial.invoiceForm.addFirstItem": "Adicione seu primeiro item",
|
|
84
|
+
"financial.invoiceForm.addItem": "Adicionar Item",
|
|
85
|
+
"financial.invoiceForm.addItemsFirst": "Adicione itens primeiro",
|
|
86
|
+
"financial.invoiceForm.additionalNotes": "Observações adicionais...",
|
|
87
|
+
"financial.invoiceForm.cancel": "Cancelar",
|
|
88
|
+
"financial.invoiceForm.close": "Fechar",
|
|
89
|
+
"financial.invoiceForm.creating": "Criando nova fatura",
|
|
90
|
+
"financial.invoiceForm.date": "Data",
|
|
91
|
+
"financial.invoiceForm.description": "Descrição",
|
|
92
|
+
"financial.invoiceForm.discountSurcharge": "Desconto / Acréscimo",
|
|
93
|
+
"financial.invoiceForm.done": "Pronto",
|
|
94
|
+
"financial.invoiceForm.editing": "Editando fatura",
|
|
95
|
+
"financial.invoiceForm.fiscalNumber": "Número Fiscal (opcional)",
|
|
96
|
+
"financial.invoiceForm.headquarters": "Sede",
|
|
97
|
+
"financial.invoiceForm.installments": "Parcelas",
|
|
98
|
+
"financial.invoiceForm.item": "Item",
|
|
99
|
+
"financial.invoiceForm.itemDescription": "Descrição do item",
|
|
100
|
+
"financial.invoiceForm.items": "Itens",
|
|
101
|
+
"financial.invoiceForm.noDescription": "Sem descrição",
|
|
102
|
+
"financial.invoiceForm.noItems": "Nenhum item adicionado ainda",
|
|
103
|
+
"financial.invoiceForm.noUnitsFound": "Nenhuma unidade encontrada",
|
|
104
|
+
"financial.invoiceForm.observations": "Observações",
|
|
105
|
+
"financial.invoiceForm.payTo": "Pagar para",
|
|
106
|
+
"financial.invoiceForm.qty": "Qtd",
|
|
107
|
+
"financial.invoiceForm.receiveFrom": "Receber de",
|
|
108
|
+
"financial.invoiceForm.save": "Salvar",
|
|
109
|
+
"financial.invoiceForm.saving": "Salvando...",
|
|
110
|
+
"financial.invoiceForm.searchType": "Digite para buscar...",
|
|
111
|
+
"financial.invoiceForm.searchUnit": "Buscar unidade...",
|
|
112
|
+
"financial.invoiceForm.selectInstallments": "Selecione a quantidade de parcelas acima",
|
|
113
|
+
"financial.invoiceForm.selectItemType": "Selecione o tipo do item:",
|
|
114
|
+
"financial.invoiceForm.selectUnit": "Selecionar unidade",
|
|
115
|
+
"financial.invoiceForm.selectUnitTitle": "Selecionar Unidade",
|
|
116
|
+
"financial.invoiceForm.unit": "Unidade",
|
|
117
|
+
"financial.invoiceForm.unitPrice": "Preço Unitário",
|
|
118
|
+
"financial.nav.cards": "Cartões",
|
|
119
|
+
"financial.nav.cashRegisters": "Caixas",
|
|
120
|
+
"financial.nav.commissions": "Comissões",
|
|
121
|
+
"financial.nav.list": "Lista",
|
|
122
|
+
"financial.nav.new": "Novo",
|
|
123
|
+
"financial.nav.overview": "Visão Geral",
|
|
124
|
+
"financial.nav.payables": "Contas a Pagar",
|
|
125
|
+
"financial.nav.receivables": "Contas a Receber",
|
|
126
|
+
"financial.nav.reconciliation": "Conciliação",
|
|
127
|
+
"financial.nav.recurringExpenses": "Despesas Recorrentes",
|
|
128
|
+
"financial.nav.rules": "Regras",
|
|
129
|
+
"financial.nav.statements": "Extratos",
|
|
130
|
+
"financial.nav.summary": "Resumo",
|
|
131
|
+
"financial.onboarding.back": "Voltar",
|
|
132
|
+
"financial.onboarding.configureHint": "Você pode configurar isso em detalhes pelo ícone de Configurações dentro do módulo Financeiro.",
|
|
133
|
+
"financial.onboarding.getStarted": "Começar",
|
|
134
|
+
"financial.onboarding.next": "Próximo",
|
|
135
|
+
"financial.onboarding.startUsing": "Começar a usar o Financeiro",
|
|
136
|
+
"financial.onboarding.skip": "Pular configuração",
|
|
137
|
+
"financial.onboarding.welcome": "Bem-vindo ao Financeiro",
|
|
138
|
+
"financial.onboarding.description": "Vamos configurar seu módulo financeiro. Este assistente rápido ajudará a configurar o essencial.",
|
|
139
|
+
"financial.onboarding.accounts.title": "Contas Bancárias",
|
|
140
|
+
"financial.onboarding.accounts.description": "Adicione suas contas bancárias, caixas registradoras e cartões de crédito. Você pode adicionar mais depois em Configurações.",
|
|
141
|
+
"financial.onboarding.payments.title": "Métodos de Pagamento",
|
|
142
|
+
"financial.onboarding.payments.description": "Revise os tipos de pagamento que você aceita. Os tipos padrão (Dinheiro, PIX, Cartão de Crédito, etc.) já estão configurados.",
|
|
143
|
+
"financial.onboarding.chart.title": "Plano de Contas",
|
|
144
|
+
"financial.onboarding.chart.description": "Um modelo padrão de plano de contas foi criado. Você pode personalizá-lo a qualquer momento em Configurações.",
|
|
145
|
+
"financial.page.newPayable": "Nova Conta a Pagar",
|
|
146
|
+
"financial.page.newPayableDesc": "Registrar uma despesa ou conta a pagar",
|
|
147
|
+
"financial.page.newReceivable": "Nova Conta a Receber",
|
|
148
|
+
"financial.page.newReceivableDesc": "Registrar receita ou valor a receber",
|
|
149
|
+
"financial.page.openCash": "Abrir Caixa",
|
|
150
|
+
"financial.page.openCashDesc": "Iniciar uma nova sessão de caixa",
|
|
151
|
+
"financial.page.settingsSubtitle": "Preferências, métodos de pagamento e contas",
|
|
152
|
+
"financial.page.settingsTitle": "Configurações Financeiras",
|
|
153
|
+
"financial.payment.amount": "Valor",
|
|
154
|
+
"financial.payment.bankAccount": "Conta Bancária",
|
|
155
|
+
"financial.payment.cancel": "Cancelar",
|
|
156
|
+
"financial.payment.card": "Cartão",
|
|
157
|
+
"financial.payment.cardBrand": "Bandeira do Cartão",
|
|
158
|
+
"financial.payment.cardInstallments": "Parcelas",
|
|
159
|
+
"financial.payment.date": "Data",
|
|
160
|
+
"financial.payment.installment": "Parcela #{{number}}",
|
|
161
|
+
"financial.payment.method": "Método de Pagamento",
|
|
162
|
+
"financial.payment.notes": "Observações",
|
|
163
|
+
"financial.payment.optionalNotes": "Observações opcionais...",
|
|
164
|
+
"financial.payment.payAmount": "Pagar {{amount}}",
|
|
165
|
+
"financial.payment.processing": "Processando...",
|
|
166
|
+
"financial.payment.remaining": "{{amount}} restante",
|
|
167
|
+
"financial.payment.select": "Selecionar...",
|
|
168
|
+
"financial.payment.selectAccount": "Selecionar conta...",
|
|
169
|
+
"financial.payment.selectBrand": "Selecionar bandeira...",
|
|
170
|
+
"financial.payment.title": "Registrar Pagamento",
|
|
171
|
+
"financial.settings.allowPartial": "Permitir pagamentos parciais",
|
|
172
|
+
"financial.settings.allowPartialDesc": "Aceitar pagamentos menores que o valor total da parcela",
|
|
173
|
+
"financial.settings.autoClose": "Fechamento automático no fim do dia",
|
|
174
|
+
"financial.settings.autoCloseDesc": "Lembrar de fechar sessões abertas no fim do expediente",
|
|
175
|
+
"financial.settings.autoInstallments": "Gerar parcelas automaticamente",
|
|
176
|
+
"financial.settings.autoInstallmentsDesc": "Dividir automaticamente o total da fatura em parcelas iguais",
|
|
177
|
+
"financial.settings.cashRegister": "Caixa Registradora",
|
|
178
|
+
"financial.settings.cashRegisterDesc": "Comportamento da sessão de caixa",
|
|
179
|
+
"financial.settings.dailySummary": "Resumo financeiro diário",
|
|
180
|
+
"financial.settings.dailySummaryDesc": "Enviar um resumo diário por e-mail de contas a receber e a pagar",
|
|
181
|
+
"financial.settings.invoices": "Faturas",
|
|
182
|
+
"financial.settings.invoicesDesc": "Como faturas e pagamentos são processados",
|
|
183
|
+
"financial.settings.notifications": "Notificações",
|
|
184
|
+
"financial.settings.notificationsDesc": "Alertas e lembretes",
|
|
185
|
+
"financial.settings.overdueAlerts": "Alertas de pagamento atrasado",
|
|
186
|
+
"financial.settings.overdueAlertsDesc": "Notificar quando faturas passarem da data de vencimento",
|
|
187
|
+
"financial.settings.requireDoc": "Exigir número do documento",
|
|
188
|
+
"financial.settings.requireDocDesc": "Tornar obrigatório o número do documento/fatura nos pagamentos",
|
|
189
|
+
"financial.settings.requireOpening": "Exigir saldo de abertura",
|
|
190
|
+
"financial.settings.requireOpeningDesc": "O saldo de abertura deve ser confirmado antes de iniciar uma sessão",
|
|
191
|
+
"financial.settingsPage.subtitle": "Gerenciar métodos de pagamento, contas e configurações",
|
|
192
|
+
"financial.settingsPage.title": "Configurações Financeiras",
|
|
193
|
+
"financial.payment.noMethods": "Nenhuma forma de pagamento configurada.",
|
|
194
|
+
"financial.payment.configureMethods": "Configurar formas de pagamento",
|
|
195
|
+
"financial.statements.account": "Conta",
|
|
196
|
+
"financial.statements.from": "De",
|
|
197
|
+
"financial.statements.noTransactions": "Sem transações neste período",
|
|
198
|
+
"financial.statements.selectAccount": "Selecione uma conta para ver o extrato",
|
|
199
|
+
"financial.statements.selectToView": "Selecione uma conta para ver o extrato",
|
|
200
|
+
"financial.statements.subtitle": "Transações e saldos de contas bancárias",
|
|
201
|
+
"financial.statements.title": "Extratos",
|
|
202
|
+
"financial.statements.to": "Até",
|
|
203
|
+
"financial.summary.allAccounts": "Todas as contas",
|
|
204
|
+
"financial.summary.cashFlow": "Fluxo de Caixa",
|
|
205
|
+
"financial.summary.cashFlowBreakdown": "Detalhamento do Fluxo de Caixa",
|
|
206
|
+
"financial.summary.cashFlowBreakdownSubtitle": "Contas a receber vs. contas a pagar neste mês",
|
|
207
|
+
"financial.summary.cashFlowSubtitle": "Receitas vs despesas mensais",
|
|
208
|
+
"financial.summary.expenses": "Despesas",
|
|
209
|
+
"financial.summary.income": "Receita",
|
|
210
|
+
"financial.summary.monthlyFlow": "Fluxo Mensal",
|
|
211
|
+
"financial.summary.negativeBalance": "Saldo negativo",
|
|
212
|
+
"financial.summary.net": "Líquido",
|
|
213
|
+
"financial.summary.noOverdue": "Nenhuma transação atrasada",
|
|
214
|
+
"financial.summary.noTransactions": "Nenhuma transação ainda",
|
|
215
|
+
"financial.summary.overdue": "{{count}} atrasados",
|
|
216
|
+
"financial.summary.overduePayable": "Conta a pagar atrasada",
|
|
217
|
+
"financial.summary.overdueReceivable": "Conta a receber atrasada",
|
|
218
|
+
"financial.summary.overdueTitle": "Atrasados",
|
|
219
|
+
"financial.summary.paid": "Pago",
|
|
220
|
+
"financial.summary.payable": "A Pagar",
|
|
221
|
+
"financial.summary.positiveBalance": "Saldo positivo",
|
|
222
|
+
"financial.summary.receivable": "A Receber",
|
|
223
|
+
"financial.summary.received": "Recebido",
|
|
224
|
+
"financial.summary.recentTransactions": "Transações Recentes",
|
|
225
|
+
"financial.summary.totalBalance": "Saldo Total",
|
|
226
|
+
"financial.summary.transactionsAppear": "As transações aparecerão aqui após serem registradas",
|
|
227
|
+
"financial.summary.viewAll": "Ver todos",
|
|
228
|
+
"financial.quickActions.newPayable": "Nova Conta a Pagar",
|
|
229
|
+
"financial.quickActions.newPayableDesc": "Registrar uma despesa ou conta a pagar",
|
|
230
|
+
"financial.quickActions.newReceivable": "Nova Conta a Receber",
|
|
231
|
+
"financial.quickActions.newReceivableDesc": "Registrar receita ou valor a receber",
|
|
232
|
+
"financial.quickActions.openCashRegister": "Abrir Caixa",
|
|
233
|
+
"financial.quickActions.openCashRegisterDesc": "Iniciar uma nova sessão de caixa",
|
|
234
|
+
"financial.cash.title": "Caixa Registradora",
|
|
235
|
+
"financial.cash.subtitle": "Abrir, contar e fechar sessões de caixa",
|
|
236
|
+
"financial.cash.bills": "Notas",
|
|
237
|
+
"financial.cash.coins": "Moedas",
|
|
238
|
+
"financial.cash.noAccounts": "Nenhuma conta de caixa encontrada. Crie uma conta bancária do tipo \"Caixa Registradora\" primeiro.",
|
|
239
|
+
"financial.cash.confirmOpening": "Confirmar Abertura de Caixa",
|
|
240
|
+
"financial.cash.register": "Caixa",
|
|
241
|
+
"financial.cash.openingBalance": "Saldo de Abertura",
|
|
242
|
+
"financial.cash.method": "Método",
|
|
243
|
+
"financial.cash.denominationCount": "Contagem de cédulas",
|
|
244
|
+
"financial.cash.notes": "Observações",
|
|
245
|
+
"financial.cash.opening": "Abrindo...",
|
|
246
|
+
"financial.cash.confirmAndOpen": "Confirmar e Abrir",
|
|
247
|
+
"financial.cash.quickAmount": "Valor Rápido",
|
|
248
|
+
"financial.cash.countBillsCoins": "Contar Cédulas e Moedas",
|
|
249
|
+
"financial.cash.count": "Contar",
|
|
250
|
+
"financial.cash.countedTotal": "Total Contado",
|
|
251
|
+
"financial.cash.addNotes": "Adicionar observações",
|
|
252
|
+
"financial.cash.openingObservations": "Observações de abertura...",
|
|
253
|
+
"financial.cash.openSession": "Abrir Sessão",
|
|
254
|
+
"financial.cash.closingBalance": "Saldo de Fechamento",
|
|
255
|
+
"financial.cash.differenceFromOpening": "Diferença da abertura",
|
|
256
|
+
"financial.cash.closingNotes": "Observações de Fechamento",
|
|
257
|
+
"financial.cash.closingObservations": "Observações de fechamento...",
|
|
258
|
+
"financial.cash.closing": "Fechando...",
|
|
259
|
+
"financial.cash.closeSession": "Fechar Sessão",
|
|
260
|
+
"financial.cash.openSessions": "Sessões Abertas",
|
|
261
|
+
"financial.cash.opened": "Aberto",
|
|
262
|
+
"financial.cash.by": "por",
|
|
263
|
+
"financial.cash.closeThisSession": "Fechar esta sessão",
|
|
264
|
+
"financial.cash.sessionHistory": "Histórico de Sessões",
|
|
265
|
+
"financial.cash.noClosedSessions": "Nenhuma sessão fechada ainda",
|
|
266
|
+
"financial.cash.openLabel": "Abertura",
|
|
267
|
+
"financial.cash.closeLabel": "Fechamento",
|
|
268
|
+
"financial.cash.diff": "Dif",
|
|
269
|
+
"financial.cash.openAnother": "Abrir outro caixa",
|
|
270
|
+
"financial.invoice.statusOpen": "Aberto",
|
|
271
|
+
"financial.invoice.statusPartial": "Parcial",
|
|
272
|
+
"financial.invoice.statusPaid": "Pago",
|
|
273
|
+
"financial.invoice.statusOverdue": "Vencido",
|
|
274
|
+
"financial.invoice.statusCancelled": "Cancelado",
|
|
275
|
+
"financial.invoice.statusPending": "Pendente",
|
|
276
|
+
"financial.invoice.statusDraft": "Rascunho",
|
|
277
|
+
"financial.invoice.columnDate": "Data",
|
|
278
|
+
"financial.invoice.columnDescription": "Descrição",
|
|
279
|
+
"financial.invoice.columnAmount": "Valor",
|
|
280
|
+
"financial.invoice.columnPaid": "Pago",
|
|
281
|
+
"financial.invoice.columnStatus": "Status",
|
|
282
|
+
"financial.invoice.columnInst": "Parc.",
|
|
283
|
+
"financial.invoice.columnQty": "Qtd",
|
|
284
|
+
"financial.invoice.columnUnitPrice": "Preço Unit.",
|
|
285
|
+
"financial.invoice.columnTotal": "Total",
|
|
286
|
+
"financial.invoice.columnNumber": "#",
|
|
287
|
+
"financial.invoice.invoice": "Fatura",
|
|
288
|
+
"financial.invoice.loading": "Carregando...",
|
|
289
|
+
"financial.invoiceForm.cancelInvoice": "Cancelar Fatura",
|
|
290
|
+
"financial.invoiceForm.cancelConfirm": "Esta ação não pode ser desfeita.",
|
|
291
|
+
"financial.invoiceForm.cancelDesc": "A fatura será marcada como cancelada. Todas as parcelas pendentes também serão canceladas.",
|
|
292
|
+
"financial.invoiceForm.keepInvoice": "Manter Fatura",
|
|
293
|
+
"financial.invoiceForm.yesCancel": "Sim, Cancelar",
|
|
294
|
+
"financial.invoiceForm.cancelling": "Cancelando...",
|
|
295
|
+
"financial.invoiceForm.removeAdjustments": "Remover ajustes",
|
|
296
|
+
"financial.invoiceForm.discount": "Desconto",
|
|
297
|
+
"financial.invoiceForm.surcharge": "Acréscimo",
|
|
298
|
+
"financial.invoiceForm.total": "Total:",
|
|
299
|
+
"financial.invoiceForm.itemCount": "{{count}} item{{plural}}",
|
|
300
|
+
"financial.payment.account": "Conta",
|
|
301
|
+
"financial.payment.due": "Venc.:",
|
|
302
|
+
"financial.payment.paidAmount": "Pago:",
|
|
303
|
+
"financial.payment.paidOn": "Pago em:",
|
|
304
|
+
"financial.title": "Financeiro",
|
|
305
|
+
"financial.summary.title": "Resumo Financeiro",
|
|
306
|
+
"financial.summary.revenue": "Receita",
|
|
307
|
+
"financial.invoice.title": "Faturas",
|
|
308
|
+
"financial.invoice.create": "Nova Fatura",
|
|
309
|
+
"financial.invoice.number": "Fatura #",
|
|
310
|
+
"financial.invoice.client": "Cliente",
|
|
311
|
+
"financial.invoice.amount": "Valor",
|
|
312
|
+
"financial.invoice.status": "Status",
|
|
313
|
+
"financial.invoice.dueDate": "Vencimento",
|
|
314
|
+
"financial.invoice.addItem": "Adicionar Item",
|
|
315
|
+
"financial.invoice.tax": "Imposto",
|
|
316
|
+
"financial.invoice.save": "Salvar Fatura",
|
|
317
|
+
"financial.invoice.saving": "Salvando...",
|
|
318
|
+
"financial.invoice.markPaid": "Marcar como Pago",
|
|
319
|
+
"financial.invoice.sendReminder": "Enviar Lembrete",
|
|
320
|
+
"financial.receivable.title": "Contas a Receber",
|
|
321
|
+
"financial.payable.title": "Contas a Pagar",
|
|
322
|
+
"financial.statements.loading": "Carregando...",
|
|
323
|
+
"financial.cards.empty": "Nenhuma transação de cartão ainda",
|
|
324
|
+
"financial.commissions.title": "Comissões",
|
|
325
|
+
"financial.cashRegister.title": "Caixa",
|
|
326
|
+
"financial.cashRegister.open": "Abrir Caixa",
|
|
327
|
+
"financial.cashRegister.close": "Fechar Caixa",
|
|
328
|
+
"financial.movements.title": "Movimentações",
|
|
329
|
+
"financial.bankAccounts.title": "Contas Bancárias",
|
|
330
|
+
"financial.settings.title": "Configurações Financeiras",
|
|
331
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
-- Financial Plugin: Base Tables
|
|
2
|
+
-- Pattern: uuid PK, tenant_id FK, timestamps, RLS via project_rls.sql auto-detection
|
|
3
|
+
|
|
4
|
+
CREATE TABLE IF NOT EXISTS public.payment_method_types (
|
|
5
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
6
|
+
tenant_id uuid NOT NULL REFERENCES saas_core.tenants(id) ON DELETE CASCADE,
|
|
7
|
+
name text NOT NULL,
|
|
8
|
+
transaction_type text NOT NULL,
|
|
9
|
+
is_active boolean NOT NULL DEFAULT true,
|
|
10
|
+
allowed_account_types jsonb DEFAULT '[]'::jsonb,
|
|
11
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
12
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
13
|
+
);
|
|
14
|
+
ALTER TABLE public.payment_method_types ENABLE ROW LEVEL SECURITY;
|
|
15
|
+
CREATE INDEX IF NOT EXISTS idx_payment_method_types_tenant ON public.payment_method_types(tenant_id);
|
|
16
|
+
|
|
17
|
+
CREATE TABLE IF NOT EXISTS public.payment_methods (
|
|
18
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
19
|
+
tenant_id uuid NOT NULL REFERENCES saas_core.tenants(id) ON DELETE CASCADE,
|
|
20
|
+
name text NOT NULL,
|
|
21
|
+
payment_method_type_id uuid REFERENCES public.payment_method_types(id),
|
|
22
|
+
is_active boolean NOT NULL DEFAULT true,
|
|
23
|
+
discount_mode text,
|
|
24
|
+
discount_value numeric(12,2) DEFAULT 0,
|
|
25
|
+
interest_mode text,
|
|
26
|
+
interest_value numeric(12,2) DEFAULT 0,
|
|
27
|
+
min_installments integer DEFAULT 1,
|
|
28
|
+
max_installments integer DEFAULT 1,
|
|
29
|
+
service_filter_mode text DEFAULT 'all',
|
|
30
|
+
service_filter_ids jsonb DEFAULT '[]'::jsonb,
|
|
31
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
32
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
33
|
+
);
|
|
34
|
+
ALTER TABLE public.payment_methods ENABLE ROW LEVEL SECURITY;
|
|
35
|
+
CREATE INDEX IF NOT EXISTS idx_payment_methods_tenant ON public.payment_methods(tenant_id);
|
|
36
|
+
|
|
37
|
+
CREATE TABLE IF NOT EXISTS public.bank_accounts (
|
|
38
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
39
|
+
tenant_id uuid NOT NULL REFERENCES saas_core.tenants(id) ON DELETE CASCADE,
|
|
40
|
+
name text NOT NULL,
|
|
41
|
+
account_type text NOT NULL DEFAULT 'bank_account',
|
|
42
|
+
bank_name text,
|
|
43
|
+
account_number text,
|
|
44
|
+
agency_number text,
|
|
45
|
+
current_balance numeric(14,2) NOT NULL DEFAULT 0,
|
|
46
|
+
initial_balance numeric(14,2) NOT NULL DEFAULT 0,
|
|
47
|
+
credit_limit numeric(14,2),
|
|
48
|
+
due_day integer,
|
|
49
|
+
closing_day integer,
|
|
50
|
+
is_active boolean NOT NULL DEFAULT true,
|
|
51
|
+
unit_id uuid,
|
|
52
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
53
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
54
|
+
);
|
|
55
|
+
ALTER TABLE public.bank_accounts ENABLE ROW LEVEL SECURITY;
|
|
56
|
+
CREATE INDEX IF NOT EXISTS idx_bank_accounts_tenant ON public.bank_accounts(tenant_id);
|
|
57
|
+
|
|
58
|
+
CREATE TABLE IF NOT EXISTS public.cash_register_sessions (
|
|
59
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
60
|
+
tenant_id uuid NOT NULL REFERENCES saas_core.tenants(id) ON DELETE CASCADE,
|
|
61
|
+
bank_account_id uuid NOT NULL REFERENCES public.bank_accounts(id),
|
|
62
|
+
status text NOT NULL DEFAULT 'open',
|
|
63
|
+
opened_at timestamptz NOT NULL DEFAULT now(),
|
|
64
|
+
opened_by_user_id uuid,
|
|
65
|
+
opened_by_name text,
|
|
66
|
+
opening_balance numeric(14,2) NOT NULL,
|
|
67
|
+
closed_at timestamptz,
|
|
68
|
+
closed_by_user_id uuid,
|
|
69
|
+
closed_by_name text,
|
|
70
|
+
closing_balance numeric(14,2),
|
|
71
|
+
expected_balance numeric(14,2),
|
|
72
|
+
difference numeric(14,2),
|
|
73
|
+
notes text,
|
|
74
|
+
unit_id uuid,
|
|
75
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
76
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
77
|
+
);
|
|
78
|
+
ALTER TABLE public.cash_register_sessions ENABLE ROW LEVEL SECURITY;
|
|
79
|
+
CREATE INDEX IF NOT EXISTS idx_cash_register_sessions_tenant ON public.cash_register_sessions(tenant_id);
|
|
80
|
+
|
|
81
|
+
-- Financial movements (installments, payments) — plugin-specific, not archetype
|
|
82
|
+
-- Invoices themselves use saas_core.orders (kind='invoice_payable'/'invoice_receivable')
|
|
83
|
+
CREATE TABLE IF NOT EXISTS public.financial_movements (
|
|
84
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
85
|
+
tenant_id uuid NOT NULL REFERENCES saas_core.tenants(id) ON DELETE CASCADE,
|
|
86
|
+
invoice_id uuid REFERENCES saas_core.orders(id),
|
|
87
|
+
direction text NOT NULL,
|
|
88
|
+
movement_kind text NOT NULL,
|
|
89
|
+
amount numeric(14,2) NOT NULL,
|
|
90
|
+
paid_amount numeric(14,2) DEFAULT 0,
|
|
91
|
+
status text NOT NULL DEFAULT 'pending',
|
|
92
|
+
due_date date NOT NULL,
|
|
93
|
+
payment_date date,
|
|
94
|
+
installment_number integer,
|
|
95
|
+
payment_method_id uuid REFERENCES public.payment_methods(id),
|
|
96
|
+
bank_account_id uuid REFERENCES public.bank_accounts(id),
|
|
97
|
+
cash_session_id uuid REFERENCES public.cash_register_sessions(id),
|
|
98
|
+
card_brand text,
|
|
99
|
+
card_installments integer,
|
|
100
|
+
notes text,
|
|
101
|
+
metadata jsonb DEFAULT '{}'::jsonb,
|
|
102
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
103
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
104
|
+
);
|
|
105
|
+
ALTER TABLE public.financial_movements ENABLE ROW LEVEL SECURITY;
|
|
106
|
+
CREATE INDEX IF NOT EXISTS idx_financial_movements_tenant ON public.financial_movements(tenant_id);
|
|
107
|
+
CREATE INDEX IF NOT EXISTS idx_financial_movements_invoice ON public.financial_movements(invoice_id);
|
|
108
|
+
CREATE INDEX IF NOT EXISTS idx_financial_movements_due ON public.financial_movements(tenant_id, due_date);
|
|
109
|
+
CREATE INDEX IF NOT EXISTS idx_financial_movements_bank ON public.financial_movements(bank_account_id);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
-- Financial Plugin: Chart of Accounts + Cost Centers
|
|
2
|
+
|
|
3
|
+
CREATE TABLE IF NOT EXISTS public.chart_of_accounts (
|
|
4
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
5
|
+
tenant_id uuid NOT NULL REFERENCES saas_core.tenants(id) ON DELETE CASCADE,
|
|
6
|
+
code text NOT NULL,
|
|
7
|
+
name text NOT NULL,
|
|
8
|
+
node_type text NOT NULL DEFAULT 'leaf',
|
|
9
|
+
parent_id uuid REFERENCES public.chart_of_accounts(id),
|
|
10
|
+
is_active boolean NOT NULL DEFAULT true,
|
|
11
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
12
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
13
|
+
);
|
|
14
|
+
ALTER TABLE public.chart_of_accounts ENABLE ROW LEVEL SECURITY;
|
|
15
|
+
CREATE INDEX IF NOT EXISTS idx_chart_of_accounts_tenant ON public.chart_of_accounts(tenant_id);
|
|
16
|
+
CREATE INDEX IF NOT EXISTS idx_chart_of_accounts_parent ON public.chart_of_accounts(parent_id);
|
|
17
|
+
|
|
18
|
+
CREATE TABLE IF NOT EXISTS public.cost_centers (
|
|
19
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
20
|
+
tenant_id uuid NOT NULL REFERENCES saas_core.tenants(id) ON DELETE CASCADE,
|
|
21
|
+
code text NOT NULL,
|
|
22
|
+
name text NOT NULL,
|
|
23
|
+
is_active boolean NOT NULL DEFAULT true,
|
|
24
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
25
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
26
|
+
);
|
|
27
|
+
ALTER TABLE public.cost_centers ENABLE ROW LEVEL SECURITY;
|
|
28
|
+
CREATE INDEX IF NOT EXISTS idx_cost_centers_tenant ON public.cost_centers(tenant_id);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
-- Financial Plugin: Card Brands
|
|
2
|
+
|
|
3
|
+
CREATE TABLE IF NOT EXISTS public.card_brands (
|
|
4
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
5
|
+
tenant_id uuid NOT NULL REFERENCES saas_core.tenants(id) ON DELETE CASCADE,
|
|
6
|
+
name text NOT NULL,
|
|
7
|
+
is_active boolean NOT NULL DEFAULT true,
|
|
8
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
9
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
10
|
+
);
|
|
11
|
+
ALTER TABLE public.card_brands ENABLE ROW LEVEL SECURITY;
|
|
12
|
+
CREATE INDEX IF NOT EXISTS idx_card_brands_tenant ON public.card_brands(tenant_id);
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
-- Financial plugin — order-to-cash companion SQL.
|
|
2
|
+
-- The atomic "promote an order into an invoice + installment ledger" function
|
|
3
|
+
-- that CRM (approveQuote) and the agenda financial bridge both RPC. It belongs
|
|
4
|
+
-- to the financial plugin (it writes financial_movements + reads orders), and it
|
|
5
|
+
-- ships WITH the plugin so enabling Payments provisions it. Idempotent.
|
|
6
|
+
-- Depends on: saas_core.orders, public.financial_movements (001_financial_base).
|
|
7
|
+
|
|
8
|
+
-- 1. Sequence generator (REC-00001 / PAG-00001 numbering)
|
|
9
|
+
CREATE TABLE IF NOT EXISTS saas_core.sequences (
|
|
10
|
+
tenant_id uuid NOT NULL REFERENCES saas_core.tenants(id),
|
|
11
|
+
kind text NOT NULL,
|
|
12
|
+
current_value bigint NOT NULL DEFAULT 0,
|
|
13
|
+
PRIMARY KEY (tenant_id, kind)
|
|
14
|
+
);
|
|
15
|
+
CREATE OR REPLACE FUNCTION saas_core.next_sequence(p_tenant_id uuid, p_kind text)
|
|
16
|
+
RETURNS bigint LANGUAGE plpgsql AS $$
|
|
17
|
+
DECLARE v_next bigint;
|
|
18
|
+
BEGIN
|
|
19
|
+
INSERT INTO saas_core.sequences (tenant_id, kind, current_value)
|
|
20
|
+
VALUES (p_tenant_id, p_kind, 1)
|
|
21
|
+
ON CONFLICT (tenant_id, kind)
|
|
22
|
+
DO UPDATE SET current_value = saas_core.sequences.current_value + 1
|
|
23
|
+
RETURNING current_value INTO v_next;
|
|
24
|
+
RETURN v_next;
|
|
25
|
+
END;
|
|
26
|
+
$$;
|
|
27
|
+
|
|
28
|
+
-- 2. Order-to-cash columns on the spine orders (plugin extends saas_core.orders)
|
|
29
|
+
ALTER TABLE saas_core.orders
|
|
30
|
+
ADD COLUMN IF NOT EXISTS stage text,
|
|
31
|
+
ADD COLUMN IF NOT EXISTS direction text;
|
|
32
|
+
|
|
33
|
+
-- 3. RLS + grants for financial_movements (table from 001_financial_base.sql)
|
|
34
|
+
ALTER TABLE public.financial_movements ENABLE ROW LEVEL SECURITY;
|
|
35
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON public.financial_movements TO authenticated;
|
|
36
|
+
DO $$
|
|
37
|
+
BEGIN
|
|
38
|
+
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='financial_movements' AND policyname='financial_movements_select') THEN
|
|
39
|
+
CREATE POLICY financial_movements_select ON public.financial_movements FOR SELECT TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
40
|
+
CREATE POLICY financial_movements_insert ON public.financial_movements FOR INSERT TO authenticated WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
41
|
+
CREATE POLICY financial_movements_update ON public.financial_movements FOR UPDATE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
42
|
+
CREATE POLICY financial_movements_delete ON public.financial_movements FOR DELETE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
43
|
+
END IF;
|
|
44
|
+
END $$;
|
|
45
|
+
|
|
46
|
+
-- 4. The function (v2 — backward compatible with the 3-arg CRM call via defaults)
|
|
47
|
+
DROP FUNCTION IF EXISTS public.fn_invoice_from_order(uuid, date, text);
|
|
48
|
+
CREATE OR REPLACE FUNCTION public.fn_invoice_from_order(
|
|
49
|
+
p_order_id uuid,
|
|
50
|
+
p_due_date date DEFAULT NULL,
|
|
51
|
+
p_status text DEFAULT NULL,
|
|
52
|
+
p_installments int DEFAULT 1,
|
|
53
|
+
p_direction text DEFAULT 'credit'
|
|
54
|
+
) RETURNS uuid
|
|
55
|
+
LANGUAGE plpgsql
|
|
56
|
+
SECURITY DEFINER
|
|
57
|
+
SET search_path = public, saas_core
|
|
58
|
+
AS $$
|
|
59
|
+
DECLARE
|
|
60
|
+
v_order saas_core.orders%ROWTYPE;
|
|
61
|
+
v_ref text;
|
|
62
|
+
v_seq bigint;
|
|
63
|
+
v_summary text;
|
|
64
|
+
v_contact text;
|
|
65
|
+
v_existing uuid;
|
|
66
|
+
v_kind text;
|
|
67
|
+
v_prefix text;
|
|
68
|
+
v_n int := GREATEST(COALESCE(p_installments, 1), 1);
|
|
69
|
+
v_total numeric;
|
|
70
|
+
v_base numeric;
|
|
71
|
+
v_amt numeric;
|
|
72
|
+
v_alloc numeric := 0;
|
|
73
|
+
v_due date;
|
|
74
|
+
i int;
|
|
75
|
+
BEGIN
|
|
76
|
+
SELECT * INTO v_order FROM saas_core.orders WHERE id = p_order_id;
|
|
77
|
+
IF NOT FOUND THEN RAISE EXCEPTION 'fn_invoice_from_order: order % not found', p_order_id; END IF;
|
|
78
|
+
IF v_order.tenant_id NOT IN (SELECT public.user_tenant_ids()) THEN
|
|
79
|
+
RAISE EXCEPTION 'fn_invoice_from_order: forbidden';
|
|
80
|
+
END IF;
|
|
81
|
+
|
|
82
|
+
SELECT id INTO v_existing FROM public.financial_movements
|
|
83
|
+
WHERE invoice_id = p_order_id AND movement_kind = 'bill' LIMIT 1;
|
|
84
|
+
IF v_existing IS NOT NULL THEN RETURN p_order_id; END IF;
|
|
85
|
+
|
|
86
|
+
IF p_direction = 'debit' THEN v_kind := 'invoice_payable'; v_prefix := 'PAG';
|
|
87
|
+
ELSE v_kind := 'invoice_receivable'; v_prefix := 'REC'; END IF;
|
|
88
|
+
|
|
89
|
+
SELECT saas_core.next_sequence(v_order.tenant_id, v_kind) INTO v_seq;
|
|
90
|
+
v_ref := v_prefix || '-' || lpad(v_seq::text, 5, '0');
|
|
91
|
+
|
|
92
|
+
SELECT string_agg(name, ', ' ORDER BY sort_order) INTO v_summary
|
|
93
|
+
FROM saas_core.order_items WHERE order_id = p_order_id;
|
|
94
|
+
SELECT name INTO v_contact FROM saas_core.persons WHERE id = v_order.party_id;
|
|
95
|
+
|
|
96
|
+
UPDATE saas_core.orders SET
|
|
97
|
+
status = COALESCE(p_status, status),
|
|
98
|
+
stage = 'invoiced',
|
|
99
|
+
direction = p_direction,
|
|
100
|
+
reference_number = v_ref,
|
|
101
|
+
metadata = COALESCE(metadata, '{}'::jsonb) || jsonb_build_object(
|
|
102
|
+
'itemsSummary', COALESCE(v_summary, ''),
|
|
103
|
+
'contactName', v_contact,
|
|
104
|
+
'installmentCount', v_n,
|
|
105
|
+
'quoteNumber', v_order.reference_number,
|
|
106
|
+
'direction', p_direction
|
|
107
|
+
),
|
|
108
|
+
updated_at = now()
|
|
109
|
+
WHERE id = p_order_id;
|
|
110
|
+
|
|
111
|
+
v_total := COALESCE(v_order.total, 0);
|
|
112
|
+
v_base := round(v_total / v_n, 2);
|
|
113
|
+
v_due := COALESCE(p_due_date, current_date);
|
|
114
|
+
FOR i IN 1..v_n LOOP
|
|
115
|
+
IF i = v_n THEN v_amt := round(v_total - v_alloc, 2);
|
|
116
|
+
ELSE v_amt := v_base; v_alloc := v_alloc + v_base; END IF;
|
|
117
|
+
INSERT INTO public.financial_movements
|
|
118
|
+
(tenant_id, invoice_id, direction, movement_kind, amount, paid_amount, status, due_date, installment_number)
|
|
119
|
+
VALUES
|
|
120
|
+
(v_order.tenant_id, p_order_id, p_direction, 'bill', v_amt, 0, 'pending',
|
|
121
|
+
(v_due + ((i - 1) || ' months')::interval)::date, i);
|
|
122
|
+
END LOOP;
|
|
123
|
+
|
|
124
|
+
RETURN p_order_id;
|
|
125
|
+
END;
|
|
126
|
+
$$;
|
|
127
|
+
GRANT EXECUTE ON FUNCTION public.fn_invoice_from_order(uuid, date, text, int, text) TO authenticated;
|
|
128
|
+
|
|
129
|
+
-- 5. Derived balances view (Payments page + agenda payment badge read this)
|
|
130
|
+
CREATE OR REPLACE VIEW public.v_invoice_balances AS
|
|
131
|
+
WITH bill AS (
|
|
132
|
+
SELECT
|
|
133
|
+
invoice_id,
|
|
134
|
+
SUM(amount) FILTER (WHERE status <> 'cancelled') AS billed,
|
|
135
|
+
SUM(paid_amount) FILTER (WHERE status <> 'cancelled') AS paid,
|
|
136
|
+
bool_or(status NOT IN ('paid','cancelled') AND due_date < current_date) AS has_overdue
|
|
137
|
+
FROM public.financial_movements
|
|
138
|
+
WHERE movement_kind = 'bill'
|
|
139
|
+
GROUP BY invoice_id
|
|
140
|
+
)
|
|
141
|
+
SELECT
|
|
142
|
+
o.id AS invoice_id, o.tenant_id, o.kind, o.reference_number, o.party_id, o.direction,
|
|
143
|
+
CASE WHEN o.direction = 'debit' OR o.kind = 'invoice_payable' THEN 'payable' ELSE 'receivable' END AS flow,
|
|
144
|
+
COALESCE(b.billed, o.total, 0) AS amount,
|
|
145
|
+
COALESCE(b.paid, 0) AS paid,
|
|
146
|
+
CASE WHEN o.status = 'cancelled' OR o.stage = 'cancelled' THEN 0
|
|
147
|
+
ELSE COALESCE(b.billed, o.total, 0) - COALESCE(b.paid, 0) END AS balance,
|
|
148
|
+
CASE
|
|
149
|
+
WHEN o.status = 'cancelled' OR o.stage = 'cancelled' THEN 'cancelled'
|
|
150
|
+
WHEN COALESCE(b.billed, o.total, 0) = 0 THEN 'open'
|
|
151
|
+
WHEN COALESCE(b.paid, 0) >= COALESCE(b.billed, o.total, 0) THEN 'paid'
|
|
152
|
+
WHEN COALESCE(b.paid, 0) > 0 THEN 'partial'
|
|
153
|
+
WHEN COALESCE(b.has_overdue, false) THEN 'overdue'
|
|
154
|
+
ELSE 'open'
|
|
155
|
+
END AS status,
|
|
156
|
+
o.created_at, o.updated_at
|
|
157
|
+
FROM saas_core.orders o
|
|
158
|
+
LEFT JOIN bill b ON b.invoice_id = o.id
|
|
159
|
+
WHERE o.kind IN ('invoice_receivable','invoice_payable') OR b.invoice_id IS NOT NULL;
|
|
160
|
+
ALTER VIEW public.v_invoice_balances SET (security_invoker = true);
|
|
161
|
+
GRANT SELECT ON public.v_invoice_balances TO authenticated;
|
|
162
|
+
|
|
163
|
+
-- Refresh PostgREST's schema cache so the new RPC/views are visible immediately.
|
|
164
|
+
NOTIFY pgrst, 'reload schema';
|