@@ -0,0 +1,108 @@
|
||||
// Shared pure transformations used by the actual CRM core AND its approval
|
||||
// inspector. No database, network, permission or Root authority is established.
|
||||
import { actorRef } from "@conusai-kit/business"
|
||||
import { forbidden, type ProjectScope } from "@conusai-kit/core"
|
||||
import { type ContactView, SUBJECT_SCHEME } from "../contract/index.js"
|
||||
import type { CrmService } from "./ports.js"
|
||||
|
||||
export interface PartyActionInput {
|
||||
kind: "person" | "organization"
|
||||
displayName: string
|
||||
legalName?: string | undefined
|
||||
country: string
|
||||
linkSelf?: boolean | undefined
|
||||
requestId: string
|
||||
}
|
||||
export interface ContactActionInput {
|
||||
partyId: string
|
||||
kind: "email" | "phone" | "web"
|
||||
value: string
|
||||
purposes: ContactView["purposes"]
|
||||
isPrimary: boolean
|
||||
requestId: string
|
||||
}
|
||||
export const requestKey = (scope: Pick<ProjectScope, "projectId">, requestId: string): string =>
|
||||
`app-project:${scope.projectId}:${requestId}`
|
||||
export const dayOf = (at: Date): string => at.toISOString().slice(0, 10)
|
||||
export function partyActionData(
|
||||
scope: ProjectScope,
|
||||
bindingId: string,
|
||||
input: PartyActionInput,
|
||||
): Parameters<CrmService["createParty"]>[0] {
|
||||
const identifiers: { scheme: string; value: string }[] = []
|
||||
if (input.linkSelf) {
|
||||
if (input.kind !== "person") throw forbidden("only a person can be linked to a member")
|
||||
if (scope.actor.system) throw forbidden("a system actor is nobody's party")
|
||||
identifiers.push({ scheme: SUBJECT_SCHEME, value: actorRef(bindingId, scope.actor.userId) })
|
||||
}
|
||||
const legalName = input.legalName?.trim()
|
||||
return {
|
||||
kind: input.kind,
|
||||
displayName: input.displayName.trim(),
|
||||
...(legalName ? { legalName } : {}),
|
||||
country: input.country,
|
||||
identifiers,
|
||||
key: requestKey(scope, input.requestId),
|
||||
}
|
||||
}
|
||||
export function contactActionData(
|
||||
scope: ProjectScope,
|
||||
input: ContactActionInput,
|
||||
now: Date,
|
||||
): Parameters<CrmService["addContact"]>[0] {
|
||||
return {
|
||||
partyId: input.partyId,
|
||||
kind: input.kind,
|
||||
value: input.value.trim(),
|
||||
purposes: [...new Set(input.purposes)],
|
||||
isPrimary: input.isPrimary,
|
||||
effectiveFrom: dayOf(now),
|
||||
key: requestKey(scope, input.requestId),
|
||||
}
|
||||
}
|
||||
export function partyRequestBody(input: Parameters<CrmService["createParty"]>[0]) {
|
||||
return {
|
||||
data: {
|
||||
kind: input.kind,
|
||||
display_name: input.displayName,
|
||||
country: input.country,
|
||||
...(input.legalName === undefined ? {} : { legal_name: input.legalName }),
|
||||
...(input.identifiers.length === 0 ? {} : { identifiers: input.identifiers }),
|
||||
},
|
||||
idempotency_key: input.key,
|
||||
}
|
||||
}
|
||||
export function contactRequestBody(input: Parameters<CrmService["addContact"]>[0]) {
|
||||
return {
|
||||
data: {
|
||||
kind: input.kind,
|
||||
value: input.value,
|
||||
purposes: input.purposes,
|
||||
is_primary: input.isPrimary,
|
||||
effective: { from: input.effectiveFrom },
|
||||
},
|
||||
idempotency_key: input.key,
|
||||
}
|
||||
}
|
||||
export function partyEncodedRequest(orgSlug: string, input: Parameters<CrmService["createParty"]>[0]) {
|
||||
const body = partyRequestBody(input)
|
||||
return {
|
||||
service: "crm",
|
||||
operation: "crm_create_party",
|
||||
method: "POST" as const,
|
||||
path: `/v1/orgs/${encodeURIComponent(orgSlug)}/crm/parties`,
|
||||
body,
|
||||
arguments: { body },
|
||||
}
|
||||
}
|
||||
export function contactEncodedRequest(orgSlug: string, input: Parameters<CrmService["addContact"]>[0]) {
|
||||
const body = contactRequestBody(input)
|
||||
return {
|
||||
service: "crm",
|
||||
operation: "crm_add_contact_point",
|
||||
method: "POST" as const,
|
||||
path: `/v1/orgs/${encodeURIComponent(orgSlug)}/crm/parties/${encodeURIComponent(input.partyId)}/contacts`,
|
||||
body,
|
||||
arguments: { id: input.partyId, body },
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user