Skip to main content

Customer

Source: src/data/customer/

Service

createCustomerService / CustomerService

Factory: createCustomerService(repo: CustomerRepository) — returns CustomerService.

All business logic for customer lifecycle (create/merge/link/address management) lives here.

MethodParametersReturnsDescription
findOrCreateCustomer(ctx: RequestContext, input: FindOrCreateCustomerInput)Promise<FindOrCreateResult>Finds existing customer by Discord id or creates a new one
getCustomer(ctx: RequestContext, id: string)Promise<CustomerRecord | null>Returns a customer by id
listCustomers(ctx: RequestContext)Promise<CustomerRecord[]>Lists all customers for the tenant
updateCustomer(ctx: RequestContext, id: string, input: UpdateCustomerInput)Promise<CustomerRecord>Patches an existing customer profile
deactivateCustomer(ctx: RequestContext, id: string)Promise<CustomerRecord>Marks a customer as inactive
linkCustomerToUser(ctx: RequestContext, customerId: string, userId: string)Promise<CustomerRecord>Links a customer record to a user account
mergeCustomers(ctx: RequestContext, sourceId: string, targetId: string, reassignOrders: fn)Promise<MergeResult>Merges source customer into target: combines addresses, reassigns orders, deactivates source
addAddress(ctx: RequestContext, customerId: string, address: AddressWithId)Promise<CustomerRecord>Appends an address to the customer; auto-sets default if first
removeAddress(ctx: RequestContext, customerId: string, addressId: string)Promise<CustomerRecord>Removes an address; recalculates default if needed
setDefaultAddress(ctx: RequestContext, customerId: string, addressId: string)Promise<CustomerRecord>Sets the default address for the customer
setDmPreference(ctx: RequestContext, customerId: string, key: keyof CustomerDmPreferences, value: boolean)Promise<CustomerRecord>Patches one DM notification preference; throws NOT_FOUND when customer doesn't exist
setEmailPreference(ctx: RequestContext, customerId: string, key: keyof CustomerEmailPreferences, value: boolean)Promise<CustomerRecord>Patches one email notification preference; throws NOT_FOUND when customer doesn't exist

Repository

CustomerRepository

MethodParametersReturns
getById(ctx: RequestContext, id: string)Promise<CustomerRecord | null>
listByTenant(ctx: RequestContext)Promise<CustomerRecord[]>
create(ctx: RequestContext, input: Omit<CustomerRecord, 'id' | 'createdAt' | 'updatedAt'>)Promise<CustomerRecord>
update(ctx: RequestContext, id: string, patch: CustomerPatch)Promise<CustomerRecord>
delete(ctx: RequestContext, id: string)Promise<void>
findByDiscordId(ctx: RequestContext, discordId: string)Promise<CustomerRecord | null>
findByUserId(ctx: RequestContext, userId: string)Promise<CustomerRecord | null>
findByEmail(ctx: RequestContext, email: string)Promise<CustomerRecord | null>
listByCustomerIds(ctx: RequestContext, ids: string[])Promise<CustomerRecord[]>

CustomerRecord

FieldType
idstring
tenantIdstring
userIdstring (optional)
discordIdstring
discordUsernamestring
discordDisplayNamestring
sourceCustomerSource
emailstring (optional)
phonestring (optional)
addressesAddressWithId[]
defaultAddressIdstring (optional)
notesstring (optional)
isActiveboolean
dmPreferencesCustomerDmPreferences{ orderReceived, paymentConfirmed, orderShipped, refunds } all default true
emailPreferencesCustomerEmailPreferences{ orderReceived, paymentConfirmed, orderShipped, refunds } all default true
createdAtDate
updatedAtDate

Validators

customerSchema

FieldTypeRequiredDefault
tenantIdstringYes
userIdstringNo
discordIdstringYes
discordUsernamestringYes
discordDisplayNamestringYes
sourceenum('DISCORD', 'EMAIL', 'MANUAL')No'DISCORD'
emailstring (email)No
phonestringNo
addressesAddressWithId[]No[]
defaultAddressIdstringNo
notesstringNo
isActivebooleanNotrue
createdAtDate (coerced)Yes
updatedAtDate (coerced)Yes

findOrCreateCustomerSchema

FieldTypeRequiredDefault
discordIdstringYes
discordUsernamestringYes
discordDisplayNamestringYes
sourceenum('DISCORD', 'EMAIL', 'MANUAL')No'DISCORD'
emailstring (email)No
phonestringNo
userIdstringNo

updateCustomerSchema

FieldTypeRequiredDefault
discordUsernamestringNo
discordDisplayNamestringNo
emailstring (email)No
phonestringNo
notesstringNo
userIdstringNo

Inferred Types

  • Customerz.infer<typeof customerSchema>