feat(platform): add CRM SMS and payment settings

This commit is contained in:
2026-07-29 15:41:27 +08:00
parent 6db200a2fc
commit ead7bdc2e2
25 changed files with 23250 additions and 140 deletions

View File

@@ -66,11 +66,21 @@
return String(
payload?.meta?.requestId
|| payload?.requestId
|| payload?.traceId
|| payload?.extensions?.traceId
|| response?.headers?.get?.('x-request-id')
|| '',
);
}
function responseErrorCode(payload) {
return String(payload?.code || payload?.extensions?.code || payload?.errorCode || 'PLATFORM_API_REQUEST_FAILED');
}
function responseErrorMessage(payload, status) {
return String(payload?.message || payload?.title || payload?.error || `请求失败HTTP ${status}`);
}
async function request(operationId, options = {}) {
const operation = operationCatalog[operationId];
if (!operation) {
@@ -150,10 +160,10 @@
if (trace.length > 120) trace.splice(0, trace.length - 120);
if (!response.ok) {
throw new PlatformApiError(
String(payload.message || payload.error || `请求失败HTTP ${response.status}`),
responseErrorMessage(payload, response.status),
{
status: response.status,
code: String(payload.code || 'PLATFORM_API_REQUEST_FAILED'),
code: responseErrorCode(payload),
requestId,
operationId,
details: payload,
@@ -192,6 +202,13 @@
providerToApi: { Webhook: 'generic', SMTP: 'generic', 邮件: 'generic', 短信: 'generic', 钉钉: 'dingtalk', 飞书: 'feishu', 企微: 'wecom' },
providerFromApi: { generic: 'Webhook', dingtalk: '钉钉', feishu: '飞书', wecom: '企微' },
eventStatusFromApi: { pending: '待处理', processing: '发送中', sent: '成功', retrying: '重试中', failed: '失败', discarded: '已丢弃' },
crmStatusFromApi: { pending: '待推送', processing: '推送中', retrying: '重试中', sent: '已推送', failed: '推送失败', discarded: '已忽略' },
providerStatusFromApi: { active: '正常', disabled: '未启用', testing: '测试中' },
providerStatusToApi: { 正常: 'active', 未启用: 'disabled', 测试中: 'testing' },
smsTemplateStatusFromApi: { active: '正常', disabled: '未启用' },
smsAuditStatusFromApi: { draft: '草稿', pending_review: '审核中', approved: '已通过', rejected: '已拒绝' },
paymentStatusFromApi: { active: '正常', disabled: '未启用', testing: '测试中' },
paymentStatusToApi: { 正常: 'active', 未启用: 'disabled', 测试中: 'testing' },
};
function mapValue(map, value, fallback = value) {
@@ -365,14 +382,10 @@
},
PlatformAdminBillingController_confirmPayment(input) {
return {
tenantId: input.tenantId,
invoiceId: input.invoiceId,
amountCents: yuanToCents(input.amount),
paymentNo: input.paymentNo || undefined,
provider: input.provider || 'manual',
method: input.method || 'manual',
paidAt: input.paidAt ? new Date(input.paidAt).toISOString() : undefined,
paymentId: input.paymentId || input.backendPaymentId || input.invoiceId,
providerTradeNo: input.tradeNo || input.providerTradeNo || undefined,
paidAt: input.paidAt ? new Date(input.paidAt).toISOString() : undefined,
reason: input.reason || input.paymentNo || 'platform_manual_payment_confirm',
};
},
PlatformAdminBillingController_recordUsage(input) {
@@ -434,6 +447,95 @@
note: input.note || undefined,
};
},
PlatformAdminCrmController_upsertConfig(input) {
return {
id: input.backendId || input.id || undefined,
tenantId: input.tenantId,
enabled: input.enabled !== false && input.status !== '未启用',
url: input.endpoint || input.url || undefined,
secretRef: input.secretRef || undefined,
formName: input.formName || input.pool || undefined,
examType: input.examType || input.subject || undefined,
timeoutSeconds: Number(input.timeout || input.timeoutSeconds || 10),
delaySeconds: Number(input.delaySeconds || 0),
assignmentMode: input.assignmentMode || 'round_robin',
assignmentPool: splitList(input.pool),
assignmentConfig: { retry: Number(input.retry || 3), source: 'platform_console' },
};
},
PlatformAdminCrmController_retryLead(input) {
return { queueId: input.backendId || input.queueId || input.id, note: input.note || 'platform_console_retry' };
},
PlatformAdminSmsController_upsertChannel(input) {
return {
id: input.backendId || input.id || undefined,
tenantId: input.tenantId,
provider: input.provider || 'generic',
name: input.name || `${input.provider || 'generic'} 短信渠道`,
signature: input.signature || '',
scene: input.scene || 'login',
status: mapValue(dictionaries.providerStatusToApi, input.status, input.status || 'active'),
secretRef: input.secretRef || undefined,
priority: Number(input.priority || 100),
monthlyQuota: Number(input.quota || input.monthlyQuota || 0),
configPublic: input.configPublic || { redacted: true },
metadata: { source: 'platform_console' },
};
},
PlatformAdminSmsController_upsertTemplate(input) {
return {
id: input.backendId || input.id || undefined,
tenantId: input.tenantId,
channelId: input.channelId,
code: input.code,
name: input.name,
type: input.type || 'notification',
auditStatus: input.auditStatus || 'draft',
status: input.status || 'active',
providerTemplateCode: input.providerTemplateCode || undefined,
content: input.content || '',
remark: input.remark || undefined,
metadata: { source: 'platform_console' },
};
},
PlatformAdminPaymentSettingsController_upsertApp(input) {
return {
id: input.backendId || input.id || undefined,
appCode: input.appCode || input.code || String(input.appName || '').toLowerCase().replaceAll(' ', '_'),
appName: input.appName,
status: mapValue(dictionaries.paymentStatusToApi, input.status, input.status || 'active'),
settlementMode: input.settlement || input.settlementMode || 'PlatformCollect',
description: input.description || undefined,
metadata: { source: 'platform_console' },
};
},
PlatformAdminPaymentSettingsController_upsertChannel(input) {
return {
id: input.backendId || input.id || undefined,
appId: input.appId,
provider: input.provider || 'manual',
mode: input.mode || 'PlatformCollect',
status: mapValue(dictionaries.paymentStatusToApi, input.status, input.status || 'active'),
displayName: input.displayName || input.appName || input.provider || '支付渠道',
secretRef: input.secretRef || undefined,
callbackPath: input.callbackPath || undefined,
priority: Number(input.priority || 100),
configPublic: input.configPublic || { redacted: true },
metadata: { source: 'platform_console' },
};
},
PlatformAdminTenantPaymentSettingsController_upsertApp(input) {
return {
tenantId: input.tenantId,
provider: input.provider || 'manual',
status: mapValue(dictionaries.providerStatusToApi, input.status, input.status || 'active'),
displayName: input.appName || input.displayName || undefined,
secretRef: input.secretRef || undefined,
priority: Number(input.priority || 100),
configPublic: input.configPublic || { mode: input.mode || 'TenantCollect', redacted: true },
metadata: { source: 'platform_console' },
};
},
};
function notificationBody(input) {
@@ -456,10 +558,20 @@
}
bodyBuilders.PlatformAdminAuditController_upsertChannel = notificationBody;
bodyBuilders.PlatformAdminDunningChannelsController_upsertChannel = input => ({
...notificationBody(input),
channelId: input.id || input.channelId || undefined,
channelCode: input.code || input.channelCode,
name: input.name,
description: input.description || undefined,
enabled: input.enabled !== false,
provider: mapValue(dictionaries.providerToApi, input.provider, input.provider || 'generic'),
webhookUrl: input.endpoint || input.webhookUrl,
secretRef: input.secretRef || undefined,
minReminderLevel: Number(input.minReminderLevel || 1),
reminderTypes: input.reminderTypes || ['overdue', 'final_notice'],
reminderChannels: input.reminderChannels || ['internal'],
tenantIds: input.tenantIds || [],
timeoutSeconds: Number(input.timeout || input.timeoutSeconds || 10),
metadata: { ...(input.metadata || {}), secretRedacted: Boolean(input.secretRef) },
});
function buildBody(operationId, input = {}) {
@@ -487,6 +599,42 @@
return (items || []).find(item => item.id === id) || {};
}
function itemOf(payload) {
return payload?.item || payload || {};
}
function itemsOf(payload, key = '') {
if (Array.isArray(payload)) return payload;
if (Array.isArray(payload?.items)) return payload.items;
if (key && Array.isArray(payload?.[key])) return payload[key];
return [];
}
function lowerEnum(value) {
return String(value || '').replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase();
}
function catalogPlans(payload) {
const offerings = itemsOf(payload, 'offerings');
const offeringsById = new Map(offerings.map(item => [item.id, item]));
return itemsOf(payload, 'versions')
.map(version => {
const offering = offeringsById.get(version.offeringId) || {};
return {
...version,
code: offering.code || version.offeringCode,
name: offering.name || version.offeringName,
description: offering.description || version.description,
status: lowerEnum(version.status),
billingCycle: lowerEnum(version.billingCycle),
baseAmountCents: version.amountCents ?? version.baseAmountCents,
includedQuotas: version.limits,
offeringType: lowerEnum(offering.type || version.offeringType),
};
})
.filter(item => item.offeringType !== 'add_on' && item.status !== 'retired');
}
const adapters = {
plan(item, current = {}) {
const quotas = item.includedQuotas && typeof item.includedQuotas === 'object'
@@ -535,27 +683,30 @@
return {
id: item.subscriptionId || item.id,
tenantId: item.tenantId,
planCode: item.planCode || '',
status: mapValue(dictionaries.subscriptionStatusFromApi, item.status, item.status || '-'),
cycle: ({ yearly: '年度', monthly: '月度', trial: '试用' })[item.billingCycle] || item.billingCycle || '-',
amount: centsToYuan(item.amountCents),
planCode: item.planCode || item.baseOfferingVersionId || '',
status: mapValue(dictionaries.subscriptionStatusFromApi, lowerEnum(item.status), item.status || '-'),
cycle: ({ yearly: '年度', monthly: '月度', quarterly: '季度', trial: '试用' })[lowerEnum(item.billingCycle)] || item.billingCycle || '-',
amount: centsToYuan(item.amountCents ?? item.totalAmountCents),
start: dateOnly(item.startsAt),
expires: dateOnly(item.expiresAt),
expires: dateOnly(item.expiresAt || item.currentPeriodEnd),
autoRenew: Boolean(item.metadata?.autoRenew),
};
},
invoice(item) {
const status = lowerEnum(item.status);
const totalCents = item.totalCents ?? item.totalAmountCents;
const paidCents = item.paidCents ?? (status === 'paid' ? totalCents : 0);
return {
id: item.invoiceNo || item.id,
backendId: item.id,
tenantId: item.tenantId,
type: mapValue(dictionaries.invoiceTypeFromApi, item.invoiceType, item.invoiceType || '-'),
period: item.billingPeriodStart ? monthOnly(item.billingPeriodStart) : monthOnly(item.issuedAt || item.dueDate),
total: centsToYuan(item.totalCents),
paid: centsToYuan(item.paidCents),
balance: centsToYuan(item.balanceCents),
total: centsToYuan(totalCents),
paid: centsToYuan(paidCents),
balance: centsToYuan(item.balanceCents ?? Math.max(0, Number(totalCents || 0) - Number(paidCents || 0))),
due: dateOnly(item.dueDate),
status: mapValue(dictionaries.invoiceStatusFromApi, item.status, item.status || '-'),
status: mapValue(dictionaries.invoiceStatusFromApi, status, item.status || '-'),
note: item.note || '',
};
},
@@ -709,6 +860,131 @@
error: item.lastError || '',
};
},
crmConfig(item) {
const assignmentPool = Array.isArray(item.assignmentPool) ? item.assignmentPool.join('、') : jsonSummary(item.assignmentPool);
return {
id: item.id,
backendId: item.id,
tenantId: item.tenantId,
provider: item.url ? 'Webhook' : 'generic',
endpoint: item.url || '',
assignmentMode: ({ round_robin: '按地区轮转', direct: '手工分配', referrer: '来源归属', none: '不分配' })[lowerEnum(item.assignmentMode)] || item.assignmentMode || '-',
pool: assignmentPool || item.formName || '-',
timeout: Number(item.timeoutSeconds || 0),
retry: Number(item.assignmentConfig?.retry || 0),
enabled: item.enabled !== false,
status: item.enabled === false ? '未启用' : '正常',
secretRef: item.secretRef || '',
formName: item.formName || '',
examType: item.examType || '',
};
},
crmLead(item) {
return {
id: item.id,
backendId: item.id,
tenantId: item.tenantId,
student: item.payload?.student || item.leadId || item.recordId || 'CRM 线索',
phone: item.payload?.phoneMasked || '-',
source: item.source || '-',
subject: item.payload?.subject || item.provider || '-',
owner: item.payload?.owner || '-',
attempts: Number(item.attempts || 0),
status: mapValue(dictionaries.crmStatusFromApi, lowerEnum(item.status), item.status || '-'),
lastError: item.lastError || '',
};
},
smsChannel(item) {
const status = mapValue(dictionaries.providerStatusFromApi, lowerEnum(item.status), item.status || '-');
return {
id: item.id,
backendId: item.id,
tenantId: item.tenantId,
provider: item.provider || '-',
name: item.name || item.displayName || '',
signature: item.signature || item.name || '-',
scene: item.scene || '-',
secretRef: item.secretRef || '',
quota: Number(item.monthlyQuota || 0),
used: Number(item.sentThisMonth || 0),
status,
enabled: status === '正常',
priority: Number(item.priority || 100),
};
},
smsTemplate(item) {
const sent = Number(item.sentCount || 0);
const failed = Number(item.failedCount || 0);
return {
id: item.id,
backendId: item.id,
tenantId: item.tenantId,
channelId: item.channelId,
name: item.name || '-',
code: item.code || '-',
type: lowerEnum(item.type),
status: mapValue(dictionaries.smsAuditStatusFromApi, lowerEnum(item.auditStatus), item.auditStatus || '-'),
templateStatus: mapValue(dictionaries.smsTemplateStatusFromApi, lowerEnum(item.status), item.status || '-'),
lastSend: dateTime(item.updatedAt),
successRate: sent + failed ? `${Math.round(sent / (sent + failed) * 100)}%` : '-',
content: item.content || '',
};
},
smsLog(item) {
return {
id: item.id,
tenantId: item.tenantId,
templateId: item.templateId,
channelId: item.channelId,
phone: item.phoneMasked || '-',
provider: item.provider || '-',
updatedAt: dateTime(item.sentAt || item.createdAt),
status: lowerEnum(item.status) === 'sent' ? '发送成功' : lowerEnum(item.status) === 'failed' ? '发送失败' : '待发送',
};
},
platformPaymentApp(item) {
const status = mapValue(dictionaries.paymentStatusFromApi, lowerEnum(item.status), item.status || '-');
return {
id: item.id,
backendId: item.id,
tenantId: '',
appCode: item.appCode || '',
appName: item.appName || '-',
provider: 'platform',
mode: '平台收款',
settlement: item.settlementMode || 'PlatformCollect',
secretRef: '',
status,
appScope: 'platform',
};
},
tenantPaymentApp(item) {
const status = mapValue(dictionaries.providerStatusFromApi, lowerEnum(item.status), item.status || '-');
return {
id: item.id,
backendId: item.id,
tenantId: item.tenantId || '',
appName: item.displayName || item.provider || '-',
provider: item.provider || '-',
mode: item.configPublic?.mode || 'TenantCollect',
settlement: '租户收款',
secretRef: item.secretRef || '',
status,
appScope: 'tenant',
};
},
platformPaymentEvent(item) {
return {
id: item.id,
appId: item.appId || '',
orderNo: item.providerEventId || item.eventId || item.paymentId || '-',
amount: centsToYuan(item.payload?.amountCents || item.amountCents || 0),
channel: item.provider || '-',
notified: item.eventType || '-',
updatedAt: dateTime(item.createdAt || item.processedAt),
status: item.error ? '回调失败' : '成功',
};
},
};
function aggregateUsage(items) {
@@ -752,13 +1028,29 @@
const bootstrapDescriptors = [
['overview', 'PlatformAdminOverviewController_overview', {}],
['plans', 'PlatformAdminOverviewController_plans', { query: { includeArchived: false } }],
['plans', 'PlatformAdminOverviewController_plans', {}],
['tenants', 'PlatformAdminTenantsController_list', { query: { limit: 200 } }],
['subscriptions', 'PlatformAdminBillingController_subscriptions', { query: { limit: 200 } }],
['invoices', 'PlatformAdminBillingController_invoices', { query: { limit: 200 } }],
['usage', 'PlatformAdminBillingController_usage', { query: { limit: 200 } }],
['reminders', 'PlatformAdminBillingController_reminders', { query: { limit: 100 } }],
['banks', 'PlatformAdminQuestionBanksController_banks', { query: { limit: 200 } }],
['grants', 'PlatformAdminQuestionBanksController_grants', { query: { limit: 200 } }],
['bankSync', 'PlatformAdminQuestionBanksController_syncStatus', { query: { limit: 200 } }],
['staff', 'PlatformAdminOverviewController_staff', { query: { limit: 200 } }],
['dunningChannels', 'PlatformAdminDunningChannelsController_channels', { query: { limit: 100 } }],
['dunningEvents', 'PlatformAdminDunningEventsController_events', { query: { limit: 100 } }],
['auditLogs', 'PlatformAdminAuditController_logs', { query: { limit: 200 } }],
['alerts', 'PlatformAdminAuditController_alerts', { query: { limit: 100 } }],
['crmConfigs', 'PlatformAdminCrmController_configs', { query: { limit: 200 } }],
['crmLeads', 'PlatformAdminCrmController_leads', { query: { limit: 200 } }],
['smsChannels', 'PlatformAdminSmsController_channels', { query: { limit: 200 } }],
['smsTemplates', 'PlatformAdminSmsController_templates', { query: { limit: 200 } }],
['smsLogs', 'PlatformAdminSmsController_logs', { query: { limit: 200 } }],
['platformPaymentApps', 'PlatformAdminPaymentSettingsController_apps', { query: { limit: 200 } }],
['tenantPaymentApps', 'PlatformAdminTenantPaymentSettingsController_apps', { query: { limit: 200 } }],
['platformPaymentEvents', 'PlatformAdminPaymentSettingsController_events', { query: { limit: 100 } }],
['tenantPaymentEvents', 'PlatformAdminTenantPaymentSettingsController_events', { query: { limit: 100 } }],
];
async function bootstrap(options = {}) {
@@ -782,24 +1074,26 @@
function adaptBootstrap(payloads, currentData = {}) {
const patch = {};
if (payloads.overview) patch.apiOverview = payloads.overview.item || payloads.overview;
if (payloads.permissions?.item) patch.apiPermissions = payloads.permissions.item;
if (Array.isArray(payloads.plans?.items)) {
patch.plans = payloads.plans.items.map(item => adapters.plan(item, currentById(currentData.plans, item.code)));
if (payloads.overview) patch.apiOverview = itemOf(payloads.overview);
if (payloads.permissions) patch.apiPermissions = itemOf(payloads.permissions);
const planPayload = itemsOf(payloads.plans, 'versions').length ? catalogPlans(payloads.plans) : itemsOf(payloads.plans);
if (planPayload.length) {
patch.plans = planPayload.map(item => adapters.plan(item, currentById(currentData.plans, item.code)));
}
const planItems = patch.plans || currentData.plans || [];
const planMap = Object.fromEntries(planItems.map(item => [item.code, item]));
if (Array.isArray(payloads.tenants?.items)) {
patch.tenants = payloads.tenants.items.map(item => adapters.tenant(item, currentById(currentData.tenants, item.id), planMap));
const tenants = itemsOf(payloads.tenants);
if (tenants.length) {
patch.tenants = tenants.map(item => adapters.tenant(item, currentById(currentData.tenants, item.id), planMap));
}
if (Array.isArray(payloads.staff?.items)) patch.staff = payloads.staff.items.map(adapters.staff);
if (Array.isArray(payloads.invoices?.items)) patch.invoices = payloads.invoices.items.map(adapters.invoice);
if (Array.isArray(payloads.subscriptions?.items)) {
patch.subscriptions = payloads.subscriptions.items
.filter(item => item.subscriptionId)
.map(adapters.subscription);
}
if (Array.isArray(payloads.usage?.items)) patch.usage = aggregateUsage(payloads.usage.items);
const staff = itemsOf(payloads.staff);
if (staff.length) patch.staff = staff.map(adapters.staff);
const invoices = itemsOf(payloads.invoices);
if (invoices.length) patch.invoices = invoices.map(adapters.invoice);
const subscriptions = itemsOf(payloads.subscriptions);
if (subscriptions.length) patch.subscriptions = subscriptions.map(adapters.subscription);
const usage = itemsOf(payloads.usage);
if (usage.length) patch.usage = aggregateUsage(usage);
if (Array.isArray(payloads.usageCandidates?.items) && patch.usage) {
const usageByKey = new Map(patch.usage.map(item => [`${item.tenantId}:${item.period}`, item]));
payloads.usageCandidates.items.forEach(candidate => {
@@ -809,20 +1103,49 @@
record.overage = (candidate.items || []).map(item => item.description || item.itemType).filter(Boolean);
});
}
if (Array.isArray(payloads.reminders?.items)) patch.reminders = payloads.reminders.items.map(adapters.reminder);
if (Array.isArray(payloads.dunningChannels?.items)) patch.dunningChannels = payloads.dunningChannels.items.map(adapters.channel);
if (Array.isArray(payloads.dunningEvents?.items)) patch.dunningEvents = payloads.dunningEvents.items.map(item => adapters.event(item, 'dunning'));
if (Array.isArray(payloads.banks?.items)) {
patch.banks = payloads.banks.items.map(item => adapters.bank(item, currentById(currentData.banks, item.id)));
const reminders = itemsOf(payloads.reminders);
if (reminders.length) patch.reminders = reminders.map(adapters.reminder);
const dunningChannels = itemsOf(payloads.dunningChannels);
if (dunningChannels.length) patch.dunningChannels = dunningChannels.map(adapters.channel);
const dunningEvents = itemsOf(payloads.dunningEvents);
if (dunningEvents.length) patch.dunningEvents = dunningEvents.map(item => adapters.event(item, 'dunning'));
const banks = itemsOf(payloads.banks);
if (banks.length) {
patch.banks = banks.map(item => adapters.bank(item, currentById(currentData.banks, item.id)));
}
if (Array.isArray(payloads.grants?.items)) patch.grants = payloads.grants.items.map(adapters.grant);
if (Array.isArray(payloads.bankSync?.items)) patch.bankSync = payloads.bankSync.items.map(adapters.sync);
if (Array.isArray(payloads.auditLogs?.items)) patch.auditLogs = payloads.auditLogs.items.map(adapters.audit);
if (Array.isArray(payloads.alertRules?.items)) patch.alertRules = payloads.alertRules.items.map(adapters.rule);
if (Array.isArray(payloads.alerts?.items)) patch.alerts = payloads.alerts.items.map(adapters.alert);
if (Array.isArray(payloads.auditChannels?.items)) patch.auditChannels = payloads.auditChannels.items.map(adapters.channel);
if (Array.isArray(payloads.notificationEvents?.items)) {
patch.notificationEvents = payloads.notificationEvents.items.map(item => adapters.event(item, 'audit'));
const grants = itemsOf(payloads.grants);
if (grants.length) patch.grants = grants.map(adapters.grant);
const bankSync = itemsOf(payloads.bankSync);
if (bankSync.length) patch.bankSync = bankSync.map(adapters.sync);
const auditLogs = itemsOf(payloads.auditLogs);
if (auditLogs.length) patch.auditLogs = auditLogs.map(adapters.audit);
const alertRules = itemsOf(payloads.alertRules);
if (alertRules.length) patch.alertRules = alertRules.map(adapters.rule);
const alerts = itemsOf(payloads.alerts);
if (alerts.length) patch.alerts = alerts.map(adapters.alert);
const crmConfigs = itemsOf(payloads.crmConfigs);
if (crmConfigs.length) patch.crmConfigs = crmConfigs.map(adapters.crmConfig);
const crmLeads = itemsOf(payloads.crmLeads);
if (crmLeads.length) patch.crmLeads = crmLeads.map(adapters.crmLead);
const smsChannels = itemsOf(payloads.smsChannels);
if (smsChannels.length) patch.smsChannels = smsChannels.map(adapters.smsChannel);
const smsTemplates = itemsOf(payloads.smsTemplates);
if (smsTemplates.length) patch.smsTemplates = smsTemplates.map(adapters.smsTemplate);
const smsLogs = itemsOf(payloads.smsLogs);
if (smsLogs.length) patch.smsLogs = smsLogs.map(adapters.smsLog);
const platformPaymentApps = itemsOf(payloads.platformPaymentApps).map(adapters.platformPaymentApp);
const tenantPaymentApps = itemsOf(payloads.tenantPaymentApps).map(adapters.tenantPaymentApp);
if (platformPaymentApps.length || tenantPaymentApps.length) patch.paymentApps = [...platformPaymentApps, ...tenantPaymentApps];
const paymentEvents = [
...itemsOf(payloads.platformPaymentEvents).map(adapters.platformPaymentEvent),
...itemsOf(payloads.tenantPaymentEvents).map(adapters.platformPaymentEvent),
];
if (paymentEvents.length) patch.paymentEvents = paymentEvents;
const auditChannels = itemsOf(payloads.auditChannels);
if (auditChannels.length) patch.auditChannels = auditChannels.map(adapters.channel);
const notificationEvents = itemsOf(payloads.notificationEvents);
if (notificationEvents.length) {
patch.notificationEvents = notificationEvents.map(item => adapters.event(item, 'audit'));
}
return patch;
}