IPAAS云星空对接对象说明

基本概念及字段说明参考 :3.按照CRM对象对接配置说明 | 纷享销客 | 帮助中心 ,本文只说明ipaas对接方法

1、云星空辅助资料对接

对接方案:云星空的辅助资料的数据,对接到CRM上的辅助资料对象,CRM上其它对象查找关联辅助资料

第一步 在CRM新建自定义对象-辅助资料,字段设置如下,上级资料字段查找关联辅助资料

图片

图片

图片

第三步 建立辅助资料同步策略,字段映射按照下表配置

图片

设置字段映射

图片

配置好字段映射,开启同步策略即可。

流详情

图片

2、云星空即时库存对接

第一步 在库存管理-插件管理,设置对接插件同步机制为“同步库存明细”,CRM才会有库存明细对象

图片

图片

第二步创建对象同步的集成流

图片

图片

trigger为K3C连接器的实时库存查询轮询

图片

trigger选择需要对接的字段

图片

映射等待选择查找关联数据的集成流

图片

第四步 配置字段映射,基本字段配置如下

图片

图片

配置映射关系节点

图片

3、销售价目表对接

K3 Cloud中对象是销售价目表(BD_SAL_PriceList),需要对接到CRM中两个对象价目表(PriceBookObj)和可售范围(AvailableRangeObj)

图片

第一步,检查配置项:价格管理配置-价格管理配置,已开启价目表和可售范围

图片

第二步:创建集成流,销售价目表对接价目表。trigger选择查询单据,表单基本配置如图,选择需要对接的字段

图片

对象映射如图

图片

详细字段映射如图

图片

特殊字段说明:时间转换使用公式:data2long,适用客户使用固定值

图片

第三步:创建集成流,销售价目表对可售范围。trigger选择查询单据,表单基本配置如图,选择需要对接的字段

图片

对象映射如图

图片

详细字段映射如图

图片

特殊字段说明,适用组织、可售客户范围、可售产品范围均使用固定值。客户:{"type":"FIXED","value":"FIXED"}、组织:{"type":"ALL","value":"ALL"}、产品:{"type":"FIXED","value":"FIXED"}。

图片

图片

4.多单位对接

需要对接单位和多单位关联表两个对象,对象对接如图

图片

第一步:检查配置项:商品/产品管理-商品/产品管理,多单位开启开关 已打开,多单位模式为多个单位模式

图片

第二步:创建单位对接集成流,trigger触发事件选择单据轮询,表单信息如图

图片

字段映射

图片

字段映射详情

图片

创建映射关系

图片

第三步,创建多关联表集成流,trigger触发事件选择单据轮询,表单信息如图

图片

映射等待选择关联单位和产品集成流

图片

配置多单位关联表字段映射

图片

字段映射详情

图片

保存映射关系

图片

第四步,对接单位后,对接产品的时候,使用中间表

图片

5.云星空单据上查

云星空通过下推生成的单据,同步对接的时候需要获取源单据,就会使用单据上查

第一步,获取源单,获取K3C单据后,新增一个action节点,执行动作选择查找源单据

图片

起始表单为需要上查的单据,目标表单为固定的销售订单,条目名称用于在同一张 K3C 单据存在多条“来源单据追溯路由”时,明确要按哪个分录实体追溯上游单据。

图片

输出target信息为销售订单信息,trace为中间过程表单信息(如果有)

图片

第二步,使用上查结果。

如要将上查结果,写入到获取单据的明细中,使用一个函数 action,入参使用tuple函数,将获取单据的明细及上查到的销售订单一起作为入参,输出则为重新组装后的明细。后续就可以直接使用函数节点的输出对接

图片

函数:

Map<String, Object> syncArgMap = (Map<String, Object>) syncArg
List<Object> functionArg = (List<Object>) syncArgMap.get("functionArg")

List<Map<String, Object>> receiveEntries =
        (List<Map<String, Object>>) functionArg.get(0)

Map<String, Object> saleOrder =
        (Map<String, Object>) functionArg.get(1)

Object salesOrderComId = saleOrder.get("number")

receiveEntries.each { Map<String, Object> item ->
    item.put("SalesOrderComId", salesOrderComId)
}
return [
        dataItems: receiveEntries
]

输出:

图片

6.产品组合对接物料清单

CPQ对接方案说明及字段增加参考:【金蝶云星空】CPQ对接新方案(使用CRM产品组合对象)

6.1 CRM支持选配并生成标准BOM,同步到ERP

1.物料对接到CRM的时候增加套件字段对接

图片

2.产品组合完整节点配置如图

图片

图片

条件通行:产品组合 BOM类型 等于 标准BOM

图片

函数过滤选配明细:父Bomid 不为空

图片

Map syncArgMap = (Map) (syncArg ?: [:])

Map sourceMap = syncArgMap

// 如果 BOMObj 放在 functionArg 中,则从 functionArg 读取。
if (syncArgMap['functionArg'] instanceof Map) {
    sourceMap = (Map) syncArgMap['functionArg']
}

List bomList = (List) (sourceMap['BOMObj'] ?: [])
List filteredBomList = []

bomList.each { Object bomObjItem ->
    Map bomItem = (Map) bomObjItem

    // 保留 parent_bom_id 不为 null 的数据。
    if (bomItem.containsKey('parent_bom_id') &&
            bomItem['parent_bom_id'] != null) {
        filteredBomList.add(bomItem)
    }
}

// 返回 Map 结构。
Map result = new LinkedHashMap()
result.put('BOMObjNew', filteredBomList)

return result

保存物料清单核心字段(只展示了已配置的字段)

图片

图片

产品选配明细绑定函数节点过滤后输出的明细

图片

创建3组映射关系

图片

图片

最后更新CRM 产品组合对象的ERP版本号字段

3.销售订单完整节点配置如图(本方案编辑订单没有采用新变更单,如果使用新变更单对接,只需要判断下中间表是否存在,不存在走创建,存在走更新变更单即可,配置相同)

图片

图片

数据范围:是否生成标准BOM 等于 是

图片

函数节点入参配置

图片

/*
 * CPQ 销售订单产品预处理
 *
 * 入参:
 *   syncArg.functionArg.SalesOrderProductObj
 *
 * 出参:
 *   syncArg.functionArg.SalesOrderProductObj
 *
 * 输出明细会补齐原同步前函数赋值的字段:
 *   std_bom_core__c
 *   product_type__c
 *   son_bom_id__c
 *   parent_product__c
 *
 * 后续 K3 字段映射保持原配置不变。
 */

/**
 * CPQ 销售订单产品预处理
 *
 * 函数入参:
 *   syncArg
 *
 * 实际数据路径:
 *   syncArg.functionArg.SalesOrderProductObj
 *
 * 函数出参:
 *   functionArg
 *
 * 输出新增:
 *   SalesOrderProductObjNew
 *
 * 处理逻辑:
 *   1. 按 order_by 升序排列,null 放最后
 *   2. 判断 standard / parent / son / skip
 *   3. 给明细补充原字段:
 *      - product_type__c
 *      - std_bom_core__c
 *      - son_bom_id__c
 *      - parent_product__c
 *   4. 过滤 skip 明细
 */

Map syncArgMap = (Map) (syncArg ?: [:])
Map functionArg = (Map) (syncArgMap['functionArg'] ?: [:])

List sourceLines = (List) (functionArg['SalesOrderProductObj'] ?: [])
List<Map> lines = []

// 转换为 Map 列表,保留原始明细字段。
sourceLines.each { Object item ->
    if (item instanceof Map) {
        lines.add((Map) item)
    }
}

/*
 * 按 CRM 原同步链路的方式排序:
 * order_by 升序,order_by 为 null 的数据放最后。
 */
lines.sort { Object firstObj, Object secondObj ->
    Map first = (Map) firstObj
    Map second = (Map) secondObj

    Object firstOrderValue = first['order_by']
    Object secondOrderValue = second['order_by']

    // 两个值都为空时保持原顺序。
    if (firstOrderValue == null && secondOrderValue == null) {
        return 0
    }

    // 空值放最后。
    if (firstOrderValue == null) {
        return 1
    }

    if (secondOrderValue == null) {
        return -1
    }

    try {
        BigDecimal firstOrder = new BigDecimal(String.valueOf(firstOrderValue))
        BigDecimal secondOrder = new BigDecimal(String.valueOf(secondOrderValue))
        return firstOrder.compareTo(secondOrder)
    } catch (Exception ignored) {
        // 非数字排序值按字符串升序处理。
        return String.valueOf(firstOrderValue)
                .compareTo(String.valueOf(secondOrderValue))
    }
}

// key: 订单产品明细 ID;value: 产品分类。
Map<String, String> detailId2Type = [:]

// key: prod_pkg_key;value: 对应订单产品明细。
Map<String, Map> pkg2ObjMap = [:]

// key: 订单产品明细 ID;value: 对应订单产品明细。
Map<String, Map> id2ObjMap = [:]

// 已经确定不需要同步的节点 ID。
Set<String> sonSkipIds = [] as Set<String>

/*
 * 第一遍:按排序后的顺序识别产品类型。
 *
 * 因为父项 order_by 在子项之前,
 * 所以子项处理时可以找到父项。
 */
lines.each { Map detail ->
    String id = detail['_id'] == null ?
            null : String.valueOf(detail['_id'])

    if (!id) {
        return
    }

    id2ObjMap[id] = detail

    Object bomId = detail['bom_id']

    // 没有 BOM 的记录是普通标准产品。
    if (bomId == null || String.valueOf(bomId).trim() == '') {
        detailId2Type[id] = 'standard'
        return
    }

    String pkg = detail['prod_pkg_key'] == null ?
            null : String.valueOf(detail['prod_pkg_key'])

    String parentPkg = detail['parent_prod_pkg_key'] == null ?
            null : String.valueOf(detail['parent_prod_pkg_key'])

    // 保存当前产品组合节点,供后续子项查找。
    if (pkg != null && pkg.trim() != '') {
        pkg2ObjMap[pkg] = detail
    }

    /*
     * parent_prod_pkg_key 为空,表示当前节点是 BOM 根节点。
     */
    if (parentPkg == null || parentPkg.trim() == '') {
        boolean isPackage =
                detail['is_package'] == true ||
                String.valueOf(detail['is_package']) == 'true'

        if (isPackage) {
            // 套件根节点,作为父项同步。
            detailId2Type[id] = 'parent'
        } else {
            // 非套件根节点,作为标准产品同步。
            detailId2Type[id] = 'standard'

            // 该节点的子项不再同步。
            sonSkipIds.add(id)
        }

        return
    }

    /*
     * 当前节点有 parent_prod_pkg_key,表示它是子节点。
     */
    Map parentDetail = pkg2ObjMap[parentPkg]

    String parentId = parentDetail == null ||
            parentDetail['_id'] == null ?
            null : String.valueOf(parentDetail['_id'])

    /*
     * 如果父项不存在,或者父项已被跳过,
     * 当前节点也标记为 skip。
     */
    if (parentId == null || sonSkipIds.contains(parentId)) {
        detailId2Type[id] = 'skip'
        sonSkipIds.add(id)
        return
    }

    // 正常套件子项。
    detailId2Type[id] = 'son'

    /*
     * 如果当前子项本身还是一个产品组合,
     * 当前节点保留,但它的下级不再继续同步。
     */
    Object bomCoreId = detail['bom_core_id']

    if (bomCoreId != null &&
            String.valueOf(bomCoreId).trim() != '') {
        sonSkipIds.add(id)
    }
}

/*
 * 第二遍:
 * 1. 补齐原同步前函数生成的字段;
 * 2. 过滤 skip 明细;
 * 3. 生成 SalesOrderProductObjNew。
 */
List<Map> newDetails = []

detailId2Type.each { String detailId, String type ->
    Map detail = id2ObjMap[detailId]

    if (detail == null) {
        return
    }

  
    detail['product_type__c'] = type

    /*
     * 先补齐字段。
     * 这样即使某些类型没有值,输出结构中也能看到字段。
     */
    detail['std_bom_core__c'] = null
    detail['son_bom_id__c'] = null
    detail['parent_product__c'] = null

    /*
     * 套件父项:
     *
     * standard_bom_id -> std_bom_core__c
     * std_bom_core__c -> FBomId.FNumber
     */
    if (type == 'parent') {
        detail['std_bom_core__c'] = detail['standard_bom_id']
    }

    /*
     * 套件子项:
     *
     * standard_bom_line_id -> son_bom_id__c
     * son_bom_id__c -> FBOMEntryId
     *
     * 根套件 product_id -> parent_product__c
     * parent_product__c -> FParentMatId.FNumber
     */
    if (type == 'son') {
        String rootPkg = detail['root_prod_pkg_key'] == null ?
                null : String.valueOf(detail['root_prod_pkg_key'])

        Map rootDetail = rootPkg == null ?
                null : pkg2ObjMap[rootPkg]

        detail['son_bom_id__c'] = detail['standard_bom_line_id']

        if (rootDetail != null) {
            detail['parent_product__c'] = rootDetail['product_id']
        }
    }

    /*
     * skip 明细不进入后续 K3 销售订单明细。
     */
    if (type == 'standard' ||
            type == 'parent' ||
            type == 'son') {
        newDetails.add(detail)
    }
}

/*
 * 保留原始 SalesOrderProductObj,
 * 同时新增过滤后的 SalesOrderProductObjNew。
 */
functionArg['SalesOrderProductObjNew'] = newDetails

return functionArg

增加映射等待节点,依赖产品组合和产品选配明细的中间表

图片

保存K3C订单节点,action选择保存,提交,审核单据,配置如图

要点:Is Entry Batch Fill 要设为false

图片

图片

明细要绑定函数转换后的明细列表,要点,明细的产品类型字段要挪到Primary Key之后(字段管理里配置)

图片

图片

剩余明细字段

图片

创建映射关系

图片

图片

2026-09-23
0 0