- Add K1BoxDefinition, K1LineItem, K1AggregationRule, PartnershipMembership, PartnershipValuation models
- Replace CellMapping with K1BoxDefinition module (IRS box definitions + 15 aggregation rules)
- Add K1MaterializedView service for partnership schedule rollups
- Expand aggregation rules from 3 to 15 on frontend verification page
- Fix box key 4c -> 4b in Guaranteed Payments and Total K-1 Income rules
- Add box 19 to Total Distributions rule sourceBoxKeys
- Add Cell Mapping page with aggregation rules table and IRS box definitions
- Fix Cell Mapping page routing (was falling through to wildcard)
- Add Material Icons font to index.html
- Fix text cut-off in K-Document form section titles
- Fix table column widths on K1 Import History page
- Add BOX_KEY_TO_K1DATA_FIELD mapping for confirm pipeline
- Add distribution creation fallback (box 19 total / L_WITHDRAWALS)
- Auto-populate membership capital and partnership valuation on confirm
- Improve 'no active members' error message with tax year context
- Add Prisma migrations for normalized model, drop cell-mapping, widen precision, materialized views
- Add spec 006 documentation and test fixtures
- Reduce left column xMax from 445 to 435 to prevent right-column subtype
codes (at x~455) from being captured via 15pt tolerance
- Process subtype regions before simple regions in extractPartIII to ensure
right-column codes are consumed by their correct boxes first
- Add assignItemsToRegions() closest-center matching algorithm to resolve
contention when adjacent/overlapping regions compete for the same item
- Refactor extractCheckboxes to use closest-center: fixes G_LIMITED being
detected as G_GENERAL (x=180.3 at boundary x=178) and M_NO as M_YES
- Refactor extractSections to use closest-center: fixes Section L rows
(12pt spacing < 15pt tolerance) being assigned to wrong fields
- Lower tax year y-threshold from 745 to 710 to capture year fragments
at y=727.7, enabling proper 20+25 -> 2025 combination
- Add tools/test-k1-parse.mjs for standalone PDF parsing validation
Verified against actual K-1 PDF: all fields match expected values,
unmapped items reduced from many to 3 (noise only).
- Rewrote k1-position-regions.ts with all coordinates measured from
actual e-filed K-1 PDF via pdfjs-dist text position extraction
- Fixed all y-coordinate offsets (header, Part I/II, sections J-N, Part III)
- Added missing regions: J_EXCHANGE, BOX_22, BOX_23, H2_DE_TIN
- Set clean column boundaries (left values x=370-445, right code x=445-510,
right values x=510-600) to prevent cross-column matching
- Reordered extraction: checkboxes now run before Part III to prevent
BOX_16_K3 checkbox X from being grabbed as a BOX_16 value
- Fixed stale fieldId refs: D_PARTNER_EIN->E_TIN, E_NAME->F_NAME_ADDR
- Removed SSL from client serve config for local HTTP development
- Changed API rootUrl from https to http for dev environment
- Added tools/extract-k1-positions.mjs utility for PDF coordinate dumps
- Register MulterModule with disk storage in K1ImportModule so FileInterceptor
writes uploaded files to disk (sets file.filename and file.path)
- Make UploadService.createDocument robust for both disk and memory storage
by generating filename and writing buffer to disk when file.filename is unset
- Fix reprocess method to join relative filePath with uploadDir for absolute path
- Remove duplicate 'api/v1' prefix from K1ImportController and CellMappingController
(NestJS global prefix + URI versioning already adds /api/v1/)
- Update pdf-parse usage from v1 to v2 API (PDFParse class with getText())
- Fix Prisma relation names: memberships -> members, isActive -> endDate: null
- Remove unused imports, variables, and service injections
- Fix noUnusedLocals/noUnusedParameters violations across 9 files