ETL转换与写入金蝶云星辰V2:实战案例分析

  • 轻易云集成顾问-蔡威
### 汤臣倍健营销云数据集成到金蝶云星辰V2的技术实战案例 #### 案例背景:仓库调拨-杭州佰健嘉庆 在本次案例中,我们将详细探讨如何通过轻易云数据集成平台,实现汤臣倍健营销云与金蝶云星辰V2之间的数据无缝对接。具体任务是将汤臣倍健营销云的借用订单数据(API: /erp/api/order/query/borrowOrder)高效地写入到金蝶云星辰V2系统中的库存调拨模块(API: /jdy/v2/scm/inv_tfmove)。整个方案被命名为“仓库调拨-杭州佰健嘉庆”。 #### 数据流设计与主要挑战 为了实现这一复杂的数据集成过程,首先利用轻易云平台提供的可视化数据流设计工具,对整个数据流进行清晰定义和管理。这些工具使我们直观了解各阶段的数据处理逻辑,并确保各环节都能顺利衔接。 #### 高吞吐量与实时监控 在处理大量订单数据时,高吞吐量的数据写入能力显得尤为关键。使用轻易云平台,我们能够快速抓取并处理汤臣倍健营销云接口返回的大量分页且限流受限的订单信息。同时,通过其集中式监控和告警系统,可以实时跟踪每个集成任务的状态,确保任何异常情况都能及时响应。 #### 数据格式转换与质量控制 由于两个平台在数据结构上的差异,需要自定义转换逻辑来适应特定业务需求。例如,将汤臣倍健营销云接口返回的JSON格式借用订单,成功映射并转化为符合金蝶云星辰V2要求的数据结构。这不仅涉及字段名称和类型的对应,更包括一些复杂规则下的数据加工。在这个过程中,通过支持全面而严谨的数据质量检测机制,可迅速发现并修正潜在问题,从而保证最终导入目标系统中的数据准确性。 以上只是我们实际操作的一部分内容。在下一章节中,将会深入剖析具体实现步骤、代码示例及更多技术细节。如果有兴趣了解更多有关此项目的信息,请继续关注后续内容。 ![用友与MES系统接口开发配置](https://pic.qeasy.cloud/D7.png~tplv-syqr462i7n-qeasy.image) ### 调用源系统汤臣倍健营销云接口获取并加工数据 在数据集成的生命周期中,调用源系统接口是至关重要的一步。本文将深入探讨如何通过轻易云数据集成平台调用汤臣倍健营销云的接口 `/erp/api/order/query/borrowOrder` 获取并加工数据。 #### 接口调用配置 首先,我们需要配置接口调用的元数据。根据提供的元数据配置,以下是关键参数及其含义: - **API路径**: `/erp/api/order/query/borrowOrder` - **请求方法**: `POST` - **分页设置**: 每页30条记录 - **定时任务**: 每两小时执行一次,确保遗漏数据被补救 - **请求条件**: 订单子类型为`301` #### 请求参数详解 在实际调用过程中,需要传递一系列参数来确保请求的准确性和有效性: 1. **tenantId (经销商id)**: - 类型: `string` - 描述: 经销商id(必填,营销云id),例如:`08e2fd9d074f4ef7b5e6416b74d006d6` - 示例值: `xxx` 2. **number (系统订单号)**: - 类型: `string` - 描述: 系统订单号(调拨出库单),例如:`JHDRK00000008602` - 注意: 传此参数时,其他时间状态等条件无效 3. **status (订单状态)**: - 类型: `string` - 描述: 0表示未审核,1表示已审核(已出库) - 示例值: `1` 4. **beginTime (开始时间)**: - 类型: `string` - 描述: 基于更新时间查询,格式为`YYYY-MM-DD HH:mm:ss` - 示例值: `{{DAYS_AGO_1|datetime}}` 5. **endTime (结束时间)**: - 类型: `string` - 描述: 基于更新时间查询,格式为`YYYY-MM-DD HH:mm:ss` - 示例值: `{{CURRENT_TIME|datetime}}` 6. **pageNo (页码)**: - 类型: `string` - 描述: 默认值为`1` - 示例值: `1` 7. **pageSize (每页条数)**: - 类型: `string` - 描述: 默认值为`30` - 示例值: `30` #### 数据请求与清洗 在发送请求后,接收到的数据需要进行清洗和处理。以下是一些常见的数据清洗步骤: 1. **字段映射与转换**: 将原始数据中的字段映射到目标系统所需的字段。例如,将原始数据中的`order_id`映射到目标系统中的`id`字段。 2. **数据过滤**: 根据业务需求过滤掉不必要的数据。例如,只保留状态为已审核(status=1)的订单。 3. **格式化处理**: 对日期、数字等字段进行格式化处理,以符合目标系统的要求。例如,将日期格式从`YYYY-MM-DD HH:mm:ss`转换为目标系统所需的格式。 #### 异常处理与重试机制 在实际操作中,可能会遇到网络波动、接口超时等异常情况。为了确保数据完整性和一致性,可以采用以下措施: 1. **异常捕获**: 在每次请求时捕获异常,并记录日志以便后续分析。 2. **重试机制**: 针对特定错误码或异常情况,设置重试机制。例如,每隔5分钟重试一次,最多重试3次。 3. **报警通知**: 当发生严重异常时,通过邮件、短信等方式通知相关人员及时处理。 #### 定时任务与遗漏补救 为了确保数据的实时性和完整性,可以配置定时任务定期执行数据获取操作。同时,为了防止遗漏,可以设置补救机制: - 定时任务配置:每两小时执行一次(crontab:`2 */2 * * *`) - 补救机制:在每次执行定时任务时,根据上次成功获取的数据时间段进行补救。例如,如果上次获取的数据时间段是从10点到12点,本次可以从12点开始获取。 通过上述步骤,我们可以高效地调用汤臣倍健营销云接口获取并加工数据,为后续的数据转换与写入奠定坚实基础。 ![电商OMS与WMS系统接口开发配置](https://pic.qeasy.cloud/S1.png~tplv-syqr462i7n-qeasy.image) ### 使用轻易云数据集成平台进行ETL转换并写入金蝶云星辰V2API接口 在数据集成生命周期的第二步中,我们将重点探讨如何将已经集成的源平台数据进行ETL(Extract, Transform, Load)转换,转为目标平台金蝶云星辰V2 API接口所能够接收的格式,并最终写入目标平台。本文将详细介绍如何配置元数据,以实现仓库调拨业务的数据转换和写入。 #### 配置元数据以适配金蝶云星辰V2 API接口 我们需要使用以下元数据配置,将仓库调拨业务的数据转换为金蝶云星辰V2 API接口所需的格式: ```json { "api": "/jdy/v2/scm/inv_tfmove", "effect": "EXECUTE", "method": "POST", "number": "1", "autoCheck": "inv_tfmove_bill_order", "id": "1", "name": "1", "idCheck": true, "request": [ {"field":"bill_date","label":"出库日期","type":"string","describe":"出库日期,格式:2019-01-01","value":"{created}"}, {"field":"trans_type","label":"业务类型","type":"string","describe":"1:同价调拨(默认),2:异价调拨","value":"1"}, {"field":"trans_fer_status","label":"调拨状态","type":"string","describe":"0:未出库(默认),1:未入库,2:部分入库,3:全部入库","value":"3"}, {"field":"remark","label":"单据备注","type":"string","describe":"单据备注","value":"来自营销云{number}"}, { "field":"material_entity", "label":"商品分录", "type":"array", "describe":"商品编码", "value":"itemList", "children":[ {"field":"material_id","label":"商品","type":"string","describe":"商品","value":"_findCollection find id from 395d1591-aee0-3f10-ad09-d5593167af48 where number={{itemList.helpCode}}"}, {"field":"in_stock_id","label":"调入仓库","type":"string","describe":"调入仓库","value":"_findCollection find id from f4dc9f0e-4ac1-3513-861b-a741c0e67f10 where number={{itemList.otherExtDepotCode}}"}, {"field":"out_stock_id","label":"调出仓库","type":"string","describe":"调出仓库","value":"_findCollection find id from f4dc9f0e-4ac1-3513-861b-a741c0e67f10 where number={{itemList.extDepotCode}}"}, {"field":"batch_no","label":"批次号","type":"string","value":"{{itemList._Flot}}"}, {"field":"kf_date","label":"生产日期","type":"string","value":"{{itemList._Fmfg}}"}, {"field":"valid_date","label":"有效日期","type":"string","value":"{{itemList._Fexp}}"}, {"field": "kf_period", "label": "保质期天数", "type": "string", "describe": "保质期天数", "value": "730"}, {"field": "kf_type", "label": "保质期单位", "type": "string", "describe": "保质期类型:1/天,2/月,3/年(保质期商品必填)", "value": "1"}, {"field": "qty", "label": "数量", "type": string, describe: 数量, value: {{itemList.opernumber}}}, {"field": unit_id, label: 单位, type: string, describe: 单位, value: _findCollection find base_unit_id from 395d1591-aee0-3f10-ad09-d5593167af48 where number={{itemList.helpCode}}} ] } ] } ``` #### 数据请求与清洗 在数据请求阶段,我们从源平台获取原始数据。假设原始数据包含以下字段: - `created`:创建日期 - `number`:单据编号 - `itemList`:商品列表,其中包含多个商品项,每个商品项包括`helpCode`、`otherExtDepotCode`、`extDepotCode`、`_Flot`、`_Fmfg`、`_Fexp`、和`opernumber` #### 数据转换与写入 在数据转换阶段,我们需要将上述原始数据字段映射到目标API接口所需的字段格式。具体步骤如下: 1. **出库日期** (`bill_date`): - 从原始数据中的 `created` 字段提取,并转换为 `YYYY-MM-DD` 格式。 2. **业务类型** (`trans_type`): - 固定值为 `1`, 表示同价调拨。 3. **调拨状态** (`trans_fer_status`): - 固定值为 `3`, 表示全部入库。 4. **单据备注** (`remark`): - 从原始数据中的 `number` 字段提取,并拼接字符串 `"来自营销云{number}"`. 5. **商品分录** (`material_entity`): - 对于每个商品项,需要映射多个字段,包括 `material_id`, `in_stock_id`, `out_stock_id`, `batch_no`, `kf_date`, `valid_date`, `kf_period`, `kf_type`, `qty`, 和 `unit_id`. - 使用 `_findCollection` 函数从相应的集合中查找对应的ID,例如通过商品编码(`helpCode`)查找商品ID,通过仓库编码(`otherExtDepotCode`, `extDepotCode`)查找仓库ID等。 以下是一个示例代码片段,用于处理上述映射逻辑: ```javascript const transformData = (sourceData) => { return { bill_date: formatDate(sourceData.created), trans_type: '1', trans_fer_status: '3', remark: `来自营销云${sourceData.number}`, material_entity: sourceData.itemList.map(item => ({ material_id: findCollection('395d1591-aee0-3f10-ad09-d5593167af48', item.helpCode), in_stock_id: findCollection('f4dc9f0e-4ac1-3513-861b-a741c0e67f10', item.otherExtDepotCode), out_stock_id: findCollection('f4dc9f0e-4ac1-3513-861b-a741c0e67f10', item.extDepotCode), batch_no: item._Flot, kf_date: item._Fmfg, valid_date: item._Fexp, kf_period: '730', kf_type: '1', qty: item.opernumber, unit_id: findCollection('395d1591-aee0-3f10-ad09-d5593167af48', item.helpCode) })) }; }; const formatDate = (dateStr) => { const date = new Date(dateStr); return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`; }; const findCollection = (collectionId, key) => { // 模拟查找集合中的ID return `${collectionId}-${key}`; }; ``` #### 写入目标平台 最后一步是将转换后的数据通过HTTP POST请求写入到金蝶云星辰V2 API接口: ```javascript const axios = require('axios'); const postDataToKingdee = async (data) => { try { const response = await axios.post('/jdy/v2/scm/inv_tfmove', data); console.log('成功写入金蝶云星辰V2:', response.data); } catch (error) { console.error('写入失败:', error); } }; const sourceData = getSourceData(); // 假设这是从源系统获取的数据 const transformedData = transformData(sourceData); postDataToKingdee(transformedData); ``` 通过以上步骤,我们成功地将源平台的数据进行ETL转换,并写入到金蝶云星辰V2 API接口。这种方法不仅确保了数据的一致性和准确性,还大大提高了系统集成的效率和透明度。 ![打通企业微信数据接口](https://pic.qeasy.cloud/T3.png~tplv-syqr462i7n-qeasy.image)