feat(1099): frontend models, API services, and permission module entry

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Chris Chen
2026-06-25 17:26:57 -07:00
parent 8cb6245560
commit bf247726e1
4 changed files with 126 additions and 0 deletions
@@ -33,6 +33,7 @@ export const PermissionModules = {
SystemLogs: 'SystemLogs',
AuditLogs: 'AuditLogs',
Settings: 'Settings',
Form1099: 'Form1099',
} as const;
/** A required permission, used in route data and the *appHasPermission directive. */
@@ -0,0 +1,43 @@
export interface Payee1099ListItem {
id: number; legalName: string; displayName?: string;
memberId?: number; memberName?: string; taxClassification: string;
is1099Tracked: boolean; tinType?: string; tinLast4?: string;
w9Status: string; isActive: boolean;
}
export interface Payee1099 extends Payee1099ListItem {
addressLine1?: string; addressLine2?: string; city?: string; state?: string; zip?: string;
email?: string; phone?: string; w9ReceivedDate?: string; hasW9Document: boolean; notes?: string;
}
export interface SavePayee1099Request {
legalName: string; displayName?: string; memberId?: number | null;
taxClassification: string; is1099Tracked: boolean;
tinType?: string; tin?: string | null;
addressLine1?: string; addressLine2?: string; city?: string; state?: string; zip?: string;
email?: string; phone?: string; w9Status: string; w9ReceivedDate?: string | null;
isActive: boolean; notes?: string;
}
export interface Form1099Box {
id: number; boxCode: string; name_en: string; name_zh?: string; formType: string; sortOrder: number;
}
export interface Form1099RecipientRow {
payeeId: number; legalName: string; tinLast4?: string; w9Status: string;
necTotal: number; rentsTotal: number; grandTotal: number; meetsThreshold: boolean; w9Missing: boolean;
}
export interface Form1099Summary {
taxYear: number; rows: Form1099RecipientRow[];
totalReportable: number; recipientsAtThreshold: number; recipientsMissingW9: number;
}
export interface Form1099Payment {
paidDate: string; description: string; categoryName: string; boxCode: string; amount: number;
}
export interface Form1099RecipientDetail {
payeeId: number; legalName: string; tinLast4?: string; w9Status: string;
taxYear: number; payments: Form1099Payment[];
}
@@ -0,0 +1,40 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { ApiConfigService } from '../../../core/services/api-config.service';
import {
Form1099Box, Form1099Summary, Form1099RecipientDetail,
} from '../models/payee1099.model';
@Injectable({ providedIn: 'root' })
export class Form1099ReportApiService {
private readonly endpoint: string;
constructor(private http: HttpClient, apiConfig: ApiConfigService) {
this.endpoint = apiConfig.getApiUrl('form1099-report');
}
getBoxes(): Observable<Form1099Box[]> {
return this.http.get<Form1099Box[]>(`${this.endpoint}/boxes`);
}
getSummary(taxYear: number): Observable<Form1099Summary> {
return this.http.get<Form1099Summary>(`${this.endpoint}/summary`, {
params: { taxYear: String(taxYear) },
});
}
getRecipient(payeeId: number, taxYear: number): Observable<Form1099RecipientDetail> {
return this.http.get<Form1099RecipientDetail>(`${this.endpoint}/recipient/${payeeId}`, {
params: { taxYear: String(taxYear) },
});
}
copyBUrl(payeeId: number, taxYear: number): string {
return `${this.endpoint}/recipient/${payeeId}/copy-b?taxYear=${taxYear}`;
}
exportCsvUrl(taxYear: number): string {
return `${this.endpoint}/export-csv?taxYear=${taxYear}`;
}
}
@@ -0,0 +1,42 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { ApiConfigService } from '../../../core/services/api-config.service';
import {
Payee1099ListItem, Payee1099, SavePayee1099Request,
} from '../models/payee1099.model';
@Injectable({ providedIn: 'root' })
export class Payee1099ApiService {
private readonly endpoint: string;
constructor(private http: HttpClient, apiConfig: ApiConfigService) {
this.endpoint = apiConfig.getApiUrl('payee-1099');
}
getAll(includeInactive = false): Observable<Payee1099ListItem[]> {
return this.http.get<Payee1099ListItem[]>(this.endpoint, {
params: { includeInactive: String(includeInactive) },
});
}
getById(id: number): Observable<Payee1099> {
return this.http.get<Payee1099>(`${this.endpoint}/${id}`);
}
create(req: SavePayee1099Request): Observable<{ id: number }> {
return this.http.post<{ id: number }>(this.endpoint, req);
}
update(id: number, req: SavePayee1099Request): Observable<void> {
return this.http.put<void>(`${this.endpoint}/${id}`, req);
}
delete(id: number): Observable<void> {
return this.http.delete<void>(`${this.endpoint}/${id}`);
}
revealTin(id: number): Observable<{ tin: string | null }> {
return this.http.get<{ tin: string | null }>(`${this.endpoint}/${id}/tin`);
}
}