feat: BCBS MA paper claim — fill 2024 ADA claim form; office NPI setting

- New GET /api/claims/:id/ada-form fills the 2024 ADA Dental Claim Form
  (J43024) with payer address, patient/subscriber, CDT lines, fees,
  missing teeth, billing (office) NPI and treating NPI; signatures blank
- "BCBS Claim (ADA Form)" button saves the claim and opens the PDF;
  Claim All routes BCBS patients to it; "Print ADA Form" in claim view
- Settings > NPI Providers: "Add Office NPI" (billing name, NPI, license,
  TIN) and optional per-provider license number
- Migration: office_contact billing fields, NpiProvider.licenseNumber

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-07 22:41:44 -04:00
co-authored by Claude Opus 5.5
parent d67e68c957
commit 2c0c595af5
294 changed files with 13054 additions and 1776 deletions
@@ -4,6 +4,7 @@ export const NpiProviderAggregateResultSchema = z.object({ _count: z.object({
userId: z.number(),
npiNumber: z.number(),
providerName: z.number(),
licenseNumber: z.number(),
sortOrder: z.number(),
createdAt: z.number(),
user: z.number(),
@@ -28,6 +29,7 @@ export const NpiProviderAggregateResultSchema = z.object({ _count: z.object({
userId: z.number().int().nullable(),
npiNumber: z.string().nullable(),
providerName: z.string().nullable(),
licenseNumber: z.string().nullable(),
sortOrder: z.number().int().nullable(),
createdAt: z.date().nullable()
}).nullable().optional(),
@@ -36,6 +38,7 @@ export const NpiProviderAggregateResultSchema = z.object({ _count: z.object({
userId: z.number().int().nullable(),
npiNumber: z.string().nullable(),
providerName: z.string().nullable(),
licenseNumber: z.string().nullable(),
sortOrder: z.number().int().nullable(),
createdAt: z.date().nullable()
}).nullable().optional()});
@@ -4,6 +4,7 @@ export const NpiProviderCreateResultSchema = z.object({
userId: z.number().int(),
npiNumber: z.string(),
providerName: z.string(),
licenseNumber: z.string().optional(),
sortOrder: z.number().int(),
createdAt: z.date(),
user: z.unknown(),
@@ -4,6 +4,7 @@ export const NpiProviderDeleteResultSchema = z.nullable(z.object({
userId: z.number().int(),
npiNumber: z.string(),
providerName: z.string(),
licenseNumber: z.string().optional(),
sortOrder: z.number().int(),
createdAt: z.date(),
user: z.unknown(),
@@ -4,6 +4,7 @@ export const NpiProviderFindFirstResultSchema = z.nullable(z.object({
userId: z.number().int(),
npiNumber: z.string(),
providerName: z.string(),
licenseNumber: z.string().optional(),
sortOrder: z.number().int(),
createdAt: z.date(),
user: z.unknown(),
@@ -5,6 +5,7 @@ export const NpiProviderFindManyResultSchema = z.object({
userId: z.number().int(),
npiNumber: z.string(),
providerName: z.string(),
licenseNumber: z.string().optional(),
sortOrder: z.number().int(),
createdAt: z.date(),
user: z.unknown(),
@@ -4,6 +4,7 @@ export const NpiProviderFindUniqueResultSchema = z.nullable(z.object({
userId: z.number().int(),
npiNumber: z.string(),
providerName: z.string(),
licenseNumber: z.string().optional(),
sortOrder: z.number().int(),
createdAt: z.date(),
user: z.unknown(),
@@ -4,6 +4,7 @@ export const NpiProviderGroupByResultSchema = z.array(z.object({
userId: z.number().int(),
npiNumber: z.string(),
providerName: z.string(),
licenseNumber: z.string(),
sortOrder: z.number().int(),
createdAt: z.date(),
_count: z.object({
@@ -11,6 +12,7 @@ export const NpiProviderGroupByResultSchema = z.array(z.object({
userId: z.number(),
npiNumber: z.number(),
providerName: z.number(),
licenseNumber: z.number(),
sortOrder: z.number(),
createdAt: z.number(),
user: z.number(),
@@ -35,6 +37,7 @@ export const NpiProviderGroupByResultSchema = z.array(z.object({
userId: z.number().int().nullable(),
npiNumber: z.string().nullable(),
providerName: z.string().nullable(),
licenseNumber: z.string().nullable(),
sortOrder: z.number().int().nullable(),
createdAt: z.date().nullable()
}).nullable().optional(),
@@ -43,6 +46,7 @@ export const NpiProviderGroupByResultSchema = z.array(z.object({
userId: z.number().int().nullable(),
npiNumber: z.string().nullable(),
providerName: z.string().nullable(),
licenseNumber: z.string().nullable(),
sortOrder: z.number().int().nullable(),
createdAt: z.date().nullable()
}).nullable().optional()
@@ -4,6 +4,7 @@ export const NpiProviderUpdateResultSchema = z.nullable(z.object({
userId: z.number().int(),
npiNumber: z.string(),
providerName: z.string(),
licenseNumber: z.string().optional(),
sortOrder: z.number().int(),
createdAt: z.date(),
user: z.unknown(),
@@ -4,6 +4,7 @@ export const NpiProviderUpsertResultSchema = z.object({
userId: z.number().int(),
npiNumber: z.string(),
providerName: z.string(),
licenseNumber: z.string().optional(),
sortOrder: z.number().int(),
createdAt: z.date(),
user: z.unknown(),
@@ -12,6 +12,10 @@ export const OfficeContactAggregateResultSchema = z.object({ _count: z.object({
city: z.number(),
state: z.number(),
zipCode: z.number(),
billingName: z.number(),
billingNpi: z.number(),
billingLicense: z.number(),
billingTaxId: z.number(),
user: z.number()
}).optional(),
_sum: z.object({
@@ -34,7 +38,11 @@ export const OfficeContactAggregateResultSchema = z.object({ _count: z.object({
streetAddress: z.string().nullable(),
city: z.string().nullable(),
state: z.string().nullable(),
zipCode: z.string().nullable()
zipCode: z.string().nullable(),
billingName: z.string().nullable(),
billingNpi: z.string().nullable(),
billingLicense: z.string().nullable(),
billingTaxId: z.string().nullable()
}).nullable().optional(),
_max: z.object({
id: z.number().int().nullable(),
@@ -48,5 +56,9 @@ export const OfficeContactAggregateResultSchema = z.object({ _count: z.object({
streetAddress: z.string().nullable(),
city: z.string().nullable(),
state: z.string().nullable(),
zipCode: z.string().nullable()
zipCode: z.string().nullable(),
billingName: z.string().nullable(),
billingNpi: z.string().nullable(),
billingLicense: z.string().nullable(),
billingTaxId: z.string().nullable()
}).nullable().optional()});
@@ -12,5 +12,9 @@ export const OfficeContactCreateResultSchema = z.object({
city: z.string().optional(),
state: z.string().optional(),
zipCode: z.string().optional(),
billingName: z.string().optional(),
billingNpi: z.string().optional(),
billingLicense: z.string().optional(),
billingTaxId: z.string().optional(),
user: z.unknown()
});
@@ -12,5 +12,9 @@ export const OfficeContactDeleteResultSchema = z.nullable(z.object({
city: z.string().optional(),
state: z.string().optional(),
zipCode: z.string().optional(),
billingName: z.string().optional(),
billingNpi: z.string().optional(),
billingLicense: z.string().optional(),
billingTaxId: z.string().optional(),
user: z.unknown()
}));
@@ -12,5 +12,9 @@ export const OfficeContactFindFirstResultSchema = z.nullable(z.object({
city: z.string().optional(),
state: z.string().optional(),
zipCode: z.string().optional(),
billingName: z.string().optional(),
billingNpi: z.string().optional(),
billingLicense: z.string().optional(),
billingTaxId: z.string().optional(),
user: z.unknown()
}));
@@ -13,6 +13,10 @@ export const OfficeContactFindManyResultSchema = z.object({
city: z.string().optional(),
state: z.string().optional(),
zipCode: z.string().optional(),
billingName: z.string().optional(),
billingNpi: z.string().optional(),
billingLicense: z.string().optional(),
billingTaxId: z.string().optional(),
user: z.unknown()
})),
pagination: z.object({
@@ -12,5 +12,9 @@ export const OfficeContactFindUniqueResultSchema = z.nullable(z.object({
city: z.string().optional(),
state: z.string().optional(),
zipCode: z.string().optional(),
billingName: z.string().optional(),
billingNpi: z.string().optional(),
billingLicense: z.string().optional(),
billingTaxId: z.string().optional(),
user: z.unknown()
}));
@@ -12,6 +12,10 @@ export const OfficeContactGroupByResultSchema = z.array(z.object({
city: z.string(),
state: z.string(),
zipCode: z.string(),
billingName: z.string(),
billingNpi: z.string(),
billingLicense: z.string(),
billingTaxId: z.string(),
_count: z.object({
id: z.number(),
userId: z.number(),
@@ -25,6 +29,10 @@ export const OfficeContactGroupByResultSchema = z.array(z.object({
city: z.number(),
state: z.number(),
zipCode: z.number(),
billingName: z.number(),
billingNpi: z.number(),
billingLicense: z.number(),
billingTaxId: z.number(),
user: z.number()
}).optional(),
_sum: z.object({
@@ -47,7 +55,11 @@ export const OfficeContactGroupByResultSchema = z.array(z.object({
streetAddress: z.string().nullable(),
city: z.string().nullable(),
state: z.string().nullable(),
zipCode: z.string().nullable()
zipCode: z.string().nullable(),
billingName: z.string().nullable(),
billingNpi: z.string().nullable(),
billingLicense: z.string().nullable(),
billingTaxId: z.string().nullable()
}).nullable().optional(),
_max: z.object({
id: z.number().int().nullable(),
@@ -61,6 +73,10 @@ export const OfficeContactGroupByResultSchema = z.array(z.object({
streetAddress: z.string().nullable(),
city: z.string().nullable(),
state: z.string().nullable(),
zipCode: z.string().nullable()
zipCode: z.string().nullable(),
billingName: z.string().nullable(),
billingNpi: z.string().nullable(),
billingLicense: z.string().nullable(),
billingTaxId: z.string().nullable()
}).nullable().optional()
}));
@@ -12,5 +12,9 @@ export const OfficeContactUpdateResultSchema = z.nullable(z.object({
city: z.string().optional(),
state: z.string().optional(),
zipCode: z.string().optional(),
billingName: z.string().optional(),
billingNpi: z.string().optional(),
billingLicense: z.string().optional(),
billingTaxId: z.string().optional(),
user: z.unknown()
}));
@@ -12,5 +12,9 @@ export const OfficeContactUpsertResultSchema = z.object({
city: z.string().optional(),
state: z.string().optional(),
zipCode: z.string().optional(),
billingName: z.string().optional(),
billingNpi: z.string().optional(),
billingLicense: z.string().optional(),
billingTaxId: z.string().optional(),
user: z.unknown()
});