b632ae8a73ca759f51d72315200bba0b56570b8a
Step 2 of banking. Loan creation auto-generates the full installment schedule using standard amortization (eşit taksitli kredi): monthlyPayment = P × r × (1+r)^n / ((1+r)^n − 1) Schema: - bank_loans: bankAccountId (optional FK), bankName, loanName, loanType enum (consumer/vehicle/housing/commercial/kmh/other), principal, interestRate (monthly nominal %), termMonths, monthlyPayment, startDate, paymentDay (1-28, clamped per month), status (active/closed/defaulted). - loan_installments: loanId, installmentNo, dueDate, amount, principalPart, interestPart, paid, paidAt, financeEntryId. - Indexes on bank_loans(tenantId, status) and loan_installments(tenantId, loanId) and (tenantId, paid, dueDate). Server (lib/appwrite/loan-actions.ts): - createLoanAction: validates with Zod, computes amortization including rounding-drift handling on the last installment, persists loan + N installments, audit-logs. Atomic rollback on failure (deletes any partially-created installments and the loan). - payInstallmentAction: atomically creates a finance_entry (expense, bankAccountId carried over from the loan), updates installment with paid=true + financeEntryId. If it was the last unpaid installment, marks loan status='closed'. - unpayInstallmentAction: deletes the linked finance_entry, clears paid fields, reopens the loan if it was closed. - deleteLoanAction: cascade-deletes all installments first, then the loan. UI (/finance/loans): - 3 stat cards: aktif kredi sayısı, toplam çekilen, kalan ödeme. - Loan card per loan with bank/name/type/status badges, anapara/aylık taksit/faiz/sonraki ödeme grid, progress bar (paid/total), expandable installment table. - Installment row: # / vade (red if overdue) / anapara / faiz / toplam / Ödendi-Geri al toggle. - LoanFormSheet: live preview of monthly payment, total payment, total interest as user changes principal/rate/term. paymentDay clamped 1-28 to avoid month-length issues.
Description
No description provided
Languages
TypeScript
99.5%
CSS
0.5%