diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/CustomerArchive.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/CustomerArchive.java
index 5ea8bec1..242d0f65 100644
--- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/CustomerArchive.java
+++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/CustomerArchive.java
@@ -115,6 +115,10 @@ public class CustomerArchive extends TenantEntity {
@Schema(description = "营业期限类型")
private String businessTermType;
+ @Schema(description = "营业期限开始日")
+ @TableField(updateStrategy = FieldStrategy.ALWAYS)
+ private LocalDate businessStartDate;
+
@Schema(description = "营业期限截止日")
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private LocalDate businessEndDate;
@@ -123,6 +127,10 @@ public class CustomerArchive extends TenantEntity {
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private BigDecimal registeredCapital;
+ @Schema(description = "实缴资本(万元)")
+ @TableField(updateStrategy = FieldStrategy.ALWAYS)
+ private BigDecimal paidInCapital;
+
@Schema(description = "客商负责人")
private String principal;
@@ -140,6 +148,10 @@ public class CustomerArchive extends TenantEntity {
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private BigDecimal applyCreditLimit;
+ @Schema(description = "已使用额度(万元),新建可录历史值,后续由收付款业务累加/减更新")
+ @TableField(updateStrategy = FieldStrategy.ALWAYS)
+ private BigDecimal usedCreditLimit;
+
@Schema(description = "备注")
private String remark;
diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/CustomerArchiveMapper.xml b/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/CustomerArchiveMapper.xml
index e6d9996c..2c04f248 100644
--- a/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/CustomerArchiveMapper.xml
+++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/CustomerArchiveMapper.xml
@@ -33,13 +33,16 @@
+
+
+
@@ -85,13 +88,16 @@
business_scope,
network_freight_platform,
business_term_type,
+ business_start_date,
business_end_date,
registered_capital,
+ paid_in_capital,
principal,
mnemonic_code,
customer_level,
max_credit_limit,
apply_credit_limit,
+ used_credit_limit,
remark,
qualification_attachments,
access_type,
diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/CustomerArchiveServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/CustomerArchiveServiceImpl.java
index a8444ebf..39d96798 100644
--- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/CustomerArchiveServiceImpl.java
+++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/CustomerArchiveServiceImpl.java
@@ -963,13 +963,16 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl() : customer.getContacts());
+ syncContactPhoneFromContacts(customer);
applyFixedOwnerDept(customer);
customer.setAccessType(Func.isEmpty(customer.getAccessType()) ? ACCESS_TEMPORARY : customer.getAccessType());
customer.setApprovalStatus(Func.isEmpty(customer.getApprovalStatus()) ? APPROVAL_DRAFT : customer.getApprovalStatus());
@@ -977,12 +980,33 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl() : customer.getContacts());
customer.setReceiptAccounts(customer.getReceiptAccounts() == null ? new ArrayList<>() : customer.getReceiptAccounts());
customer.setInvoices(customer.getInvoices() == null ? new ArrayList<>() : customer.getInvoices());
customer.setScores(customer.getScores() == null ? new ArrayList<>() : customer.getScores());
}
+ /**
+ * 主表联系电话改由联系人维护:取第一条有效联系人手机号回填,兼容历史 NOT NULL 及金蝶同步字段。
+ */
+ private void syncContactPhoneFromContacts(CustomerArchiveVO customer) {
+ if (Func.isNotEmpty(customer.getContactPhone())) {
+ customer.setContactPhone(trimToEmpty(customer.getContactPhone()));
+ return;
+ }
+ List contacts = customer.getContacts();
+ if (Func.isEmpty(contacts)) {
+ customer.setContactPhone(null);
+ return;
+ }
+ String phone = contacts.stream()
+ .map(CustomerContactVO::getContactPhone)
+ .filter(Func::isNotEmpty)
+ .map(String::trim)
+ .findFirst()
+ .orElse(null);
+ customer.setContactPhone(phone);
+ }
+
private void validateBase(CustomerArchiveVO customer) {
if (Func.isEmpty(customer.getFullName())) {
throw new ServiceException("客商全称不能为空");
@@ -1009,10 +1033,8 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl contacts = customer.getContacts() == null ? List.of() : customer.getContacts();
+ boolean hasContact = contacts.stream()
+ .anyMatch(item -> Func.isNotEmpty(item.getContactName()) || Func.isNotEmpty(item.getContactPhone()));
+ if (!hasContact) {
+ throw new ServiceException("请至少维护一条联系人");
+ }
+ }
+
private void validateCustomerType(String customerType) {
List typeList = Func.toStrList(customerType.replace(",", ","))
.stream()
@@ -2040,13 +2076,16 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl buildLinkmanEntries(CustomerArchiveVO customer) {
+ if (Func.isNotEmpty(customer.getContacts())) {
+ List entries = new ArrayList<>();
+ boolean defaultAssigned = false;
+ for (CustomerContactVO contact : customer.getContacts()) {
+ if (Func.isBlank(contact.getContactName()) && Func.isBlank(contact.getContactPhone())) {
+ continue;
+ }
+ BfiCustomerLinkmanEntryDTO entry = new BfiCustomerLinkmanEntryDTO();
+ entry.setContactperson(contact.getContactName());
+ entry.setPhone(contact.getContactPhone());
+ boolean isDefault = !defaultAssigned && (Objects.equals(contact.getIsDefault(), 1)
+ || Func.isNotBlank(contact.getContactName()));
+ entry.setIsdefaultLinkman(isDefault);
+ if (isDefault) {
+ defaultAssigned = true;
+ }
+ entries.add(entry);
+ }
+ if (!entries.isEmpty()) {
+ return entries;
+ }
+ }
if (Func.isBlank(customer.getPrincipal())) {
return List.of();
}
BfiCustomerLinkmanEntryDTO entry = new BfiCustomerLinkmanEntryDTO();
- // 联系人:客商负责人
entry.setContactperson(customer.getPrincipal());
- // 电话:联系电话
- entry.setPhone(customer.getContactPhone());
- // 默认联系人
+ entry.setPhone(this.resolveContactPhone(customer));
entry.setIsdefaultLinkman(Boolean.TRUE);
return List.of(entry);
}
+ private String resolveContactPhone(CustomerArchiveVO customer) {
+ if (Func.isNotBlank(customer.getContactPhone())) {
+ return customer.getContactPhone();
+ }
+ if (Func.isEmpty(customer.getContacts())) {
+ return null;
+ }
+ return customer.getContacts().stream()
+ .map(CustomerContactVO::getContactPhone)
+ .filter(Func::isNotBlank)
+ .findFirst()
+ .orElse(null);
+ }
+
/**
* 金蝶伙伴类型编码:客商性质(nature_of_client 字典)——
* 值为 dictKey(即伙伴类型编码,1~17)时直接使用;
@@ -248,35 +285,50 @@ public class CustomerBfiConverter {
}
/**
- * 经营范围多选编码 → 字典文本「、」拼接,字典缺失时回退原编码
+ * 经营范围:长文本直传;兼容历史多选编码 → 字典文本「、」拼接。
*
- * @param businessScope 逗号拼接的经营范围编码
+ * @param businessScope 经营范围长文本或历史逗号拼接编码
* @return 金蝶经营范围文本
*/
public String buildBusinessScopeText(String businessScope) {
if (Func.isEmpty(businessScope)) {
return "";
}
+ String text = businessScope.trim();
+ // 长文本(含中文描述)直接推送,不再按字典拆分
+ if (text.length() > 40 || text.contains(";") || text.contains("。") || text.contains("\n")) {
+ return text;
+ }
List dictList = DictBizCache.getList("scope_of_business");
Map scopeNames = dictList == null ? Map.of() : dictList.stream()
.collect(Collectors.toMap(DictBiz::getDictKey, DictBiz::getDictValue, (first, second) -> first));
- return Func.toStrList(businessScope.replace(",", ",")).stream()
+ return Func.toStrList(text.replace(",", ",")).stream()
.map(code -> scopeNames.getOrDefault(code, code))
.collect(Collectors.joining("、"));
}
/**
- * 营业期限:长期传「长期」;固定期限传「至 yyyy-MM-dd」(TMS 未采集起始日)
+ * 营业期限:长期传「长期」;固定期限传「yyyy-MM-dd 至 yyyy-MM-dd」或「至 yyyy-MM-dd」。
*
- * @param businessTermType 营业期限类型
- * @param businessEndDate 营业期限截止日
+ * @param businessTermType 营业期限类型
+ * @param businessStartDate 营业期限开始日
+ * @param businessEndDate 营业期限截止日
* @return 金蝶营业期限文本
*/
- public String buildBusinessTerm(String businessTermType, LocalDate businessEndDate) {
+ public String buildBusinessTerm(String businessTermType, LocalDate businessStartDate, LocalDate businessEndDate) {
if (CustomerBfiConstants.BUSINESS_TERM_LONG.equals(businessTermType)) {
- return CustomerBfiConstants.BUSINESS_TERM_LONG;
+ if (businessStartDate == null) {
+ return CustomerBfiConstants.BUSINESS_TERM_LONG;
+ }
+ return businessStartDate + " 至 " + CustomerBfiConstants.BUSINESS_TERM_LONG;
}
- return businessEndDate == null ? "" : "至 " + businessEndDate;
+ if (businessStartDate != null && businessEndDate != null) {
+ return businessStartDate + " 至 " + businessEndDate;
+ }
+ if (businessEndDate != null) {
+ return "至 " + businessEndDate;
+ }
+ return businessStartDate == null ? "" : String.valueOf(businessStartDate);
}
}
diff --git a/doc/sql/transport/blade_customer_archive.sql b/doc/sql/transport/blade_customer_archive.sql
index d2a0ef83..58bf476a 100644
--- a/doc/sql/transport/blade_customer_archive.sql
+++ b/doc/sql/transport/blade_customer_archive.sql
@@ -18,21 +18,24 @@ CREATE TABLE `blade_customer_archive` (
`registered_region_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '注册地址行政区划',
`registered_detail_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '注册地址详细地址',
`legal_person` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '法人/负责人',
- `contact_phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '联系电话',
+ `contact_phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '联系电话',
`dept_id` bigint NULL DEFAULT NULL COMMENT '所属组织ID',
`dept_ids` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属组织ID集合',
`dept_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '所属组织',
`invoice_tax_rate` decimal(6,2) NULL DEFAULT NULL COMMENT '开票税点',
- `business_scope` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '经营范围',
+ `business_scope` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '经营范围',
`network_freight_platform` tinyint NULL DEFAULT NULL COMMENT '网络货运平台:0否,1是',
`business_term_type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '营业期限类型',
+ `business_start_date` date NULL DEFAULT NULL COMMENT '营业期限开始日',
`business_end_date` date NULL DEFAULT NULL COMMENT '营业期限截止日',
`registered_capital` decimal(18,2) NULL DEFAULT NULL COMMENT '注册资金(万元)',
+ `paid_in_capital` decimal(18,2) NULL DEFAULT NULL COMMENT '实缴资本(万元)',
`principal` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '客商负责人',
`mnemonic_code` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '助记码',
`customer_level` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '客户等级',
`max_credit_limit` decimal(18,2) NULL DEFAULT NULL COMMENT '最大资金使用额度(万元)',
`apply_credit_limit` decimal(18,2) NULL DEFAULT NULL COMMENT '申请总资金使用额度(万元)',
+ `used_credit_limit` decimal(18,2) NULL DEFAULT NULL COMMENT '已使用额度(万元)',
`remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
`qualification_attachments` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '客商材料JSON',
`access_type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT 'temporary' COMMENT '准入类型:temporary临时,formal正式',
diff --git a/doc/sql/transport/blade_customer_archive_paid_in_used_credit_20261022.sql b/doc/sql/transport/blade_customer_archive_paid_in_used_credit_20261022.sql
new file mode 100644
index 00000000..08557073
--- /dev/null
+++ b/doc/sql/transport/blade_customer_archive_paid_in_used_credit_20261022.sql
@@ -0,0 +1,7 @@
+-- 客商档案:实缴资本、营业期限开始日、已使用额度;经营范围加长;联系电话改为可空(改由联系人维护)
+ALTER TABLE `blade_customer_archive`
+ ADD COLUMN `business_start_date` date NULL DEFAULT NULL COMMENT '营业期限开始日' AFTER `business_term_type`,
+ ADD COLUMN `paid_in_capital` decimal(18,2) NULL DEFAULT NULL COMMENT '实缴资本(万元)' AFTER `registered_capital`,
+ ADD COLUMN `used_credit_limit` decimal(18,2) NULL DEFAULT NULL COMMENT '已使用额度(万元)' AFTER `apply_credit_limit`,
+ MODIFY COLUMN `business_scope` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '经营范围',
+ MODIFY COLUMN `contact_phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '联系电话';