This commit is contained in:
2026-08-19 14:02:11 +08:00
590 changed files with 23946 additions and 5168 deletions
@@ -21,7 +21,15 @@ VALUES
(5105041,0,'PLATFORM','MENU',5105000,'platform:finance:customer-arap:list','客户应收应付','/finance/customer-arap','GET',20,'ACTIVE',1,0),
(5105042,0,'PLATFORM','MENU',5105000,'platform:finance:customer-statement:list','客户对账单','/finance/customer-statements','GET',30,'ACTIVE',1,0),
(5105043,0,'PLATFORM','MENU',5105000,'platform:finance:settlement-ar:list','结算单应收','/finance/settlement-receivables','GET',40,'ACTIVE',1,0),
(5105044,0,'PLATFORM','MENU',5105000,'platform:finance:settlement-ap:list','结算单应付','/finance/settlement-payables','GET',50,'ACTIVE',1,0)
(5105044,0,'PLATFORM','MENU',5105000,'platform:finance:settlement-ap:list','结算单应付','/finance/settlement-payables','GET',50,'ACTIVE',1,0),
(5105045,0,'PLATFORM','MENU',5105000,'platform:finance:receivable-statistics:list','应收款统计表','/finance/receivable-statistics','GET',25,'ACTIVE',1,0),
(5105050,0,'PLATFORM','BUTTON',5105040,'platform:finance:customer-account:export','导出客户账户',NULL,'POST',90,'ACTIVE',1,0),
(5105051,0,'PLATFORM','BUTTON',5105041,'platform:finance:customer-arap:export','导出客户应收应付',NULL,'POST',90,'ACTIVE',1,0),
(5105052,0,'PLATFORM','BUTTON',5105042,'platform:finance:customer-statement:export','导出客户对账单',NULL,'POST',90,'ACTIVE',1,0),
(5105053,0,'PLATFORM','BUTTON',5105043,'platform:finance:settlement-ar:export','导出应收结算单',NULL,'POST',90,'ACTIVE',1,0),
(5105054,0,'PLATFORM','BUTTON',5105044,'platform:finance:settlement-ap:export','导出应付结算单',NULL,'POST',90,'ACTIVE',1,0),
(5105055,0,'PLATFORM','BUTTON',5105045,'platform:finance:receivable-statistics:export','导出应收款统计表',NULL,'POST',90,'ACTIVE',1,0),
(5205012,10001,'MERCHANT','BUTTON',5205000,'merchant:finance:statement:confirm','确认客户对账单',NULL,'POST',30,'ACTIVE',1,0)
ON DUPLICATE KEY UPDATE
permission_type=VALUES(permission_type), parent_id=VALUES(parent_id),
permission_name=VALUES(permission_name), route_path=VALUES(route_path),
@@ -54,7 +62,12 @@ SELECT 0, r.id, p.id, CURRENT_TIMESTAMP(3)
AND p.permission_code IN (
'platform:finance:customer-account:list','platform:finance:customer-arap:list',
'platform:finance:customer-statement:list','platform:finance:settlement-ar:list',
'platform:finance:settlement-ap:list','platform:firstleg:inbound:measure:view',
'platform:finance:settlement-ap:list','platform:finance:customer-account:export',
'platform:finance:customer-arap:export','platform:finance:customer-statement:export',
'platform:finance:settlement-ar:export','platform:finance:settlement-ap:export',
'platform:finance:receivable-statistics:list','platform:finance:receivable-statistics:export',
'platform:download:list',
'platform:firstleg:inbound:measure:view',
'firstleg:inbound:measurement-review','platform:supplier:list',
'platform:supplier:create','platform:supplier:edit','platform:supplier:status',
'platform:domestic-container:list','platform:domestic-container:inbound:create',
@@ -74,7 +87,7 @@ UPDATE iam_permission p
UPDATE iam_permission p
JOIN (SELECT 'platform:finance:fee-source:review' code, 5105041 parent_id UNION ALL
SELECT 'platform:finance:fee-source:settlement', 5105041 UNION ALL
SELECT 'platform:finance:fee-source:edit', 5105041 UNION ALL
SELECT 'platform:finance:reconciliation:create', 5105042 UNION ALL
SELECT 'platform:finance:reconciliation:review', 5105042 UNION ALL
SELECT 'platform:finance:reconciliation:issue', 5105042 UNION ALL
@@ -86,3 +99,10 @@ UPDATE iam_permission p
ON mapping.code=p.permission_code
SET p.parent_id=mapping.parent_id
WHERE p.tenant_id=0 AND p.app_code='PLATFORM' AND p.permission_type='BUTTON';
INSERT IGNORE INTO iam_role_permission (tenant_id, role_id, permission_id, created_at)
SELECT 10001, r.id, p.id, CURRENT_TIMESTAMP(3)
FROM iam_role r
JOIN iam_permission p ON p.tenant_id=10001 AND p.app_code='MERCHANT'
WHERE r.tenant_id=10001 AND r.app_code='MERCHANT' AND r.role_code IN ('MERCHANT_OWNER','MERCHANT_ADMIN')
AND p.permission_code='merchant:finance:statement:confirm';
@@ -3,6 +3,14 @@
USE baiyue_iam;
SET NAMES utf8mb4;
DELETE rp FROM iam_role_permission rp
JOIN iam_permission p ON p.id=rp.permission_id AND p.tenant_id=rp.tenant_id
WHERE p.tenant_id=0 AND p.app_code='PLATFORM'
AND p.permission_code IN ('platform:finance:fee-source:settlement','platform:finance:bill:create','platform:finance:bill:issue');
DELETE FROM iam_permission
WHERE tenant_id=0 AND app_code='PLATFORM'
AND permission_code IN ('platform:finance:fee-source:settlement','platform:finance:bill:create','platform:finance:bill:issue');
DROP PROCEDURE IF EXISTS migrate_finance_g1_g2_permissions;
DELIMITER $$
CREATE PROCEDURE migrate_finance_g1_g2_permissions()
@@ -12,10 +20,10 @@ BEGIN
FROM iam_permission
WHERE (id = 5105000 AND permission_code <> 'platform:finance')
OR (id = 5105024 AND permission_code <> 'platform:finance:fee-source:review')
OR (id = 5105025 AND permission_code <> 'platform:finance:fee-source:settlement')
OR (id = 5105025 AND permission_code <> 'platform:finance:fee-source:edit')
OR (permission_code = 'platform:finance' AND id <> 5105000)
OR (permission_code = 'platform:finance:fee-source:review' AND id <> 5105024)
OR (permission_code = 'platform:finance:fee-source:settlement' AND id <> 5105025)
OR (permission_code = 'platform:finance:fee-source:edit' AND id <> 5105025)
OR (id IN (5105000, 5105024, 5105025)
AND (tenant_id <> 0 OR app_code <> 'PLATFORM'))
) THEN
@@ -31,8 +39,8 @@ BEGIN
'财务管理', '/finance', NULL, 60, 'ACTIVE', 1, 0),
(5105024, 0, 'PLATFORM', 'BUTTON', 5105000, 'platform:finance:fee-source:review',
'审核财务费用来源', NULL, 'POST', 150, 'ACTIVE', 1, 0),
(5105025, 0, 'PLATFORM', 'BUTTON', 5105000, 'platform:finance:fee-source:settlement',
'设置费用来源参与结算', NULL, 'PUT', 160, 'ACTIVE', 1, 0)
(5105025, 0, 'PLATFORM', 'BUTTON', 5105000, 'platform:finance:fee-source:edit',
'编辑财务费用来源', NULL, 'PUT', 160, 'ACTIVE', 1, 0)
ON DUPLICATE KEY UPDATE
permission_type = VALUES(permission_type), parent_id = VALUES(parent_id),
permission_name = VALUES(permission_name), route_path = VALUES(route_path),
@@ -55,7 +63,7 @@ BEGIN
AND deleted = 0
AND permission_code IN (
'platform:finance:fee-source:review',
'platform:finance:fee-source:settlement')) <> 2 THEN
'platform:finance:fee-source:edit')) <> 2 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'finance G1/G2 permission catalog is incomplete';
END IF;
+1 -1
View File
@@ -10,7 +10,7 @@ CREATE TABLE IF NOT EXISTS iam_tenant (
tenant_code VARCHAR(64) NOT NULL COMMENT '全局唯一客户编码',
tenant_name VARCHAR(128) NOT NULL COMMENT '客户企业名称',
tenant_type VARCHAR(20) NOT NULL DEFAULT 'MERCHANT' COMMENT '主体类型:MERCHANT企业客户',
status VARCHAR(20) NOT NULL DEFAULT 'PROFILE_REQUIRED' COMMENT '客户状态:PROFILE_REQUIRED待完善资料、PENDING待审核、ACTIVE正常、REJECTED已驳回、DISABLED已停用',
status VARCHAR(20) NOT NULL DEFAULT 'PROFILE_REQUIRED' COMMENT '客户状态:PROFILE_REQUIRED待完善资料、PENDING待审核、ACTIVE正常、REJECTED已驳回、DISABLED已停用、ARCHIVED已归档',
legal_name VARCHAR(128) NULL COMMENT '企业法定名称',
legal_representative VARCHAR(64) NULL COMMENT '法定代表人',
unified_social_credit_code VARCHAR(32) NULL COMMENT '统一社会信用代码',
@@ -38,6 +38,22 @@ ON DUPLICATE KEY UPDATE
contact_email = VALUES(contact_email), approved_at = COALESCE(approved_at, NOW(3)),
approved_by = VALUES(approved_by), deleted = 0;
-- The built-in IT customer must be immediately usable for order acceptance tests.
-- These approved metadata rows intentionally have no document URL: initialization must not
-- point at qualification files that do not exist in File service storage.
INSERT INTO iam_tenant_qualification (
id, tenant_id, qualification_type, certificate_no, document_url,
valid_from, valid_to, status, review_comment, deleted
) VALUES
(2100001, 10001, 'BUSINESS_LICENSE', '91310000ITTEST0001', NULL,
NULL, NULL, 'APPROVED', '开发测试初始化资质,无文件附件', 0),
(2100002, 10001, 'LEGAL_PERSON_ID', NULL, NULL,
NULL, NULL, 'APPROVED', '开发测试初始化资质,无文件附件', 0)
ON DUPLICATE KEY UPDATE
tenant_id = VALUES(tenant_id), qualification_type = VALUES(qualification_type),
certificate_no = VALUES(certificate_no), status = 'APPROVED',
review_comment = VALUES(review_comment), deleted = 0;
INSERT INTO iam_user (
id, auth_user_id, user_type, display_name, phone, email, status, deleted, version
) VALUES
+158 -10
View File
@@ -44,8 +44,8 @@ paths:
parameters:
- {name: page, in: query, required: false, schema: {type: integer, minimum: 1, default: 1}}
- {name: size, in: query, required: false, schema: {type: integer, minimum: 1, maximum: 200, default: 20}}
- {name: keyword, in: query, required: false, schema: {type: string}, description: 企业编码、名称、信用代码或联系人关键字}
- {name: status, in: query, required: false, schema: {type: string, enum: [PROFILE_REQUIRED, PENDING, ACTIVE, REJECTED, DISABLED]}}
- {name: keyword, in: query, required: false, schema: {type: string}, description: 客户名称关键字,不支持客户编号、信用代码或联系人搜索}
- {name: status, in: query, required: false, schema: {type: string, enum: [PROFILE_REQUIRED, PENDING, ACTIVE, REJECTED, DISABLED, ARCHIVED]}}
responses:
'200':
description: 企业客户分页查询成功
@@ -259,7 +259,11 @@ paths:
summary: List pending tenant reviews / 查询待审核企业
description: Return enterprise registrations waiting for a platform decision. / 返回等待平台处理的企业注册审核记录。
responses:
'200': {$ref: '#/components/responses/Success'}
'200':
description: 待审核企业及客户摘要查询成功
content:
application/json:
schema: {$ref: '#/components/schemas/PendingEnterpriseReviewListApiResponse'}
'403': {$ref: '#/components/responses/Forbidden'}
/api/platform/v1/iam/reviews/{id}/approve:
post:
@@ -498,7 +502,11 @@ paths:
tags: [Merchant Tenant / 商户企业]
summary: List enterprise members / 查询企业成员
responses:
'200': {$ref: '#/components/responses/Success'}
'200':
description: 企业成员列表,包含真实登录账号与最后登录时间
content:
application/json:
schema: {$ref: '#/components/schemas/MerchantMemberListApiResponse'}
'403': {$ref: '#/components/responses/Forbidden'}
post:
tags: [Merchant Tenant / 商户企业]
@@ -510,7 +518,11 @@ paths:
application/json:
schema: {$ref: '#/components/schemas/CreateMemberRequest'}
responses:
'200': {$ref: '#/components/responses/Success'}
'200':
description: 新增后的企业成员
content:
application/json:
schema: {$ref: '#/components/schemas/MerchantMemberApiResponse'}
'400': {$ref: '#/components/responses/BadRequest'}
'403': {$ref: '#/components/responses/Forbidden'}
'409': {$ref: '#/components/responses/Conflict'}
@@ -526,7 +538,11 @@ paths:
summary: 查询成员详情及当前角色
description: 返回当前客户成员资料,roleIds 为服务端实时查询的当前角色集合;跨客户成员按不存在处理。
responses:
'200': {$ref: '#/components/responses/Success'}
'200':
description: 企业成员详情
content:
application/json:
schema: {$ref: '#/components/schemas/MerchantMemberApiResponse'}
'403': {$ref: '#/components/responses/Forbidden'}
'404': {$ref: '#/components/responses/NotFound'}
put:
@@ -539,7 +555,11 @@ paths:
application/json:
schema: {$ref: '#/components/schemas/UpdateMemberRequest'}
responses:
'200': {$ref: '#/components/responses/Success'}
'200':
description: 更新后的企业成员
content:
application/json:
schema: {$ref: '#/components/schemas/MerchantMemberApiResponse'}
'403': {$ref: '#/components/responses/Forbidden'}
'404': {$ref: '#/components/responses/NotFound'}
'409': {$ref: '#/components/responses/Conflict'}
@@ -548,7 +568,11 @@ paths:
tags: [IAM Resources / IAM 资源]
summary: List tenant addresses / 查询企业地址
responses:
'200': {$ref: '#/components/responses/Success'}
'200':
description: 角色列表及各角色实时成员数
content:
application/json:
schema: {$ref: '#/components/schemas/RoleListApiResponse'}
'403': {$ref: '#/components/responses/Forbidden'}
post:
tags: [IAM Resources / IAM 资源]
@@ -559,7 +583,11 @@ paths:
application/json:
schema: {$ref: '#/components/schemas/AddressRequest'}
responses:
'200': {$ref: '#/components/responses/Success'}
'200':
description: 新增后的角色及实时成员数
content:
application/json:
schema: {$ref: '#/components/schemas/RoleApiResponse'}
'400': {$ref: '#/components/responses/BadRequest'}
'403': {$ref: '#/components/responses/Forbidden'}
/api/merchant/v1/iam/tenant/qualifications:
@@ -740,6 +768,39 @@ paths:
application/json:
schema: {$ref: '#/components/schemas/RequiredQualificationPackageApiResponse'}
'403': {$ref: '#/components/responses/Forbidden'}
/internal/iam/finance-customers:
get:
tags: [IAM Resources / IAM 资源]
summary: 提供财务客户主数据摘要
description: 仅供 Finance Service 调用;只返回正常/停用客户及财务账户所需的客户编号、名称和联系方式,不依赖财务表是否已有记录。
security: []
parameters:
- {$ref: '#/components/parameters/InternalServiceToken'}
- {name: page, in: query, required: false, schema: {type: integer, minimum: 1, default: 1}}
- {name: size, in: query, required: false, schema: {type: integer, minimum: 1, maximum: 200, default: 20}}
- {name: keyword, in: query, required: false, schema: {type: string}}
- {name: status, in: query, required: false, schema: {type: string, enum: [ACTIVE, DISABLED]}}
- {name: customerId, in: query, required: false, schema: {type: integer, format: int64, minimum: 1}}
responses:
'200':
description: 财务客户主数据分页摘要
content:
application/json:
schema:
allOf:
- {$ref: '#/components/schemas/ApiResponse'}
- type: object
properties:
data:
type: object
required: [records, page, size, total, pages]
properties:
records: {type: array, items: {$ref: '#/components/schemas/FinanceCustomerSummary'}}
page: {type: integer}
size: {type: integer}
total: {type: integer, format: int64}
pages: {type: integer}
'403': {$ref: '#/components/responses/Forbidden'}
/internal/exports/v1/CUSTOMER_LIST/batches:
post:
tags: [Internal Export Provider]
@@ -850,6 +911,60 @@ components:
type: array
uniqueItems: true
items: {type: string}
MerchantMemberResponse:
type: object
required: [membershipId, userId, authUserId, username, displayName, memberType, status, lastLoginAt, roleIds]
properties:
membershipId: {type: string, pattern: '^\d+$'}
userId: {type: string, pattern: '^\d+$'}
authUserId: {type: string, pattern: '^\d+$'}
username: {type: string, description: 统一认证登录账号}
displayName: {type: string}
phone: {type: string, nullable: true}
email: {type: string, format: email, nullable: true}
memberType: {type: string, enum: [OWNER, EMPLOYEE]}
memberNo: {type: string, nullable: true, description: 企业内部成员编号,不作为登录账号}
status: {type: string, enum: [ACTIVE, DISABLED]}
lastLoginAt: {type: string, format: date-time, nullable: true, description: 从 Auth 账号事实返回;null 表示从未登录}
roleIds: {type: array, items: {type: string, pattern: '^\d+$'}}
MerchantMemberListApiResponse:
allOf:
- {$ref: '#/components/schemas/ApiResponse'}
- type: object
properties:
data: {type: array, items: {$ref: '#/components/schemas/MerchantMemberResponse'}}
MerchantMemberApiResponse:
allOf:
- {$ref: '#/components/schemas/ApiResponse'}
- type: object
properties:
data: {$ref: '#/components/schemas/MerchantMemberResponse'}
RoleResponse:
type: object
required: [id, tenantId, appCode, roleCode, roleName, roleType, status, memberCount, permissionIds]
properties:
id: {type: string, pattern: '^\d+$'}
tenantId: {type: string, pattern: '^\d+$'}
appCode: {type: string, enum: [PLATFORM, MERCHANT]}
roleCode: {type: string}
roleName: {type: string}
roleType: {type: string, enum: [SYSTEM, CUSTOM]}
status: {type: string, enum: [ACTIVE, DISABLED]}
description: {type: string, nullable: true}
memberCount: {type: integer, format: int64, minimum: 0, description: 当前客户及应用域内分配该角色的成员数}
permissionIds: {type: array, uniqueItems: true, items: {type: string, pattern: '^\d+$'}}
RoleListApiResponse:
allOf:
- {$ref: '#/components/schemas/ApiResponse'}
- type: object
properties:
data: {type: array, items: {$ref: '#/components/schemas/RoleResponse'}}
RoleApiResponse:
allOf:
- {$ref: '#/components/schemas/ApiResponse'}
- type: object
properties:
data: {$ref: '#/components/schemas/RoleResponse'}
TenantPageApiResponse:
allOf:
- {$ref: '#/components/schemas/ApiResponse'}
@@ -870,6 +985,29 @@ components:
- type: object
properties:
data: {$ref: '#/components/schemas/TenantApprovalResponse'}
PendingEnterpriseReviewListApiResponse:
allOf:
- {$ref: '#/components/schemas/ApiResponse'}
- type: object
properties:
data:
type: array
items: {$ref: '#/components/schemas/PendingEnterpriseReviewResponse'}
PendingEnterpriseReviewResponse:
type: object
required: [id, tenantId, reviewType, status, tenantName, tenantCode, contactName, submittedAt]
properties:
id: {type: string, pattern: '^\d+$', description: 审核单 ID}
tenantId: {type: string, pattern: '^\d+$', description: 客户 ID}
reviewType: {type: string, example: REGISTER}
status: {type: string, enum: [PENDING]}
tenantName: {type: string, description: 客户名称}
tenantCode: {type: string, description: 客户编号}
contactName: {type: string, description: 联系人}
contactPhone: {type: string, nullable: true, description: 联系电话}
contactEmail: {type: string, format: email, nullable: true, description: 联系邮箱}
submittedAt: {type: string, format: date-time, description: 提交审核时间}
reviewComment: {type: string, nullable: true, description: 审核意见}
TenantCreationApiResponse:
allOf:
- {$ref: '#/components/schemas/ApiResponse'}
@@ -952,7 +1090,7 @@ components:
id: {type: string, pattern: '^\d+$', example: '190000000000000001'}
tenantCode: {type: string}
tenantName: {type: string}
status: {type: string, enum: [PROFILE_REQUIRED, PENDING, ACTIVE, REJECTED, DISABLED]}
status: {type: string, enum: [PROFILE_REQUIRED, PENDING, ACTIVE, REJECTED, DISABLED, ARCHIVED]}
legalName: {type: string}
legalRepresentative: {type: string, maxLength: 64}
unifiedSocialCreditCode: {type: string}
@@ -971,6 +1109,16 @@ components:
internalRemark: {type: string, maxLength: 1000, description: 仅平台端可见}
createdAt: {type: string, format: date-time, description: 入驻时间}
approvedAt: {type: string, format: date-time, description: 审批通过时间}
FinanceCustomerSummary:
type: object
required: [id, tenantCode, tenantName, status]
properties:
id: {type: string, pattern: '^\d+$'}
tenantCode: {type: string}
tenantName: {type: string}
status: {type: string, enum: [ACTIVE, DISABLED]}
contactName: {type: string, nullable: true}
contactPhone: {type: string, nullable: true}
TenantAddressListApiResponse:
allOf:
- {$ref: '#/components/schemas/ApiResponse'}
@@ -50,7 +50,7 @@ paths:
tags: [Platform notification administration]
summary: Create an IN_APP notification task
requestBody: {$ref: '#/components/requestBodies/CreateNotification'}
responses: {'200': {$ref: '#/components/responses/TaskDetail'}}
responses: {'200': {$ref: '#/components/responses/TaskItem'}}
/platform/v1/notification-templates:
get:
tags: [Platform notification administration]
@@ -95,18 +95,26 @@ paths:
- {name: title, in: query, description: Fuzzy match rendered title, schema: {type: string, maxLength: 128}}
- {name: status, in: query, schema: {type: string, enum: [CREATED, SCHEDULED, DISPATCHING, RETRYING, SENT, DEAD, CANCELLED]}}
responses: {'200': {$ref: '#/components/responses/TaskPage'}}
/platform/v1/notification-tasks/{id}:
get:
tags: [Platform notification administration]
summary: Get notification task delivery details
description: Uses the task list permission and exposes bounded operational evidence without message body content.
parameters: [{$ref: '#/components/parameters/IdPath'}]
responses: {'200': {$ref: '#/components/responses/TaskDetail'}}
/platform/v1/notification-tasks/{id}/cancel:
put:
tags: [Platform notification administration]
summary: Cancel a CREATED or SCHEDULED task
parameters: [{$ref: '#/components/parameters/IdPath'}]
responses: {'200': {$ref: '#/components/responses/TaskDetail'}}
responses: {'200': {$ref: '#/components/responses/TaskItem'}}
/platform/v1/notification-tasks/{id}/retry:
put:
tags: [Platform notification administration]
summary: Retry a RETRYING or DEAD task
summary: Requeue a RETRYING or DEAD task
description: Resets the current delivery-attempt counter and returns the task in RETRYING; scheduler delivery starts after the retry delay.
parameters: [{$ref: '#/components/parameters/IdPath'}]
responses: {'200': {$ref: '#/components/responses/TaskDetail'}}
responses: {'200': {$ref: '#/components/responses/TaskItem'}}
components:
parameters:
AppPath: {name: app, in: path, required: true, schema: {type: string, enum: [platform, merchant]}}
@@ -126,6 +134,7 @@ components:
TemplatePage: {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/TemplatePageResponse'}}}}
TemplateDetail: {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/TemplateDetailResponse'}}}}
TaskPage: {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/TaskPageResponse'}}}}
TaskItem: {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/TaskItemResponse'}}}}
TaskDetail: {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/TaskDetailResponse'}}}}
schemas:
CreateNotificationRequest:
@@ -159,10 +168,12 @@ components:
type: object
required: [targetStatus, version]
properties: {targetStatus: {type: string, enum: [ACTIVE, DISABLED], description: ACTIVE is accepted only from DRAFT; DISABLED only from ACTIVE.}, version: {type: integer, minimum: 1}}
InboxItem: {type: object, required: [id, category, title, status, sentAt], properties: {id: {type: integer, format: int64}, category: {type: string}, title: {type: string}, status: {type: string, enum: [UNREAD, READ]}, sentAt: {type: string, format: date-time}, readAt: {type: string, format: date-time, nullable: true}}}
InboxItem: {type: object, required: [id, category, title, summary, status, sentAt], properties: {id: {type: integer, format: int64}, category: {type: string}, title: {type: string}, summary: {type: string, maxLength: 120, description: Whitespace-compacted body preview limited to 120 Unicode code points; never contains the full body unless the body itself fits.}, status: {type: string, enum: [UNREAD, READ]}, sentAt: {type: string, format: date-time}, readAt: {type: string, format: date-time, nullable: true}}}
InboxDetail: {allOf: [{$ref: '#/components/schemas/InboxItem'}, {type: object, required: [body], properties: {body: {type: string}, sourceType: {type: string, nullable: true}, sourceId: {type: string, nullable: true}}}]}
TemplateItem: {type: object, required: [id, templateCode, templateName, category, channel, titleTemplate, bodyTemplate, variableWhitelist, status, version], properties: {id: {type: integer, format: int64}, templateCode: {type: string}, templateName: {type: string}, category: {type: string}, channel: {type: string, enum: [IN_APP]}, titleTemplate: {type: string}, bodyTemplate: {type: string}, variableWhitelist: {type: array, items: {type: string}}, status: {type: string, enum: [DRAFT, ACTIVE, DISABLED]}, version: {type: integer}}}
TaskItem: {type: object, required: [id, taskNo, category, title, status, recipientCount, duplicated], properties: {id: {type: integer, format: int64}, taskNo: {type: string}, category: {type: string}, title: {type: string}, status: {type: string, enum: [CREATED, SCHEDULED, DISPATCHING, RETRYING, SENT, DEAD, CANCELLED]}, recipientCount: {type: integer}, scheduledAt: {type: string, format: date-time, nullable: true}, sentAt: {type: string, format: date-time, nullable: true}, duplicated: {type: boolean}}}
TaskRecipientItem: {type: object, required: [id, displayName, appCode, status], properties: {id: {type: integer, format: int64}, displayName: {type: string}, appCode: {type: string}, status: {type: string}, failureReason: {type: string, nullable: true}, deliveredAt: {type: string, format: date-time, nullable: true}}}
TaskDetail: {type: object, required: [id, taskNo, category, title, status, recipientCount, attemptCount, recipients], properties: {id: {type: integer, format: int64}, taskNo: {type: string}, category: {type: string}, title: {type: string}, status: {type: string, enum: [CREATED, SCHEDULED, DISPATCHING, RETRYING, SENT, DEAD, CANCELLED]}, recipientCount: {type: integer}, attemptCount: {type: integer, minimum: 0, maximum: 3, description: Number of started delivery attempts in the current automatic retry cycle.}, scheduledAt: {type: string, format: date-time, nullable: true}, sentAt: {type: string, format: date-time, nullable: true}, lastError: {type: string, nullable: true}, recipients: {type: array, items: {$ref: '#/components/schemas/TaskRecipientItem'}}}}
InboxPageData: {type: object, required: [records, page, size, total, pages], properties: {records: {type: array, items: {$ref: '#/components/schemas/InboxItem'}}, page: {type: integer}, size: {type: integer}, total: {type: integer}, pages: {type: integer}}}
TemplatePageData: {type: object, required: [records, page, size, total, pages], properties: {records: {type: array, items: {$ref: '#/components/schemas/TemplateItem'}}, page: {type: integer}, size: {type: integer}, total: {type: integer}, pages: {type: integer}}}
TaskPageData: {type: object, required: [records, page, size, total, pages], properties: {records: {type: array, items: {$ref: '#/components/schemas/TaskItem'}}, page: {type: integer}, size: {type: integer}, total: {type: integer}, pages: {type: integer}}}
@@ -173,4 +184,5 @@ components:
TemplatePageResponse: {type: object, required: [code, data], properties: {code: {type: string, example: '200'}, data: {$ref: '#/components/schemas/TemplatePageData'}}}
TemplateDetailResponse: {type: object, required: [code, data], properties: {code: {type: string, example: '200'}, data: {$ref: '#/components/schemas/TemplateItem'}}}
TaskPageResponse: {type: object, required: [code, data], properties: {code: {type: string, example: '200'}, data: {$ref: '#/components/schemas/TaskPageData'}}}
TaskDetailResponse: {type: object, required: [code, data], properties: {code: {type: string, example: '200'}, data: {$ref: '#/components/schemas/TaskItem'}}}
TaskItemResponse: {type: object, required: [code, data], properties: {code: {type: string, example: '200'}, data: {$ref: '#/components/schemas/TaskItem'}}}
TaskDetailResponse: {type: object, required: [code, data], properties: {code: {type: string, example: '200'}, data: {$ref: '#/components/schemas/TaskDetail'}}}