| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
feat(ios): parse slice small finance bank statement PDFs (#660) * feat(ios): parse slice small finance bank statement PDFs Adds SliceSharedStatementParser to the shared statement-import pipeline (GPay and PhonePe were the only supported formats). Detection keys on the bank's own footer strings; rows start with a dd MMM 'yy date and end in a ref/amount/balance tail, with UPI rows wrapping their details over multiple lines, so lines accumulate until the tail appears. Classification keeps totals honest: interest credits are INCOME, UPI rows are EXPENSE/INCOME by amount sign with the merchant reassembled from the descriptor segments between the UPI ref and the IFSC token, and slice's own pot movements ("atom" transfers, Auto save, Round ups) are TRANSFERs so saving money never counts as spending. The IST date-to-epoch helper and month table move from the PhonePe parser into SharedParserUtils, now shared by both. Test fixtures are fully synthetic (layout-alike, invented values); the parser was additionally smoke-checked against a real statement locally - 8/8 rows parsed with correct types and paisa-exact amounts - with nothing from it persisted anywhere in the repo. Stacked on fix/ios-correctness-batch (touches the same import use case). * feat(ios): open PDFs with PennyWise — statements import from anywhere Digging into Settings > Import is the only way in; the natural iPhone flow is opening a statement wherever it arrives (Files, Mail, WhatsApp) and handing it to the app. PennyWise now registers as a PDF handler (CFBundleDocumentTypes + LSSupportsOpeningDocumentsInPlace) and imports any PDF it is handed via onOpenURL, showing the result in an alert. The extraction+import sequence existed as two identical copies (SettingsScreen, OnboardingViewModel); both now delegate to a single StatementImportService, which also handles the security-scoped access that externally-handed files need. * feat(ios): Android-parity UX — FAB speed dial and analytics upgrade Home's + button now expands into labeled actions (Add Transaction / Import Statement) instead of jumping straight to the form — statement import was previously buried in Settings. Import from the FAB runs the shared StatementImportService and refreshes Home. Analytics moves toward Android's structure: - Summary card shows Income / Expenses / Net plus a spending trend badge vs the equal-length previous period, computed honestly (spend = EXPENSE only, income = INCOME only) regardless of the type-filter chip. - Category and merchant rows drill through to their underlying transactions in a sheet, with row tap opening the usual detail view — mirroring Android's breakdown drill-downs. - One unfiltered fetch per load; the chip filters in memory, and the period's transactions are retained for the drill-downs. * feat(ios): Android-parity transaction filters — one row of dropdown chips The transactions screen stacked three always-expanded chip rows (period, type, category), eating a third of the screen. It now mirrors Android's TransactionFilterHeader: a single horizontal row of dropdown chips — period (always highlighted, calendar icon), type, and category — each opening an anchored menu with checkmarks on the active choice, and the category chip carrying the category's color dot. "Clear filters" moves into the toolbar sort menu, where Android keeps it, replacing the standalone Clear All chip. Custom range still opens the date sheet. * fix(slice): survive per-page footers; normalize pot names in any casing Greptile on #660: - "Generated on" now skips (resetting any open block) instead of breaking the scan, so a multi-page extraction with per-page footers parses every page rather than silently accepting a partial import. - Pot prefixes/suffix are stripped by length after the case-insensitive match, so "AUTO SAVE TO Daily saver ATOM" normalizes to the same merchant as the lowercase form. Both regression-tested. The ParserTestUtils suggestion is declined: that harness belongs to parser-core's JUnit5 Android SMS tests and isn't usable from the KMP commonTest source set. * fix(slice): carry blocks across page boundaries, skip page furniture Greptile held #660 at 4/5: the footer skip cleared any open block, so a transaction whose details end on one page and whose amount tail arrives on the next was silently dropped from an otherwise-successful import. Page furniture (footer, help line, "N/N" marker, and the repeated range and table headers) is now skipped without touching the open block, so a straddling row keeps accumulating across the boundary. The range header is the treacherous one — it starts with a date and would otherwise read as a new transaction row and clobber the pending block; it gets its own exact-match pattern. Regression test covers the full straddle with every furniture line between the details and the tail. | 28 天前 | |
fix(ios): correctness batch — currency picker, totals, migrations, live rules (#659) * fix(ios): correctness batch — currency picker, totals, migrations, live rules Four defects found during the iOS/Android comparison, smallest-risk tier of the parity plan: 1. Currency picker was unreachable. The screen existed but nothing navigated to it, so every user was permanently stuck on INR display formatting. Settings > Personalization now has a Currency row. 2. Totals counted TRANSFER/INVESTMENT/CREDIT as spending. The home snapshot, the transaction list totals and the budget spent calculation all used "everything that isn't INCOME"; a transfer to your own savings ate budget and inflated "Spent this month". All three now count EXPENSE only, mirroring Android's home breakdown. 3. Destructive migration fallback removed. dropAllTables on a version bump silently wipes a finance database; the schema was born at v2 so nothing needs migrating today, and future bumps must now ship real Migrations or fail loudly in development. 4. Smart Rules now evaluate. Rules were write-only — stored, listed, toggled, never consulted. A SharedRuleEvaluator (kotlinx-serialization parsed, unknown shapes = non-match) runs in the statement-import pipeline: first active match by priority sets category/type. Manual entry is deliberately exempt — the user just picked those values. Unit-tested in commonTest, green on Android-host and iOS-simulator targets. Android is untouched by behavior: shared changes are in iOS-only code paths (Android imports only DefaultCategoryData/SharedCategoryMapping), and the full Android gate passes. Verified on the iPhone 17 Pro simulator: the Currency row navigates, setting USD reformats every figure, and seeded USD 100 EXPENSE + USD 50 TRANSFER + USD 200 INCOME renders Spent=100 / Income=200 / Saved=100 (previously Spent=150). * fix(shared): rule evaluator never throws on non-primitive JSON fields Greptile on #659: jsonPrimitive on a valid-JSON-but-non-primitive field ("value": {...}) threw instead of treating the rule as a non-match, aborting the statement import over one bad rule — exactly what the evaluator's contract promised couldn't happen. Field access now goes through a safe cast; regression-tested with object/array-shaped condition and action fields. | 28 天前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 28 天前 | ||
| 28 天前 |