hookehuyr

fix(plan): 修正 coverage 与 annual_premium 字段映射错误

修复 coverage 字段错误映射到 annual_premium API 字段的问题,
新增独立的 annual_premium 字段定义,同步更新 API 文档。

- coverage 现正确映射到 coverage API 字段(保额)
- annual_premium 独立映射到 annual_premium API 字段(年缴保费)
- 更新 API 文档补充 coverage 参数和完整请求示例

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
......@@ -569,7 +569,7 @@ GET /api/plan/config/:form_sn
},
"submit_mapping": {
"customer_name": { "api_field": "customer_name" },
"coverage": { "api_field": "annual_premium", "transform": "fen_to_yuan" }
"annual_premium": { "api_field": "annual_premium", "transform": "fen_to_yuan" }
// ... 更多映射
}
}
......@@ -676,7 +676,7 @@ CREATE TABLE product_configs (
},
"submit_mapping": {
"customer_name": { "api_field": "customer_name" },
"coverage": { "api_field": "annual_premium", "transform": "fen_to_yuan" }
"annual_premium": { "api_field": "annual_premium", "transform": "fen_to_yuan" }
}
}
```
......
......@@ -616,7 +616,7 @@
"submit_mapping": {
"customer_name": { "api_field": "customer_name" },
"gender": { "api_field": "customer_gender" },
"coverage": { "api_field": "annual_premium", "transform": "fen_to_yuan" },
"annual_premium": { "api_field": "annual_premium", "transform": "fen_to_yuan" },
"payment_period": { "api_field": "payment_years" },
"withdrawal_enabled": { "api_field": "allow_reduce_amount" },
"withdrawal_mode": { "api_field": "withdrawal_option" },
......
......@@ -79,7 +79,7 @@ const reset_map = {
```javascript
// submit_mapping 示例(金额字段统一从分转元)
const submit_mapping = {
coverage: { api_field: 'annual_premium', transform: 'fen_to_yuan' },
annual_premium: { api_field: 'annual_premium', transform: 'fen_to_yuan' },
annual_withdrawal_amount: { api_field: 'annual_withdrawal_amount', transform: 'fen_to_yuan' },
withdrawal_mode: { api_field: 'withdrawal_option' }
}
......@@ -101,7 +101,7 @@ const submit_mapping = {
withdrawal_modes: ['年龄指定金额', '最高固定金额'],
withdrawal_periods: ['1年', '3年', '5年', '10年'],
form_schema: { base_fields: [], withdrawal_fields: [], reset_map: {} },
submit_mapping: { coverage: { api_field: 'annual_premium', transform: 'fen_to_yuan' } },
submit_mapping: { annual_premium: { api_field: 'annual_premium', transform: 'fen_to_yuan' } },
source_file: '产品说明书.pdf',
warnings: []
}
......
......@@ -52,15 +52,12 @@ paths:
customer_age:
type: integer
title: 年龄
description: 与 customer_birthday 二选一,至少提供一个
customer_birthday:
type: string
title: 出生年月日
format: date
description: 与 customer_age 二选一,至少提供一个。格式:YYYY-MM-DD
annual_premium:
type: integer
title: 保额
title: 年缴保费
payment_years:
type: string
title: 繳費年期
......@@ -94,12 +91,14 @@ paths:
annual_increase_percentage:
type: integer
title: 每年递增提取百分比
coverage:
type: string
title: 保额
required:
- customer_name
- customer_gender
# 年龄与出生年月日二选一(至少提供一个)
# - customer_age
# - customer_birthday
- customer_age
- customer_birthday
- annual_premium
- payment_years
- currency_type
......@@ -112,12 +111,14 @@ paths:
- product_id
- annual_increase_percentage
- annual_withdrawal_amount
- coverage
x-apifox-orders:
- customer_name
- customer_gender
- customer_age
- annual_premium
- payment_years
- coverage
- currency_type
- product_id
- customer_birthday
......@@ -129,7 +130,23 @@ paths:
- total_premium
- annual_withdrawal_amount
- annual_increase_percentage
example: "{\r\n customer_name: '张三',\r\n customer_gender: 'male',\r\n customer_age: 30,\r\n annual_premium: 5000,\r\n payment_years: '10年',\r\n currency_type: 'CNY',\r\n product_id: 1\r\n }"
example:
customer_name: 张三
customer_gender:
customer_age: 30
annual_premium: 5000
payment_years: 10年
currency_type: CNY
product_id: 3151974
customer_birthday: '2025-03-21'
allow_reduce_amount:
withdrawal_option: 指定提取金额
withdrawal_start_age: 60
withdrawal_period: 10
smoking_status:
total_premium: 0
annual_withdrawal_amount: 6
annual_increase_percentage: 33
responses:
'200':
description: ''
......@@ -169,15 +186,13 @@ paths:
x-apifox-ordering: 0
security: []
x-apifox-folder: 计划书
x-apifox-status: developing
x-apifox-status: released
x-run-in-apifox: https://app.apifox.com/web/project/7792797/apis/api-417310981-run
components:
schemas: {}
responses: {}
securitySchemes: {}
servers:
- url: https://manulife.onwall.cn
description: 正式环境
servers: []
security: []
```\
```
......
......@@ -13,9 +13,9 @@ const Api = {
* @param {Object} params 请求参数
* @param {string} params.customer_name 申请人
* @param {string} params.customer_gender 性别
* @param {integer} params.customer_age (可选) 与 customer_birthday 二选一,至少提供一个
* @param {string} params.customer_birthday (可选) 与 customer_age 二选一,至少提供一个。格式:YYYY-MM-DD
* @param {integer} params.annual_premium 保额
* @param {integer} params.customer_age 年龄
* @param {string} params.customer_birthday 出生年月日
* @param {integer} params.annual_premium 年缴保费
* @param {string} params.payment_years 繳費年期
* @param {string} params.currency_type 币种
* @param {string} params.allow_reduce_amount 是否容许减少名义金额
......@@ -27,6 +27,7 @@ const Api = {
* @param {integer} params.product_id 产品id
* @param {integer} params.annual_withdrawal_amount 每年提取金额
* @param {integer} params.annual_increase_percentage 每年递增提取百分比
* @param {string} params.coverage 保额
* @returns {Promise<{
* code: number; // 状态码
* msg: string; // 消息
......
......@@ -277,7 +277,8 @@ const submit = async () => {
gender: { api_field: 'customer_gender' },
birthday: { api_field: 'customer_birthday' },
smoker: { api_field: 'smoking_status' },
coverage: { api_field: 'annual_premium', transform: 'fen_to_yuan' },
coverage: { api_field: 'coverage', transform: 'fen_to_yuan' },
annual_premium: { api_field: 'annual_premium', transform: 'fen_to_yuan' },
payment_period: { api_field: 'payment_years' },
withdrawal_enabled: { api_field: 'allow_reduce_amount' },
withdrawal_mode: { api_field: 'withdrawal_option' },
......
import { describe, expect, it } from 'vitest'
import { PLAN_TEMPLATES } from '../plan-templates'
import { PLAN_FIELD_DEFINITIONS } from '../plan-fields'
describe('plan template amount field mapping', () => {
it('should map protection coverage to coverage api field', () => {
expect(PLAN_TEMPLATES['life-insurance-wiop3e'].config.submit_mapping.coverage).toEqual({
api_field: 'coverage',
transform: 'fen_to_yuan'
})
})
it('should use annual_premium field for savings schema and submit mapping', () => {
const savingsConfig = PLAN_TEMPLATES['savings-gs'].config
const annualPremiumField = savingsConfig.form_schema.base_fields.find(field => field.key === 'annual_premium')
expect(annualPremiumField).toMatchObject({
key: 'annual_premium',
label: '年缴保费',
type: 'amount'
})
expect(savingsConfig.submit_mapping.annual_premium).toEqual({
api_field: 'annual_premium',
transform: 'fen_to_yuan'
})
expect(savingsConfig.submit_mapping.coverage).toBeUndefined()
})
})
describe('plan field definitions amount semantics', () => {
it('should expose separate coverage and annual_premium definitions', () => {
expect(PLAN_FIELD_DEFINITIONS.coverage).toMatchObject({
label: '保额',
api_field: 'coverage',
transform: 'fen_to_yuan'
})
expect(PLAN_FIELD_DEFINITIONS.annual_premium).toMatchObject({
label: '年缴保费',
api_field: 'annual_premium',
transform: 'fen_to_yuan'
})
})
})
......@@ -51,6 +51,7 @@ export const TRANSFORM_TYPES = {
* @property {Object} birthday - 出生日期
* @property {Object} smoker - 是否吸烟
* @property {Object} coverage - 保额
* @property {Object} annual_premium - 年缴保费
* @property {Object} payment_period - 缴费年期
* @property {Object} withdrawal_enabled - 是否启用提取
* @property {Object} withdrawal_mode - 提取模式
......@@ -126,13 +127,13 @@ export const PLAN_FIELD_DEFINITIONS = {
},
/**
* 保额(年缴)
* 保额
*/
coverage: {
label: '保额',
type: FIELD_TYPES.AMOUNT,
required: true,
api_field: 'annual_premium',
api_field: 'coverage',
transform: TRANSFORM_TYPES.FEN_TO_YUAN,
component: 'PlanFieldAmount',
group: FIELD_GROUPS.COVERAGE,
......@@ -145,6 +146,25 @@ export const PLAN_FIELD_DEFINITIONS = {
},
/**
* 年缴保费
*/
annual_premium: {
label: '年缴保费',
type: FIELD_TYPES.AMOUNT,
required: true,
api_field: 'annual_premium',
transform: TRANSFORM_TYPES.FEN_TO_YUAN,
component: 'PlanFieldAmount',
group: FIELD_GROUPS.COVERAGE,
placeholder: '请输入年缴保费',
validation: {
required: (value) => value > 0,
min: (value, config) => value >= (config?.min_coverage || 1000),
max: (value, config) => value <= (config?.max_coverage || 10000000)
}
},
/**
* 缴费年期
*/
payment_period: {
......
......@@ -43,7 +43,7 @@ const baseSubmitMapping = {
age: { api_field: 'customer_age' },
birthday: { api_field: 'customer_birthday' },
smoker: { api_field: 'smoking_status' },
coverage: { api_field: 'annual_premium', transform: 'fen_to_yuan' },
coverage: { api_field: 'coverage', transform: 'fen_to_yuan' },
payment_period: { api_field: 'payment_years' },
total_amount: { api_field: 'total_premium', transform: 'fen_to_yuan' }
}
......@@ -70,7 +70,7 @@ const savingsSubmitMapping = {
age: { api_field: 'customer_age' },
birthday: { api_field: 'customer_birthday' },
// smoker: { api_field: 'smoking_status' }, // 储蓄类产品不需要吸烟字段
coverage: { api_field: 'annual_premium', transform: 'fen_to_yuan' },
annual_premium: { api_field: 'annual_premium', transform: 'fen_to_yuan' },
payment_period: { api_field: 'payment_years' },
total_amount: { api_field: 'total_premium', transform: 'fen_to_yuan' },
withdrawal_enabled: { api_field: 'allow_reduce_amount' },
......@@ -97,7 +97,7 @@ const savingsFormSchema = {
// 年龄与出生年月日二选一填写
{ id: 'age', key: 'age', type: 'age', label: '年龄', placeholder: '请输入年龄', input_label: '岁', required: false },
{ id: 'birthday', key: 'birthday', type: 'date', label: '出生年月日', placeholder: '请选择年月日', required: false },
{ id: 'coverage', key: 'coverage', type: 'amount', label: '年缴保费', placeholder: '请输入年缴保费', input_label: '请输入年缴保费金额', required: true, currency_from: 'currency' },
{ id: 'annual_premium', key: 'annual_premium', type: 'amount', label: '年缴保费', placeholder: '请输入年缴保费', input_label: '请输入年缴保费金额', required: true, currency_from: 'currency' },
{ id: 'payment_period', key: 'payment_period', type: 'payment_period', label: '缴费年期', required: true, options_from: 'payment_periods' }
],
// 提取计划字段:由 withdrawal_plan 开关控制
......