152 Commits

Author SHA1 Message Date
Chris Chen 4b949dff9b 更新支票列印
ci-cd-vm / ci-cd (push) Successful in 1m56s
2026-06-27 21:37:40 -07:00
Chris Chen a4ded78442 feat(1099): show payer EIN on church profile page and 1099-NEC PDF
Populate the PAYER's TIN (EIN) box in Form1099FormService.BuildCopyBHtml
from ChurchProfile.PayerEin (blank when null, matching prior behaviour).
Add payerEin field to ChurchProfileDto TS model (flows into
UpdateChurchProfileRequest via the existing Omit type) and a text input on
the Church Info tab of the church-profile settings page, mirroring the
Routing # field pattern. CSV left unchanged — adding a payer context line
would break the existing ExportFilingCsvAsync assertion (3 lines expected).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 18:23:49 -07:00
Chris Chen 831b868d9d feat(1099): add payer EIN to ChurchProfile (entity, DTO, migration)
Add PayerEin (nullable string, max 20) to ChurchProfile entity, AppDbContext
config, ChurchProfileDto response, UpdateChurchProfileRequest, and
ChurchProfileService round-trip — mirroring the Phone/BankRoutingNumber
nullable-string pattern. Migration AddPayerEinToChurchProfile adds only the
one nullable column to ChurchProfiles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 18:23:40 -07:00
Chris Chen d29de83116 feat(1099): wire W-9 document upload/view for recipients
Adds POST/GET payee-1099/{id}/w9, mirroring the expense-receipt upload:
IFileStorage saves to finance/w9/{id}{ext}, content-type derived from the
blob extension. Frontend dialog (edit mode) gains a W-9 file input and an
auth-correct blob "View W-9" link. Payee1099Service ctor now takes
IFileStorage; tests updated with an in-memory FakeStorage.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 18:11:11 -07:00
Chris Chen ad276c01f3 docs(1099): document Payee1099s/Form1099Boxes schema and seed Form1099 permissions
- DB_SCHEMA.md §8: add Form1099Box catalog table, Payee1099 recipient master
  (with TIN at-rest encryption note), and new FK columns on Expenses /
  ExpenseSubCategories / ExpenseCategoryGroups; update TOC and Seed Data section
- DbSeeder.cs: grant Modules.Form1099 to finance (R/W/D), pastor (R), and
  board_member (R), mirroring the Form990Report + Disbursements pattern;
  idempotent (only inserts if row absent, never clobbers admin edits)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 17:56:09 -07:00
Chris Chen 402826ee3d feat(1099): round-trip Form1099BoxId through expense category DTOs/service
Mirror Form990LineId: add Form1099BoxId + Form1099BoxCode to all four
category DTOs (response + request, group + sub); load a boxCodes lookup
dictionary in GetAllAsync and project it; set/copy the field in
CreateGroupAsync, UpdateGroupAsync, CreateSubCategoryAsync, and
UpdateSubCategoryAsync. All 4 category-service unit tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 17:46:31 -07:00
Chris Chen 8cb6245560 feat(1099): add 1099 Copy B + filing CSV download endpoints
Injects I1099FormService into Form1099ReportController and adds two
Read-gated GET endpoints: recipient/{payeeId}/copy-b (Copy B PDF) and
export-csv (filing-data CSV). Registers Form1099FormService in DI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 17:21:14 -07:00
Chris Chen b7eb95056d feat(1099): add I1099FormService with filing CSV export + Copy B PDF
Adds I1099FormService and Form1099FormService: an IRIS/accountant filing-data
CSV (one row per reportable recipient) and a plain-paper recipient Copy B
1099-NEC PDF rendered via the DevExpress RichEdit/Office API (mirroring
CheckPrintService). Includes a CSV-export unit test over a stub report service.

Service lives in namespace ROLAC.API.Services (not ...Services.Form1099) to
avoid shadowing the ROLAC.API.Entities.Form1099 constants class.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 17:21:04 -07:00
Chris Chen 556abba687 feat(1099): EF migration for Payee1099, Form1099Box, mapping columns
Creates Form1099Boxes and Payee1099s tables; adds Form1099BoxId to
ExpenseSubCategories and ExpenseCategoryGroups; adds PayeeId to
Expenses. All new columns nullable, all FKs with SetNull, unique index
on Form1099Boxes.BoxCode. No data backfill.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 17:14:57 -07:00
Chris Chen 1a8002015a feat(1099): seed Form1099Box catalog and default subcategory mappings
Adds Form1099BoxSeed (NEC-1, MISC-1) and Form1099SubMappingSeed
(6 service/rent subcategories), SeedForm1099BoxesAsync method with
null-fill idempotency (never clobbers admin edits), and wires it into
SeedAsync after SeedForm990ExpenseLinesAsync.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 17:13:44 -07:00
Chris Chen 7c63f6c9ba feat(1099): carry PayeeId through expense create/update/read
Add int? PayeeId to CreateExpenseRequest (UpdateExpenseRequest inherits)
and to ExpenseListItemDto (so it round-trips to the form). Set e.PayeeId
unconditionally in CreateAsync and UpdateAsync so 1099 attribution is
independent of VendorPayment vs StaffReimbursement type. Map PayeeId in
both DTO projections: the paged-list lambda and GetByIdAsync.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 17:08:01 -07:00
Chris Chen 7c5348969b feat(1099): add recipient and report controllers
Payee1099Controller (api/payee-1099): CRUD + TIN reveal, class-level
Read gate, method-level Write/Delete overrides — mirrors the
HasPermission class+method stacking pattern from ExpensesController.
Form1099ReportController (api/form1099-report): boxes, annual summary,
and per-recipient detail; read-only, no method-level overrides needed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 17:06:49 -07:00
Chris Chen 0a9b82544d feat(1099): register Form1099 permission module and services
Add Form1099 const to Modules.cs (after Form990Report) and insert it
into the All display-order list. Register IForm1099ReportService and
IPayee1099Service in Program.cs beside the existing Form990Report entry.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 17:06:03 -07:00
Chris Chen 6080946e74 feat(1099): add Payee1099Service recipient CRUD with TIN protection
Implement IPayee1099Service and Payee1099Service: list/get/create/update/
soft-delete and RevealTin. TIN is encrypted via ITinProtector on write;
TinLast4 is the only clear-text fragment stored. Null Tin on update
preserves the existing ciphertext. Four xUnit tests cover encrypt-on-create,
null-tin-keeps-ciphertext, list-masks-to-last4, and soft-delete hides from list.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 17:02:45 -07:00
Chris Chen 560fb79bf0 feat(1099): add recipient DTOs
Add Payee1099ListItemDto, Payee1099Dto, and SavePayee1099Request in
DTOs/Payee for the 1099 recipient CRUD surface.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 17:02:33 -07:00
Chris Chen 0767a3fe94 refactor(1099): materialize report query for Npgsql safety; deterministic year + ordering
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 16:58:28 -07:00
Chris Chen 0754ed8d69 feat(1099): add Form1099ReportService cash-basis annual aggregation
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 16:53:28 -07:00
Chris Chen 9aa64b5f4c feat(1099): add report and recipient DTOs
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 16:53:15 -07:00
Chris Chen 5e2fbe800c feat(1099): add ITinProtector with Data Protection encryption + last-4 helper
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 16:47:49 -07:00
Chris Chen 89238bba99 fix(1099): pin max-lengths on Payee1099/Form1099Box columns to match codebase
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 16:45:02 -07:00
Chris Chen 225e64b992 feat(1099): configure Payee1099, Form1099Box, and mapping FKs in DbContext
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 16:40:49 -07:00
Chris Chen 7809ba9741 feat(1099): add Form1099BoxId mapping FKs and Expense.PayeeId
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 16:40:40 -07:00
Chris Chen 48ae014def feat(1099): add Payee1099 recipient master entity
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 16:40:34 -07:00
Chris Chen 89f02d020b feat(1099): add Form1099Box catalog entity
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 16:40:30 -07:00
Chris Chen 3b76ff43fc feat(1099): add Form1099 constants (threshold, box codes, W9 statuses)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 16:40:22 -07:00
Chris Chen 55543af5e1 checks
ci-cd-vm / ci-cd (push) Successful in 2m17s
2026-06-25 15:51:52 -07:00
Chris Chen 8922bb69de fix(expense-snapshot): validate functional class + stamp DeletedBy on soft delete
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 15:07:55 -07:00
Chris Chen 4877fec1da feat(expense-snapshot): REST controller + DI registration 2026-06-25 15:01:38 -07:00
Chris Chen 73c52ded88 feat(expense-snapshot): snapshot service with creator-name resolution + tests 2026-06-25 15:00:36 -07:00
Chris Chen f1de8d7ab7 feat(expense-snapshot): add snapshot DTOs 2026-06-25 14:58:53 -07:00
Chris Chen 5957d0f45e feat(expense-snapshot): register snapshot tables + EF migration 2026-06-25 14:58:18 -07:00
Chris Chen c5405a95c3 feat(expense-snapshot): add ExpenseSnapshot + ExpenseSnapshotLine entities 2026-06-25 14:55:50 -07:00
Chris Chen 73077295a4 feat(expense-categories): AI 建議 for group/sub name + 990 line
ci-cd-vm / ci-cd (push) Successful in 2m25s
Add an AI assist button to the Edit/New Group (大項) and Subcategory
(小項) dialogs: the user enters a Chinese name, and the model refines
the Chinese, translates it to English, and suggests the matching IRS
Form 990 Part IX line. Suggestions surface in a confirm card; Apply
fills the Chinese name, English name, and 990 line fields.

Backend mirrors the existing expense-classification AI family but over
the Form 990 line catalog: IExpenseCategoryAiService + base (catalog
load, prompt, id validation) + Claude/Gemini providers + factory that
picks the provider from ChurchProfile.AiProvider. New write-gated
POST api/expense-categories/ai-suggest endpoint; sub-category requests
pass the parent group + its 990 line to bias the choice.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 14:18:34 -07:00
Chris Chen c5b1a9372a test(ai): cover config-provider default fallback when no profile row 2026-06-25 13:34:20 -07:00
Chris Chen 120240ad0c feat(ai): DB-only config + runtime provider selection via factory 2026-06-25 13:23:13 -07:00
Chris Chen ece9938bfb feat(ai): add DB-backed church AI config provider 2026-06-25 13:18:04 -07:00
Chris Chen a16e21dbfd feat(church-profile): masked-read + leave-unchanged write for AI keys 2026-06-25 13:13:42 -07:00
Chris Chen 75905e7036 feat(church-profile): add AI provider/model/key columns + migration 2026-06-25 13:07:30 -07:00
Chris Chen bdccb79029 WIP 2026-06-25 12:47:14 -07:00
Chris Chen a89e936f4d Implement AI 2026-06-25 11:11:26 -07:00
Chris Chen fa3e75a333 add approve.
ci-cd-vm / ci-cd (push) Successful in 2m24s
2026-06-25 10:22:01 -07:00
Chris Chen 8bdb942a49 update detail.
ci-cd-vm / ci-cd (push) Successful in 4m27s
2026-06-25 09:33:49 -07:00
Chris Chen 609ce6a439 WIP
ci-cd-vm / ci-cd (push) Successful in 1m49s
2026-06-24 21:47:22 -07:00
Chris Chen 46a4298a71 WIP 2026-06-24 21:37:41 -07:00
Chris Chen 1a03a1cbba feat(finance): expose Form 990 line catalog endpoint
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 19:36:01 -07:00
Chris Chen b41297f972 feat(finance): Form 990 functional-expenses report endpoint 2026-06-24 19:30:33 -07:00
Chris Chen a5de2dbbb1 feat(finance): Form 990 Part IX functional-expense aggregation service
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 19:26:59 -07:00
Chris Chen 1fa36ae62f fix(finance): make Form990 row DTO use properties (System.Text.Json skips fields) 2026-06-24 19:23:54 -07:00
Chris Chen 1353b5571f feat(finance): add Form 990 report DTOs and permission module
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 19:23:05 -07:00
Chris Chen 4e83f27703 feat(seed): default Administration ministry to Management & General
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 19:21:04 -07:00