✨ 新增客商档案同步金蝶功能(A902-1查询回填+A902-2审批推送)
This commit is contained in:
+9
@@ -158,4 +158,13 @@ public class CustomerArchive extends TenantEntity {
|
||||
@Schema(description = "审核通过时间")
|
||||
private LocalDateTime approvedTime;
|
||||
|
||||
@Schema(description = "金蝶协同状态:none未推送/exist金蝶已有/synced已推送/failed推送失败")
|
||||
private String kingdeeStatus;
|
||||
|
||||
@Schema(description = "金蝶推送失败原因")
|
||||
private String kingdeeFailReason;
|
||||
|
||||
@Schema(description = "金蝶推送时间")
|
||||
private LocalDateTime kingdeeSyncTime;
|
||||
|
||||
}
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.transport.constant;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 客商档案金蝶(星瀚)协同常量
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class CustomerBfiConstants {
|
||||
|
||||
/**
|
||||
* 推送金蝶固定值:业务职能全选(1销售,2结算,3付款,4收货)
|
||||
*/
|
||||
public static final String BIZ_FUNCTION_ALL = "1,2,3,4";
|
||||
|
||||
/**
|
||||
* 推送金蝶固定值:伙伴类型兜底编码(民营企业),客商性质未命中映射时使用
|
||||
*/
|
||||
public static final String DEFAULT_PARTNER_TYPE = "6";
|
||||
|
||||
/**
|
||||
* 营业期限类型:长期(TMS 表单文本)
|
||||
*/
|
||||
public static final String BUSINESS_TERM_LONG = "长期";
|
||||
|
||||
/**
|
||||
* 客商性质(nature_of_client 字典 dictKey)→ 金蝶伙伴类型编码
|
||||
* 键名以数据库字典 nature_of_client 实际 dictKey 为准核对;未命中走 DEFAULT_PARTNER_TYPE
|
||||
*/
|
||||
public static final Map<String, String> NATURE_TYPE_MAPPING = Map.of(
|
||||
"企业法人", "1",
|
||||
"个人", "4",
|
||||
"个体工商户", "5",
|
||||
"民营企业", "6",
|
||||
"国有企业", "8",
|
||||
"政府事业单位", "9",
|
||||
"其他", "12"
|
||||
);
|
||||
|
||||
private CustomerBfiConstants() {
|
||||
}
|
||||
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.transport.controller;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springblade.core.boot.ctrl.BladeController;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiCustomerQueryDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiCustomerVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiPageVO;
|
||||
import org.springblade.thirdparty.bfi.service.IBfiService;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 业财融合(BFI)客商查询控制器
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
@RequestMapping("/bfi")
|
||||
@Tag(name = "BFI客商", description = "业财融合客商查询接口")
|
||||
public class BfiCustomerController extends BladeController {
|
||||
|
||||
private final IBfiService bfiService;
|
||||
|
||||
@GetMapping("/customer/query-by-credit-code")
|
||||
@Operation(summary = "按统一社会信用代码查询金蝶客商", description = "新增客商时查询金蝶是否已有该客商,已审核则回填工商信息")
|
||||
public R<BfiCustomerVO> queryByCreditCode(
|
||||
@Parameter(description = "统一社会信用代码", required = true) @RequestParam String creditCode) {
|
||||
if (StringUtil.isBlank(creditCode)) {
|
||||
return R.fail("统一社会信用代码不能为空");
|
||||
}
|
||||
BfiCustomerQueryDTO param = new BfiCustomerQueryDTO();
|
||||
param.setPageNo(1);
|
||||
param.setPageSize(1);
|
||||
param.setSocietycreditcode(List.of(creditCode.trim().toUpperCase()));
|
||||
BfiPageVO<BfiCustomerVO> page = bfiService.queryCustomer(param);
|
||||
List<BfiCustomerVO> rows = page == null ? null : page.getRows();
|
||||
return R.data(rows == null || rows.isEmpty() ? null : rows.get(0));
|
||||
}
|
||||
|
||||
}
|
||||
+22
-2
@@ -31,6 +31,7 @@ import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springblade.core.boot.ctrl.BladeController;
|
||||
import org.springblade.core.excel.util.ExcelUtil;
|
||||
import org.springblade.core.mp.support.Condition;
|
||||
@@ -60,6 +61,7 @@ import java.util.List;
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
@PreAuth(menu = "customer_archive")
|
||||
@@ -133,13 +135,21 @@ public class CustomerArchiveController extends BladeController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核通过
|
||||
* 审核通过(通过后自动推送金蝶,推送失败不影响审批结果)
|
||||
*/
|
||||
@PostMapping("/approve")
|
||||
@ApiOperationSupport(order = 6)
|
||||
@Operation(summary = "审核通过", description = "传入id")
|
||||
public R approve(@Parameter(description = "主键", required = true) @RequestParam Long id) {
|
||||
return R.status(customerArchiveService.approve(id));
|
||||
boolean result = customerArchiveService.approve(id);
|
||||
if (result) {
|
||||
try {
|
||||
customerArchiveService.syncKingdee(id);
|
||||
} catch (Exception exception) {
|
||||
log.error("客商审批通过后推送金蝶异常,id={}", id, exception);
|
||||
}
|
||||
}
|
||||
return R.status(result);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,6 +183,16 @@ public class CustomerArchiveController extends BladeController {
|
||||
return R.status(customerArchiveService.removeDraft(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 推送金蝶(审批通过后失败重推入口)
|
||||
*/
|
||||
@PostMapping("/sync-kingdee")
|
||||
@ApiOperationSupport(order = 12)
|
||||
@Operation(summary = "推送金蝶", description = "传入id,仅审批通过的客商可推送,已推送/金蝶已有自动幂等跳过")
|
||||
public R<CustomerArchive> syncKingdee(@Parameter(description = "主键", required = true) @RequestParam Long id) {
|
||||
return R.data(customerArchiveService.syncKingdee(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 评分明细模板
|
||||
*/
|
||||
|
||||
+3
@@ -105,4 +105,7 @@ public class CustomerArchiveExcel implements Serializable {
|
||||
@ExcelProperty("审核通过时间")
|
||||
private LocalDateTime approvedTime;
|
||||
|
||||
@ExcelProperty("金蝶同步状态")
|
||||
private String kingdeeStatusName;
|
||||
|
||||
}
|
||||
|
||||
+7
-1
@@ -46,6 +46,9 @@
|
||||
<result column="current_node" property="currentNode"/>
|
||||
<result column="current_processor" property="currentProcessor"/>
|
||||
<result column="approved_time" property="approvedTime"/>
|
||||
<result column="kingdee_status" property="kingdeeStatus"/>
|
||||
<result column="kingdee_fail_reason" property="kingdeeFailReason"/>
|
||||
<result column="kingdee_sync_time" property="kingdeeSyncTime"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectCustomerArchivePage" resultMap="customerArchiveResultMap">
|
||||
@@ -92,7 +95,10 @@
|
||||
approval_status,
|
||||
current_node,
|
||||
current_processor,
|
||||
approved_time
|
||||
approved_time,
|
||||
kingdee_status,
|
||||
kingdee_fail_reason,
|
||||
kingdee_sync_time
|
||||
FROM blade_customer_archive
|
||||
WHERE is_deleted = 0
|
||||
<if test="userId != null">
|
||||
|
||||
+8
@@ -124,6 +124,14 @@ public interface ICustomerArchiveService extends BaseService<CustomerArchive> {
|
||||
*/
|
||||
boolean removeDraft(String ids);
|
||||
|
||||
/**
|
||||
* 推送金蝶(A902-1 复查 + A902-2 保存),幂等:已推送/金蝶已有直接返回
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 更新后的客商档案
|
||||
*/
|
||||
CustomerArchive syncKingdee(Long id);
|
||||
|
||||
/**
|
||||
* 基于启用评分量化表生成评分记录
|
||||
*
|
||||
|
||||
+138
@@ -29,12 +29,22 @@ import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springblade.core.log.exception.ServiceException;
|
||||
import org.springblade.core.mp.base.BaseServiceImpl;
|
||||
import org.springblade.core.secure.utils.AuthUtil;
|
||||
import org.springblade.core.tool.jackson.JsonUtil;
|
||||
import org.springblade.core.tool.utils.BeanUtil;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
import org.springblade.thirdparty.bfi.constant.BfiConstant;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiCustomerQueryDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiBillSaveResultErrorVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiBillSaveResultItemVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiBillSaveResultVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiCustomerVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiPageVO;
|
||||
import org.springblade.thirdparty.bfi.service.IBfiService;
|
||||
import org.springblade.transport.excel.CustomerArchiveExcel;
|
||||
import org.springblade.transport.mapper.CreditRatingStandardMapper;
|
||||
import org.springblade.transport.mapper.CreditScoreCategoryMapper;
|
||||
@@ -101,6 +111,7 @@ import java.util.stream.Collectors;
|
||||
* @author Chill
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class CustomerArchiveServiceImpl extends BaseServiceImpl<CustomerArchiveMapper, CustomerArchive> implements ICustomerArchiveService {
|
||||
|
||||
@@ -112,6 +123,10 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl<CustomerArchiveM
|
||||
private static final String APPROVAL_REVIEWING = "reviewing";
|
||||
private static final String APPROVAL_APPROVED = "approved";
|
||||
private static final String APPROVAL_REJECTED = "rejected";
|
||||
private static final String KINGDEE_STATUS_NONE = "none";
|
||||
private static final String KINGDEE_STATUS_EXIST = "exist";
|
||||
private static final String KINGDEE_STATUS_SYNCED = "synced";
|
||||
private static final String KINGDEE_STATUS_FAILED = "failed";
|
||||
private static final String CUSTOMER_CODE_PREFIX = "KS";
|
||||
/**
|
||||
* 变更快照忽略字段:明细每次保存会重建主键/审计字段,不能作为“是否有修改”的依据
|
||||
@@ -137,6 +152,8 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl<CustomerArchiveM
|
||||
private final CreditRatingStandardMapper standardMapper;
|
||||
private final UserCustomerScopeMapper userCustomerScopeMapper;
|
||||
private final PaymentApplicationMapper paymentApplicationMapper;
|
||||
private final IBfiService bfiService;
|
||||
private final CustomerBfiConverter customerBfiConverter;
|
||||
|
||||
@Override
|
||||
public IPage<CustomerArchiveVO> selectCustomerArchivePage(IPage<CustomerArchiveVO> page, CustomerArchiveVO customer) {
|
||||
@@ -268,6 +285,112 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl<CustomerArchiveM
|
||||
return updateById(after);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public CustomerArchive syncKingdee(Long id) {
|
||||
CustomerArchive customer = ensureCustomerAccessible(id);
|
||||
if (!Objects.equals(customer.getApprovalStatus(), APPROVAL_APPROVED)) {
|
||||
throw new ServiceException("仅审批通过的客商允许推送金蝶");
|
||||
}
|
||||
if (List.of(KINGDEE_STATUS_SYNCED, KINGDEE_STATUS_EXIST).contains(customer.getKingdeeStatus())) {
|
||||
// 幂等:已推送或金蝶已有档案,直接返回
|
||||
return customer;
|
||||
}
|
||||
CustomerArchive after = copyCustomer(customer);
|
||||
after.setKingdeeSyncTime(LocalDateTime.now());
|
||||
BfiCustomerVO kingdeeCustomer = queryKingdeeCustomer(customer.getUnifiedCreditCode());
|
||||
if (kingdeeCustomer != null && BfiConstant.BILL_STATUS_AUDITED.equals(kingdeeCustomer.getStatus())) {
|
||||
// 金蝶已有已审核档案:跳过推送
|
||||
after.setKingdeeStatus(KINGDEE_STATUS_EXIST);
|
||||
after.setKingdeeFailReason(null);
|
||||
addChangeRecord(id, "金蝶已存在该客商档案,跳过推送", customer, after);
|
||||
updateById(after);
|
||||
return after;
|
||||
}
|
||||
if (kingdeeCustomer != null) {
|
||||
// 金蝶侧暂存/已提交:审核中,置失败待重推
|
||||
after.setKingdeeStatus(KINGDEE_STATUS_FAILED);
|
||||
after.setKingdeeFailReason("金蝶侧该客商审核中,请稍后重推");
|
||||
addChangeRecord(id, "推送金蝶失败:金蝶侧客商审核中", customer, after);
|
||||
updateById(after);
|
||||
return after;
|
||||
}
|
||||
pushCustomerToKingdee(id, customer, after);
|
||||
updateById(after);
|
||||
return after;
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装 A902-2 报文推送金蝶并回写协同状态
|
||||
*/
|
||||
private void pushCustomerToKingdee(Long id, CustomerArchive customer, CustomerArchive after) {
|
||||
try {
|
||||
BfiBillSaveResultVO result = bfiService.saveCustomer(customerBfiConverter.buildSaveDTO(detail(id)));
|
||||
BfiBillSaveResultItemVO item = firstSaveItem(result);
|
||||
if (item != null && Boolean.TRUE.equals(item.getBillStatus())) {
|
||||
after.setKingdeeStatus(KINGDEE_STATUS_SYNCED);
|
||||
after.setKingdeeFailReason(null);
|
||||
addChangeRecord(id, "推送金蝶成功,金蝶客户编码与客商编号一致:" + customer.getCustomerCode(), customer, after);
|
||||
} else {
|
||||
after.setKingdeeStatus(KINGDEE_STATUS_FAILED);
|
||||
after.setKingdeeFailReason(buildSaveFailReason(result, item));
|
||||
addChangeRecord(id, "推送金蝶失败:" + after.getKingdeeFailReason(), customer, after);
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
log.error("客商推送金蝶失败,id={},unifiedCreditCode={}", id, customer.getUnifiedCreditCode(), exception);
|
||||
after.setKingdeeStatus(KINGDEE_STATUS_FAILED);
|
||||
after.setKingdeeFailReason(truncateText(exception.getMessage() == null ? "金蝶接口调用异常" : exception.getMessage()));
|
||||
addChangeRecord(id, "推送金蝶失败:" + after.getKingdeeFailReason(), customer, after);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A902-1 按统一社会信用代码查询金蝶客商,无数据返回 null
|
||||
*/
|
||||
private BfiCustomerVO queryKingdeeCustomer(String unifiedCreditCode) {
|
||||
BfiCustomerQueryDTO param = new BfiCustomerQueryDTO();
|
||||
param.setPageNo(1);
|
||||
param.setPageSize(1);
|
||||
param.setSocietycreditcode(List.of(unifiedCreditCode));
|
||||
BfiPageVO<BfiCustomerVO> page = bfiService.queryCustomer(param);
|
||||
List<BfiCustomerVO> rows = page == null ? null : page.getRows();
|
||||
return rows == null || rows.isEmpty() ? null : rows.get(0);
|
||||
}
|
||||
|
||||
private BfiBillSaveResultItemVO firstSaveItem(BfiBillSaveResultVO result) {
|
||||
if (result == null || result.getResult() == null || result.getResult().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return result.getResult().get(0);
|
||||
}
|
||||
|
||||
private String buildSaveFailReason(BfiBillSaveResultVO result, BfiBillSaveResultItemVO item) {
|
||||
if (item != null && Func.isNotEmpty(item.getErrors())) {
|
||||
String messages = item.getErrors().stream()
|
||||
.map(BfiBillSaveResultErrorVO::getRowMsg)
|
||||
.filter(Func::isNotEmpty)
|
||||
.flatMap(List::stream)
|
||||
.collect(Collectors.joining(";"));
|
||||
if (Func.isEmpty(messages)) {
|
||||
messages = item.getErrors().stream()
|
||||
.map(error -> String.valueOf(error.getEntityKey()))
|
||||
.collect(Collectors.joining(";"));
|
||||
}
|
||||
return truncateText(messages);
|
||||
}
|
||||
if (result != null && Func.isNotEmpty(result.getFailCount())) {
|
||||
return truncateText("金蝶返回失败数量:" + result.getFailCount());
|
||||
}
|
||||
return "金蝶返回结果为空";
|
||||
}
|
||||
|
||||
private String truncateText(String text) {
|
||||
if (text == null) {
|
||||
return null;
|
||||
}
|
||||
return text.length() > 500 ? text.substring(0, 500) : text;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean changeStatus(Long id, Integer status) {
|
||||
@@ -343,6 +466,7 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl<CustomerArchiveM
|
||||
customer.setDeptName(trimToEmpty(customer.getDeptName()));
|
||||
customer.setAccessType(Func.isEmpty(customer.getAccessType()) ? ACCESS_TEMPORARY : customer.getAccessType());
|
||||
customer.setApprovalStatus(Func.isEmpty(customer.getApprovalStatus()) ? APPROVAL_DRAFT : customer.getApprovalStatus());
|
||||
customer.setKingdeeStatus(Func.isEmpty(customer.getKingdeeStatus()) ? KINGDEE_STATUS_NONE : customer.getKingdeeStatus());
|
||||
if (Func.isEmpty(customer.getStatus())) {
|
||||
customer.setStatus(STATUS_ENABLED);
|
||||
}
|
||||
@@ -1266,6 +1390,7 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl<CustomerArchiveM
|
||||
excel.setContactPhone(customer.getContactPhone());
|
||||
excel.setLegalPerson(customer.getLegalPerson());
|
||||
excel.setCreateTime(customer.getCreateTime());
|
||||
excel.setKingdeeStatusName(kingdeeStatusName(customer.getKingdeeStatus()));
|
||||
return excel;
|
||||
}
|
||||
|
||||
@@ -1286,6 +1411,19 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl<CustomerArchiveM
|
||||
return "草稿";
|
||||
}
|
||||
|
||||
private String kingdeeStatusName(String kingdeeStatus) {
|
||||
if (Objects.equals(kingdeeStatus, KINGDEE_STATUS_SYNCED)) {
|
||||
return "已推送";
|
||||
}
|
||||
if (Objects.equals(kingdeeStatus, KINGDEE_STATUS_EXIST)) {
|
||||
return "金蝶已有";
|
||||
}
|
||||
if (Objects.equals(kingdeeStatus, KINGDEE_STATUS_FAILED)) {
|
||||
return "推送失败";
|
||||
}
|
||||
return "未推送";
|
||||
}
|
||||
|
||||
private void validateLength(String value, int maxLength, String message) {
|
||||
if (Func.isNotEmpty(value) && value.length() > maxLength) {
|
||||
throw new ServiceException(message);
|
||||
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.transport.service.impl;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
import org.springblade.system.cache.DictBizCache;
|
||||
import org.springblade.system.pojo.entity.DictBiz;
|
||||
import org.springblade.thirdparty.bfi.constant.BfiConstant;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiCustomerGroupEntryDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiCustomerSaveDTO;
|
||||
import org.springblade.transport.constant.CustomerBfiConstants;
|
||||
import org.springblade.transport.pojo.vo.CustomerArchiveVO;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 客商档案金蝶(星瀚)报文转换器
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class CustomerBfiConverter {
|
||||
|
||||
/**
|
||||
* 数据来源系统编码,默认 WLTMS(运输TMS)
|
||||
*/
|
||||
@Value("${thirdParty.bfi.customer.srcSys:WLTMS}")
|
||||
private String srcSys;
|
||||
|
||||
/**
|
||||
* 创建组织.编码,默认 WLTMS,需与财务确认
|
||||
*/
|
||||
@Value("${thirdParty.bfi.customer.createOrg:WLTMS}")
|
||||
private String createOrg;
|
||||
|
||||
/**
|
||||
* 组装 A902-2 客户保存参数
|
||||
*
|
||||
* @param customer 客商档案
|
||||
* @return 客户保存参数
|
||||
*/
|
||||
public BfiCustomerSaveDTO buildSaveDTO(CustomerArchiveVO customer) {
|
||||
BfiCustomerSaveDTO param = new BfiCustomerSaveDTO();
|
||||
// 金蝶客户编码与 TMS 客商编号保持一致
|
||||
param.setNumber(customer.getCustomerCode());
|
||||
param.setStatus(BfiConstant.BILL_STATUS_SUBMITTED);
|
||||
param.setName(customer.getFullName());
|
||||
param.setSocietycreditcode(customer.getUnifiedCreditCode());
|
||||
param.setTxRegisterNo(customer.getUnifiedCreditCode());
|
||||
param.setArtificialperson(customer.getLegalPerson());
|
||||
param.setType(resolvePartnerType(customer.getCustomerNature()));
|
||||
param.setBizpartnerAddress(customer.getRegisteredAddress());
|
||||
param.setBusinessscope(buildBusinessScopeText(customer.getBusinessScope()));
|
||||
param.setBusinessterm(buildBusinessTerm(customer.getBusinessTermType(), customer.getBusinessEndDate()));
|
||||
param.setBizpartnerPhone(customer.getContactPhone());
|
||||
param.setFcusbeizhu(customer.getRemark());
|
||||
param.setBizfunction(CustomerBfiConstants.BIZ_FUNCTION_ALL);
|
||||
param.setAwrpDatasourcesys(srcSys);
|
||||
param.setAwrpCusfortrade(BfiConstant.CUS_FOR_TRADE_YES);
|
||||
param.setCreateorgNumber(createOrg);
|
||||
BfiCustomerGroupEntryDTO groupEntry = new BfiCustomerGroupEntryDTO();
|
||||
groupEntry.setStandardidNumber(BfiConstant.GROUP_STANDARD_BASIC);
|
||||
groupEntry.setGroupidNumber(BfiConstant.CUSTOMER_GROUP_EXTERNAL);
|
||||
param.setEntryGroupstandard(List.of(groupEntry));
|
||||
return param;
|
||||
}
|
||||
|
||||
/**
|
||||
* 客商性质(字典 dictKey)→ 金蝶伙伴类型编码,未命中走兜底值
|
||||
*
|
||||
* @param customerNature 客商性质字典值
|
||||
* @return 金蝶伙伴类型编码
|
||||
*/
|
||||
public String resolvePartnerType(String customerNature) {
|
||||
if (Func.isNotEmpty(customerNature)) {
|
||||
String partnerType = CustomerBfiConstants.NATURE_TYPE_MAPPING.get(customerNature.trim());
|
||||
if (StringUtil.isNotBlank(partnerType)) {
|
||||
return partnerType;
|
||||
}
|
||||
}
|
||||
return CustomerBfiConstants.DEFAULT_PARTNER_TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 经营范围多选编码 → 字典文本「、」拼接,字典缺失时回退原编码
|
||||
*
|
||||
* @param businessScope 逗号拼接的经营范围编码
|
||||
* @return 金蝶经营范围文本
|
||||
*/
|
||||
public String buildBusinessScopeText(String businessScope) {
|
||||
if (Func.isEmpty(businessScope)) {
|
||||
return "";
|
||||
}
|
||||
List<DictBiz> dictList = DictBizCache.getList("scope_of_business");
|
||||
Map<String, String> scopeNames = dictList == null ? Map.of() : dictList.stream()
|
||||
.collect(Collectors.toMap(DictBiz::getDictKey, DictBiz::getDictValue, (first, second) -> first));
|
||||
return Func.toStrList(businessScope.replace(",", ",")).stream()
|
||||
.map(code -> scopeNames.getOrDefault(code, code))
|
||||
.collect(Collectors.joining("、"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 营业期限:长期传「长期」;固定期限传「至 yyyy-MM-dd」(TMS 未采集起始日)
|
||||
*
|
||||
* @param businessTermType 营业期限类型
|
||||
* @param businessEndDate 营业期限截止日
|
||||
* @return 金蝶营业期限文本
|
||||
*/
|
||||
public String buildBusinessTerm(String businessTermType, LocalDate businessEndDate) {
|
||||
if (CustomerBfiConstants.BUSINESS_TERM_LONG.equals(businessTermType)) {
|
||||
return CustomerBfiConstants.BUSINESS_TERM_LONG;
|
||||
}
|
||||
return businessEndDate == null ? "" : "至 " + businessEndDate;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
-- 客商档案:金蝶(星瀚)协同字段
|
||||
-- kingdee_status:none未推送 / exist金蝶已有档案(A902-1查到已审核,跳过推送) / synced已推送成功 / failed推送失败或金蝶审核中
|
||||
-- 金蝶客户编码与 TMS 客商编号(customer_code)一致(A902-2 number 传入客商编号),无需单独存储
|
||||
|
||||
ALTER TABLE `blade_customer_archive`
|
||||
ADD COLUMN `kingdee_status` varchar(20) NOT NULL DEFAULT 'none' COMMENT '金蝶协同状态:none未推送/exist金蝶已有/synced已推送/failed推送失败' AFTER `approved_time`,
|
||||
ADD COLUMN `kingdee_fail_reason` varchar(500) NULL DEFAULT NULL COMMENT '金蝶推送失败原因' AFTER `kingdee_status`,
|
||||
ADD COLUMN `kingdee_sync_time` datetime NULL DEFAULT NULL COMMENT '金蝶推送时间' AFTER `kingdee_fail_reason`;
|
||||
|
||||
CREATE INDEX idx_kingdee_status ON blade_customer_archive (kingdee_status);
|
||||
|
||||
-- 列表「同步金蝶」按钮权限(审批通过后推送失败的重推入口;parent_id 通过菜单 code 关联,避免写死 id)
|
||||
INSERT INTO blade_menu (id, parent_id, code, name, alias, path, source, sort, category, action, is_open, component, remark, is_deleted)
|
||||
SELECT 2075431800000000001, m.id, 'customer_archive_sync', '同步金蝶', 'customer_archive_sync', '', '', 1, 2, 0, 1, '', '', 0
|
||||
FROM blade_menu m
|
||||
WHERE m.code = 'customer_archive' AND m.is_deleted = 0;
|
||||
Reference in New Issue
Block a user