@fayz-ai/plugin-financial 0.1.7 → 0.8.0
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/README.md +2 -0
- package/dist/FinancialContext.d.ts +2 -0
- package/dist/FinancialContext.d.ts.map +1 -1
- package/dist/FinancialPage.d.ts.map +1 -1
- package/dist/data/index.d.ts +1 -0
- package/dist/data/index.d.ts.map +1 -1
- package/dist/data/mock.d.ts +15 -0
- package/dist/data/mock.d.ts.map +1 -1
- package/dist/data/supabase.d.ts.map +1 -1
- package/dist/data/tables.d.ts +11 -0
- package/dist/data/tables.d.ts.map +1 -0
- package/dist/data/types.d.ts +2 -1
- package/dist/data/types.d.ts.map +1 -1
- package/dist/index.cjs +1594 -252
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1456 -131
- package/dist/index.js.map +1 -1
- package/dist/locales/en.d.ts.map +1 -1
- package/dist/locales/pt-BR.d.ts.map +1 -1
- package/dist/migrations/index.d.ts +16 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/quick-add.d.ts +13 -0
- package/dist/quick-add.d.ts.map +1 -0
- package/dist/registries.d.ts.map +1 -1
- package/dist/store.d.ts +3 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/types.d.ts +42 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/views/CardsView.d.ts.map +1 -1
- package/dist/views/InvoiceListView.d.ts.map +1 -1
- package/dist/views/QuickTransactionForm.d.ts +16 -0
- package/dist/views/QuickTransactionForm.d.ts.map +1 -0
- package/dist/views/SummaryView.d.ts +5 -4
- package/dist/views/SummaryView.d.ts.map +1 -1
- package/dist/views/dashboardWidgets.d.ts.map +1 -1
- package/package.json +7 -4
- package/src/FinancialContext.tsx +2 -0
- package/src/FinancialPage.tsx +86 -7
- package/src/README.md +5 -5
- package/src/contract.test.ts +1 -1
- package/src/data/capability.test.ts +45 -0
- package/src/data/index.ts +1 -0
- package/src/data/mock.ts +50 -10
- package/src/data/supabase.ts +95 -49
- package/src/data/tables.ts +12 -0
- package/src/data/types.ts +2 -1
- package/src/index.ts +24 -4
- package/src/locales/en.ts +75 -0
- package/src/locales/pt-BR.ts +75 -0
- package/src/migrations/000_plg_rename.sql +30 -0
- package/src/migrations/001_financial_base.sql +30 -30
- package/src/migrations/002_chart_of_accounts.sql +10 -10
- package/src/migrations/003_card_brands.sql +4 -4
- package/src/migrations/004_order_to_cash.sql +28 -28
- package/src/migrations/005_seed_defaults.sql +6 -6
- package/src/migrations/006_rls_policies.sql +5 -5
- package/src/migrations/{006_extract_fee_amount.sql → 006b_extract_fee_amount.sql} +4 -4
- package/src/migrations/007_reconciliation.sql +9 -9
- package/src/migrations/007b_movement_payment_method_type.sql +6 -0
- package/src/migrations/008_split_payment_movements.sql +5 -5
- package/src/migrations/index.ts +544 -0
- package/src/quick-add.ts +58 -0
- package/src/registries.ts +8 -7
- package/src/store.ts +88 -0
- package/src/types.ts +45 -0
- package/src/views/CardsView.tsx +186 -50
- package/src/views/InvoiceListView.tsx +60 -3
- package/src/views/QuickTransactionForm.tsx +537 -0
- package/src/views/SummaryView.tsx +197 -6
- package/src/views/dashboardWidgets.tsx +251 -5
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import type { PluginManifest, PluginScope, VerticalId } from '@fayz-ai/core'
|
|
2
|
+
import type { PluginManifest, PluginRegistryDef, PluginScope, VerticalId } from '@fayz-ai/core'
|
|
3
3
|
import type { EntityLookupMap } from '@fayz-ai/saas'
|
|
4
4
|
import { FinancialPage } from './FinancialPage'
|
|
5
5
|
import { createFinancialDashboardWidgets } from './views/dashboardWidgets'
|
|
@@ -75,6 +75,13 @@ export interface FinancialPluginOptions {
|
|
|
75
75
|
locale?: string
|
|
76
76
|
symbol?: string
|
|
77
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Show the plugin's own quick-add affordances (the "New transaction" + "Send
|
|
80
|
+
* receipt" header buttons and, on mobile, the FAB). Opt-in (default: false) so
|
|
81
|
+
* hosts that already surface a "New" menu / global center-action don't render
|
|
82
|
+
* redundant controls. The shared quick-add sheet still opens via openQuickAdd().
|
|
83
|
+
*/
|
|
84
|
+
quickAdd?: boolean
|
|
78
85
|
navPosition?: number
|
|
79
86
|
navSection?: 'main' | 'secondary'
|
|
80
87
|
scope?: PluginScope
|
|
@@ -109,6 +116,9 @@ export interface FinancialPluginOptions {
|
|
|
109
116
|
/** Contact/person lookup for "Pay to" / "Receive from" fields. Queries persons archetype. */
|
|
110
117
|
contactLookup?: import('@fayz-ai/saas').EntityLookup
|
|
111
118
|
|
|
119
|
+
/** App-owned registries shown under /settings/financial Properties. */
|
|
120
|
+
settingsRegistries?: PluginRegistryDef[]
|
|
121
|
+
|
|
112
122
|
/** Callback when user clicks a booking link on an invoice. Receives the order ID. */
|
|
113
123
|
onBookingClick?: (orderId: string) => void
|
|
114
124
|
}
|
|
@@ -162,6 +172,8 @@ function resolveConfig(options?: FinancialPluginOptions): ResolvedFinancialConfi
|
|
|
162
172
|
// Opt-in: only shown when an app explicitly enables reconciliation (bank connector present).
|
|
163
173
|
reconciliation: options?.modules?.reconciliation === true,
|
|
164
174
|
},
|
|
175
|
+
// Opt-in: only render the plugin's own quick-add buttons/FAB when the host asks.
|
|
176
|
+
quickAdd: options?.quickAdd === true,
|
|
165
177
|
labels: { ...DEFAULT_LABELS, ...options?.labels },
|
|
166
178
|
currency: { ...DEFAULT_CURRENCY, ...options?.currency },
|
|
167
179
|
itemTypes: options?.itemTypes ?? DEFAULT_ITEM_TYPES,
|
|
@@ -188,6 +200,7 @@ export function createFinancialPlugin(options?: FinancialPluginOptions): PluginM
|
|
|
188
200
|
const provider = options?.dataProvider ?? createSafeFinancialProvider()
|
|
189
201
|
const store = createFinancialStore(provider)
|
|
190
202
|
const dashboardWidgets = createFinancialDashboardWidgets({ config, provider, store })
|
|
203
|
+
const registries = [...financialRegistries, ...(options?.settingsRegistries ?? [])]
|
|
191
204
|
|
|
192
205
|
// Per-person statement tab (account_central-style): bound to this plugin's provider.
|
|
193
206
|
const PersonStatementBound: React.FC<any> = (props) =>
|
|
@@ -195,7 +208,7 @@ export function createFinancialPlugin(options?: FinancialPluginOptions): PluginM
|
|
|
195
208
|
PersonStatementBound.displayName = 'FinancialPersonStatement'
|
|
196
209
|
|
|
197
210
|
const PageComponent: React.FC<any> = () =>
|
|
198
|
-
React.createElement(FinancialPage, { config, provider, store, registries
|
|
211
|
+
React.createElement(FinancialPage, { config, provider, store, registries })
|
|
199
212
|
|
|
200
213
|
return {
|
|
201
214
|
id: 'financial',
|
|
@@ -301,7 +314,7 @@ export function createFinancialPlugin(options?: FinancialPluginOptions): PluginM
|
|
|
301
314
|
],
|
|
302
315
|
},
|
|
303
316
|
],
|
|
304
|
-
registries
|
|
317
|
+
registries,
|
|
305
318
|
settings: [
|
|
306
319
|
{
|
|
307
320
|
id: 'financial',
|
|
@@ -313,7 +326,7 @@ export function createFinancialPlugin(options?: FinancialPluginOptions): PluginM
|
|
|
313
326
|
title: 'Financial Settings',
|
|
314
327
|
subtitle: 'Payment methods, accounts, and configurations',
|
|
315
328
|
generalSettings: React.createElement(FinancialGeneralSettings),
|
|
316
|
-
registries
|
|
329
|
+
registries,
|
|
317
330
|
hostPluginId: 'financial',
|
|
318
331
|
routeBase: '/settings/financial',
|
|
319
332
|
})
|
|
@@ -331,3 +344,10 @@ export function createFinancialPlugin(options?: FinancialPluginOptions): PluginM
|
|
|
331
344
|
// Re-export types and factories for consumers
|
|
332
345
|
export type { FinancialDataProvider } from './data/types'
|
|
333
346
|
export type { ResolvedFinancialConfig } from './FinancialContext'
|
|
347
|
+
// Seedable in-memory provider — apps pass a seed to render the module populated
|
|
348
|
+
// (demo/dogfood data) instead of the empty onboarding state.
|
|
349
|
+
export { createMockFinancialProvider } from './data/mock'
|
|
350
|
+
export type { MockFinancialSeed, MockFinancialProviderOptions } from './data/mock'
|
|
351
|
+
// FAY-1242: global quick-add trigger — apps wire this to a shell action (e.g.
|
|
352
|
+
// the bottom-nav center "+") to open the transaction sheet from anywhere.
|
|
353
|
+
export { openQuickAdd } from './quick-add'
|
package/src/locales/en.ts
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
// financial.* — merged plugin-own + saas-core central i18n
|
|
2
2
|
export const en: Record<string, string> = {
|
|
3
|
+
"financial.cards.addExpense": "Add expense",
|
|
4
|
+
"financial.cards.allBillsValue": "All bills value",
|
|
5
|
+
"financial.cards.availableLimit": "Available limit",
|
|
6
|
+
"financial.cards.currentBill": "Current bill",
|
|
7
|
+
"financial.cards.dueOn": "Due on the {{day}}",
|
|
3
8
|
"financial.cards.installment": "Installment {{current}}/{{total}}",
|
|
9
|
+
"financial.cards.noCards": "No cards yet",
|
|
10
|
+
"financial.cards.noCardsHint": "Add a credit card in settings to track your bills here",
|
|
4
11
|
"financial.cards.noTransactions": "No card transactions",
|
|
12
|
+
"financial.cards.tabClosed": "Closed",
|
|
13
|
+
"financial.cards.tabOpen": "Open",
|
|
14
|
+
"financial.cards.usedOfLimit": "{{percent}}% of limit used",
|
|
5
15
|
"financial.cards.pending": "Pending",
|
|
6
16
|
"financial.cards.received": "Received",
|
|
7
17
|
"financial.cards.subtitle": "Credit and debit card transactions",
|
|
@@ -128,6 +138,10 @@ export const en: Record<string, string> = {
|
|
|
128
138
|
"financial.nav.rules": "Rules",
|
|
129
139
|
"financial.nav.statements": "Statements",
|
|
130
140
|
"financial.nav.summary": "Summary",
|
|
141
|
+
"financial.invoice.filterAccount": "Chart account",
|
|
142
|
+
"financial.invoice.filterAllAccounts": "All accounts",
|
|
143
|
+
"financial.invoice.filterCostCenter": "Cost center",
|
|
144
|
+
"financial.invoice.filterAllCostCenters": "All cost centers",
|
|
131
145
|
"financial.reconciliation.title": "Reconciliation",
|
|
132
146
|
"financial.reconciliation.subtitle": "Match imported bank lines to your movements",
|
|
133
147
|
"financial.reconciliation.pending": "{{count}} to reconcile",
|
|
@@ -242,6 +256,36 @@ export const en: Record<string, string> = {
|
|
|
242
256
|
"financial.summary.totalBalance": "Total Balance",
|
|
243
257
|
"financial.summary.transactionsAppear": "Transactions will appear here once recorded",
|
|
244
258
|
"financial.summary.viewAll": "View all",
|
|
259
|
+
"financial.summary.today": "Today",
|
|
260
|
+
"financial.summary.yesterday": "Yesterday",
|
|
261
|
+
"financial.summary.transactionsTitle": "Transactions",
|
|
262
|
+
"financial.home.balance": "Balance",
|
|
263
|
+
"financial.home.inflow": "Income",
|
|
264
|
+
"financial.home.outflow": "Expenses",
|
|
265
|
+
"financial.home.showBalance": "Show balance",
|
|
266
|
+
"financial.home.hideBalance": "Hide balance",
|
|
267
|
+
"financial.home.upcomingBills": "Upcoming bills",
|
|
268
|
+
"financial.home.noBills": "No upcoming bills.",
|
|
269
|
+
"financial.home.dueToday": "Due today",
|
|
270
|
+
"financial.home.dueTomorrow": "Due tomorrow",
|
|
271
|
+
"financial.home.dueInDays": "Due in {{count}} days",
|
|
272
|
+
"financial.home.overdueDays": "Overdue by {{count}} days",
|
|
273
|
+
"financial.home.cards": "Cards",
|
|
274
|
+
"financial.home.currentBill": "Current bill",
|
|
275
|
+
"financial.home.availableLimit": "Available limit",
|
|
276
|
+
"financial.home.addCard": "New card",
|
|
277
|
+
"financial.home.bill": "Bill",
|
|
278
|
+
"financial.home.spendByCategory": "Spending by category",
|
|
279
|
+
"financial.home.noSpend": "No spending this month.",
|
|
280
|
+
"financial.home.category.groceries": "Groceries",
|
|
281
|
+
"financial.home.category.transport": "Transport",
|
|
282
|
+
"financial.home.category.subscriptions": "Subscriptions",
|
|
283
|
+
"financial.home.category.dining": "Dining",
|
|
284
|
+
"financial.home.category.home": "Home",
|
|
285
|
+
"financial.home.category.health": "Health",
|
|
286
|
+
"financial.home.category.leisure": "Leisure",
|
|
287
|
+
"financial.home.category.shopping": "Shopping",
|
|
288
|
+
"financial.home.category.other": "Other",
|
|
245
289
|
"financial.quickActions.newPayable": "New Payable",
|
|
246
290
|
"financial.quickActions.newPayableDesc": "Record an expense or bill to pay",
|
|
247
291
|
"financial.quickActions.newReceivable": "New Receivable",
|
|
@@ -404,4 +448,35 @@ export const en: Record<string, string> = {
|
|
|
404
448
|
"financial.transfer.failed": "Failed to record transfer",
|
|
405
449
|
"financial.transfer.sameAccount": "Source and destination must differ",
|
|
406
450
|
"financial.transfer.invalidAmount": "Amount must be greater than zero",
|
|
451
|
+
"financial.quickTx.title": "New transaction",
|
|
452
|
+
"financial.quickTx.close": "Close",
|
|
453
|
+
"financial.quickTx.newTransaction": "New transaction",
|
|
454
|
+
"financial.quickTx.expense": "Expense",
|
|
455
|
+
"financial.quickTx.income": "Income",
|
|
456
|
+
"financial.quickTx.transfer": "Transfer",
|
|
457
|
+
"financial.quickTx.paid": "Paid",
|
|
458
|
+
"financial.quickTx.received": "Received",
|
|
459
|
+
"financial.quickTx.yes": "Yes",
|
|
460
|
+
"financial.quickTx.no": "No",
|
|
461
|
+
"financial.quickTx.category": "Category",
|
|
462
|
+
"financial.quickTx.selectCategory": "No category",
|
|
463
|
+
"financial.quickTx.account": "Account",
|
|
464
|
+
"financial.quickTx.selectAccount": "Select account",
|
|
465
|
+
"financial.quickTx.fromAccount": "From account",
|
|
466
|
+
"financial.quickTx.toAccount": "To account",
|
|
467
|
+
"financial.quickTx.card": "Card",
|
|
468
|
+
"financial.quickTx.recurring": "Recurring",
|
|
469
|
+
"financial.quickTx.attachment": "Attachment",
|
|
470
|
+
"financial.quickTx.attachmentSoon": "Attachments coming soon",
|
|
471
|
+
"financial.quickTx.receipt": "Receipt",
|
|
472
|
+
"financial.quickTx.receiptCapture": "Snap or attach a receipt",
|
|
473
|
+
"financial.quickTx.receiptAttached": "Receipt attached",
|
|
474
|
+
"financial.quickTx.receiptReplace": "Replace",
|
|
475
|
+
"financial.quickTx.receiptRemove": "Remove receipt",
|
|
476
|
+
"financial.quickTx.receiptInvalid": "Please choose an image file",
|
|
477
|
+
"financial.quickTx.sendReceipt": "Send receipt",
|
|
478
|
+
"financial.quickTx.descriptionPlaceholder": "e.g. Groceries, Salary…",
|
|
479
|
+
"financial.quickTx.enterAmount": "Enter an amount",
|
|
480
|
+
"financial.quickTx.save": "Save",
|
|
481
|
+
"financial.quickTx.saving": "Saving…",
|
|
407
482
|
}
|
package/src/locales/pt-BR.ts
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
// financial.* — merged plugin-own + saas-core central i18n
|
|
2
2
|
export const ptBR: Record<string, string> = {
|
|
3
|
+
"financial.cards.addExpense": "Adicionar despesa",
|
|
4
|
+
"financial.cards.allBillsValue": "Total das faturas",
|
|
5
|
+
"financial.cards.availableLimit": "Limite disponível",
|
|
6
|
+
"financial.cards.currentBill": "Fatura atual",
|
|
7
|
+
"financial.cards.dueOn": "Vence dia {{day}}",
|
|
3
8
|
"financial.cards.installment": "Parcela {{current}}/{{total}}",
|
|
9
|
+
"financial.cards.noCards": "Nenhum cartão cadastrado",
|
|
10
|
+
"financial.cards.noCardsHint": "Adicione um cartão de crédito nas configurações para acompanhar suas faturas aqui",
|
|
4
11
|
"financial.cards.noTransactions": "Nenhuma transação com cartão",
|
|
12
|
+
"financial.cards.tabClosed": "Fechados",
|
|
13
|
+
"financial.cards.tabOpen": "Abertos",
|
|
14
|
+
"financial.cards.usedOfLimit": "{{percent}}% do limite usado",
|
|
5
15
|
"financial.cards.pending": "Pendente",
|
|
6
16
|
"financial.cards.received": "Recebido",
|
|
7
17
|
"financial.cards.subtitle": "Transações de cartão de crédito e débito",
|
|
@@ -128,6 +138,10 @@ export const ptBR: Record<string, string> = {
|
|
|
128
138
|
"financial.nav.rules": "Regras",
|
|
129
139
|
"financial.nav.statements": "Extratos",
|
|
130
140
|
"financial.nav.summary": "Resumo",
|
|
141
|
+
"financial.invoice.filterAccount": "Plano de contas",
|
|
142
|
+
"financial.invoice.filterAllAccounts": "Todos os planos",
|
|
143
|
+
"financial.invoice.filterCostCenter": "Centro de custo",
|
|
144
|
+
"financial.invoice.filterAllCostCenters": "Todos os centros",
|
|
131
145
|
"financial.reconciliation.title": "Conciliação",
|
|
132
146
|
"financial.reconciliation.subtitle": "Concilie as linhas importadas do banco com seus lançamentos",
|
|
133
147
|
"financial.reconciliation.pending": "{{count}} para conciliar",
|
|
@@ -242,6 +256,36 @@ export const ptBR: Record<string, string> = {
|
|
|
242
256
|
"financial.summary.totalBalance": "Saldo Total",
|
|
243
257
|
"financial.summary.transactionsAppear": "As transações aparecerão aqui após serem registradas",
|
|
244
258
|
"financial.summary.viewAll": "Ver todos",
|
|
259
|
+
"financial.summary.today": "Hoje",
|
|
260
|
+
"financial.summary.yesterday": "Ontem",
|
|
261
|
+
"financial.summary.transactionsTitle": "Transações",
|
|
262
|
+
"financial.home.balance": "Saldo",
|
|
263
|
+
"financial.home.inflow": "Entradas",
|
|
264
|
+
"financial.home.outflow": "Saídas",
|
|
265
|
+
"financial.home.showBalance": "Mostrar saldo",
|
|
266
|
+
"financial.home.hideBalance": "Ocultar saldo",
|
|
267
|
+
"financial.home.upcomingBills": "Próximas contas",
|
|
268
|
+
"financial.home.noBills": "Nenhuma conta a vencer.",
|
|
269
|
+
"financial.home.dueToday": "Vence hoje",
|
|
270
|
+
"financial.home.dueTomorrow": "Vence amanhã",
|
|
271
|
+
"financial.home.dueInDays": "Vence em {{count}} dias",
|
|
272
|
+
"financial.home.overdueDays": "Venceu há {{count}} dias",
|
|
273
|
+
"financial.home.cards": "Cartões",
|
|
274
|
+
"financial.home.currentBill": "Fatura atual",
|
|
275
|
+
"financial.home.availableLimit": "Limite disponível",
|
|
276
|
+
"financial.home.addCard": "Novo cartão",
|
|
277
|
+
"financial.home.bill": "Conta",
|
|
278
|
+
"financial.home.spendByCategory": "Gastos por categoria",
|
|
279
|
+
"financial.home.noSpend": "Sem gastos neste mês.",
|
|
280
|
+
"financial.home.category.groceries": "Mercado",
|
|
281
|
+
"financial.home.category.transport": "Transporte",
|
|
282
|
+
"financial.home.category.subscriptions": "Assinaturas",
|
|
283
|
+
"financial.home.category.dining": "Alimentação",
|
|
284
|
+
"financial.home.category.home": "Casa",
|
|
285
|
+
"financial.home.category.health": "Saúde",
|
|
286
|
+
"financial.home.category.leisure": "Lazer",
|
|
287
|
+
"financial.home.category.shopping": "Compras",
|
|
288
|
+
"financial.home.category.other": "Outros",
|
|
245
289
|
"financial.quickActions.newPayable": "Nova Conta a Pagar",
|
|
246
290
|
"financial.quickActions.newPayableDesc": "Registrar uma despesa ou conta a pagar",
|
|
247
291
|
"financial.quickActions.newReceivable": "Nova Conta a Receber",
|
|
@@ -404,4 +448,35 @@ export const ptBR: Record<string, string> = {
|
|
|
404
448
|
"financial.transfer.failed": "Falha ao registrar transferência",
|
|
405
449
|
"financial.transfer.sameAccount": "Origem e destino devem ser diferentes",
|
|
406
450
|
"financial.transfer.invalidAmount": "O valor deve ser maior que zero",
|
|
451
|
+
"financial.quickTx.title": "Nova transação",
|
|
452
|
+
"financial.quickTx.close": "Fechar",
|
|
453
|
+
"financial.quickTx.newTransaction": "Nova transação",
|
|
454
|
+
"financial.quickTx.expense": "Despesa",
|
|
455
|
+
"financial.quickTx.income": "Receita",
|
|
456
|
+
"financial.quickTx.transfer": "Transferência",
|
|
457
|
+
"financial.quickTx.paid": "Pago",
|
|
458
|
+
"financial.quickTx.received": "Recebido",
|
|
459
|
+
"financial.quickTx.yes": "Sim",
|
|
460
|
+
"financial.quickTx.no": "Não",
|
|
461
|
+
"financial.quickTx.category": "Categoria",
|
|
462
|
+
"financial.quickTx.selectCategory": "Sem categoria",
|
|
463
|
+
"financial.quickTx.account": "Conta",
|
|
464
|
+
"financial.quickTx.selectAccount": "Selecione a conta",
|
|
465
|
+
"financial.quickTx.fromAccount": "Conta de origem",
|
|
466
|
+
"financial.quickTx.toAccount": "Conta de destino",
|
|
467
|
+
"financial.quickTx.card": "Cartão",
|
|
468
|
+
"financial.quickTx.recurring": "Recorrente",
|
|
469
|
+
"financial.quickTx.attachment": "Anexo",
|
|
470
|
+
"financial.quickTx.attachmentSoon": "Anexos em breve",
|
|
471
|
+
"financial.quickTx.receipt": "Recibo",
|
|
472
|
+
"financial.quickTx.receiptCapture": "Fotografar ou anexar recibo",
|
|
473
|
+
"financial.quickTx.receiptAttached": "Recibo anexado",
|
|
474
|
+
"financial.quickTx.receiptReplace": "Substituir",
|
|
475
|
+
"financial.quickTx.receiptRemove": "Remover recibo",
|
|
476
|
+
"financial.quickTx.receiptInvalid": "Escolha um arquivo de imagem",
|
|
477
|
+
"financial.quickTx.sendReceipt": "Enviar recibo",
|
|
478
|
+
"financial.quickTx.descriptionPlaceholder": "ex.: Mercado, Salário…",
|
|
479
|
+
"financial.quickTx.enterAmount": "Informe um valor",
|
|
480
|
+
"financial.quickTx.save": "Salvar",
|
|
481
|
+
"financial.quickTx.saving": "Salvando…",
|
|
407
482
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
-- 000_plg_rename.sql — rename legacy financial tables to plg_financial_* for pools
|
|
2
|
+
-- provisioned before the industry-pool rename. Guarded: fires only when the legacy
|
|
3
|
+
-- name exists and the target does not, so fresh pools skip every branch.
|
|
4
|
+
DO $$
|
|
5
|
+
BEGIN
|
|
6
|
+
IF to_regclass('public.financial_movements') IS NOT NULL AND to_regclass('public.plg_financial_movements') IS NULL THEN
|
|
7
|
+
ALTER TABLE public.financial_movements RENAME TO plg_financial_movements;
|
|
8
|
+
END IF;
|
|
9
|
+
IF to_regclass('public.chart_of_accounts') IS NOT NULL AND to_regclass('public.plg_financial_chart_of_accounts') IS NULL THEN
|
|
10
|
+
ALTER TABLE public.chart_of_accounts RENAME TO plg_financial_chart_of_accounts;
|
|
11
|
+
END IF;
|
|
12
|
+
IF to_regclass('public.bank_accounts') IS NOT NULL AND to_regclass('public.plg_financial_bank_accounts') IS NULL THEN
|
|
13
|
+
ALTER TABLE public.bank_accounts RENAME TO plg_financial_bank_accounts;
|
|
14
|
+
END IF;
|
|
15
|
+
IF to_regclass('public.card_brands') IS NOT NULL AND to_regclass('public.plg_financial_card_brands') IS NULL THEN
|
|
16
|
+
ALTER TABLE public.card_brands RENAME TO plg_financial_card_brands;
|
|
17
|
+
END IF;
|
|
18
|
+
IF to_regclass('public.cost_centers') IS NOT NULL AND to_regclass('public.plg_financial_cost_centers') IS NULL THEN
|
|
19
|
+
ALTER TABLE public.cost_centers RENAME TO plg_financial_cost_centers;
|
|
20
|
+
END IF;
|
|
21
|
+
IF to_regclass('public.cash_register_sessions') IS NOT NULL AND to_regclass('public.plg_financial_cash_register_sessions') IS NULL THEN
|
|
22
|
+
ALTER TABLE public.cash_register_sessions RENAME TO plg_financial_cash_register_sessions;
|
|
23
|
+
END IF;
|
|
24
|
+
IF to_regclass('public.payment_methods') IS NOT NULL AND to_regclass('public.plg_financial_payment_methods') IS NULL THEN
|
|
25
|
+
ALTER TABLE public.payment_methods RENAME TO plg_financial_payment_methods;
|
|
26
|
+
END IF;
|
|
27
|
+
IF to_regclass('public.payment_method_types') IS NOT NULL AND to_regclass('public.plg_financial_payment_method_types') IS NULL THEN
|
|
28
|
+
ALTER TABLE public.payment_method_types RENAME TO plg_financial_payment_method_types;
|
|
29
|
+
END IF;
|
|
30
|
+
END $$;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
-- Financial Plugin: Base Tables
|
|
2
2
|
-- Pattern: uuid PK, tenant_id FK, timestamps, RLS via project_rls.sql auto-detection
|
|
3
3
|
|
|
4
|
-
CREATE TABLE IF NOT EXISTS public.
|
|
4
|
+
CREATE TABLE IF NOT EXISTS public.plg_financial_payment_method_types (
|
|
5
5
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
6
|
-
tenant_id uuid NOT NULL REFERENCES
|
|
6
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
7
7
|
name text NOT NULL,
|
|
8
8
|
transaction_type text NOT NULL,
|
|
9
9
|
is_active boolean NOT NULL DEFAULT true,
|
|
@@ -11,14 +11,14 @@ CREATE TABLE IF NOT EXISTS public.payment_method_types (
|
|
|
11
11
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
12
12
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
13
13
|
);
|
|
14
|
-
ALTER TABLE public.
|
|
15
|
-
CREATE INDEX IF NOT EXISTS
|
|
14
|
+
ALTER TABLE public.plg_financial_payment_method_types ENABLE ROW LEVEL SECURITY;
|
|
15
|
+
CREATE INDEX IF NOT EXISTS idx_plg_financial_payment_method_types_tenant ON public.plg_financial_payment_method_types(tenant_id);
|
|
16
16
|
|
|
17
|
-
CREATE TABLE IF NOT EXISTS public.
|
|
17
|
+
CREATE TABLE IF NOT EXISTS public.plg_financial_payment_methods (
|
|
18
18
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
19
|
-
tenant_id uuid NOT NULL REFERENCES
|
|
19
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
20
20
|
name text NOT NULL,
|
|
21
|
-
payment_method_type_id uuid REFERENCES public.
|
|
21
|
+
payment_method_type_id uuid REFERENCES public.plg_financial_payment_method_types(id),
|
|
22
22
|
is_active boolean NOT NULL DEFAULT true,
|
|
23
23
|
discount_mode text,
|
|
24
24
|
discount_value numeric(12,2) DEFAULT 0,
|
|
@@ -31,12 +31,12 @@ CREATE TABLE IF NOT EXISTS public.payment_methods (
|
|
|
31
31
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
32
32
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
33
33
|
);
|
|
34
|
-
ALTER TABLE public.
|
|
35
|
-
CREATE INDEX IF NOT EXISTS
|
|
34
|
+
ALTER TABLE public.plg_financial_payment_methods ENABLE ROW LEVEL SECURITY;
|
|
35
|
+
CREATE INDEX IF NOT EXISTS idx_plg_financial_payment_methods_tenant ON public.plg_financial_payment_methods(tenant_id);
|
|
36
36
|
|
|
37
|
-
CREATE TABLE IF NOT EXISTS public.
|
|
37
|
+
CREATE TABLE IF NOT EXISTS public.plg_financial_bank_accounts (
|
|
38
38
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
39
|
-
tenant_id uuid NOT NULL REFERENCES
|
|
39
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
40
40
|
name text NOT NULL,
|
|
41
41
|
account_type text NOT NULL DEFAULT 'bank_account',
|
|
42
42
|
bank_name text,
|
|
@@ -52,13 +52,13 @@ CREATE TABLE IF NOT EXISTS public.bank_accounts (
|
|
|
52
52
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
53
53
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
54
54
|
);
|
|
55
|
-
ALTER TABLE public.
|
|
56
|
-
CREATE INDEX IF NOT EXISTS
|
|
55
|
+
ALTER TABLE public.plg_financial_bank_accounts ENABLE ROW LEVEL SECURITY;
|
|
56
|
+
CREATE INDEX IF NOT EXISTS idx_plg_financial_bank_accounts_tenant ON public.plg_financial_bank_accounts(tenant_id);
|
|
57
57
|
|
|
58
|
-
CREATE TABLE IF NOT EXISTS public.
|
|
58
|
+
CREATE TABLE IF NOT EXISTS public.plg_financial_cash_register_sessions (
|
|
59
59
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
60
|
-
tenant_id uuid NOT NULL REFERENCES
|
|
61
|
-
bank_account_id uuid NOT NULL REFERENCES public.
|
|
60
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
61
|
+
bank_account_id uuid NOT NULL REFERENCES public.plg_financial_bank_accounts(id),
|
|
62
62
|
status text NOT NULL DEFAULT 'open',
|
|
63
63
|
opened_at timestamptz NOT NULL DEFAULT now(),
|
|
64
64
|
opened_by_user_id uuid,
|
|
@@ -75,15 +75,15 @@ CREATE TABLE IF NOT EXISTS public.cash_register_sessions (
|
|
|
75
75
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
76
76
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
77
77
|
);
|
|
78
|
-
ALTER TABLE public.
|
|
79
|
-
CREATE INDEX IF NOT EXISTS
|
|
78
|
+
ALTER TABLE public.plg_financial_cash_register_sessions ENABLE ROW LEVEL SECURITY;
|
|
79
|
+
CREATE INDEX IF NOT EXISTS idx_plg_financial_cash_register_sessions_tenant ON public.plg_financial_cash_register_sessions(tenant_id);
|
|
80
80
|
|
|
81
81
|
-- Financial movements (installments, payments) — plugin-specific, not archetype
|
|
82
|
-
-- Invoices themselves use
|
|
83
|
-
CREATE TABLE IF NOT EXISTS public.
|
|
82
|
+
-- Invoices themselves use public.orders (kind='invoice_payable'/'invoice_receivable')
|
|
83
|
+
CREATE TABLE IF NOT EXISTS public.plg_financial_movements (
|
|
84
84
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
85
|
-
tenant_id uuid NOT NULL REFERENCES
|
|
86
|
-
invoice_id uuid REFERENCES
|
|
85
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
86
|
+
invoice_id uuid REFERENCES public.orders(id),
|
|
87
87
|
direction text NOT NULL,
|
|
88
88
|
movement_kind text NOT NULL,
|
|
89
89
|
amount numeric(14,2) NOT NULL,
|
|
@@ -92,9 +92,9 @@ CREATE TABLE IF NOT EXISTS public.financial_movements (
|
|
|
92
92
|
due_date date NOT NULL,
|
|
93
93
|
payment_date date,
|
|
94
94
|
installment_number integer,
|
|
95
|
-
payment_method_id uuid REFERENCES public.
|
|
96
|
-
bank_account_id uuid REFERENCES public.
|
|
97
|
-
cash_session_id uuid REFERENCES public.
|
|
95
|
+
payment_method_id uuid REFERENCES public.plg_financial_payment_methods(id),
|
|
96
|
+
bank_account_id uuid REFERENCES public.plg_financial_bank_accounts(id),
|
|
97
|
+
cash_session_id uuid REFERENCES public.plg_financial_cash_register_sessions(id),
|
|
98
98
|
card_brand text,
|
|
99
99
|
card_installments integer,
|
|
100
100
|
notes text,
|
|
@@ -102,8 +102,8 @@ CREATE TABLE IF NOT EXISTS public.financial_movements (
|
|
|
102
102
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
103
103
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
104
104
|
);
|
|
105
|
-
ALTER TABLE public.
|
|
106
|
-
CREATE INDEX IF NOT EXISTS
|
|
107
|
-
CREATE INDEX IF NOT EXISTS
|
|
108
|
-
CREATE INDEX IF NOT EXISTS
|
|
109
|
-
CREATE INDEX IF NOT EXISTS
|
|
105
|
+
ALTER TABLE public.plg_financial_movements ENABLE ROW LEVEL SECURITY;
|
|
106
|
+
CREATE INDEX IF NOT EXISTS idx_plg_financial_movements_tenant ON public.plg_financial_movements(tenant_id);
|
|
107
|
+
CREATE INDEX IF NOT EXISTS idx_plg_financial_movements_invoice ON public.plg_financial_movements(invoice_id);
|
|
108
|
+
CREATE INDEX IF NOT EXISTS idx_plg_financial_movements_due ON public.plg_financial_movements(tenant_id, due_date);
|
|
109
|
+
CREATE INDEX IF NOT EXISTS idx_plg_financial_movements_bank ON public.plg_financial_movements(bank_account_id);
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
-- Financial Plugin: Chart of Accounts + Cost Centers
|
|
2
2
|
|
|
3
|
-
CREATE TABLE IF NOT EXISTS public.
|
|
3
|
+
CREATE TABLE IF NOT EXISTS public.plg_financial_chart_of_accounts (
|
|
4
4
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
5
|
-
tenant_id uuid NOT NULL REFERENCES
|
|
5
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
6
6
|
code text NOT NULL,
|
|
7
7
|
name text NOT NULL,
|
|
8
8
|
node_type text NOT NULL DEFAULT 'leaf',
|
|
9
|
-
parent_id uuid REFERENCES public.
|
|
9
|
+
parent_id uuid REFERENCES public.plg_financial_chart_of_accounts(id),
|
|
10
10
|
is_active boolean NOT NULL DEFAULT true,
|
|
11
11
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
12
12
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
13
13
|
);
|
|
14
|
-
ALTER TABLE public.
|
|
15
|
-
CREATE INDEX IF NOT EXISTS
|
|
16
|
-
CREATE INDEX IF NOT EXISTS
|
|
14
|
+
ALTER TABLE public.plg_financial_chart_of_accounts ENABLE ROW LEVEL SECURITY;
|
|
15
|
+
CREATE INDEX IF NOT EXISTS idx_plg_financial_chart_of_accounts_tenant ON public.plg_financial_chart_of_accounts(tenant_id);
|
|
16
|
+
CREATE INDEX IF NOT EXISTS idx_plg_financial_chart_of_accounts_parent ON public.plg_financial_chart_of_accounts(parent_id);
|
|
17
17
|
|
|
18
|
-
CREATE TABLE IF NOT EXISTS public.
|
|
18
|
+
CREATE TABLE IF NOT EXISTS public.plg_financial_cost_centers (
|
|
19
19
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
20
|
-
tenant_id uuid NOT NULL REFERENCES
|
|
20
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
21
21
|
code text NOT NULL,
|
|
22
22
|
name text NOT NULL,
|
|
23
23
|
is_active boolean NOT NULL DEFAULT true,
|
|
24
24
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
25
25
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
26
26
|
);
|
|
27
|
-
ALTER TABLE public.
|
|
28
|
-
CREATE INDEX IF NOT EXISTS
|
|
27
|
+
ALTER TABLE public.plg_financial_cost_centers ENABLE ROW LEVEL SECURITY;
|
|
28
|
+
CREATE INDEX IF NOT EXISTS idx_plg_financial_cost_centers_tenant ON public.plg_financial_cost_centers(tenant_id);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
-- Financial Plugin: Card Brands
|
|
2
2
|
|
|
3
|
-
CREATE TABLE IF NOT EXISTS public.
|
|
3
|
+
CREATE TABLE IF NOT EXISTS public.plg_financial_card_brands (
|
|
4
4
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
5
|
-
tenant_id uuid NOT NULL REFERENCES
|
|
5
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
6
6
|
name text NOT NULL,
|
|
7
7
|
is_active boolean NOT NULL DEFAULT true,
|
|
8
8
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
9
9
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
10
10
|
);
|
|
11
|
-
ALTER TABLE public.
|
|
12
|
-
CREATE INDEX IF NOT EXISTS
|
|
11
|
+
ALTER TABLE public.plg_financial_card_brands ENABLE ROW LEVEL SECURITY;
|
|
12
|
+
CREATE INDEX IF NOT EXISTS idx_plg_financial_card_brands_tenant ON public.plg_financial_card_brands(tenant_id);
|
|
@@ -1,45 +1,45 @@
|
|
|
1
1
|
-- Financial plugin — order-to-cash companion SQL.
|
|
2
2
|
-- The atomic "promote an order into an invoice + installment ledger" function
|
|
3
3
|
-- that CRM (approveQuote) and the agenda financial bridge both RPC. It belongs
|
|
4
|
-
-- to the financial plugin (it writes
|
|
4
|
+
-- to the financial plugin (it writes plg_financial_movements + reads orders), and it
|
|
5
5
|
-- ships WITH the plugin so enabling Payments provisions it. Idempotent.
|
|
6
|
-
-- Depends on:
|
|
6
|
+
-- Depends on: public.orders, public.plg_financial_movements (001_financial_base).
|
|
7
7
|
|
|
8
8
|
-- 1. Sequence generator (REC-00001 / PAG-00001 numbering)
|
|
9
|
-
CREATE TABLE IF NOT EXISTS
|
|
10
|
-
tenant_id uuid NOT NULL REFERENCES
|
|
9
|
+
CREATE TABLE IF NOT EXISTS public.sequences (
|
|
10
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id),
|
|
11
11
|
kind text NOT NULL,
|
|
12
12
|
current_value bigint NOT NULL DEFAULT 0,
|
|
13
13
|
PRIMARY KEY (tenant_id, kind)
|
|
14
14
|
);
|
|
15
|
-
CREATE OR REPLACE FUNCTION
|
|
15
|
+
CREATE OR REPLACE FUNCTION public.next_sequence(p_tenant_id uuid, p_kind text)
|
|
16
16
|
RETURNS bigint LANGUAGE plpgsql AS $$
|
|
17
17
|
DECLARE v_next bigint;
|
|
18
18
|
BEGIN
|
|
19
|
-
INSERT INTO
|
|
19
|
+
INSERT INTO public.sequences (tenant_id, kind, current_value)
|
|
20
20
|
VALUES (p_tenant_id, p_kind, 1)
|
|
21
21
|
ON CONFLICT (tenant_id, kind)
|
|
22
|
-
DO UPDATE SET current_value =
|
|
22
|
+
DO UPDATE SET current_value = public.sequences.current_value + 1
|
|
23
23
|
RETURNING current_value INTO v_next;
|
|
24
24
|
RETURN v_next;
|
|
25
25
|
END;
|
|
26
26
|
$$;
|
|
27
27
|
|
|
28
|
-
-- 2. Order-to-cash columns on the spine orders (plugin extends
|
|
29
|
-
ALTER TABLE
|
|
28
|
+
-- 2. Order-to-cash columns on the spine orders (plugin extends public.orders)
|
|
29
|
+
ALTER TABLE public.orders
|
|
30
30
|
ADD COLUMN IF NOT EXISTS stage text,
|
|
31
31
|
ADD COLUMN IF NOT EXISTS direction text;
|
|
32
32
|
|
|
33
|
-
-- 3. RLS + grants for
|
|
34
|
-
ALTER TABLE public.
|
|
35
|
-
GRANT SELECT, INSERT, UPDATE, DELETE ON public.
|
|
33
|
+
-- 3. RLS + grants for plg_financial_movements (table from 001_financial_base.sql)
|
|
34
|
+
ALTER TABLE public.plg_financial_movements ENABLE ROW LEVEL SECURITY;
|
|
35
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON public.plg_financial_movements TO authenticated;
|
|
36
36
|
DO $$
|
|
37
37
|
BEGIN
|
|
38
|
-
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='
|
|
39
|
-
CREATE POLICY
|
|
40
|
-
CREATE POLICY
|
|
41
|
-
CREATE POLICY
|
|
42
|
-
CREATE POLICY
|
|
38
|
+
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='plg_financial_movements' AND policyname='plg_financial_movements_select') THEN
|
|
39
|
+
CREATE POLICY plg_financial_movements_select ON public.plg_financial_movements FOR SELECT TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
40
|
+
CREATE POLICY plg_financial_movements_insert ON public.plg_financial_movements FOR INSERT TO authenticated WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
41
|
+
CREATE POLICY plg_financial_movements_update ON public.plg_financial_movements FOR UPDATE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
42
|
+
CREATE POLICY plg_financial_movements_delete ON public.plg_financial_movements FOR DELETE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
43
43
|
END IF;
|
|
44
44
|
END $$;
|
|
45
45
|
|
|
@@ -54,10 +54,10 @@ CREATE OR REPLACE FUNCTION public.fn_invoice_from_order(
|
|
|
54
54
|
) RETURNS uuid
|
|
55
55
|
LANGUAGE plpgsql
|
|
56
56
|
SECURITY DEFINER
|
|
57
|
-
SET search_path = public
|
|
57
|
+
SET search_path = public
|
|
58
58
|
AS $$
|
|
59
59
|
DECLARE
|
|
60
|
-
v_order
|
|
60
|
+
v_order public.orders%ROWTYPE;
|
|
61
61
|
v_ref text;
|
|
62
62
|
v_seq bigint;
|
|
63
63
|
v_summary text;
|
|
@@ -73,27 +73,27 @@ DECLARE
|
|
|
73
73
|
v_due date;
|
|
74
74
|
i int;
|
|
75
75
|
BEGIN
|
|
76
|
-
SELECT * INTO v_order FROM
|
|
76
|
+
SELECT * INTO v_order FROM public.orders WHERE id = p_order_id;
|
|
77
77
|
IF NOT FOUND THEN RAISE EXCEPTION 'fn_invoice_from_order: order % not found', p_order_id; END IF;
|
|
78
78
|
IF v_order.tenant_id NOT IN (SELECT public.user_tenant_ids()) THEN
|
|
79
79
|
RAISE EXCEPTION 'fn_invoice_from_order: forbidden';
|
|
80
80
|
END IF;
|
|
81
81
|
|
|
82
|
-
SELECT id INTO v_existing FROM public.
|
|
82
|
+
SELECT id INTO v_existing FROM public.plg_financial_movements
|
|
83
83
|
WHERE invoice_id = p_order_id AND movement_kind = 'bill' LIMIT 1;
|
|
84
84
|
IF v_existing IS NOT NULL THEN RETURN p_order_id; END IF;
|
|
85
85
|
|
|
86
86
|
IF p_direction = 'debit' THEN v_kind := 'invoice_payable'; v_prefix := 'PAG';
|
|
87
87
|
ELSE v_kind := 'invoice_receivable'; v_prefix := 'REC'; END IF;
|
|
88
88
|
|
|
89
|
-
SELECT
|
|
89
|
+
SELECT public.next_sequence(v_order.tenant_id, v_kind) INTO v_seq;
|
|
90
90
|
v_ref := v_prefix || '-' || lpad(v_seq::text, 5, '0');
|
|
91
91
|
|
|
92
92
|
SELECT string_agg(name, ', ' ORDER BY sort_order) INTO v_summary
|
|
93
|
-
FROM
|
|
94
|
-
SELECT name INTO v_contact FROM
|
|
93
|
+
FROM public.order_items WHERE order_id = p_order_id;
|
|
94
|
+
SELECT name INTO v_contact FROM public.people WHERE id = v_order.party_id;
|
|
95
95
|
|
|
96
|
-
UPDATE
|
|
96
|
+
UPDATE public.orders SET
|
|
97
97
|
status = COALESCE(p_status, status),
|
|
98
98
|
stage = 'invoiced',
|
|
99
99
|
direction = p_direction,
|
|
@@ -114,7 +114,7 @@ BEGIN
|
|
|
114
114
|
FOR i IN 1..v_n LOOP
|
|
115
115
|
IF i = v_n THEN v_amt := round(v_total - v_alloc, 2);
|
|
116
116
|
ELSE v_amt := v_base; v_alloc := v_alloc + v_base; END IF;
|
|
117
|
-
INSERT INTO public.
|
|
117
|
+
INSERT INTO public.plg_financial_movements
|
|
118
118
|
(tenant_id, invoice_id, direction, movement_kind, amount, paid_amount, status, due_date, installment_number)
|
|
119
119
|
VALUES
|
|
120
120
|
(v_order.tenant_id, p_order_id, p_direction, 'bill', v_amt, 0, 'pending',
|
|
@@ -134,7 +134,7 @@ WITH bill AS (
|
|
|
134
134
|
SUM(amount) FILTER (WHERE status <> 'cancelled') AS billed,
|
|
135
135
|
SUM(paid_amount) FILTER (WHERE status <> 'cancelled') AS paid,
|
|
136
136
|
bool_or(status NOT IN ('paid','cancelled') AND due_date < current_date) AS has_overdue
|
|
137
|
-
FROM public.
|
|
137
|
+
FROM public.plg_financial_movements
|
|
138
138
|
WHERE movement_kind = 'bill'
|
|
139
139
|
GROUP BY invoice_id
|
|
140
140
|
)
|
|
@@ -154,7 +154,7 @@ SELECT
|
|
|
154
154
|
ELSE 'open'
|
|
155
155
|
END AS status,
|
|
156
156
|
o.created_at, o.updated_at
|
|
157
|
-
FROM
|
|
157
|
+
FROM public.orders o
|
|
158
158
|
LEFT JOIN bill b ON b.invoice_id = o.id
|
|
159
159
|
WHERE o.kind IN ('invoice_receivable','invoice_payable') OR b.invoice_id IS NOT NULL;
|
|
160
160
|
ALTER VIEW public.v_invoice_balances SET (security_invoker = true);
|