@fayz-ai/plugin-financial 0.9.0 → 0.9.2
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 +3 -3
- package/dist/components/PersonStatementWidget.d.ts +1 -1
- package/dist/components/PersonStatementWidget.d.ts.map +1 -1
- package/dist/{FinancialContext.d.ts → context.d.ts} +4 -2
- package/dist/context.d.ts.map +1 -0
- package/dist/data/registries.d.ts.map +1 -0
- package/dist/index.d.ts +13 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1426 -1426
- package/dist/index.js.map +1 -1
- package/dist/integrations/stripe/connectorDef.d.ts +14 -0
- package/dist/integrations/stripe/connectorDef.d.ts.map +1 -0
- package/dist/integrations/stripe/data.d.ts +43 -0
- package/dist/integrations/stripe/data.d.ts.map +1 -0
- package/dist/lib/message-events.d.ts +12 -0
- package/dist/lib/message-events.d.ts.map +1 -0
- package/dist/{quick-add.d.ts → lib/quick-add.d.ts} +1 -1
- package/dist/lib/quick-add.d.ts.map +1 -0
- package/dist/locales/en.d.ts.map +1 -1
- package/dist/locales/pt-BR.d.ts.map +1 -1
- package/dist/{FinancialPage.d.ts → views/FinancialPage.d.ts} +3 -3
- package/dist/views/FinancialPage.d.ts.map +1 -0
- package/dist/views/InvoiceDetailView.d.ts.map +1 -1
- package/dist/views/InvoiceFormView.d.ts.map +1 -1
- package/dist/views/InvoiceListView.d.ts.map +1 -1
- package/dist/views/PayablesView.d.ts +1 -1
- package/dist/views/PayablesView.d.ts.map +1 -1
- package/dist/views/ReceivablesView.d.ts +1 -1
- package/dist/views/ReceivablesView.d.ts.map +1 -1
- package/dist/views/StatementsView.d.ts.map +1 -1
- package/dist/views/dashboardWidgets.d.ts +1 -1
- package/dist/views/dashboardWidgets.d.ts.map +1 -1
- package/package.json +12 -14
- package/dist/FinancialContext.d.ts.map +0 -1
- package/dist/FinancialPage.d.ts.map +0 -1
- package/dist/contract.test.d.ts +0 -2
- package/dist/contract.test.d.ts.map +0 -1
- package/dist/quick-add.d.ts.map +0 -1
- package/dist/registries.d.ts.map +0 -1
- package/src/FinancialContext.tsx +0 -59
- package/src/FinancialPage.tsx +0 -413
- package/src/README.md +0 -155
- package/src/components/FinancialGeneralSettings.tsx +0 -39
- package/src/components/FinancialOnboarding.tsx +0 -87
- package/src/components/FinancialSettings.tsx +0 -31
- package/src/components/PaymentModal.tsx +0 -369
- package/src/components/PersonStatementWidget.tsx +0 -133
- package/src/components/TransferModal.tsx +0 -150
- package/src/contract.test.ts +0 -58
- package/src/data/capability.test.ts +0 -135
- package/src/data/index.ts +0 -3
- package/src/data/mock.ts +0 -842
- package/src/data/supabase.ts +0 -968
- package/src/data/tables.ts +0 -13
- package/src/data/types.ts +0 -86
- package/src/index.ts +0 -487
- package/src/lib/tenant.ts +0 -3
- package/src/locales/en.ts +0 -493
- package/src/locales/index.ts +0 -7
- package/src/locales/pt-BR.ts +0 -493
- package/src/migrations/000_plg_rename.sql +0 -30
- package/src/migrations/001_financial_base.sql +0 -109
- package/src/migrations/002_chart_of_accounts.sql +0 -28
- package/src/migrations/003_card_brands.sql +0 -12
- package/src/migrations/004_order_to_cash.sql +0 -178
- package/src/migrations/005_seed_defaults.sql +0 -38
- package/src/migrations/006_rls_policies.sql +0 -37
- package/src/migrations/006b_extract_fee_amount.sql +0 -20
- package/src/migrations/007_reconciliation.sql +0 -32
- package/src/migrations/007b_movement_payment_method_type.sql +0 -6
- package/src/migrations/008_split_payment_movements.sql +0 -29
- package/src/migrations/009_agent_rpcs.sql +0 -165
- package/src/migrations/010_invoice_internal.sql +0 -133
- package/src/migrations/011_nfe.sql +0 -58
- package/src/migrations/index.ts +0 -923
- package/src/quick-add.ts +0 -58
- package/src/registries.ts +0 -308
- package/src/store.ts +0 -329
- package/src/types.ts +0 -592
- package/src/views/CardsView.tsx +0 -213
- package/src/views/CashRegistersView.tsx +0 -597
- package/src/views/CommissionsView.tsx +0 -18
- package/src/views/InvoiceDetailView.tsx +0 -616
- package/src/views/InvoiceFormView.tsx +0 -945
- package/src/views/InvoiceListView.tsx +0 -323
- package/src/views/NotasFiscaisView.tsx +0 -209
- package/src/views/PayablesView.tsx +0 -48
- package/src/views/QuickTransactionForm.tsx +0 -548
- package/src/views/ReceivablesView.tsx +0 -48
- package/src/views/ReconciliationView.tsx +0 -211
- package/src/views/StatementsView.tsx +0 -335
- package/src/views/SummaryView.tsx +0 -203
- package/src/views/dashboardWidgets.tsx +0 -437
- package/src/views/navReferrer.ts +0 -24
- /package/dist/{registries.d.ts → data/registries.d.ts} +0 -0
package/src/data/tables.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// Central physical-table-name registry for plugin-financial. Providers import T so
|
|
2
|
-
// the plg_financial_* strings live in one place.
|
|
3
|
-
export const T = {
|
|
4
|
-
movements: 'plg_financial_movements',
|
|
5
|
-
chartOfAccounts: 'plg_financial_chart_of_accounts',
|
|
6
|
-
bankAccounts: 'plg_financial_bank_accounts',
|
|
7
|
-
cardBrands: 'plg_financial_card_brands',
|
|
8
|
-
costCenters: 'plg_financial_cost_centers',
|
|
9
|
-
cashRegisterSessions: 'plg_financial_cash_register_sessions',
|
|
10
|
-
paymentMethods: 'plg_financial_payment_methods',
|
|
11
|
-
paymentMethodTypes: 'plg_financial_payment_method_types',
|
|
12
|
-
notas: 'plg_financial_nfe',
|
|
13
|
-
} as const
|
package/src/data/types.ts
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
Invoice, InvoiceItem, FinancialMovement, BankAccount,
|
|
3
|
-
CashSession, PaymentMethod, PaymentMethodType, ChartOfAccountsNode,
|
|
4
|
-
CostCenter, CardTransaction,
|
|
5
|
-
CreateInvoiceInput, PayMovementInput, CreateTransferInput, TransferResult,
|
|
6
|
-
OpenCashSessionInput, CloseCashSessionInput, CreateBankAccountInput,
|
|
7
|
-
InvoiceQuery, MovementQuery, StatementQuery,
|
|
8
|
-
PaginatedResult, FinancialSummary, StatementResult, CashSessionSummary,
|
|
9
|
-
DateRange,
|
|
10
|
-
ImportBankTransactionsInput, ImportBankTransactionsResult,
|
|
11
|
-
UnreconciledQuery, ReconciliationCandidate, ReconcileInput,
|
|
12
|
-
NotaFiscal, CreateNotaFiscalInput, NotaFiscalQuery,
|
|
13
|
-
} from '../types'
|
|
14
|
-
|
|
15
|
-
export interface FinancialDataProvider {
|
|
16
|
-
// --- Invoices ---
|
|
17
|
-
getInvoices(query: InvoiceQuery): Promise<PaginatedResult<Invoice>>
|
|
18
|
-
getInvoiceById(id: string): Promise<Invoice | null>
|
|
19
|
-
getInvoiceItems(invoiceId: string): Promise<InvoiceItem[]>
|
|
20
|
-
createInvoice(input: CreateInvoiceInput): Promise<Invoice>
|
|
21
|
-
updateInvoice(id: string, data: Partial<Invoice>): Promise<Invoice>
|
|
22
|
-
cancelInvoice(id: string): Promise<void>
|
|
23
|
-
|
|
24
|
-
// --- Movements ---
|
|
25
|
-
getMovements(query: MovementQuery): Promise<PaginatedResult<FinancialMovement>>
|
|
26
|
-
payMovement(input: PayMovementInput): Promise<FinancialMovement>
|
|
27
|
-
cancelMovement(id: string): Promise<void>
|
|
28
|
-
|
|
29
|
-
// --- Transfers (between accounts) ---
|
|
30
|
-
createTransfer(input: CreateTransferInput): Promise<TransferResult>
|
|
31
|
-
|
|
32
|
-
// --- Bank Accounts ---
|
|
33
|
-
getBankAccounts(): Promise<BankAccount[]>
|
|
34
|
-
createBankAccount(data: CreateBankAccountInput): Promise<BankAccount>
|
|
35
|
-
updateBankAccount(id: string, data: Partial<BankAccount>): Promise<BankAccount>
|
|
36
|
-
|
|
37
|
-
// --- Cash Sessions ---
|
|
38
|
-
getCashSessions(bankAccountId?: string): Promise<CashSession[]>
|
|
39
|
-
getOpenSession(bankAccountId: string): Promise<CashSession | null>
|
|
40
|
-
openCashSession(input: OpenCashSessionInput): Promise<CashSession>
|
|
41
|
-
closeCashSession(input: CloseCashSessionInput): Promise<CashSession>
|
|
42
|
-
getCashSessionSummary(sessionId: string): Promise<CashSessionSummary>
|
|
43
|
-
|
|
44
|
-
// --- Payment Methods ---
|
|
45
|
-
getPaymentMethods(): Promise<PaymentMethod[]>
|
|
46
|
-
getPaymentMethodTypes(): Promise<PaymentMethodType[]>
|
|
47
|
-
|
|
48
|
-
// --- Chart of Accounts ---
|
|
49
|
-
getChartOfAccounts(): Promise<ChartOfAccountsNode[]>
|
|
50
|
-
getCostCenters(): Promise<CostCenter[]>
|
|
51
|
-
|
|
52
|
-
// --- Card Transactions ---
|
|
53
|
-
getCardTransactions(dateRange?: DateRange): Promise<CardTransaction[]>
|
|
54
|
-
|
|
55
|
-
// --- Statements ---
|
|
56
|
-
getStatement(query: StatementQuery): Promise<StatementResult>
|
|
57
|
-
|
|
58
|
-
// --- Summary / Dashboard ---
|
|
59
|
-
getSummary(dateRange?: DateRange): Promise<FinancialSummary>
|
|
60
|
-
|
|
61
|
-
// --- Reconciliation (conciliação) ---
|
|
62
|
-
// Optional: implemented by providers that back the matching UI. A bank
|
|
63
|
-
// connector imports lines; the SDK ReconciliationView reads/matches them.
|
|
64
|
-
/** Upsert normalized bank-statement lines as movements (idempotent by external id). */
|
|
65
|
-
importBankTransactions?(input: ImportBankTransactionsInput): Promise<ImportBankTransactionsResult>
|
|
66
|
-
/** Imported lines not yet reconciled (externalSource set, reconciledAt null). */
|
|
67
|
-
getUnreconciled?(query?: UnreconciledQuery): Promise<FinancialMovement[]>
|
|
68
|
-
/** Internal-movement candidates to match a given imported line, ranked by score. */
|
|
69
|
-
suggestReconciliation?(bankMovementId: string): Promise<ReconciliationCandidate[]>
|
|
70
|
-
/** Reconcile: link to an internal movement, or accept the line standalone. */
|
|
71
|
-
reconcileMovement?(input: ReconcileInput): Promise<void>
|
|
72
|
-
/** Undo a reconciliation. */
|
|
73
|
-
unreconcileMovement?(bankMovementId: string): Promise<void>
|
|
74
|
-
|
|
75
|
-
// --- Notas fiscais (NF-e / NFC-e / NFS-e) ---
|
|
76
|
-
// Optional: implemented by providers that back the Notas Fiscais tab. Emission
|
|
77
|
-
// to SEFAZ is delegated — `issueNota` is the seam an external emissor plugs
|
|
78
|
-
// into; until then it assigns a número/série locally and marks it issued.
|
|
79
|
-
getNotas?(query: NotaFiscalQuery): Promise<PaginatedResult<NotaFiscal>>
|
|
80
|
-
getNotaById?(id: string): Promise<NotaFiscal | null>
|
|
81
|
-
createNota?(input: CreateNotaFiscalInput): Promise<NotaFiscal>
|
|
82
|
-
updateNota?(id: string, data: Partial<NotaFiscal>): Promise<NotaFiscal>
|
|
83
|
-
/** Request authorization. Decoupled from the fiscal gateway — see note above. */
|
|
84
|
-
issueNota?(id: string): Promise<NotaFiscal>
|
|
85
|
-
cancelNota?(id: string, reason?: string): Promise<NotaFiscal>
|
|
86
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,487 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import type { PluginManifest, PluginRegistryDef, PluginScope, VerticalId } from '@fayz-ai/core'
|
|
3
|
-
import type { EntityLookupMap } from '@fayz-ai/saas'
|
|
4
|
-
import { FinancialPage } from './FinancialPage'
|
|
5
|
-
import { createFinancialDashboardWidgets } from './views/dashboardWidgets'
|
|
6
|
-
import type { ResolvedFinancialConfig } from './FinancialContext'
|
|
7
|
-
import type { FinancialDataProvider } from './data/types'
|
|
8
|
-
import { createMockFinancialProvider } from './data/mock'
|
|
9
|
-
import { createSupabaseFinancialProvider } from './data/supabase'
|
|
10
|
-
import { createSafeDataProvider, registerTranslations } from '@fayz-ai/core'
|
|
11
|
-
import { createFinancialStore } from './store'
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Public: a lazy supabase-or-mock financial provider. Apps use this to share one
|
|
15
|
-
* provider between the plugin and a cross-plugin bridge (e.g. agenda's financial
|
|
16
|
-
* bridge in beauty-saas). Thin wrapper over the shared createSafeDataProvider.
|
|
17
|
-
*/
|
|
18
|
-
export function createSafeFinancialProvider(): FinancialDataProvider {
|
|
19
|
-
return createSafeDataProvider(
|
|
20
|
-
() => createSupabaseFinancialProvider(),
|
|
21
|
-
() => createMockFinancialProvider(),
|
|
22
|
-
)
|
|
23
|
-
}
|
|
24
|
-
import { financialRegistries } from './registries'
|
|
25
|
-
import { financialLocales } from './locales'
|
|
26
|
-
import { FinancialGeneralSettings } from './components/FinancialGeneralSettings'
|
|
27
|
-
import { PersonStatementWidget } from './components/PersonStatementWidget'
|
|
28
|
-
import { PluginSettingsPanel } from '@fayz-ai/saas'
|
|
29
|
-
|
|
30
|
-
// ---------------------------------------------------------------------------
|
|
31
|
-
// Public types
|
|
32
|
-
// ---------------------------------------------------------------------------
|
|
33
|
-
|
|
34
|
-
export interface FinancialPluginLabels {
|
|
35
|
-
pageTitle: string
|
|
36
|
-
pageSubtitle: string
|
|
37
|
-
summary: string
|
|
38
|
-
payables: string
|
|
39
|
-
payablesNew: string
|
|
40
|
-
payablesList: string
|
|
41
|
-
payablesRecurring: string
|
|
42
|
-
receivables: string
|
|
43
|
-
receivablesNew: string
|
|
44
|
-
receivablesList: string
|
|
45
|
-
cashRegisters: string
|
|
46
|
-
statements: string
|
|
47
|
-
commissions: string
|
|
48
|
-
commissionsOverview: string
|
|
49
|
-
commissionsRules: string
|
|
50
|
-
cards: string
|
|
51
|
-
cardsOverview: string
|
|
52
|
-
cardsReconciliation: string
|
|
53
|
-
notasFiscais: string
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export interface ItemTypeOption {
|
|
57
|
-
value: string
|
|
58
|
-
label: string
|
|
59
|
-
icon?: string
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export interface FinancialPluginOptions {
|
|
63
|
-
modules?: {
|
|
64
|
-
payables?: boolean
|
|
65
|
-
receivables?: boolean
|
|
66
|
-
cashRegisters?: boolean
|
|
67
|
-
statements?: boolean
|
|
68
|
-
commissions?: boolean
|
|
69
|
-
cards?: boolean
|
|
70
|
-
/** Bank reconciliation (conciliação). Defaults off — enable with a bank connector. */
|
|
71
|
-
reconciliation?: boolean
|
|
72
|
-
/** Notas fiscais (NF-e/NFC-e/NFS-e). Defaults off — opt-in per app. */
|
|
73
|
-
notasFiscais?: boolean
|
|
74
|
-
}
|
|
75
|
-
labels?: Partial<FinancialPluginLabels>
|
|
76
|
-
currency?: {
|
|
77
|
-
code?: string
|
|
78
|
-
locale?: string
|
|
79
|
-
symbol?: string
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Show the plugin's own quick-add affordances (the "New transaction" + "Send
|
|
83
|
-
* receipt" header buttons and, on mobile, the FAB). Opt-in (default: false) so
|
|
84
|
-
* hosts that already surface a "New" menu / global center-action don't render
|
|
85
|
-
* redundant controls. The shared quick-add sheet still opens via openQuickAdd().
|
|
86
|
-
*/
|
|
87
|
-
quickAdd?: boolean
|
|
88
|
-
navPosition?: number
|
|
89
|
-
navSection?: 'main' | 'secondary'
|
|
90
|
-
scope?: PluginScope
|
|
91
|
-
verticalId?: VerticalId
|
|
92
|
-
|
|
93
|
-
/** Data provider. Defaults to mock (in-memory) if not supplied. */
|
|
94
|
-
dataProvider?: FinancialDataProvider
|
|
95
|
-
|
|
96
|
-
/** Available item types for invoice lines. Default: product + service + other */
|
|
97
|
-
itemTypes?: ItemTypeOption[]
|
|
98
|
-
|
|
99
|
-
/** Enable service execution tracking on invoice items (default: false) */
|
|
100
|
-
enableServiceExecution?: boolean
|
|
101
|
-
|
|
102
|
-
/** Contact entity config — which person kind to use */
|
|
103
|
-
contactEntity?: { archetypeKind: string; label?: string }
|
|
104
|
-
|
|
105
|
-
/** Seed payment method types for mock provider */
|
|
106
|
-
paymentMethodTypes?: Array<{ name: string; transactionType?: string }>
|
|
107
|
-
|
|
108
|
-
/** Business units / locations. Unit selector only shows when 2+ locations are provided. */
|
|
109
|
-
locations?: Array<{ id: string; name: string; isHQ?: boolean }>
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Entity lookups for cross-plugin references.
|
|
113
|
-
* Keys match `itemTypes` values (e.g., 'product', 'service').
|
|
114
|
-
* When a lookup is provided, item forms show a search selector for that type.
|
|
115
|
-
* When absent, users type descriptions manually.
|
|
116
|
-
*/
|
|
117
|
-
entityLookups?: EntityLookupMap
|
|
118
|
-
|
|
119
|
-
/** Contact/person lookup for "Pay to" / "Receive from" fields. Queries persons archetype. */
|
|
120
|
-
contactLookup?: import('@fayz-ai/saas').EntityLookup
|
|
121
|
-
|
|
122
|
-
/** App-owned registries shown under /settings/financial Properties. */
|
|
123
|
-
settingsRegistries?: PluginRegistryDef[]
|
|
124
|
-
|
|
125
|
-
/** Callback when user clicks a booking link on an invoice. Receives the order ID. */
|
|
126
|
-
onBookingClick?: (orderId: string) => void
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Which internal-nav links this APP gates, as `nav item id → feature id`.
|
|
130
|
-
* Empty by default: the plugin ships no opinion about what is paid — packaging
|
|
131
|
-
* is the app's decision, declared alongside its `permissions.ts` (RBAC) and
|
|
132
|
-
* `billing.ts` (plan entitlements). An id absent from this map is never hidden
|
|
133
|
-
* and never gated, in the nav OR in the content.
|
|
134
|
-
*
|
|
135
|
-
* {@link FINANCIAL_NAV_FEATURES} is an opt-in preset of the `fin_*` ids used
|
|
136
|
-
* by the reference apps — spread the entries you actually want:
|
|
137
|
-
*
|
|
138
|
-
* ```ts
|
|
139
|
-
* navFeatureMap: { reconciliation: FINANCIAL_NAV_FEATURES.reconciliation }
|
|
140
|
-
* ```
|
|
141
|
-
*/
|
|
142
|
-
navFeatureMap?: Record<string, string>
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// ---------------------------------------------------------------------------
|
|
146
|
-
// Defaults
|
|
147
|
-
// ---------------------------------------------------------------------------
|
|
148
|
-
|
|
149
|
-
const DEFAULT_LABELS: FinancialPluginLabels = {
|
|
150
|
-
pageTitle: 'Financial',
|
|
151
|
-
pageSubtitle: 'Financial overview and cash flow management',
|
|
152
|
-
summary: 'Summary',
|
|
153
|
-
payables: 'Accounts Payable',
|
|
154
|
-
payablesNew: 'New',
|
|
155
|
-
payablesList: 'List',
|
|
156
|
-
payablesRecurring: 'Recurring Expenses',
|
|
157
|
-
receivables: 'Accounts Receivable',
|
|
158
|
-
receivablesNew: 'New',
|
|
159
|
-
receivablesList: 'List',
|
|
160
|
-
cashRegisters: 'Cash Registers',
|
|
161
|
-
statements: 'Statements',
|
|
162
|
-
commissions: 'Commissions',
|
|
163
|
-
commissionsOverview: 'Overview',
|
|
164
|
-
commissionsRules: 'Rules',
|
|
165
|
-
cards: 'Cards',
|
|
166
|
-
cardsOverview: 'Overview',
|
|
167
|
-
cardsReconciliation: 'Reconciliation',
|
|
168
|
-
notasFiscais: 'Fiscal Invoices',
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
const DEFAULT_CURRENCY = { code: 'BRL', locale: 'pt-BR', symbol: 'R$' }
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* OPT-IN preset of feature ids for the financial sub-modules — a naming
|
|
175
|
-
* convention offered to apps, NOT a default. Nothing here is applied unless an
|
|
176
|
-
* app passes the entries it wants through `options.navFeatureMap`, because what
|
|
177
|
-
* is paid is a product decision that belongs to the app (its `permissions.ts` +
|
|
178
|
-
* `billing.ts`), never to the plugin.
|
|
179
|
-
*/
|
|
180
|
-
export const FINANCIAL_NAV_FEATURES = {
|
|
181
|
-
reconciliation: 'fin_reconciliation',
|
|
182
|
-
cards: 'fin_cards',
|
|
183
|
-
commissions: 'fin_commissions',
|
|
184
|
-
statements: 'fin_statements',
|
|
185
|
-
receivables: 'fin_receivables',
|
|
186
|
-
payables: 'fin_payables',
|
|
187
|
-
'cash-registers': 'fin_cash_registers',
|
|
188
|
-
} as const satisfies Record<string, string>
|
|
189
|
-
|
|
190
|
-
const DEFAULT_ITEM_TYPES: ItemTypeOption[] = [
|
|
191
|
-
{ value: 'service', label: 'Service', icon: 'Briefcase' },
|
|
192
|
-
{ value: 'product', label: 'Product', icon: 'Package' },
|
|
193
|
-
{ value: 'other', label: 'Other', icon: 'MoreHorizontal' },
|
|
194
|
-
]
|
|
195
|
-
|
|
196
|
-
// ---------------------------------------------------------------------------
|
|
197
|
-
// Config resolver
|
|
198
|
-
// ---------------------------------------------------------------------------
|
|
199
|
-
|
|
200
|
-
function resolveConfig(options?: FinancialPluginOptions): ResolvedFinancialConfig {
|
|
201
|
-
return {
|
|
202
|
-
modules: {
|
|
203
|
-
payables: options?.modules?.payables !== false,
|
|
204
|
-
receivables: options?.modules?.receivables !== false,
|
|
205
|
-
cashRegisters: options?.modules?.cashRegisters !== false,
|
|
206
|
-
statements: options?.modules?.statements !== false,
|
|
207
|
-
commissions: options?.modules?.commissions !== false,
|
|
208
|
-
cards: options?.modules?.cards !== false,
|
|
209
|
-
// Opt-in: only shown when an app explicitly enables reconciliation (bank connector present).
|
|
210
|
-
reconciliation: options?.modules?.reconciliation === true,
|
|
211
|
-
// Opt-in: only shown when an app explicitly enables fiscal-invoice tracking.
|
|
212
|
-
notasFiscais: options?.modules?.notasFiscais === true,
|
|
213
|
-
},
|
|
214
|
-
// Opt-in: only render the plugin's own quick-add buttons/FAB when the host asks.
|
|
215
|
-
quickAdd: options?.quickAdd === true,
|
|
216
|
-
labels: { ...DEFAULT_LABELS, ...options?.labels },
|
|
217
|
-
currency: { ...DEFAULT_CURRENCY, ...options?.currency },
|
|
218
|
-
itemTypes: options?.itemTypes ?? DEFAULT_ITEM_TYPES,
|
|
219
|
-
enableServiceExecution: options?.enableServiceExecution ?? false,
|
|
220
|
-
contactEntity: {
|
|
221
|
-
archetypeKind: options?.contactEntity?.archetypeKind ?? 'client',
|
|
222
|
-
label: options?.contactEntity?.label ?? 'Contact',
|
|
223
|
-
},
|
|
224
|
-
locations: options?.locations ?? [],
|
|
225
|
-
entityLookups: options?.entityLookups ?? {},
|
|
226
|
-
contactLookup: options?.contactLookup,
|
|
227
|
-
onBookingClick: options?.onBookingClick,
|
|
228
|
-
navFeatureMap: { ...options?.navFeatureMap },
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// ---------------------------------------------------------------------------
|
|
233
|
-
// Factory
|
|
234
|
-
// ---------------------------------------------------------------------------
|
|
235
|
-
|
|
236
|
-
export function createFinancialPlugin(options?: FinancialPluginOptions): PluginManifest {
|
|
237
|
-
const config = resolveConfig(options)
|
|
238
|
-
registerTranslations(financialLocales)
|
|
239
|
-
|
|
240
|
-
const provider = options?.dataProvider ?? createSafeFinancialProvider()
|
|
241
|
-
const store = createFinancialStore(provider)
|
|
242
|
-
const dashboardWidgets = createFinancialDashboardWidgets({ config, provider, store })
|
|
243
|
-
const registries = [...financialRegistries, ...(options?.settingsRegistries ?? [])]
|
|
244
|
-
|
|
245
|
-
// Per-person statement tab (account_central-style): bound to this plugin's provider.
|
|
246
|
-
const PersonStatementBound: React.FC<any> = (props) =>
|
|
247
|
-
React.createElement(PersonStatementWidget, { person: props.item, provider, config })
|
|
248
|
-
PersonStatementBound.displayName = 'FinancialPersonStatement'
|
|
249
|
-
|
|
250
|
-
const PageComponent: React.FC<any> = () =>
|
|
251
|
-
React.createElement(FinancialPage, { config, provider, store, registries })
|
|
252
|
-
|
|
253
|
-
return {
|
|
254
|
-
id: 'financial',
|
|
255
|
-
name: config.labels.pageTitle,
|
|
256
|
-
icon: 'DollarSign',
|
|
257
|
-
version: '1.0.0',
|
|
258
|
-
scope: options?.scope ?? 'universal',
|
|
259
|
-
verticalId: options?.verticalId,
|
|
260
|
-
defaultEnabled: true,
|
|
261
|
-
dependencies: [],
|
|
262
|
-
declaredFeatures: [
|
|
263
|
-
{ id: 'financial', label: config.labels.pageTitle, group: config.labels.pageTitle },
|
|
264
|
-
...(config.modules.receivables ? [{ id: 'financial.receivables', label: config.labels.receivables, group: config.labels.pageTitle }] : []),
|
|
265
|
-
...(config.modules.payables ? [{ id: 'financial.payables', label: config.labels.payables, group: config.labels.pageTitle }] : []),
|
|
266
|
-
...(config.modules.commissions ? [{ id: 'financial.commissions', label: config.labels.commissions, group: config.labels.pageTitle }] : []),
|
|
267
|
-
],
|
|
268
|
-
// Recurring monthly quota — counts financial movement rows created this
|
|
269
|
-
// month (invoices write one per installment; quick transactions one, or two
|
|
270
|
-
// for a transfer).
|
|
271
|
-
declaredLimits: [
|
|
272
|
-
{ key: 'movements_month', label: 'Financial movements this month', table: 'plg_financial_movements', period: 'month' },
|
|
273
|
-
],
|
|
274
|
-
queryEntities: [
|
|
275
|
-
{
|
|
276
|
-
key: 'financial:invoices',
|
|
277
|
-
entity: {
|
|
278
|
-
name: 'Invoice',
|
|
279
|
-
namePlural: 'Invoices (receipts REC- / payables PAG-)',
|
|
280
|
-
icon: 'Receipt',
|
|
281
|
-
permission: { feature: 'financial', action: 'read' },
|
|
282
|
-
fields: [
|
|
283
|
-
{ key: 'referenceNumber', label: 'Reference (REC-/PAG-)', type: 'text', searchable: true },
|
|
284
|
-
{ key: 'flow', label: 'Flow (receivable/payable)', type: 'text' },
|
|
285
|
-
{ key: 'amount', label: 'Amount', type: 'number' },
|
|
286
|
-
{ key: 'paid', label: 'Paid', type: 'number' },
|
|
287
|
-
{ key: 'balance', label: 'Balance', type: 'number' },
|
|
288
|
-
{ key: 'status', label: 'Status', type: 'text' },
|
|
289
|
-
{ key: 'createdAt', label: 'Created at', type: 'text' },
|
|
290
|
-
],
|
|
291
|
-
data: {
|
|
292
|
-
table: 'v_invoice_balances',
|
|
293
|
-
tenantScoped: true,
|
|
294
|
-
searchColumns: ['reference_number'],
|
|
295
|
-
},
|
|
296
|
-
},
|
|
297
|
-
},
|
|
298
|
-
{
|
|
299
|
-
key: 'financial:movements',
|
|
300
|
-
entity: {
|
|
301
|
-
name: 'Financial movement',
|
|
302
|
-
namePlural: 'Financial movements (installment ledger)',
|
|
303
|
-
icon: 'Banknote',
|
|
304
|
-
permission: { feature: 'financial', action: 'read' },
|
|
305
|
-
fields: [
|
|
306
|
-
{ key: 'direction', label: 'Direction', type: 'text' },
|
|
307
|
-
{ key: 'movementKind', label: 'Kind (bill/payment)', type: 'text' },
|
|
308
|
-
{ key: 'amount', label: 'Amount', type: 'number' },
|
|
309
|
-
{ key: 'paidAmount', label: 'Paid amount', type: 'number' },
|
|
310
|
-
{ key: 'status', label: 'Status', type: 'text' },
|
|
311
|
-
{ key: 'dueDate', label: 'Due date', type: 'text' },
|
|
312
|
-
{ key: 'paymentDate', label: 'Payment date', type: 'text' },
|
|
313
|
-
{ key: 'installmentNumber', label: 'Installment', type: 'number' },
|
|
314
|
-
{ key: 'cardInstallments', label: 'Card installments', type: 'number' },
|
|
315
|
-
{ key: 'createdAt', label: 'Created at', type: 'text' },
|
|
316
|
-
],
|
|
317
|
-
data: {
|
|
318
|
-
table: 'plg_financial_movements',
|
|
319
|
-
tenantScoped: true,
|
|
320
|
-
},
|
|
321
|
-
},
|
|
322
|
-
},
|
|
323
|
-
],
|
|
324
|
-
declaredRpcs: [
|
|
325
|
-
{
|
|
326
|
-
name: 'agent_financial_mark_payment_received',
|
|
327
|
-
kind: 'write' as const,
|
|
328
|
-
description:
|
|
329
|
-
'Guarded settle: invoices the order via fn_invoice_from_order (installments for credit card) and marks the receivable paid, audited with the acting user.',
|
|
330
|
-
audits: true,
|
|
331
|
-
},
|
|
332
|
-
],
|
|
333
|
-
navigation: [
|
|
334
|
-
{
|
|
335
|
-
section: options?.navSection ?? 'main',
|
|
336
|
-
position: options?.navPosition ?? 6,
|
|
337
|
-
label: config.labels.pageTitle,
|
|
338
|
-
route: '/financial',
|
|
339
|
-
icon: 'DollarSign',
|
|
340
|
-
permission: { feature: 'financial', action: 'read' as const },
|
|
341
|
-
},
|
|
342
|
-
],
|
|
343
|
-
routes: [
|
|
344
|
-
{
|
|
345
|
-
path: '/financial',
|
|
346
|
-
component: PageComponent,
|
|
347
|
-
permission: { feature: 'financial', action: 'read' as const },
|
|
348
|
-
},
|
|
349
|
-
],
|
|
350
|
-
widgets: [
|
|
351
|
-
{
|
|
352
|
-
id: 'financial-person-statement',
|
|
353
|
-
zone: 'person.detail.financial',
|
|
354
|
-
component: PersonStatementBound as unknown as React.ComponentType<unknown>,
|
|
355
|
-
order: 0,
|
|
356
|
-
permission: { feature: 'financial', action: 'read' as const },
|
|
357
|
-
},
|
|
358
|
-
],
|
|
359
|
-
dashboardWidgets,
|
|
360
|
-
aiTools: [
|
|
361
|
-
{
|
|
362
|
-
id: 'financial.get-revenue',
|
|
363
|
-
name: 'getRevenue',
|
|
364
|
-
description: 'Returns revenue for the business in a given period.',
|
|
365
|
-
icon: 'DollarSign',
|
|
366
|
-
mode: 'read' as const,
|
|
367
|
-
category: 'Finance',
|
|
368
|
-
parameters: {
|
|
369
|
-
type: 'object' as const,
|
|
370
|
-
properties: {
|
|
371
|
-
period: { type: 'string' as const, description: 'today, week, month, or custom date range' },
|
|
372
|
-
},
|
|
373
|
-
},
|
|
374
|
-
suggestions: [
|
|
375
|
-
{ label: 'How much did we make today?' },
|
|
376
|
-
{ label: "What's this month's revenue?" },
|
|
377
|
-
{ label: "Compare this week's revenue to last week" },
|
|
378
|
-
],
|
|
379
|
-
},
|
|
380
|
-
{
|
|
381
|
-
id: 'financial.create-invoice',
|
|
382
|
-
name: 'createInvoice',
|
|
383
|
-
description: 'Creates a new invoice/payable for a contact.',
|
|
384
|
-
icon: 'FileText',
|
|
385
|
-
mode: 'persist' as const,
|
|
386
|
-
limitKey: 'movements_month',
|
|
387
|
-
category: 'Finance',
|
|
388
|
-
parameters: {
|
|
389
|
-
type: 'object' as const,
|
|
390
|
-
properties: {
|
|
391
|
-
contact: { type: 'string' as const, description: 'Contact/customer name' },
|
|
392
|
-
amount: { type: 'number' as const, description: 'Invoice amount' },
|
|
393
|
-
description: { type: 'string' as const, description: 'Invoice description' },
|
|
394
|
-
},
|
|
395
|
-
required: ['contact', 'amount'],
|
|
396
|
-
},
|
|
397
|
-
suggestions: [
|
|
398
|
-
{ label: 'Create an invoice for a new client' },
|
|
399
|
-
],
|
|
400
|
-
permission: { feature: 'financial', action: 'create' as const },
|
|
401
|
-
},
|
|
402
|
-
{
|
|
403
|
-
id: 'financial.mark-payment-received',
|
|
404
|
-
name: 'markPaymentReceived',
|
|
405
|
-
description:
|
|
406
|
-
'Marks an order/appointment as paid: invoices it (with installments for credit card, e.g. "cartão 2x") and settles the receivable. Resolve the booking or order id via search tools first.',
|
|
407
|
-
icon: 'BadgeDollarSign',
|
|
408
|
-
mode: 'persist' as const,
|
|
409
|
-
execution: { plane: 'server' as const, kind: 'rpc' as const, rpc: 'agent_financial_mark_payment_received' },
|
|
410
|
-
category: 'Finance',
|
|
411
|
-
parameters: {
|
|
412
|
-
type: 'object' as const,
|
|
413
|
-
properties: {
|
|
414
|
-
booking_id: { type: 'string' as const, description: 'Appointment id (alternative to order_id)' },
|
|
415
|
-
order_id: { type: 'string' as const, description: 'Order id' },
|
|
416
|
-
method: {
|
|
417
|
-
type: 'string' as const,
|
|
418
|
-
description: 'Payment method',
|
|
419
|
-
enum: ['cash', 'pix', 'credit_card', 'debit_card', 'transfer'],
|
|
420
|
-
},
|
|
421
|
-
installments: { type: 'number' as const, description: 'Credit-card installments (1-12), e.g. 2 for "cartão 2x"' },
|
|
422
|
-
},
|
|
423
|
-
required: ['method'],
|
|
424
|
-
},
|
|
425
|
-
suggestions: [
|
|
426
|
-
{ label: 'Marcar o atendimento como pago no cartão em 2x' },
|
|
427
|
-
],
|
|
428
|
-
permission: { feature: 'financial.receivables', action: 'update' as const },
|
|
429
|
-
},
|
|
430
|
-
{
|
|
431
|
-
id: 'financial.list-payables',
|
|
432
|
-
name: 'listPayables',
|
|
433
|
-
description: 'Lists outstanding payables/bills.',
|
|
434
|
-
icon: 'FileDown',
|
|
435
|
-
mode: 'read' as const,
|
|
436
|
-
category: 'Finance',
|
|
437
|
-
parameters: {
|
|
438
|
-
type: 'object' as const,
|
|
439
|
-
properties: {
|
|
440
|
-
status: { type: 'string' as const, enum: ['pending', 'overdue', 'paid'] },
|
|
441
|
-
contact: { type: 'string' as const, description: 'Filter by contact name' },
|
|
442
|
-
},
|
|
443
|
-
},
|
|
444
|
-
permission: { feature: 'financial', action: 'read' as const },
|
|
445
|
-
suggestions: [
|
|
446
|
-
{ label: 'Show me overdue bills' },
|
|
447
|
-
{ label: 'What bills are due this week?' },
|
|
448
|
-
],
|
|
449
|
-
},
|
|
450
|
-
],
|
|
451
|
-
registries,
|
|
452
|
-
settings: [
|
|
453
|
-
{
|
|
454
|
-
id: 'financial',
|
|
455
|
-
label: 'Financial',
|
|
456
|
-
icon: 'DollarSign',
|
|
457
|
-
component: (() => {
|
|
458
|
-
const FinancialSettingsTab: React.FC = () =>
|
|
459
|
-
React.createElement(PluginSettingsPanel, {
|
|
460
|
-
title: 'Financial Settings',
|
|
461
|
-
subtitle: 'Payment methods, accounts, and configurations',
|
|
462
|
-
generalSettings: React.createElement(FinancialGeneralSettings),
|
|
463
|
-
registries,
|
|
464
|
-
hostPluginId: 'financial',
|
|
465
|
-
routeBase: '/settings/financial',
|
|
466
|
-
})
|
|
467
|
-
FinancialSettingsTab.displayName = 'FinancialSettingsTab'
|
|
468
|
-
return FinancialSettingsTab as unknown as React.ComponentType<unknown>
|
|
469
|
-
})(),
|
|
470
|
-
order: 10,
|
|
471
|
-
permission: { feature: 'financial', action: 'read' as const },
|
|
472
|
-
},
|
|
473
|
-
],
|
|
474
|
-
locales: financialLocales,
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
// Re-export types and factories for consumers
|
|
479
|
-
export type { FinancialDataProvider } from './data/types'
|
|
480
|
-
export type { ResolvedFinancialConfig } from './FinancialContext'
|
|
481
|
-
// Seedable in-memory provider — apps pass a seed to render the module populated
|
|
482
|
-
// (demo/dogfood data) instead of the empty onboarding state.
|
|
483
|
-
export { createMockFinancialProvider } from './data/mock'
|
|
484
|
-
export type { MockFinancialSeed, MockFinancialProviderOptions } from './data/mock'
|
|
485
|
-
// FAY-1242: global quick-add trigger — apps wire this to a shell action (e.g.
|
|
486
|
-
// the bottom-nav center "+") to open the transaction sheet from anywhere.
|
|
487
|
-
export { openQuickAdd } from './quick-add'
|
package/src/lib/tenant.ts
DELETED