|
|
преди 6 дни | |
|---|---|---|
| .mvn | преди 1 месец | |
| src | преди 6 дни | |
| .gitignore | преди 1 месец | |
| DATA-DICTIONARY-API.md | преди 6 дни | |
| ERP-YIDA-PUSH-API.md | преди 4 седмици | |
| README.md | преди 6 дни | |
| SKILL.md | преди 1 месец | |
| pom.xml | преди 2 седмици |
明磊业务集成服务。项目基于 Spring Boot 2.7 构建,用于对接钉钉、宜搭、员工花名册以及明磊外部 T100 接口。
本文档说明当前工程的模块边界、配置项、REST 接口、ERP 推送规则和本地构建方式。文档中的凭证均使用占位符,真实密钥必须通过环境变量或部署配置注入。
| 技术 | 说明 |
|---|---|
| Java | JDK 8 |
| Spring Boot | 2.7.18 |
| Spring MVC | REST Controller、参数绑定、异常处理 |
| Spring Validation | 请求参数校验 |
| Maven | 构建和依赖管理 |
com.malk:mjava |
钉钉、宜搭客户端和基础模型,当前版本 0.0.3 |
| Jackson / Fastjson | JSON 绑定、序列化和表单字段组装 |
| RestTemplate | 调用外部 T100 HTTP 接口 |
| Logback + SLF4J | 应用日志、错误日志和请求响应日志 |
| JUnit 5 + Mockito | 单元测试 |
src/main/java/com/malk/minglei
|-- MjavaMingleiApplication.java
|-- config
| |-- DingTalkRosterConfiguration.java
| |-- EmployeeRosterConfiguration.java
| |-- EmployeeRosterProperties.java
| |-- HttpRequestResponseLoggingFilter.java
| |-- MingleiPortConfiguration.java
| |-- MingleiPortProperties.java
| |-- MjavaYidaConfiguration.java
| `-- YidaApplicationsProperties.java
|-- controller
| |-- ApprovalTransferDepartmentController.java
| |-- EmployeeRosterController.java
| |-- ErpYidaPushController.java
| |-- GlobalExceptionHandler.java
| |-- MingleiPortController.java
| `-- YidaProcessController.java
|-- dto
`-- service
|-- approval
|-- employee
|-- port
|-- yida
`-- impl
|-- approval
|-- employee
|-- port
`-- yida
| 层级 | 职责 |
|---|---|
controller |
暴露 HTTP 接口,处理请求校验和响应包装 |
dto |
请求体、响应体和业务数据模型 |
service.approval |
钉钉审批实例查询、表单解析,以及通过宜搭审批矩阵(按"部门"字段匹配)解析转入部门各级别负责人与部门负责人 |
service.employee |
员工花名册同步、查询和钉钉人员数据处理 |
service.port |
明磊外部 T100 接口转发 |
service.yida |
宜搭流程、宜搭表单查询、ERP 推送分发 |
service.impl.* |
各业务实现、处理器和内部辅助类 |
新增能力时优先放入现有业务域。只有出现清晰的新业务边界、独立生命周期或独立外部依赖时,才新增新的 Service 分类。
配置文件位于 src/main/resources/application.yml。生产环境不要使用文件中的默认示例值,应通过环境变量覆盖。
| 配置项 | 环境变量 | 用途 |
|---|---|---|
server.port |
SERVER_PORT |
HTTP 服务端口 |
spring.profiles.active |
SPRING_PROFILES_ACTIVE |
Spring Profile |
dingtalk.agent-id |
DINGTALK_AGENT_ID |
钉钉应用 AgentId |
dingtalk.app-key |
DINGTALK_APP_KEY |
钉钉应用 Key |
dingtalk.app-secret |
DINGTALK_APP_SECRET |
钉钉应用 Secret |
minglei.yida.coordination-office.app-type |
YIDA_COORDINATION_OFFICE_APP_TYPE |
协同办公宜搭应用编码 |
minglei.yida.coordination-office.system-token |
YIDA_COORDINATION_OFFICE_SYSTEM_TOKEN |
协同办公宜搭应用 System Token |
minglei.yida.coordination-office.process-instance-query-user-id |
YIDA_COORDINATION_OFFICE_PROCESS_INSTANCE_QUERY_USER_ID |
查询宜搭流程实例时用于数据权限校验的钉钉用户 ID,默认 41603502201288023 |
minglei.yida.master-data.app-type |
YIDA_MASTER_DATA_APP_TYPE |
主数据宜搭应用编码 |
minglei.yida.master-data.system-token |
YIDA_MASTER_DATA_SYSTEM_TOKEN |
主数据宜搭应用 System Token |
minglei.port.supplier-price-approval-url |
MINGLEI_SUPPLIER_PRICE_APPROVAL_URL |
外部 T100 接口地址 |
minglei.port.supplier-price-approval-key |
MINGLEI_SUPPLIER_PRICE_APPROVAL_KEY |
外部 T100 接口接入密钥 |
minglei.banking.base-url |
MINGLEI_BANKING_BASE_URL |
银企全部接口地址,默认正式环境 https://open.nexbankapi.com |
minglei.banking.app-id |
MINGLEI_BANKING_APP_ID |
NexBank 应用标识 |
minglei.banking.app-secret |
MINGLEI_BANKING_APP_SECRET |
NexBank API Key |
minglei.banking.customer-code |
MINGLEI_BANKING_CUSTOMER_CODE |
NexBank 客户编号 |
minglei.banking.default-from-account-no |
MINGLEI_BANKING_DEFAULT_FROM_ACCOUNT_NO |
默认付款账号;支付请求未传 fromAccountNo 时使用 |
minglei.banking.default-from-account-name |
MINGLEI_BANKING_DEFAULT_FROM_ACCOUNT_NAME |
默认付款账户名称;支付请求未传 fromAccountName 时使用 |
minglei.banking.intra-bank-name |
MINGLEI_BANKING_INTRA_BANK_NAME |
本行名称;匹配收款银行时自动发送 crossBank=0 |
minglei.banking.payment-encryption-enabled |
MINGLEI_BANKING_PAYMENT_ENCRYPTION_ENABLED |
单笔支付是否启用 SM2/SM4 加密,默认 true |
minglei.banking.xencio-public-key |
MINGLEI_BANKING_XENCIO_PUBLIC_KEY |
NexBank 的 SM2 十六进制公钥,仅支付制单需要 |
minglei.banking.enterprise-private-key |
MINGLEI_BANKING_ENTERPRISE_PRIVATE_KEY |
企业 SM2 十六进制私钥,仅支付制单需要 |
minglei.banking.pending-payment.table-name |
MINGLEI_BANKING_PENDING_PAYMENT_TABLE_NAME |
异步支付状态补偿表名,默认 banking_payment_tracking |
minglei.banking.pending-payment.schedule-fixed-delay-millis |
MINGLEI_BANKING_PENDING_PAYMENT_SCHEDULE_FIXED_DELAY_MILLIS |
支付状态补偿间隔,默认 300000 毫秒(5 分钟) |
minglei.employee-roster.datasource.url |
MINGLEI_EMPLOYEE_ROSTER_DATASOURCE_URL |
员工花名册 MySQL JDBC 地址 |
minglei.employee-roster.datasource.username |
MINGLEI_EMPLOYEE_ROSTER_DATASOURCE_USERNAME |
员工花名册数据库用户名 |
minglei.employee-roster.datasource.password |
MINGLEI_EMPLOYEE_ROSTER_DATASOURCE_PASSWORD |
员工花名册数据库密码 |
minglei.employee-roster.datasource.driver-class-name |
MINGLEI_EMPLOYEE_ROSTER_DATASOURCE_DRIVER_CLASS_NAME |
JDBC 驱动类 |
minglei.dictionary.datasource.url |
MINGLEI_DICTIONARY_DATASOURCE_URL |
数据字典 Oracle JDBC 地址 |
minglei.dictionary.datasource.username |
MINGLEI_DICTIONARY_DATASOURCE_USERNAME |
数据字典 Oracle 用户名 |
minglei.dictionary.datasource.password |
MINGLEI_DICTIONARY_DATASOURCE_PASSWORD |
数据字典 Oracle 密码 |
minglei.dictionary.datasource.driver-class-name |
MINGLEI_DICTIONARY_DATASOURCE_DRIVER_CLASS_NAME |
Oracle JDBC 驱动类,默认 oracle.jdbc.OracleDriver |
logging.file.path |
LOGGING_FILE_PATH |
日志输出目录 |
MjavaYidaConfiguration 注册两套宜搭客户端:
先在花名册数据源所连接的数据库执行 banking_payment_tracking.sql 创建表。制单成功后会根据
businessTransNo 写入待处理记录;定时任务每 5 分钟查询 PENDING 记录。状态为 X0000
时下载回单并记录预览链接和下载链接;回单尚未生成时记录为 RECEIPT_PENDING,
后续任务只重试下载回单。
支付请求可额外传入 formID 和 formInstanceId,它们只保存到跟踪表用于后续宜搭回写,
不会传给银企接口。状态回写字段为 selectField_mvq9jruo,说明字段为
textField_mvq9jrup,回单附件字段为 attachmentField_mvq9jruq。
付款申请表单 FORM-5EF5C90019AE4E5AA1AFB3FC6572A7E63KRY 使用以下回写字段:
付款状态 selectField_mvrimme0、详细说明 textField_mvrimmdx、回单附件
attachmentField_mvrimmdz。服务端会根据请求中的 formID 自动选择对应字段。
费用报销表单 FORM-9785C335A34449B3B806DAF63B6C5AB7PRH1 使用以下回写字段:
付款状态 selectField_mvrj87p7、详细说明 textField_mvrj87p8、回单附件
attachmentField_mvrj87p9。服务端会根据请求中的 formID 自动选择对应字段。
| 银企状态码 | 宜搭付款状态 | 处理方式 |
|---|---|---|
X0000 |
付款成功 | 下载回单并回写回单附件,结束补偿 |
X5555、X5556 |
待付款 | 保持定时查询 |
X5554、X9997、X9999 |
付款失败 | 回写说明并停止定时查询 |
| Bean | 用途 |
|---|---|
coordinationOfficeYidaClient |
协同办公应用,主要用于发起流程 |
masterDataYidaClient |
主数据应用,主要用于查询主数据表单 |
POST /api/yida/process-instances
Content-Type: application/json
请求示例:
{
"type": "cpmp402",
"userId": "41603502201288023",
"dataTitle": "包材核价单",
"fields": {
"mainData": {
"rq": "2026-09-08",
"bm": "ML07000000",
"tjr": "3075",
"gs": "ML",
"t100id": "ML",
"ent": "87",
"t100bm": "ML07000000"
},
"detailData": {
"detailData": [
{
"hjdh": "MLCH326090800001",
"gysbh": "113009",
"gysmc": "供应商名称",
"t100id": "ML",
"ent": "87",
"yy": "zh_CN"
}
]
}
}
}
成功响应为 HTTP 201 Created:
{
"code": 200,
"isSuccess": true,
"result": {
"processInstanceId": "process-instance-id"
}
}
GET /api/yida/process-instances/{processInstanceId}
该接口直接返回钉钉宜搭流程实例详情,仅用于核对实例表单数据和字段映射,不会发起 ERP 推送。processInstanceId 使用宜搭流程实例 ID。
分页查询:
GET /api/yida/minglei/forms/instances?page=1&size=20
精确查询:
POST /api/yida/minglei/forms/instances/query
Content-Type: application/json
请求示例:
{
"dept_id": "123456",
"user_id": "dingTalkUserId",
"dept_name": "明磊锂能技术部"
}
精确查询优先级为 dept_id、user_id、dept_name。传入 user_id 时,服务端会先查询人员所属部门,再按部门 ID 查询主数据。响应固定包含 employeeField_mszdqrl8、employeeField_mszdqrl9、employeeField_mszdqrla、employeeField_mszdqrlb、employeeField_mualkf6a(部门负责人)和 employeeField_mszdqrl3;未匹配到审批矩阵记录或字段未配置时,对应字段值为 null。
POST /api/yida/minglei/departments/users
Content-Type: application/json
请求示例:
{
"dept_Id": "123456,234567",
"type": 0,
"userIds": ["user-1", "user-2"]
}
userIds 为可选的用户 ID 列表。未传或传入空数组时不影响部门成员查询结果;传入非空列表时,列表中的用户 ID 会按传入顺序追加在部门成员列表之后,并与部门成员及列表内其他 ID 一并去重。
dept_Id 支持单个部门 ID,或多个以英文逗号分隔的部门 ID;返回结果为各部门查询范围内人员的去重合集。
type 取值:
| 值 | 说明 |
|---|---|
0 |
查询指定部门和所有子部门 |
1 |
仅查询指定部门 |
本地表 employee_roster 的 is_resigned 字段以 1 表示在职、0 表示离职。同步读取到钉钉通讯录用户的 active=false 时,会将该人员更新为离职;花名册按钉钉用户 ID 或工号的查询会自动排除离职人员。
同步还会按钉钉花名册字段名读取“入职时间”“职位”“银行卡号”“开户行”“支行联行号”,分别写入 hire_date、position_name、bank_card_no、bank_name、bank_branch_code。
每次同步完成后,服务会按 username 检查在职重名人员。存在重名时,服务从主数据宜搭表单 FORM-66F0B2216DD64580834D75815BFEF24138F7 的首条记录读取成员字段 employeeField_mv94lty1,并向其中配置的人事人员发送钉钉工作通知。
同步指定部门:
POST /api/yida/minglei/employee-roster/sync?departmentId=1&type=0
全量同步:
POST /api/yida/minglei/employee-roster/sync-full
按钉钉用户 ID 查询花名册:
POST /api/yida/minglei/employee-roster/getUserRoster
Content-Type: application/json
响应的 result 包含 hireDate(入职时间)、positionName(职位)、bank_card_no(银行卡号)、bank_name(开户行)和 bank_branch_code(支行联行号)。
POST /api/yida/minglei/employee-roster/dingtalk-dedicated-accounts
Content-Type: application/json
接口请求体仅接收钉钉 OA 审批实例 ID,也兼容字段名 processInstanceId:
{
"oaProcessInstanceId": "4iO8yQmvTNiRhLl4-jgjjQ05031793083009"
}
服务端调用钉钉 GET /v1.0/workflow/processInstances 查询审批实例的 result.formComponentValues,从控件名称或 bizAlias 读取姓名、部门、工号、岗位、性别、年龄、预计到岗日期、职称、职等和身份证号。姓名和部门为审批表单必填项;工号为空时按既有 YYMMDD + 四位日流水 规则生成。接口忽略旧请求体中直接传入的员工字段,以审批实例数据为准。
部门优先使用部门控件 extValue 中的部门 ID;若 OA 仅返回部门名称或层级路径,则按现有部门名称解析规则转换为钉钉部门 ID。随后以工号为登录名、ML 加工号为初始密码创建钉钉账号,并把数据库已有字段写入 employee_roster。
OA 的“职位”控件会写入钉钉创建用户接口的标准 title 字段;职位为空时才回退使用职称。职位不写入本地 employee_roster,职称仍按既有字段写入花名册。
以下历史直接传员工字段的请求体不再适用:
接口调用钉钉 topapi/v2/user/create 创建自建企业账号,仅已购买并开通该能力的组织可使用。请求中的 departmentList 支持钉钉 OA 部门名称、部门 ID 或部门选择器原始对象。传入名称时,服务从根部门开始通过钉钉 topapi/v2/department/listsub 逐级查询直属子部门并解析为 dept_id_list,不会遍历全部部门树;支持以 - 或 / 连接的层级名称,例如 集团运营中心-人力资源部。非根级部门应传入完整路径。路径未匹配或当前层级存在同名部门时接口返回 400,不创建账号。
{
"name": "张三",
"positionName": "研发工程师",
"gender": "男",
"age": 28,
"expectedArrivalDate": "2026-11-01",
"jobTitle": "高级工程师",
"jobGrade": "P6",
"idCardNo": "330101199801010011",
"departmentList": ["集团运营中心-人力资源部"],
"employeeNo": "1001"
}
employeeNo 为可选字段:传入时直接作为员工工号;未传或为空时,服务端从 employee_roster.employee_no 读取当日最大工号,按 YYMMDD 加当日四位流水号生成,例如 2610260001。无论工号来自入参还是自动生成,钉钉登录名均为工号本身(例如 2610260001),初始登录密码为 ML 加工号(例如 ML2610260001)。岗位、年龄、职等和身份证号通过钉钉 extension 推送;职称、性别和预计到岗日期分别映射为钉钉 title、gender 和 hired_date,其中日期按上海时区转换为毫秒时间戳。性别支持 1/2、男/女 或 male/female。本地仅写入 employee_roster 已存在的列;性别、年龄和身份证号不写入本地表。成功时返回 HTTP 201 Created;result.userId 为钉钉创建的用户 ID,result.employeeNo 为实际使用的员工工号,result.departmentIds 为实际提交的部门 ID。接口不回显登录密码。
{
"code": 200,
"isSuccess": true,
"result": {
"userId": "ding-user-1",
"employeeNo": "2610260001",
"departmentIds": [1, 2]
}
}
完整调用说明见 数据字典接口文档。
按字典编码查询已注册的数据字典,筛选条件通过 URL 查询参数传入。当前支持:
| 字典编码 | 查询对象 | 返回字段 | 筛选条件 |
|---|---|---|---|
erp-supplier |
DSDATA.erp_apmt440_pmaauc_v |
视图全部字段 | 必填:t100id、ent;可选:pmaal004 |
erp-packaging-b9-window-view |
DSDATA.imaf_t、DSDATA.imaal_t |
imaf001、imaal003、imaal004 |
必填:t100id、ent;可选:keyword |
erp-packaging-material |
DSDATA.pmaauc_t |
pmaauc001、pmaauc002、tp |
必填:ent;可选:keyword |
erp-material-original-price |
DSDATA.pmaauc_t |
pmaauc002、pmaauc015、pmaauc001、pmaaucent |
必填:czbh、ent |
erp-item-view |
DSDATA.erp_apmt440_imaauc_v |
视图全部字段 | 必填:ent;可选:keyword(匹配 imaa001、imaal003) |
erp-sales-order |
DSDATA.xmda_t、DSDATA.xmdc_t、DSDATA.xmdd_t、DSDATA.ooff_t |
销售订单、客户、料件、未交数量和开票信息 | 必填:t100id;可选:keyword(匹配 xmdadocno) |
erp-production-order |
DSDATA.xmda_t、DSDATA.xmdc_t、DSDATA.xmdd_t、DSDATA.ooff_t |
生产令、客户、料件、数量和开票信息 | 必填:t100id、userId |
erp-supplier-disabled |
DSDATA.ERP_APMT440_PMAAUC_N |
禁用供应商视图全部字段 | 必填:t100id、ent;可选:keyword(匹配 pmaal004) |
erp-active-item |
DSDATA.imaa_t、DSDATA.imaf_t、DSDATA.imaal_t |
imaa001、imaal003、imaal004 |
可选:keyword(匹配 imaa001、imaal003) |
erp-template-item |
DSDATA.imaa_t、DSDATA.imaal_t |
imaa001、imaal003、imaal004 |
可选:keyword(匹配 imaa001、imaal003) |
erp-template-orders |
DSDATA.xmda_t、DSDATA.xmdc_t |
范本料号关联订单及料件明细 | 必填:bgfblh;可选:keyword(匹配 xmdadocno) |
erp-last-price |
DSDATA.pmdi_t、DSDATA.pmdj_t |
pmdj011 |
必填:main.pmdi004、detail_1.ljbh |
erp-unfulfilled-order |
DSDATA.xmdg_t、DSDATA.xmdh_t、DSDATA.xmda_t、DSDATA.xmdc_t、DSDATA.imaal_t、DSDATA.pmaal_t |
xmdgdocno、xmdhseq、xmda048、xmdcud010、xmdh006、imaal003、imaal004、xmdg005、pmaal003 |
必填:ent、site、keyword |
erp-delivery-order |
DSDATA.xmdg_t、DSDATA.xmdh_t、DSDATA.xmdc_t |
xmdgdocno、xmdcud010、xmdc019、k |
必填:ent、site;可选:keyword(匹配 出通单号-项次) |
erp-outsourced-purchase-order-window |
DSDATA.pmdp_t、DSDATA.imaal_t、DSDATA.sfaa_t |
pmdpseq、pmdp003、pmdp001、imaal003、imaal004、pmdp023、sfaaud009 |
必填:formtable_main_158_dt1_wwcgdh |
erp-outsourced-bom |
DSDATA.pmdp_t、DSDATA.sfba_t、DSDATA.imaal_t |
sfba006、imaal003、imaal004、sfba013 |
必填:formtable_main_158_dt1_wwcgdh、formtable_main_158_dt1_cgxc |
供应商视图:
GET /api/dictionary/erp-supplier?t100id=ML&ent=明磊&pmaal004=供应商
明磊包材B9开窗视图:
GET /api/dictionary/erp-packaging-b9-window-view?t100id=ML&ent=明磊&keyword=B9开窗
包材材质:
GET /api/dictionary/erp-packaging-material?ent=明磊&keyword=彩盒
根据材料编号取原单价:
GET /api/dictionary/erp-material-original-price?czbh=B9-001&ent=明磊
ERP 料件视图:
GET /api/dictionary/erp-item-view?ent=明磊&keyword=电池
销售订单开窗:
GET /api/dictionary/erp-sales-order?t100id=ML&keyword=SO-001
生产令开窗:
GET /api/dictionary/erp-production-order?t100id=ML&userId=USER-001
userId 为钉钉用户 ID。服务端先从本地员工花名册取得对应的 employee_no,再使用该工号执行 Oracle 查询。
ERP 供应商禁用视图:
GET /api/dictionary/erp-supplier-disabled?t100id=ML&ent=明磊&keyword=供应商
T100 有效料号:
GET /api/dictionary/erp-active-item?keyword=B9
范本料号开窗:
GET /api/dictionary/erp-template-item?keyword=B9
范本料号开窗对应所有订单:
GET /api/dictionary/erp-template-orders?bgfblh=B9&keyword=SO-001
取料号上次价格:
GET /api/dictionary/erp-last-price?main.pmdi004=SUP-001&detail_1.ljbh=B9-001
已审核未发齐出通单:
GET /api/dictionary/erp-unfulfilled-order?ent=明磊&site=ML&keyword=MLCT6261023002-1
出通单列表:
GET /api/dictionary/erp-delivery-order?ent=明磊&site=ML&keyword=110001-1
委外采购单开窗:
GET /api/dictionary/erp-outsourced-purchase-order-window?formtable_main_158_dt1_wwcgdh=WWCG-001
委外采购对应工单备料:
GET /api/dictionary/erp-outsourced-bom?formtable_main_158_dt1_wwcgdh=WWCG-001&formtable_main_158_dt1_cgxc=10
erp-supplier 的 pmaal004 按供应商名称模糊匹配。erp-packaging-b9-window-view 使用单一 keyword 参数,后端会将其分别与 imaf001(料件编号)、imaal003(中文品名)和 imaal004(规格)进行模糊匹配,任一字段命中即可返回。明磊包材B9开窗视图仅返回中文料件信息,排除 imaf016 为 TY 或 LTY 的记录,并只包含编码以 B9、VB9 或 J 开头的料件。
erp-supplier、erp-packaging-b9-window-view 和 erp-supplier-disabled 的 t100id、ent 均为必填筛选条件;erp-packaging-material 和 erp-item-view 仅需传入 ent。销售订单开窗仅需传入 t100id,固定查询公司 86 中已审核、存在未交数量且不属于指定排除客户的订单。生产令开窗需传入 t100id 与 userId,服务端按该用户在 ooag_t 中的部门字段 ooag003 匹配订单部门字段 xmdaowndp,固定查询公司 86 中已审核的订单。范本料号关联订单需传入 bgfblh,服务端按该料号前缀匹配 ML 据点未作废订单。取料号上次价格需同时传入 main.pmdi004(主表料号)和 detail_1.ljbh(子表料件编号),服务端返回有效采购价格单中最新确认时间的 pmdj011。已审核未发齐出通单需传入 ent、site 和 keyword,其中 keyword 按“出通单号-项次”精确匹配,返回项次、内外销、料号、料件中文名称、规格、客户编号及客户中文名称。有效料号和范本料号均可选 keyword,同时模糊匹配 imaa001(料号)和 imaal003(中文品名);范本料号关联订单可选 keyword 模糊匹配 xmdadocno(订单号);ERP 供应商禁用视图可选 keyword 模糊匹配 pmaal004(供应商名称)。包材材质可用单一 keyword 对 pmaauc001(包材编号)、pmaauc002(包材名称)和 tp(中文材质类型)进行模糊匹配,任一字段命中即可返回;ERP 料件视图的 keyword 会同时模糊匹配 imaa001(料号)和 imaal003(中文品名)。委外采购单开窗仅需传入 formtable_main_158_dt1_wwcgdh;委外采购对应工单备料需同时传入采购单号 formtable_main_158_dt1_wwcgdh 和采购项次 formtable_main_158_dt1_cgxc。两者 SQL 均固定查询公司 86、据点 ML。ent=明磊 映射为 ERP 公司编号 86,ent=越南 映射为 ERP 公司编号 60,其他公司名称会返回 400。十五个字典接口不接收 page 和 pageSize,服务端固定返回符合条件的前 100 条记录。包材材质的 tp 字段会将 pmaauc016 转换为 说明书、彩盒、纸箱 或 标贴。
成功响应的 result 统一为:
{
"page": 1,
"pageSize": 100,
"total": 238,
"records": []
}
数据字典实现约定:固定 SQL、字典编码和允许的筛选参数统一维护在 DictionaryQueryServiceImpl,Controller 只处理 HTTP 参数与响应封装;SQL 必须使用 NamedParameterJdbcTemplate 绑定参数,不得拼接外部输入;新增字典时在同一 ServiceImpl 中增加路由分支、参数校验、单元测试和本节文档。未注册的字典编码或未声明的筛选条件会返回 400。
POST /api/minglei/ports/travel-standards
Content-Type: application/json
请求体:
{
"userId": "ding-user-001",
"city": "海口"
}
userId 和 city 均为必填参数;为兼容已有调用,userID 也可作为 userId 传入。接口先从本地员工花名册查询用户职等,再按职等精确查询宜搭差旅标准表单 FORM-47ED3C35E3C34A9CA275039F93FA5ED1VR2J,最后依据国内城市类别或国外国家类别返回住宿标准。金额不再由后端固定维护。
numberField_mvevi2d3(一类国家标准,人民币)。numberField_mvevi2d4(其他国家标准,人民币)。国外城市会先匹配常用城市名称;城市值也可附带国家名称,例如 巴黎(法国),以支持未预置的国外城市。响应的 country 字段返回命中的国家,cityClass 对国外分别返回 一类国家 或 其他国家。无法识别国家的中文城市维持原有国内三类城市逻辑,保障已接入的国内调用不受影响。
差旅标准表单与审批矩阵复用主数据宜搭应用配置 minglei.yida.master-data,无需新增 system-token。员工不存在、职等未维护、职等不是数值或宜搭未配置该职等的标准时,接口返回 400。
响应示例:
{
"code": 200,
"isSuccess": true,
"result": {
"userID": "ding-user-001",
"jobGrade": "8",
"city": "海口",
"country": "中国",
"cityClass": "二类城市",
"amount": 400,
"currency": "CNY"
}
}
POST /api/expense-reimbursement/flight-standards/resolve
Content-Type: application/json
请求体:
{
"userId": "728378541",
"travelRegion": "东南亚",
"ticketType": "往返",
"tripCount": 2,
"budgetAmount": 8001
}
userId 为必填项。服务先按 userId 查询本地员工花名册中的职等,再按职等精确查询同一份宜搭差旅标准主表。机票标准全部从主表字段读取,不查询子表;travelRegion 或 ticketType 为空或不符合预置选项时,接口正常返回,标准相关字段为 null。
传入 tripCount(次数)和 budgetAmount(预算金额)时,接口按 budgetAmount > limitAmount × tripCount 返回 isOverStandard:严格大于返回 是,小于或等于返回 否。任一计算参数或机票标准为空时,isOverStandard 返回 null。
travelRegion |
ticketType |
名称 | 宜搭主表字段 |
|---|---|---|---|
国内 |
单程 |
国内机票-单程 | numberField_mvevi2dd |
国内 |
往返 |
国内机票-往返 | numberField_mvevi2dc |
东南亚 |
单程 |
东南亚机票-单程 | numberField_mvevi2dg |
东南亚 |
往返 |
东南亚机票-往返 | numberField_mvevi2de |
欧美及其它 |
单程 |
欧美及其他机票-单程 | numberField_mvevi2dl |
欧美及其它 |
往返 |
欧美及其他机票-往返 | numberField_mvevi2dj |
响应示例:
{
"code": 200,
"isSuccess": true,
"result": {
"expenseType": "FLIGHT",
"userId": "728378541",
"jobGrade": "8",
"jobGradeId": "GRADE-8",
"travelRegion": "东南亚",
"ticketType": "往返",
"flightOption": "SOUTHEAST_ASIA_ROUND_TRIP",
"flightOptionName": "东南亚机票-往返",
"limitAmount": 4000,
"tripCount": 2,
"budgetAmount": 8001,
"isOverStandard": "是",
"currency": "CNY",
"unit": "PER_TRIP"
}
}
员工不存在、职等未维护、职等不是数值、未找到对应职等的宜搭主表记录或对应金额未维护时,接口返回 400。出差区域或机票类型不支持时不返回错误,标准相关字段为 null。
当前接口只接收钉钉 OA 审批实例 ID。下方本节中旧的主表和子表请求字段说明不再适用,连接器不得再传入
userId、departmentId、title或三张子表数据。
服务端调用钉钉“获取单个审批实例详情”接口 GET https://api.dingtalk.com/v1.0/workflow/processInstances,从 result、formComponentValues 及三个明细组件中读取申请人、申请部门、标题、行程、飞机航程和费用预算,再按照原有宜搭字段映射发起出差申请流程。附件不处理。
当前请求体:
{
"oaProcessInstanceId": "4iO8yQmvTNiRhLl4-jgjjQ05031793083009"
}
oaProcessInstanceId 是唯一必填字段,也兼容使用 processInstanceId 传入。审批实例中缺少发起人、标题、申请部门或表单组件数据时,接口返回 HTTP 400,不会创建宜搭流程。
POST /api/minglei/ports/travel-applications
Content-Type: application/json
钉钉 OA 连接器在审批通过后只需传入审批实例 ID。服务端查询实例详情,使用 OA 发起人作为宜搭流程发起人,并将部门名称或部门 ID解析为钉钉部门 ID后写入申请部门;附件字段不处理,当前不做重复拦截。
请求示例:
{
"oaProcessInstanceId": "oa-process-001"
}
解析兼容钉钉明细控件常见的 rowValue、componentValues 和名称值数组结构。行程中的“出发地/出发城市”“目的地/目的城市”“开始时间/开始日期”“结束时间/结束日期”等名称会按语义匹配;人员扩展值兼容 userid、userId、emplId、itemId。查询到的字段按以下宜搭字段写入:
| OA 数据 | 宜搭目标 |
|---|---|
| 申请人、申请公司、申请部门、申请日期、申请人职位、手机号、实际出差人、工号、职等、出差类型、关联客户、出差事由、交通工具、单程往返 | 主表对应字段 |
| 出发地、目的地、开始/结束时间、时长、出差天数、出行人(同行人)、备注 | 行程子表 tableField_mvorr6o1 |
| 是否预定机票、出差区域类型、机票类型、次数、预算金额、单价、标准金额、是否超标、备注 | 飞机航程子表 tableField_mvorr6oe |
| 出发地点、到达地点、住宿天数、交通费用(除飞机外)、住宿费、住宿费标准、业务招待费、出差补贴、费用合计 | 费用预算子表 tableField_mvorr6oo |
oaProcessInstanceId 是唯一必填字段。审批实例缺少发起人、标题、申请部门或表单组件数据时返回 HTTP 400。
成功响应示例:
{
"code": 200,
"isSuccess": true,
"result": {
"oaProcessInstanceId": "oa-process-001",
"yidaProcessInstanceId": "yida-process-001",
"formUuid": "FORM-E1A24F72B06247ADAC36335CF7E1FEAC6DJX"
}
}
POST /api/dingtalk/approval/transfer-department/managers
Content-Type: application/json
请求示例:
{
"processInstanceId": "YuRRlAutRFi4CcsrPkqvQg05031789886060"
}
服务端处理链路:
GET https://api.dingtalk.com/v1.0/workflow/processInstances,通过 x-acs-dingtalk-access-token 请求头传入应用凭证。result.formComponentValues 中查找 name 为 转入部门 的表单组件;未匹配到时回退匹配 bizAlias 为 transferDepartment 的组件。extValue,取第一个元素的 id 作为转入部门 ID,deptName 或 name 作为部门名称。extValue 中的 id 可能是字符串或数字,服务端统一按字符串处理。MingleiDocumentService.queryDepartmentManagersByDepartmentId(宜搭审批矩阵表单 FORM-8F527F696C5B4AF7AB7A53979527FBA23USO)按"部门"选择字段 departmentSelectField_mszdqrks 内嵌的部门 ID 精确匹配,查询各级别负责人,不再调用钉钉通讯录部门详情接口。注意:第 4 步改为按"部门"选择字段匹配(而非原先的"部门编号"文本字段
textField_msztwhs2),且返回结果新增"部门负责人"字段(审批矩阵employeeField_mualkf6a)。
响应中各级别负责人按字段分开返回,分别对应审批矩阵表单中的 employeeField_mszdqrl8(一级部门主管)、employeeField_mszdqrl9(二级部门主管)、employeeField_mszdqrla(三级部门主管)、employeeField_mszdqrlb(四级部门主管)、employeeField_mualkf6a(部门负责人)与 employeeField_mszdqrl3(部门分管领导)。
成功响应:
{
"code": 200,
"isSuccess": true,
"result": {
"departmentId": "972414534",
"departmentName": "合作伙伴",
"firstLevelManagerUserId": "manager-1",
"secondLevelManagerUserId": "manager-2",
"thirdLevelManagerUserId": "manager-3",
"fourthLevelManagerUserId": "manager-4",
"departmentHeadUserId": "manager-head",
"departmentLeaderUserId": "manager-5"
}
}
各部门负责人字段为对应级别审批人的钉钉 userid,审批矩阵未配置该级别负责人时该字段为 null。getAllManagerUserIds() 按一级至四级部门主管、部门负责人、部门分管领导的顺序返回所有非空的负责人 ID。
| 异常场景 | HTTP 状态码 | 说明 |
|---|---|---|
processInstanceId 为空 |
400 |
请求参数不合法 |
| 审批实例无表单数据或未包含转入部门字段 | 400 |
表单结构与预期不一致 |
转入部门 extValue 缺少部门 ID |
400 |
无法解析部门 ID |
| 审批实例接口调用失败或宜搭审批矩阵查询失败 | 502 |
返回 DINGTALK_APPROVAL_CALL_FAILED 或 YIDA_CALL_FAILED 及上游错误码 |
| 宜搭应用或钉钉凭证配置缺失 | 412 |
返回配置缺失信息 |
POST /api/minglei/ports/supplier-price-approvals
Content-Type: application/json
宜搭连接器调用时传表单 ID 和宜搭流程实例 ID。服务端按 formId 选择字段映射规则,再通过钉钉开放平台 GET /v2.0/yida/processes/instancesInfos/{id} 读取顶层 data(支持对象或 JSON 字符串,同时兼容旧响应的 formData),后转换为 T100 核价单,并补齐 T100 协议外层的 key、host、service、datakey、type,以及生成 17 位毫秒时间戳。推送 T100 时使用 Content-Type: application/json;charset=UTF-8。该请求使用钉钉应用 access token,并传入 appType、systemToken、查询用户 ID;配置项见上表。不要在连接器请求体中传入表头、明细、密钥或 T100 外层字段。
{
"formId": "FORM-468B6FB2D5BF490A8BC6DBD6FAF9BCCA28R9",
"processInstanceId": "宜搭流程实例 ID"
}
接口按 formId 选择对应字段映射,当前已注册表单如下:
| 表单 | formId |
明细字段映射 |
|---|---|---|
| 供应商价格审批单(核价) | FORM-468B6FB2D5BF490A8BC6DBD6FAF9BCCA28R9 |
tableField_mszqctqd:料件编号、核价、备注 |
| 供应商价格审批单(暂估) | FORM-F906C997A4A44DC8B9180198C0B2E55F6W0S |
tableField_msh186sv:料件编号、材料价格、备注 |
| 供应商价格审批单-核价(子公司) | FORM-C09818E73B1640A9AA9F6D7F55C47612EFV8 |
tableField_mszqctqd:料件编号、核价、备注 |
| 供应商价格审批单-暂估(子公司) | FORM-EC46C7109182497796AA0B70F3848576UYBU |
tableField_msh186sv:料件编号、暂估单价、备注 |
| 包材材质核价 | FORM-69A12600F87349D3B653BF86E419224DLIX9 |
tableField_mt1av9od:材质编号、单价(克) |
| 供应商暂停/退出流程 | FORM-0A05D30C6E0745EC9F4B74D0E038EE73O7B6 |
主表:变更类型、供应商编号、企业代码;不发送企业据点 |
| 包材料号清单维护审核流程 | FORM-F88BDA6B3A114E668AD5A6347AE4E01C91O9 |
tableField_msh186sv:包材料号清单字段 |
四个供应商价格审批表单都会将单据编号、委外否、单号、报价单日期、核价供应商、生效日期、失效日期、使用部门、申请人映射至 T100 表头;其中申请人由宜搭成员数组的第一项姓名查询本地在职花名册后,使用对应的 employee_no 写入 T100 pmdi002。明细的料件编号、价格、备注分别映射至 pmdj002、pmdj011、pmdj030。宜搭委外否字段为“是”时,T100 pmdi001 传 Y;为“否”时传 N(兼容历史 Y/N 值)。暂估表单 FORM-F906C997A4A44DC8B9180198C0B2E55F6W0S 和 FORM-EC46C7109182497796AA0B70F3848576UYBU 的 pmdiud001 传 Y,其余供应商价格审批表单传 N;pmdistus 固定传 I。新增的三张表单按照各自 T100 请求体层级组装 parameter,并填充对应的 datakey.type 与 service.name=DingTalk To T100;包材材质核价以 textField_mviyetxy 判断 pmaaucent,供应商暂停/退出流程以 textField_mvewj97z 判断 pmaaent、pmabent,包材料号清单维护以 selectField_msy2rh6q 判断 pmabucent,字段值为“明磊”时均传 87,其余值传 60;包材料号清单子表的 textField_mvix39fn、textField_mvix39fm、numberField_mvjb17mf 分别映射至 pmabuc001、pmabuc002、pmabuc024,且 pmabucsite 固定传 ML,供应商暂停/退出流程的 selectField_mt82p09c 为“正常供应商”时 pmaa083、pmab074 传 1,为“停用”时传 0,并保留 pmabsite;包材料号清单维护固定传 pmabucstus=Y。未注册的 formId 会返回参数错误,不会访问宜搭或 T100。外部 T100 接口地址与密钥分别由 MINGLEI_SUPPLIER_PRICE_APPROVAL_URL、MINGLEI_SUPPLIER_PRICE_APPROVAL_KEY 配置。
当四张供应商价格审批单推送 T100 且返回 success=true 时,服务会从 content.payload.std_data.parameter.pmdidocno 读取 T100 单号,并按原流程实例 ID 调用宜搭流程更新接口回写单号。回写字段分别为:核价与核价(子公司)使用 textField_mszqctqb,暂估与暂估(子公司)使用 textField_mt7yf5wu。T100 未成功时不会回写;T100 已成功但宜搭回写失败时接口返回失败,避免单据状态被误判为已完整同步。
POST /api/erp/yida/push
Content-Type: application/json
请求示例:
{
"type": "axmt140",
"mainData": {
"rq": "2026-09-08",
"bm": "123456",
"tjr": "3075",
"gs": "ML"
},
"detailData": {
"detailData1": [
{
"xmfyseq": "10",
"xmfy002": "DN-001",
"xmfy003": "2026-09-08",
"xmfy004": "CUS-001",
"pmaal004": "客户名称"
}
]
}
}
成功响应使用 McR.success():
{
"success": true,
"code": "200",
"message": "SUCCESS"
}
type 会去除首尾空格并转为大写后匹配,调用方传入大小写不敏感。
type 或别名 |
处理器 | 单据或流程 | 表单 UUID | 流程编码 |
|---|---|---|---|---|
cpmp402 |
Cpmp402YidaProcessHandler |
包材核价单 | FORM-A3D4889187E54697A59590BE54F350E7AOO5 |
TPROC--98G66QB1NTF8E1R1LI0OK4D6JI9437HC92YSM1 |
FORM-4403B45A7F184CB79088FCDAFD2FD925LZ3K |
MlWorkOrderCraftPriceFormPushHandler |
ML-工单工艺工价审定 | FORM-4403B45A7F184CB79088FCDAFD2FD925LZ3K |
TPROC--WG966BA1VWF8Q1K4OGF8H9KW47RR3ZREH0YSM2 |
axmt500 |
ApproveOrderFormPushHandler |
客户订单审批 | FORM-8454FA17732746058A2D90B1C559CC19G5SR |
TPROC--9VD66QA18AJ8317KK3NXM54W1HIT30C7N28TM7 |
axmt140 |
CustomerReleaseFormPushHandler |
客户放行审批 | FORM-3BA9FE18494F4FDD85FE6ABF7DE741BAE30C |
TPROC--6TG66381N8G8Y7L9GBEEY7QVXTUY2LBBGZ7TMU |
cint301 |
MiscReceiptIssueFormPushHandler |
杂收杂发审批 | FORM-4B08ADABCDAA45788C043729A855E03ED76G |
TPROC--MQD66371C1N84FPSJZO4W79IN4BW2AE7I08TM0 |
asft800 |
Asft800FormPushHandler |
包装工单变更审批流程 | FORM-40D6FBBBF4A94864A2AF9535AAC7924CRBH2 |
TPROC--U2I66F719HF854X6PIGK5A2AP9VC2LODB7YSM1 |
aqct300 |
Aqct300FormPushHandler |
检验情况审批流程 | FORM-38C8592E7F5F45B3A388DA3FEFBA67C2GCEV |
TPROC--LX766PC193N85EWUJ9ZLACNJNPSW3HBRG78TM1 |
axmt510 |
Axmt510FormPushHandler |
订单变更申请流程 | FORM-8F318292B70D4ED39080EE0C631DC74BG3MD |
TPROC--BHC66W71Q1N87Q0YFD7FVBNYXRJ62OIA378TM4 |
apmt100 |
Apmt100FormPushHandler |
供应商导入流程 | FORM-9EE14CA14D8D4AEE8102944E669E6B0CFUKS |
TPROC--75G66PD15YG82766OFSWD8BS4ZJ33YPRFOZSM2 |
mainData 规则| 字段 | 说明 |
|---|---|
rq |
申请日期,通常为 yyyy-MM-dd 或毫秒时间戳 |
bm |
钉钉部门 ID |
tjr |
提交人工号,用于查询员工花名册并解析钉钉 userId |
gs |
公司或组织编码 |
t100id |
T100 业务标识 |
ent |
地区或企业编号 |
t100bm |
T100 部门 |
顶层 bm、gs、tjr 非空时,会覆盖写入 mainData。服务端会将 mainData 中的通用字段补入各明细行,便于表单处理器复用。
detailData 规则detailData 外层必须是对象,内部至少包含一个数组字段。数组字段名支持:
detailDatadetailData1detailData2detailData\d* 格式的字段不同单据的约定:
| 类型 | 明细字段 |
|---|---|
cpmp402 |
detailData |
FORM-4403B45A7F184CB79088FCDAFD2FD925LZ3K |
detailData |
axmt500 |
detailData1、detailData2,兼容历史 detailData |
axmt140 |
优先 detailData1,缺失时回退到 detailData |
cint301 |
detailData1 |
asft800 |
detailData1 |
aqct300 |
detailData1~detailData4 |
axmt510 |
detailData1~detailData3 |
apmt100 |
无明细,传入空对象 {} |
明细对象中可以直接传入宜搭 fieldId。服务端会保留包含 Field_ 的字段值,用于补充默认字段映射。
ErpYidaPushServiceImpl 优先使用顶层 tjr,其次使用 mainData.tjr。dingtalkId。dingtalkId 会作为 originatorUserId、userId 和 applicant 写入请求上下文或明细行。YidaFormPushHandler 时,提交人工号允许为空,具体处理器可以使用默认发起人兜底。YidaProcessService 时,提交人工号不能为空。asft800 包装工单变更审批流程调用 POST /api/erp/yida/push 时传入 type: "asft800"。表头使用 ERP 原始字段,明细必须放在 detailData.detailData1。
{
"type": "asft800",
"bm": "123456789",
"gs": "87",
"tjr": "EMP0001",
"mainData": {
"rq": "2026-09-16",
"bm": "123456789",
"gs": "87",
"tjr": "EMP0001",
"t100id": "EMP0001",
"ent": "87",
"t100bm": "PACK",
"sfkaent": "87",
"sfkasite": "ML",
"sfkadocno": "WO-20260916-001",
"sfka900": "2",
"sfka902": "2026/09/16",
"sfka057": "包装工单",
"sfka010": "ITEM-001",
"imaal003": "锂电池包装组件",
"imaal004": "标准规格",
"sfka012": 100.5,
"sfka006": "SOURCE-001",
"sfkaud009": "MO-001",
"sfka906": "变更物料及数量",
"ooagud004": "dingtalk-user-id"
},
"detailData": {
"detailData1": [
{
"sfkgent": "87",
"sfkgdocno": "WO-20260916-001",
"sfkg900": "2",
"sfkgseq": "10",
"sfkg901": "变更",
"sfkg006": "MAT-002",
"imaal003": "新物料名称",
"imaal004": "新物料规格",
"sfkg013": 101.5,
"sfkg014": "PCS",
"sfba006": "MAT-001",
"o_imaal003": "原物料名称",
"o_imaal004": "原物料规格",
"sfba013": 100.0
}
]
}
}
tjr 是员工工号,服务端会从员工花名册解析对应钉钉用户作为发起人;未传时,处理器使用 mainData.ooagud004 作为钉钉用户 ID。bm 为钉钉部门 ID,sfka902 支持 yyyy-MM-dd 或 yyyy/MM/dd 格式。
aqct300 检验情况审批流程调用 POST /api/erp/yida/push 时传入 type: "aqct300"。表头使用 ERP 原始字段;明细分别放入 detailData1(检验项目)、detailData2(缺点原因)、detailData3(计量检验)、detailData4(来源明细)。
当前仅发起宜搭流程,不做 ERP 回写。以下字段宜搭无对应控件,推送时丢弃:qcba005(交易对象编号)、qcba010(料件编号)、qcba027(不良数)、detailData3.qcbd002(检验位置)。qcba000 需直接传宜搭选项值:IQC / FQC / Inventory QC。qcbadocno 同时写入宜搭「单号」textField_mt87k1g0 与新增字段 textField_muz22qad。
{
"type": "aqct300",
"bm": "123456789",
"gs": "87",
"tjr": "EMP0001",
"mainData": {
"rq": "2026-09-21",
"bm": "123456789",
"gs": "87",
"tjr": "EMP0001",
"qcbaent": "87",
"qcbadocno": "QC-20260921-001",
"qcbadocdt": "2026/09/21",
"qcba000": "IQC",
"qcba008": 100,
"qcba009": "PCS",
"imaal003": "料件品名",
"imaal004": "规格",
"qcba012": "产品特征",
"qcba016": "EA",
"qcba017": 80,
"qcba022": "PASS",
"qcba023": 75,
"qcba024": "张三",
"qcba034": "LOT-001"
},
"detailData": {
"detailData1": [
{
"qcbdent": "87",
"qcbddocno": "QC-20260921-001",
"qcbdseq": "10",
"qcbd001": "DIM",
"oocql004": "尺寸检验",
"qcbd009": 20,
"qcbd010": 1,
"qcbd011": "NG",
"qcbd021": 1
}
],
"detailData2": [
{
"qcbeent": "87",
"qcbedocno": "QC-20260921-001",
"qcbeseq": "10",
"qcbe001": "划伤",
"qcbe002": 2,
"qcbe003": "备注",
"qcbe004": 2
}
],
"detailData3": [
{
"qcbdent": "87",
"qcbddocno": "QC-20260921-001",
"qcbdseq": "10",
"qcbd013": 10.5,
"qcbd015": 9.5,
"qcbg002": 10.1,
"qcbd017": "mm",
"qcbg003": "Y",
"qcbd001": "SIZE",
"oocql004": "检验标准",
"qcbd019": "备注"
}
],
"detailData4": [
{
"qcbaucseq": "1",
"qcbauc014": "PO",
"qcbauc001": "PO-001",
"qcbauc002": "10",
"qcbauc003": "REF-001",
"qcbauc004": "20",
"qcbauc005": "SUP-001",
"qcbauc008": 100,
"qcbauc009": "PCS",
"qcbauc010": "ITEM-001",
"imaal003": "料件品名",
"imaal004": "规格"
}
]
}
}
tjr 为员工工号,服务端从花名册解析钉钉用户作为发起人与申请人;bm 为钉钉部门 ID;qcbadocdt / rq 支持 yyyy-MM-dd 或 yyyy/MM/dd。
axmt510 订单变更申请流程调用 POST /api/erp/yida/push 时传入 type: "axmt510"。表头使用 ERP 原始字段;明细分别放入 detailData1(订单变更单身)、detailData2(交期明细)、detailData3(配件明细)。
当前仅发起宜搭流程,不做 ERP 回写。表头「变更事件」、附件与已到物料相关字段无对应 ERP 字段,推送时不填。子表1 xmegkk 映射到「变更事件」选项:数量变更 / 交期变更 / 其他变更。
{
"type": "axmt510",
"bm": "123456789",
"gs": "87",
"tjr": "EMP0001",
"mainData": {
"rq": "2026-09-23",
"bm": "123456789",
"gs": "87",
"tjr": "EMP0001",
"xmeeent": "87",
"xmeedocno": "SO-20260923-001",
"xmee900": "1",
"xmeedocdt": "2026/09/20",
"xmee001": 2,
"xmee002": "dingtalk-sales-user",
"xmee003": "dingtalk-dept-id",
"xmee004": "C001",
"pmaal004": "客户简称",
"xmee013": "Y",
"xmee042": 12800.5,
"xmee901": "2",
"xmee902": "2026/09/23",
"xmee903": "R01",
"xmee904": "交期调整"
},
"detailData": {
"detailData1": [
{
"xmegent": "87",
"xmegdocno": "SO-20260923-001",
"xmegseq": "10",
"xmeg900": "1",
"xmeg001": "ITEM-001",
"xmeg002": "feature-a",
"imaal003": "品名",
"imaal004": "规格",
"xmdc007": 100,
"xmdc012": "2026/09/30",
"xmdc015": 10.5,
"xmeg006": "PCS",
"xmeg007": 120,
"xmeg012": "2026/10/15",
"xmeg015": 11,
"xmeg046": 1100,
"xmeg047": 1243,
"xmeg048": 143,
"xmeg049": "RC01",
"xmeg053": "HC01",
"xmeg901": "2",
"xmegud010": "MO-001",
"xmegkk": "交期变更"
}
],
"detailData2": [
{
"xmehent": "87",
"xmehdocno": "SO-20260923-001",
"xmehseq": "10",
"xmehseq1": "1",
"xmehseq2": "1",
"xmeh900": "1",
"xmeh001": "ITEM-001",
"xmeh004": "PCS",
"xmeh005": 120,
"xmeh009": "1",
"xmeh011": "2026/10/15"
}
],
"detailData3": [
{
"xmfwucent": "87",
"xmfwucdocno": "SO-20260923-001",
"xmfwucseq": "10",
"xmfwucseq1": "1",
"xmfwuc001": "PART-001",
"imaal003": "配件品名",
"imaal004": "配件规格",
"xmfwucud001": "feat-p",
"xmfwuc006": 2,
"xmfwuc007": 1,
"xmfwuc008": "PCS",
"xmfwuc009": 240,
"xmfwuc900": "1",
"xmfwuc901": "2"
}
]
}
}
tjr 为员工工号;xmee002 / xmee003 需传钉钉用户 ID / 部门 ID。日期字段支持 yyyy-MM-dd 或 yyyy/MM/dd。流程标题为 订单变更申请流程-{订单单号}-{变更序}。
apmt100 供应商导入流程调用 POST /api/erp/yida/push 时传入 type: "apmt100"。该流程无明细,detailData 必须为 {}。
{
"type": "apmt100",
"bm": "123456789",
"gs": "ML",
"tjr": "EMP0001",
"mainData": {
"rq": "2026-09-16",
"sqlx": "NEW",
"gysmc": "供应商名称",
"gysbm": "SUP-001",
"sh": "91330100TEST",
"gczczj": "1000000.50",
"clsj": "2026/09/16",
"zysccp": "锂电池包装组件",
"gcgm": "120",
"lcbh": "PM-001",
"smzq": "ACTIVE",
"pmbb033all": "CNY",
"pmbb034all": "VAT",
"pmbb053all": "NET30",
"pmbb033": "CNY",
"pmbb034": "VAT",
"pmbb053": "NET30",
"pmbb037": "NET30",
"gst100": "ML",
"lxr": "张三",
"gsdz": "浙江省杭州市",
"lxfs": "13800000000"
},
"detailData": {}
}
lcbh 用于生成流程标题;若其为空,可使用 docno。clsj 支持 yyyy-MM-dd 或 yyyy/MM/dd。所有 pmbb***all 字段映射到集团惯用数据,未带 all 后缀的 pmbb*** 映射到据点惯用数据。
Logback 输出:
${LOGGING_FILE_PATH}/application.log。${LOGGING_FILE_PATH}/error.log。archive 目录下的滚动归档日志。HttpRequestResponseLoggingFilter 会记录 HTTP 方法、URI、状态码、耗时、请求体和响应体。单个载荷最大记录 10KB,并对 password、secret、token、authorization、accessToken、systemToken、key 等字段脱敏。
| 场景 | HTTP 状态码 | 说明 |
|---|---|---|
| 请求体格式错误或参数校验失败 | 400 |
请求不合法 |
| 配置缺失 | 412 |
必要配置未提供 |
| 宜搭或钉钉上游业务错误 | 502 |
返回上游错误码和错误信息 |
| 外部 T100 调用失败 | 502 |
返回 MINGLEI_PORT_CALL_FAILED |
环境要求:
malk 依赖本地构建:
mvn clean package
本地运行:
$env:SERVER_PORT = "8080"
$env:DINGTALK_APP_KEY = "<dingTalk-app-key>"
$env:DINGTALK_APP_SECRET = "<dingTalk-app-secret>"
$env:YIDA_COORDINATION_OFFICE_APP_TYPE = "<coordination-office-app-type>"
$env:YIDA_COORDINATION_OFFICE_SYSTEM_TOKEN = "<coordination-office-system-token>"
$env:YIDA_MASTER_DATA_APP_TYPE = "<master-data-app-type>"
$env:YIDA_MASTER_DATA_SYSTEM_TOKEN = "<master-data-system-token>"
mvn spring-boot:run
运行打包产物:
java -jar target\mjava-minglei-1.0.0-SNAPSHOT.jar
执行完整测试:
mvn clean test
当前测试覆盖:
当前验证结果:
Tests run: 52, Failures: 0, Errors: 0, Skipped: 1
新增可由 /api/yida/process-instances 触发的通用流程时:
XxxYidaProcessHandler。YidaProcessHandler。getType() 返回业务路由编码。新增可由 /api/erp/yida/push 路由的表单流程时:
XxxFormPushHandler。YidaFormPushHandler。getTypes() 返回主 type 和必要别名。src/test/java 中补充字段映射和异常测试。type 是路由键,不等于表单 UUID。fieldId 字段。LOGGING_FILE_PATH 有写权限。mainData.tjr 无法解析,优先检查花名册同步状态和员工 dingtalkId。