Add member identifiers table for ID documents (DL, passport, school ID)
member_identifier table with type, value, issuing authority, expiry, front/back image storage (base64 in Postgres), primary flag. CRUD endpoints under /members/:memberId/identifiers. Zod schemas with constrained type enum.
This commit is contained in:
@@ -3,6 +3,7 @@ import type { PostgresJsDatabase } from 'drizzle-orm/postgres-js'
|
||||
import {
|
||||
accounts,
|
||||
members,
|
||||
memberIdentifiers,
|
||||
accountProcessorLinks,
|
||||
accountPaymentMethods,
|
||||
taxExemptions,
|
||||
@@ -10,6 +11,8 @@ import {
|
||||
import type {
|
||||
AccountCreateInput,
|
||||
AccountUpdateInput,
|
||||
MemberIdentifierCreateInput,
|
||||
MemberIdentifierUpdateInput,
|
||||
ProcessorLinkCreateInput,
|
||||
ProcessorLinkUpdateInput,
|
||||
PaymentMethodCreateInput,
|
||||
@@ -564,3 +567,92 @@ export const TaxExemptionService = {
|
||||
return exemption ?? null
|
||||
},
|
||||
}
|
||||
|
||||
export const MemberIdentifierService = {
|
||||
async create(db: PostgresJsDatabase, companyId: string, input: MemberIdentifierCreateInput) {
|
||||
// If setting as primary, unset existing primary for this member
|
||||
if (input.isPrimary) {
|
||||
await db
|
||||
.update(memberIdentifiers)
|
||||
.set({ isPrimary: false })
|
||||
.where(
|
||||
and(
|
||||
eq(memberIdentifiers.memberId, input.memberId),
|
||||
eq(memberIdentifiers.isPrimary, true),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
const [identifier] = await db
|
||||
.insert(memberIdentifiers)
|
||||
.values({
|
||||
companyId,
|
||||
memberId: input.memberId,
|
||||
type: input.type,
|
||||
label: input.label,
|
||||
value: input.value,
|
||||
issuingAuthority: input.issuingAuthority,
|
||||
issuedDate: input.issuedDate,
|
||||
expiresAt: input.expiresAt,
|
||||
imageFrontUrl: input.imageFrontUrl,
|
||||
imageBackUrl: input.imageBackUrl,
|
||||
notes: input.notes,
|
||||
isPrimary: input.isPrimary,
|
||||
})
|
||||
.returning()
|
||||
return identifier
|
||||
},
|
||||
|
||||
async listByMember(db: PostgresJsDatabase, companyId: string, memberId: string) {
|
||||
return db
|
||||
.select()
|
||||
.from(memberIdentifiers)
|
||||
.where(
|
||||
and(
|
||||
eq(memberIdentifiers.companyId, companyId),
|
||||
eq(memberIdentifiers.memberId, memberId),
|
||||
),
|
||||
)
|
||||
},
|
||||
|
||||
async getById(db: PostgresJsDatabase, companyId: string, id: string) {
|
||||
const [identifier] = await db
|
||||
.select()
|
||||
.from(memberIdentifiers)
|
||||
.where(and(eq(memberIdentifiers.id, id), eq(memberIdentifiers.companyId, companyId)))
|
||||
.limit(1)
|
||||
return identifier ?? null
|
||||
},
|
||||
|
||||
async update(db: PostgresJsDatabase, companyId: string, id: string, input: MemberIdentifierUpdateInput) {
|
||||
if (input.isPrimary) {
|
||||
const existing = await this.getById(db, companyId, id)
|
||||
if (existing) {
|
||||
await db
|
||||
.update(memberIdentifiers)
|
||||
.set({ isPrimary: false })
|
||||
.where(
|
||||
and(
|
||||
eq(memberIdentifiers.memberId, existing.memberId),
|
||||
eq(memberIdentifiers.isPrimary, true),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const [identifier] = await db
|
||||
.update(memberIdentifiers)
|
||||
.set({ ...input, updatedAt: new Date() })
|
||||
.where(and(eq(memberIdentifiers.id, id), eq(memberIdentifiers.companyId, companyId)))
|
||||
.returning()
|
||||
return identifier ?? null
|
||||
},
|
||||
|
||||
async delete(db: PostgresJsDatabase, companyId: string, id: string) {
|
||||
const [identifier] = await db
|
||||
.delete(memberIdentifiers)
|
||||
.where(and(eq(memberIdentifiers.id, id), eq(memberIdentifiers.companyId, companyId)))
|
||||
.returning()
|
||||
return identifier ?? null
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user