Commit Graph

3 Commits

Author SHA1 Message Date
kovakmedya 1f79abe404 feat(finance): personal vs company scope for banking + finance entries
User-level data privacy on finance entities. Bireysel = sadece sahibi
görür/düzenler/siler, Şirket = takım görür (mevcut davranış).

Schema additions (4 tables, all enum company|personal default 'company'):
- bank_accounts.scope
- bank_loans.scope
- credit_cards.scope
- finance_entries.scope
+ tenantId_scope index on each.

Inherited fields (no own scope, parent's used):
- loan_installments → from bank_loan
- credit_card_statements → from credit_card

Permissions (lib/appwrite/scope-permissions.ts):
- scopedRowPermissions(tenantId, createdBy, scope):
  * company: Permission.read/update Role.team(tenantId), delete Role.team
    owner|admin (current behavior)
  * personal: read/update/delete Role.user(createdBy) only
- canAccessRow(row, userId): true if scope=company OR createdBy=userId.
  Used as a defense-in-depth check inside actions because we use the
  admin SDK (which bypasses row-level perms).

Action updates:
- bank-account-actions, loan-actions, credit-card-actions, finance-actions:
  pickFormFields includes scope; create uses scopedRowPermissions; update
  re-applies perms when scope changes; update/delete check canAccessRow
  on top of the existing tenantId check.
- loan installment payment & credit card statement payment auto-create
  finance entries that inherit the parent's scope, so a personal loan
  installment doesn't create a company income/expense.

Query updates (all accept optional currentUserId):
- listBankAccounts, listLoans, listCreditCards, listFinanceEntries:
  pull all tenant rows then in-JS filter via canAccessRow.
- getBankAccountBalances respects visible accounts only.
- listAllInstallments / listStatements: filter to only those whose
  parent loan/card is visible.

UI:
- New shared component components/finance/scope-toggle.tsx with
  ScopeToggle (form input) and ScopeBadge (visual marker).
- Bank, loan, card form sheets and the finance form sheet now include
  a Şirket/Bireysel toggle at the top.
- Bank account cards display ScopeBadge for personal entries.
- Page-level queries everywhere now pass ctx.user.id so each user only
  sees their personal rows + the team's company rows.

Reports & Dashboard:
- getDashboardData filters finance entries to scope=company only — so
  team-level metrics never include any user's personal data.
- getFinancialReport (CFO view): bank accounts, loans, cards, finance
  entries, installments and statements all filtered to company scope.
  Personal entities never appear in reports anywhere.

Invoice → finance entry sync explicitly tags scope=company since invoices
are inherently company-scope.
2026-04-30 08:36:01 +03:00
kovakmedya 7b6be623ae feat(banking A): bank accounts module + finance integration
First of 3-step banking expansion. Banks tracked separately from
customer/supplier debts so we can compute real cash position later.

Schema:
- New bank_accounts table: bankName, accountName, iban, openingBalance,
  notes, archived. Indexes on (tenantId, archived).
- New column finance_entries.bankAccountId (FK, optional). Index on
  (tenantId, bankAccountId).
- schema.ts: TABLES.bankAccounts, BankAccount type, FinanceEntry gains
  bankAccountId.

Server side:
- lib/validation/bank-accounts.ts (Zod): IBAN normalized to upper-case
  no-spaces; openingBalance defaults to 0.
- lib/appwrite/bank-account-actions.ts: create/update/archive(toggle)/
  delete with audit. Delete refuses if any finance_entry still references
  the account; archive toggle replaces it for safe disable.
- lib/appwrite/bank-account-queries.ts:
  * listBankAccounts
  * getBankAccountBalances — computes opening + Σ(income) − Σ(expense)
    per account by scanning up to 5000 entries with bankAccountId set.
    Pure cash flow; debt/receivable don't move balance.
  * listEntriesForAccount

UI:
- /finance/banks server page renders BanksClient with computed balances.
- BanksClient: card grid for active accounts, collapsed details for
  archived. Sum card on top showing total active balance (color-coded by
  sign). Each card shows bank, account name, formatted IBAN, current
  balance + opening (if drifted). Dropdown: Düzenle / Arşivle / Sil.
- BankFormSheet: bank/account/IBAN/openingBalance/notes form.
- Finance form gets a bank-account Select (sentinel-stripped). Existing
  finance entries get a 'bankAccountLabel' subtitle in their row.

Sidebar: Finans group expanded with Bankalar submenu (Banka hesapları
/ Krediler / Kredi kartları). The latter two land in B and C.
2026-04-30 07:22:51 +03:00
kovakmedya 98ab73235f feat(finance): income/expense/debt/receivable tracking + summary
Multi-tenant cash flow tracker. All amounts in TRY, decimals preserved.

Schema/validation:
- lib/validation/finance.ts: financeEntrySchema with type enum, positive
  amount, date required, optional customer/invoice link, optional payment
  method.
- lib/appwrite/finance-actions.ts: create/update/delete with audit; date
  HTML input normalized to ISO before write.
- lib/appwrite/finance-queries.ts: listFinanceEntries ordered by date desc.

UI:
- /finance server page passes entries + customers to FinanceClient.
- 5 stat cards: Gelir / Gider / Net (income-expense, color-coded by sign)
  / Alacaklar / Borçlar.
- Type filter dropdown (Tümü/Gelir/Gider/Alacaklar/Borçlar) + global
  search (description/customer/amount).
- 4 quick-add buttons let users start a new entry pre-filled with the
  desired type. Single FinanceFormSheet handles all 4 types via a Select.
- Table: type badge (color-coded), signed amount (+ for income/receivable,
  − for expense/debt), date, customer, payment method label, description
  preview. Row dropdown: Edit / Delete.
- Inline destructive Sil button in Sheet footer when editing.
2026-04-30 06:04:46 +03:00