From fb95bf004852cb6b520cc4edd225935ae7ae5d75 Mon Sep 17 00:00:00 2001 From: Chris Chen Date: Thu, 25 Jun 2026 17:50:25 -0700 Subject: [PATCH] feat(1099): add 1099 recipient picker to expense form MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add optional payeeId to CreateExpenseRequest + ExpenseListItemDto frontend models. In the expense form dialog: inject Payee1099ApiService, load active payees on init, add payeeId to the form state, pre-populate it from expense.payeeId in edit mode, and include it in the emitSave payload. Render a "1099 Recipient / 1099 收款人" Kendo DropdownList (textField=legalName, valueField=id, [valuePrimitive]="true", md:col-span-2) inside the vendor-mode ng-container below Vendor Name and Check #. Co-Authored-By: Claude Opus 4.8 --- .../expense-form-dialog.component.html | 8 +++++++- .../expense-form-dialog/expense-form-dialog.component.ts | 9 +++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/APP/src/app/features/expense/components/expense-form-dialog/expense-form-dialog.component.html b/APP/src/app/features/expense/components/expense-form-dialog/expense-form-dialog.component.html index 1d9ea19..8e50caa 100644 --- a/APP/src/app/features/expense/components/expense-form-dialog/expense-form-dialog.component.html +++ b/APP/src/app/features/expense/components/expense-form-dialog/expense-form-dialog.component.html @@ -158,7 +158,7 @@ - + diff --git a/APP/src/app/features/expense/components/expense-form-dialog/expense-form-dialog.component.ts b/APP/src/app/features/expense/components/expense-form-dialog/expense-form-dialog.component.ts index 2f33e04..d4de709 100644 --- a/APP/src/app/features/expense/components/expense-form-dialog/expense-form-dialog.component.ts +++ b/APP/src/app/features/expense/components/expense-form-dialog/expense-form-dialog.component.ts @@ -15,6 +15,8 @@ import { ExpenseSnapshotDto, CreateExpenseSnapshotRequest } from '../../models/e import { ExpenseAiService } from '../../services/expense-ai.service'; import { MemberApiService } from '../../../members/services/member-api.service'; import { MemberListItemDto, memberDisplayName } from '../../../members/models/member.model'; +import { Payee1099ApiService } from '../../../payee1099/services/payee1099-api.service'; +import { Payee1099ListItem } from '../../../payee1099/models/payee1099.model'; import { MinistryDto, ExpenseCategoryGroupDto, ExpenseSubCategoryDto, ExpenseType, CreateExpenseRequest, ExpenseDto, FunctionalClass, ExpenseAiSuggestion, @@ -66,6 +68,8 @@ export class ExpenseFormDialogComponent implements OnInit, OnDestroy { ministries: MinistryDto[] = []; groups: ExpenseCategoryGroupDto[] = []; + payees: Payee1099ListItem[] = []; + /** Saved snapshots (vendor mode only) for the "Load from snapshot" picker. */ snapshots: ExpenseSnapshotDto[] = []; /** Picker binding; reset to null after each apply so the same snapshot can be re-picked. */ @@ -95,6 +99,7 @@ export class ExpenseFormDialogComponent implements OnInit, OnDestroy { vendorName: '', checkNumber: '', memberId: null as number | null, + payeeId: null as number | null, expenseDate: new Date(), }; /** At least one line always; "+ Add line" appends, each line is independently removable down to one. */ @@ -133,11 +138,13 @@ export class ExpenseFormDialogComponent implements OnInit, OnDestroy { private expenseApi: ExpenseApiService, private snapshotApi: ExpenseSnapshotApiService, private aiApi: ExpenseAiService, + private payeeApi: Payee1099ApiService, private sanitizer: DomSanitizer, ) {} ngOnInit(): void { this.ministryApi.getAll().subscribe(m => (this.ministries = m)); + this.payeeApi.getAll(false).subscribe(list => (this.payees = list)); if (this.showSnapshotTools) this.loadSnapshots(); this.catApi.getAll(false).subscribe(groups => { this.groups = groups; @@ -169,6 +176,7 @@ export class ExpenseFormDialogComponent implements OnInit, OnDestroy { vendorName: expense.vendorName ?? '', checkNumber: expense.checkNumber ?? '', memberId: expense.memberId, + payeeId: expense.payeeId ?? null, expenseDate: new Date(year, month - 1, day), }; this.lines = (expense.lines ?? []).map(l => ({ @@ -424,6 +432,7 @@ export class ExpenseFormDialogComponent implements OnInit, OnDestroy { checkNumber: this.mode === 'vendor' ? (this.form.checkNumber || null) : null, expenseDate, notes: null, + payeeId: this.form.payeeId, }; // The request and receipt are snapshotted here, so resetting the form right // after emitting is safe even though the parent saves asynchronously.