案例分享:销售退货单同步——销货单到畅捷通T+的集成实现
在企业信息系统中,数据的高效、准确流转是业务顺利运作的关键。本文将详细介绍如何通过轻易云数据集成平台,实现旺店通·企业奇门的数据无缝同步到畅捷通T+系统。我们具体探讨一个典型案例,即销售退货单同步至销货单,并最终写入到畅捷通T+。
在这个方案中,我们利用了旺店通·企业奇门API接口wdt.stockin.order.query.refund
来抓取销售退货单的数据,通过轻易云平台进行数据处理和转换,最后通过畅捷通T+ API /tplus/api/v2/saleDelivery/Create
将整理好的销货数据信息写入到目标系统。
数据获取与处理
首先,通过调用旺店通·企业奇门的接口wdt.stockin.order.query.refund
, 我们可以定时可靠地抓取最新的销售退货单实例。这些实例可能涉及大量分页请求与限流机制,为此我们配置了自动重试及错误处理机制,以确保数据获取过程中的稳定性和连续性。
# 伪代码示意:
import requests
def fetch_refund_orders():
url = "https://api.wdt.com/wdt.stockin.order.query.refund"
params = {
'appkey': 'YOUR_APP_KEY',
'timestamp': int(time.time()),
... # 其他必要参数
}
response = requests.get(url, params=params)
if response.status_code == 200:
return response.json()
else:
handle_error(response.content)
data = fetch_refund_orders()
数据转换与映射
取得原始退款订单后,我们使用轻易云的平台特性进行自定义数据转换逻辑,将旺店通·企业奇门的数据格式适配为畅捷通T+所需格式。在这一环节中特别注意两者之间字段名称及结构差异并采取一致性的映射规则,这可大幅减少手动对接工作量,提高效率。
例如,在我们的实际操作中,需要从源数据抽取关键信息如订单号、商品详情、数量等,经由脚本或内置函数做相应变换以匹配目的端所需字段:
# 示例 Python 转换脚本:
def transform_data(raw_order):
transformed_order = {
'sourceOrderNo': raw_order['order_no'],
'items': [{'itemCode': item['sku'],
'quantity': item['qty']} for item in raw_order['items']],
# 其他字段映射...
}
return transformed_order
数据写
调用旺店通·企业奇门接口wdt.stockin.order.query.refund获取并加工数据
在数据集成的生命周期中,调用源系统接口是至关重要的一步。本文将详细探讨如何通过轻易云数据集成平台调用旺店通·企业奇门接口wdt.stockin.order.query.refund
来获取销售退货单数据,并进行初步加工。
接口调用配置
首先,我们需要配置元数据,以便正确调用wdt.stockin.order.query.refund
接口。以下是具体的元数据配置:
{
"api": "wdt.stockin.order.query.refund",
"effect": "QUERY",
"method": "POST",
"number": "order_no",
"id": "stockin_id",
"name": "order_no",
"idCheck": true,
"request": [
{
"field": "start_time",
"label": "开始时间",
"type": "datetime",
"describe": "增量获取数据,start_time作为开始时间,格式:yyyy-MM-dd HH:mm:ss",
"value": "{{LAST_SYNC_TIME|datetime}}"
},
{
"field": "end_time",
"label": "结束时间",
"type": "datetime",
"describe": "增量获取数据,end_time作为结束时间,格式:yyyy-MM-dd HH:mm:ss",
"value": "{{CURRENT_TIME|datetime}}"
},
{
"field": "status",
"label": "状态",
"type": "string",
"describe":
"入库单状态 10已取消20编辑中30待审核60待结算80已完成(默认查询80已完成单据)",
"value":"80"
},
{
"field":"shop_nos","label":"店铺编号","type":"string","describe":"代表店铺所有属性的唯一编码,用于店铺区分,ERP内支持自定义(ERP店铺界面设置),用于获取指定店铺单据数据信息","value":"01,05"}
],
...
}
请求参数说明
- start_time 和 end_time: 用于增量获取数据。
start_time
表示上次同步的时间点,而end_time
表示当前时间点。这两个字段确保我们只获取在这段时间内新增或更新的数据。 - status: 表示入库单的状态。默认值为80,即查询已完成的单据。
- shop_nos: 用于指定需要查询的店铺编号。在本例中,我们查询编号为01和05的店铺。
此外,还有分页参数page_size
和page_no
,用于控制每次请求返回的数据条数和页码。
数据请求与清洗
通过上述配置,我们可以发送POST请求到旺店通·企业奇门接口以获取销售退货单数据。轻易云平台会自动处理请求参数,并将响应结果进行初步清洗和转换。
示例代码片段
以下是一个简化的Python代码示例,用于展示如何调用该接口并处理返回的数据:
import requests
import json
from datetime import datetime
# 设置请求URL和头信息
url = 'https://api.wangdian.cn/openapi2/wdt.stockin.order.query.refund'
headers = {'Content-Type': 'application/json'}
# 设置请求参数
params = {
'start_time': datetime.strftime(LAST_SYNC_TIME, '%Y-%m-%d %H:%M:%S'),
'end_time': datetime.strftime(datetime.now(), '%Y-%m-%d %H:%M:%S'),
'status': '80',
'shop_nos': '01,05',
'page_size': PAGINATION_PAGE_SIZE,
'page_no': PAGINATION_START_PAGE
}
# 发起POST请求
response = requests.post(url, headers=headers, data=json.dumps(params))
# 检查响应状态码
if response.status_code == 200:
data = response.json()
# 数据清洗与转换逻辑
for order in data['orders']:
process_order(order)
else:
print(f"Error: {response.status_code}")
def process_order(order):
# 数据清洗与转换逻辑实现
pass
数据转换与写入
在成功获取并清洗数据后,我们需要将其转换为目标系统所需的格式,并写入到相应的数据存储中。这一步通常包括字段映射、数据类型转换以及必要的数据校验。
示例代码片段
def transform_and_write(data):
transformed_data = []
for order in data['orders']:
transformed_order = {
'订单号': order['order_no'],
'入库ID': order['stockin_id'],
# 更多字段映射...
}
transformed_data.append(transformed_order)
# 将转换后的数据写入目标系统或数据库
write_to_target_system(transformed_data)
def write_to_target_system(data):
# 写入逻辑实现,例如插入数据库或调用另一个API接口
pass
通过上述步骤,我们实现了从旺店通·企业奇门接口获取销售退货单数据,并进行初步清洗、转换和写入目标系统的全过程。这一过程不仅确保了数据的一致性和完整性,还极大提升了业务处理效率。
轻易云数据集成平台:将源平台数据转换为畅捷通T+API接口格式并写入
在数据集成的生命周期中,第二步是将已经集成的源平台数据进行ETL(Extract, Transform, Load)转换,转为目标平台畅捷通T+API接口所能够接收的格式,最终写入目标平台。本文将详细探讨如何通过轻易云数据集成平台实现这一过程。
API接口配置
首先,我们需要了解畅捷通T+API接口的配置。以下是一个典型的API接口配置元数据:
{
"api": "/tplus/api/v2/saleDelivery/Create",
"effect": "EXECUTE",
"method": "POST",
"idCheck": true,
"request": [
{"field": "Code", "label": "单据编码", "type": "string", "describe": "如果设置了自动编号,可不传;如果设置的手动编码,必录", "value": "{order_no}"},
{"field": "VoucherDate", "label": "单据日期", "type": "string", "describe": "默认系统日期", "value": "{{check_time|date}}"},
{"field": "ExternalCode", "label": "外部系统单据编码", "type": "string", "describe": "编码必须唯一,且此字段不为空", "value": "{order_no}-{warehouse_no}"},
{"field": "BusinessType", "label": "业务类型", "type": "string", "describe":"业务类型编码,15–普通销售;16–销售退货","parser":{"name":"ConvertObjectParser","params":"Code"},"value":"16"},
{"field":"Customer","label":"客户","type":"string","describe":"PartnerDTO对象;举例:Customer:{Code:\"001\"}","parser":{"name":"ConvertObjectParser","params":"Code"},"value":"{shop_no}"},
{"field":"Warehouse","label":"仓库","type":"string","describe":"WarehouseDTO对象。\n\n业务流程为合并流程时,必录;开启了负库存校验(不管是控制还是提示),必录;","parser":{"name":"ConvertObjectParser","params":"Code"},"value":"{warehouse_no}"},
{"field":"RdStyle","label":"出库类别","type":"string","describe":"RdStyleDTO对象,默认为“线上销售”类别;举例:RdStyle:{Code:\"001\"}","parser":{"name":"ConvertObjectParser","params":"Code"},"value":"201"},
{"field":"Memo","label":"备注","type":"string","describe":"备注","value":"{remark}"},
{"field":"TransDocNo","label":"运单号","type":"string","describe":"运单号","value":"{logistics_code}"},
{"field":"DeliveryCode","label":"发货单号","type":"string","describe":"","value" :"{logistics_code}"},
{"field" :"IsAutoGenerateSaleOut" ,"label" :"是否自动销售出库单" ,"type" :"string" ,"value" :"true"},
{"field" :"InvoiceType" ,"label" :"票据类型" ,"type" :"string" ,"describe" :"枚举类型;00--普通发票,01--专用发票,02–收据;为空时,默认按收据处理" ,"parser":{"name" :"ConvertObjectParser" ,"params" :"Code"},"value" :"01"},
{"field" :"DynamicPropertyKeys" ,"label" :"DynamicPropertyKeys" ,"type" :"string" ,"value" :"pubuserdefnvc1,pubuserdefnvc2,pubuserdefnvc3 ","parser":{"name ":"StringToArray ","params ": ","}},
{"field ":"DynamicPropertyValues ","label ":"DynamicPropertyValues ","type ":"string ","value ":"{src_order_no},{logistics_no},{trade_no} ","parser":{"name ":"StringToArray ","params ": ","}},
{
field: 'SaleDeliveryDetails',
label: '销货单明细',
type: 'array',
describe: '销货单明细',
value: 'details_list',
children: [
{
field: 'Inventory',
label: '存货',
type: 'string',
describe: 'InventoryDTO对象,存货档案信息;举例:Inventory:{Code:"001\'}',
parser: { name: 'ConvertObjectParser', params: 'Code' },
value: '{{details_list.goods_no}}'
},
{
field: 'Unit',
label: '存货计量单位',
type: 'string',
value:
'_mongoQuery e6b53fa8-d8bf-3037-80c0-022b574a4a74 findField=content.Unit.Name where={"content.Code":{"$eq":"' +
'{{details_list.goods_no}}' +
'"}}',
parser: { name: 'ConvertObjectParser', params: 'Code' }
},
{
field: 'Batch',
label: '批号',
type: 'string',
describe:
'批号为空时,系统选项“自动带出批号”勾选,按规则带出批号',
value:
"_function case when '{{details_list.IsBatch}}'=true and '{{details_list.batch_no}}'<>'' then '{{details_list.batch_no}}' when '{{details_list.IsBatch}}'=true and '{{details_list.batch_no}}'='' then '0000' else '0000' end"
},
{
field: 'Quantity',
label: '数量',
type: 'string',
describe:
'普通销售是,设置正数;销售退货时,设置负数',
value:
"_function '{{details_list.goods_count}}'*(-1)"
},
{
field: 'OrigTaxPrice',
label: '原币含税单价',
type: 'string',
describe:
'原币含税单价 {{details_list.tax_price}}',
value:
'{{details_list.src_price}}'
},
{
field:'DetailMemo','label':'备注','type':'string','describe':'备注','value':'{{details_list.remark}}'
},
{
field:'ProductionDate','label':'生产日期','type':'date','value':'_function DATE_SUB(\'{{position_list.expire_date}}\ ', INTERVAL {{details_list.Expired}} DAY)'
},
{
field:'ExpiryDate','label':'失效日期','type':'date','value':'_function case when \'{{position_list.expire_date}}\ '<> \'0000-00-00 00 :00 :00\' then \'{{position_list.expire_date}}\ '\' else \'9999-12-31\' end'
},
{
field:'is_batch','label':'是否开启批号','type':' string ',' value ':'{{ details _list .IsBatch }}'
},
{
field:'Expired ',' label ':'有效天数 ',' type ':' string ',' value ':'_function case when {{ details _list .Expired }}>1 then {{ details _list .Expired }}-1 else 0 end'
}
]
}
],
otherRequest:[
{'field':dataKey,'label':dataKey,'type': string,' describe ': dataKey,' value ':' dto'},
{' field ': strategyId ,' label ':' 联查方案 ID ',' type ':' string ',' value ':'429c148b-da42-3e38-8ba0-25dadf1602c7'}
]
}
数据请求与清洗
在ETL过程中,我们首先需要从源平台请求数据,并对其进行清洗和转换。下面是一个示例代码片段,用于从源平台获取订单数据:
import requests
# 请求源平台的数据
source_url = "<source_platform_api>"
response = requests.get(source_url)
data = response.json()
# 清洗和转换数据
cleaned_data = []
for order in data['orders']:
cleaned_order = {
# 提取和转换所需字段
# 示例:将订单编号映射到目标字段
'order_no': order['id'],
# 更多字段映射...
}
cleaned_data.append(cleaned_order)
数据转换与写入
接下来,将清洗后的数据按照畅捷通T+API接口的要求进行转换,并写入目标平台。以下是一个示例代码片段,用于将清洗后的数据转换为目标格式并通过API写入:
import json
# 定义目标API URL
target_url = "/tplus/api/v2/saleDelivery/Create"
# 定义请求头
headers = {
'Content-Type': 'application/json'
}
# 遍历清洗后的数据并发送POST请求
for order in cleaned_data:
payload = {
# 映射和填充目标API所需字段
# 示例:将订单编号映射到目标字段
'Code': order['order_no'],
# 更多字段映射...
# 销售退货明细处理
SaleDeliveryDetails:[
{
Inventory:{
Code:"001"
},
Unit:{
Name:"个"
},
Quantity:-1 * order['quantity'],
OrigTaxPrice : order['price']
}
# 更多明细项...
]
}
response = requests.post(target_url, headers=headers, data=json.dumps(payload))
if response.status_code == 200:
print(f'Successfully created sale delivery for order {order["order_no"]}')
else:
print(f'Failed to create sale delivery for order {order["order_no"]}: {response.text}')
技术要点总结
- 元数据配置:通过元数据配置文件定义API接口、请求方法、字段映射等信息。
- 清洗与转换:从源平台获取原始数据,对其进行必要的清洗和格式转换,以满足目标平台的要求。
- 批量处理:遍历清洗后的数据,通过循环批量发送POST请求,将每条记录写入目标平台。
- 错误处理:在实际操作中,需要对每个请求的响应进行检查,并处理可能出现的错误,以确保数据同步过程的可靠性。
通过以上步骤,可以实现从源平台到畅捷通T+API接口的数据无缝对接,有效提升业务流程的自动化程度和效率。