日志记录修改

This commit is contained in:
luojiaquan
2026-09-30 16:57:44 +08:00
parent 02c281fd07
commit 903d19cad1
9 changed files with 794 additions and 101 deletions
@@ -16,6 +16,17 @@ public class BmsCustomerLog extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 业务模块:客户档案 */
public static final String MODULE_MAIN = "main";
/** 业务模块:公司主体 */
public static final String MODULE_COMPANY = "company";
/** 业务模块:联系人 */
public static final String MODULE_CONTACT = "contact";
/** 业务模块:附件资料 */
public static final String MODULE_ATTACHMENT = "attachment";
/** 业务模块:绑定套餐 */
public static final String MODULE_PRICE_SET = "priceset";
/** 操作类型:新建 */
public static final String OP_INSERT = "1";
/** 操作类型:修改 */
@@ -35,6 +46,12 @@ public class BmsCustomerLog extends BaseEntity
/** 客户名称(操作时快照) */
private String customerName;
/** 业务模块(main/company/contact/attachment/priceset) */
private String bizModule;
/** 操作对象名称(公司全称/联系人姓名/文件名/套餐名) */
private String bizName;
/** 操作类型(1新建 2修改 3删除) */
private String operationType;
@@ -3,7 +3,12 @@ package com.bms.customer.customerinfo.service;
import java.util.List;
import com.bms.customer.customerinfo.domain.BmsCustomer;
import com.bms.customer.customerinfo.domain.BmsCustomerAttachment;
import com.bms.customer.customerinfo.domain.BmsCustomerCompany;
import com.bms.customer.customerinfo.domain.BmsCustomerContact;
import com.bms.customer.customerinfo.domain.BmsCustomerLog;
import com.bms.customer.customerinfo.domain.BmsCustomerPriceSet;
import com.bms.customer.customerinfo.domain.BmsPriceSetOption;
/**
* 客户业务操作日志Service接口
@@ -28,6 +33,60 @@ public interface IBmsCustomerLogService
*/
void recordDelete(BmsCustomer customer);
/**
* 记录新增公司主体
*/
void recordCompanyInsert(BmsCustomerCompany company);
/**
* 记录修改公司主体(字段级变更,无变更不记录)
*/
void recordCompanyUpdate(BmsCustomerCompany oldCompany, BmsCustomerCompany newCompany);
/**
* 记录删除公司主体
*/
void recordCompanyDelete(BmsCustomerCompany company);
/**
* 记录新增联系人
*/
void recordContactInsert(BmsCustomerContact contact);
/**
* 记录修改联系人(字段级变更,无变更不记录)
*/
void recordContactUpdate(BmsCustomerContact oldContact, BmsCustomerContact newContact);
/**
* 记录删除联系人
*/
void recordContactDelete(BmsCustomerContact contact);
/**
* 客户档案附件全量重建前后的差异记录(新增/删除/修改的文件逐条记录)
*
* @param oldList 重建前附件(客户档案模块)
* @param newList 重建后附件
*/
void recordAttachmentRebuild(List<BmsCustomerAttachment> oldList, List<BmsCustomerAttachment> newList);
/**
* 记录新增客户档案附件(随客户新建上传)
*/
void recordAttachmentInsert(BmsCustomerAttachment attachment);
/**
* 记录套餐绑定/更换(existing 为空=首次绑定)
*/
void recordPriceSetBind(BmsCustomer customer, BmsCustomerPriceSet existing,
BmsCustomerPriceSet bind, BmsPriceSetOption newSet);
/**
* 记录套餐解绑
*/
void recordPriceSetUnbind(BmsCustomerPriceSet bind);
/**
* 查询某客户的全部业务日志(时间倒序,含已解析的变更明细)
*/
@@ -1,7 +1,10 @@
package com.bms.customer.customerinfo.service.impl;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -12,9 +15,16 @@ import com.bms.common.core.domain.entity.SysUser;
import com.bms.common.utils.DateUtils;
import com.bms.common.utils.SecurityUtils;
import com.bms.customer.customerinfo.domain.BmsCustomer;
import com.bms.customer.customerinfo.domain.BmsCustomerAttachment;
import com.bms.customer.customerinfo.domain.BmsCustomerCompany;
import com.bms.customer.customerinfo.domain.BmsCustomerContact;
import com.bms.customer.customerinfo.domain.BmsCustomerLog;
import com.bms.customer.customerinfo.domain.BmsCustomerPriceSet;
import com.bms.customer.customerinfo.domain.BmsPriceSetOption;
import com.bms.customer.customerinfo.mapper.BmsCustomerLogMapper;
import com.bms.customer.customerinfo.service.IBmsCustomerLogService;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -30,6 +40,9 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
@Autowired
private BmsCustomerLogMapper bmsCustomerLogMapper;
private static final ThreadLocal<SimpleDateFormat> DATE_FMT =
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
/** 业务类型字典 */
private static final Map<String, String> CUSTOMER_TYPE_MAP = Map.of(
"0", "直客", "1", "同行", "2", "集运");
@@ -41,6 +54,17 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
private static final Map<String, String> SETTLEMENT_TYPE_MAP = Map.of(
"0", "月结", "1", "周结", "2", "日结");
/** 联系人类型字典 */
private static final Map<String, String> CONTACT_TYPE_MAP = Map.of(
"0", "业务联系人", "1", "财务联系人", "2", "紧急联系人", "3", "其他");
/** 是否类字典 */
private static final Map<String, String> YES_NO_MAP = Map.of("0", "否", "1", "是");
/** 附件分类字典 */
private static final Map<String, String> ATTACHMENT_TYPE_MAP = Map.of(
"0", "附件资料", "1", "客户Logo", "2", "合同文件", "3", "其他");
/**
* 需要记录日志的主表字段(顺序即展示顺序)。
* requireNonBlank 为 true 的字段对应 update SQL 的 &lt;if test="x!=null and x!=''"&gt;,
@@ -66,6 +90,80 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
new FieldDef("productCodes", "绑定产品", BmsCustomer::getProductCodes, false, Function.identity()),
new FieldDef("remark", "备注", BmsCustomer::getRemark, false, Function.identity()));
/** 公司主体需记录的字段(顺序即展示顺序) */
private static final LinkedHashMap<String, String> COMPANY_FIELDS = new LinkedHashMap<>();
static
{
COMPANY_FIELDS.put("companyNameFull", "公司全称");
COMPANY_FIELDS.put("englishName", "英文名称");
COMPANY_FIELDS.put("creditCode", "统一社会信用代码");
COMPANY_FIELDS.put("legalPerson", "法定代表人");
COMPANY_FIELDS.put("legalPersonPhone", "法定代表人电话");
COMPANY_FIELDS.put("registeredCapital", "注册资本(万元)");
COMPANY_FIELDS.put("capitalCurrency", "注册资本币种");
COMPANY_FIELDS.put("paidInCapital", "实收资本(万元)");
COMPANY_FIELDS.put("establishDate", "成立日期");
COMPANY_FIELDS.put("businessTermStart", "营业期限起");
COMPANY_FIELDS.put("businessTermEnd", "营业期限止");
COMPANY_FIELDS.put("businessTermPermanent", "是否长期有效");
COMPANY_FIELDS.put("registrationAuthority", "登记机关");
COMPANY_FIELDS.put("registrationNumber", "注册号");
COMPANY_FIELDS.put("operatingStatus", "经营状态");
COMPANY_FIELDS.put("employeeCount", "员工人数");
COMPANY_FIELDS.put("businessScope", "经营范围");
COMPANY_FIELDS.put("shareholders", "主要股东");
COMPANY_FIELDS.put("companyPhone", "公司电话");
COMPANY_FIELDS.put("companyFax", "公司传真");
COMPANY_FIELDS.put("companyWebsite", "公司网址");
COMPANY_FIELDS.put("companyEmail", "公司邮箱");
COMPANY_FIELDS.put("registeredProvince", "注册省份");
COMPANY_FIELDS.put("registeredCity", "注册城市");
COMPANY_FIELDS.put("registeredDistrict", "注册区县");
COMPANY_FIELDS.put("registeredAddressDetail", "注册详细地址");
COMPANY_FIELDS.put("remark", "备注");
}
/** 联系人需记录的字段 */
private static final LinkedHashMap<String, String> CONTACT_FIELDS = new LinkedHashMap<>();
static
{
CONTACT_FIELDS.put("contactName", "联系人姓名");
CONTACT_FIELDS.put("position", "职位");
CONTACT_FIELDS.put("department", "所属部门");
CONTACT_FIELDS.put("phone", "手机号");
CONTACT_FIELDS.put("landline", "座机");
CONTACT_FIELDS.put("email", "电子邮箱");
CONTACT_FIELDS.put("wechat", "微信号");
CONTACT_FIELDS.put("qq", "QQ号");
CONTACT_FIELDS.put("country", "国家/地区");
CONTACT_FIELDS.put("province", "省份");
CONTACT_FIELDS.put("city", "城市");
CONTACT_FIELDS.put("district", "区/县");
CONTACT_FIELDS.put("contactAddress", "详细地址");
CONTACT_FIELDS.put("postalCode", "邮政编码");
CONTACT_FIELDS.put("contactType", "联系人类型");
CONTACT_FIELDS.put("isDefault", "是否默认");
CONTACT_FIELDS.put("sortOrder", "排序");
}
/** 附件需记录的字段 */
private static final LinkedHashMap<String, String> ATTACHMENT_FIELDS = new LinkedHashMap<>();
static
{
ATTACHMENT_FIELDS.put("fileName", "文件名称");
ATTACHMENT_FIELDS.put("attachmentType", "附件分类");
ATTACHMENT_FIELDS.put("sortOrder", "排序");
ATTACHMENT_FIELDS.put("remark", "备注");
}
private static final Map<String, Map<String, String>> FIELD_DICTS = Map.of(
"businessTermPermanent", YES_NO_MAP,
"contactType", CONTACT_TYPE_MAP,
"isDefault", YES_NO_MAP,
"attachmentType", ATTACHMENT_TYPE_MAP);
/* ============================== 客户主表 ============================== */
@Override
public void recordInsert(BmsCustomer customer)
{
@@ -82,7 +180,8 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
changes.add(new BmsCustomerLog.FieldChange(def.field, def.label, "", value));
}
}
saveLog(customer, BmsCustomerLog.OP_INSERT, changes);
saveLog(customer.getCustomerId(), customer.getCustomerCode(), customer.getCustomerName(),
BmsCustomerLog.MODULE_MAIN, null, BmsCustomerLog.OP_INSERT, changes);
}
@Override
@@ -117,8 +216,8 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
{
return;
}
// 日志快照以修改后的客户编码/名称为准
saveLog(newCustomer, BmsCustomerLog.OP_UPDATE, changes);
saveLog(newCustomer.getCustomerId(), newCustomer.getCustomerCode(), newCustomer.getCustomerName(),
BmsCustomerLog.MODULE_MAIN, null, BmsCustomerLog.OP_UPDATE, changes);
}
@Override
@@ -128,9 +227,236 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
{
return;
}
saveLog(customer, BmsCustomerLog.OP_DELETE, null);
saveLog(customer.getCustomerId(), customer.getCustomerCode(), customer.getCustomerName(),
BmsCustomerLog.MODULE_MAIN, null, BmsCustomerLog.OP_DELETE, null);
}
/* ============================== 公司主体 ============================== */
@Override
public void recordCompanyInsert(BmsCustomerCompany company)
{
if (company == null || company.getCustomerId() == null)
{
return;
}
saveLog(company.getCustomerId(), null, null, BmsCustomerLog.MODULE_COMPANY,
company.getCompanyNameFull(), BmsCustomerLog.OP_INSERT,
beanInsertChanges(company, COMPANY_FIELDS));
}
@Override
public void recordCompanyUpdate(BmsCustomerCompany oldCompany, BmsCustomerCompany newCompany)
{
if (oldCompany == null || newCompany == null || newCompany.getCustomerId() == null)
{
return;
}
List<BmsCustomerLog.FieldChange> changes = beanDiff(oldCompany, newCompany, COMPANY_FIELDS);
if (changes.isEmpty())
{
return;
}
String bizName = trimToNull(newCompany.getCompanyNameFull());
if (bizName == null)
{
bizName = oldCompany.getCompanyNameFull();
}
saveLog(newCompany.getCustomerId(), null, null, BmsCustomerLog.MODULE_COMPANY,
bizName, BmsCustomerLog.OP_UPDATE, changes);
}
@Override
public void recordCompanyDelete(BmsCustomerCompany company)
{
if (company == null || company.getCustomerId() == null)
{
return;
}
saveLog(company.getCustomerId(), null, null, BmsCustomerLog.MODULE_COMPANY,
company.getCompanyNameFull(), BmsCustomerLog.OP_DELETE, null);
}
/* ============================== 联系人 ============================== */
@Override
public void recordContactInsert(BmsCustomerContact contact)
{
if (contact == null || contact.getCustomerId() == null)
{
return;
}
saveLog(contact.getCustomerId(), null, null, BmsCustomerLog.MODULE_CONTACT,
contact.getContactName(), BmsCustomerLog.OP_INSERT,
beanInsertChanges(contact, CONTACT_FIELDS));
}
@Override
public void recordContactUpdate(BmsCustomerContact oldContact, BmsCustomerContact newContact)
{
if (oldContact == null || newContact == null || newContact.getCustomerId() == null)
{
return;
}
List<BmsCustomerLog.FieldChange> changes = beanDiff(oldContact, newContact, CONTACT_FIELDS);
if (changes.isEmpty())
{
return;
}
String bizName = trimToNull(newContact.getContactName());
if (bizName == null)
{
bizName = oldContact.getContactName();
}
saveLog(newContact.getCustomerId(), null, null, BmsCustomerLog.MODULE_CONTACT,
bizName, BmsCustomerLog.OP_UPDATE, changes);
}
@Override
public void recordContactDelete(BmsCustomerContact contact)
{
if (contact == null || contact.getCustomerId() == null)
{
return;
}
saveLog(contact.getCustomerId(), null, null, BmsCustomerLog.MODULE_CONTACT,
contact.getContactName(), BmsCustomerLog.OP_DELETE, null);
}
/* ============================== 附件 ============================== */
@Override
public void recordAttachmentInsert(BmsCustomerAttachment attachment)
{
if (attachment == null || attachment.getCustomerId() == null)
{
return;
}
saveLog(attachment.getCustomerId(), null, null, BmsCustomerLog.MODULE_ATTACHMENT,
attachment.getFileName(), BmsCustomerLog.OP_INSERT,
beanInsertChanges(attachment, ATTACHMENT_FIELDS));
}
@Override
public void recordAttachmentRebuild(List<BmsCustomerAttachment> oldListIn, List<BmsCustomerAttachment> newListIn)
{
List<BmsCustomerAttachment> oldList = safe(oldListIn);
List<BmsCustomerAttachment> newList = safe(newListIn);
Map<String, BmsCustomerAttachment> oldMap = new LinkedHashMap<>();
for (BmsCustomerAttachment a : oldList)
{
if (a.getFilePath() != null)
{
oldMap.put(a.getFilePath(), a);
}
}
Map<String, BmsCustomerAttachment> newMap = new LinkedHashMap<>();
for (BmsCustomerAttachment a : newList)
{
if (a.getFilePath() != null)
{
newMap.put(a.getFilePath(), a);
}
}
Long customerId = null;
if (!oldList.isEmpty())
{
customerId = oldList.get(0).getCustomerId();
}
if (!newList.isEmpty())
{
customerId = newList.get(0).getCustomerId();
}
if (customerId == null)
{
return;
}
// 新增的文件
for (Map.Entry<String, BmsCustomerAttachment> e : newMap.entrySet())
{
if (!oldMap.containsKey(e.getKey()))
{
saveLog(customerId, null, null, BmsCustomerLog.MODULE_ATTACHMENT,
e.getValue().getFileName(), BmsCustomerLog.OP_INSERT,
beanInsertChanges(e.getValue(), ATTACHMENT_FIELDS));
}
}
// 修改的文件(分类/排序/备注/文件名)
for (Map.Entry<String, BmsCustomerAttachment> e : newMap.entrySet())
{
BmsCustomerAttachment old = oldMap.get(e.getKey());
if (old == null)
{
continue;
}
List<BmsCustomerLog.FieldChange> changes = beanDiff(old, e.getValue(), ATTACHMENT_FIELDS);
if (!changes.isEmpty())
{
String fileName = trimToNull(e.getValue().getFileName());
saveLog(customerId, null, null, BmsCustomerLog.MODULE_ATTACHMENT,
fileName != null ? fileName : old.getFileName(), BmsCustomerLog.OP_UPDATE, changes);
}
}
// 删除的文件
for (Map.Entry<String, BmsCustomerAttachment> e : oldMap.entrySet())
{
if (!newMap.containsKey(e.getKey()))
{
saveLog(customerId, null, null, BmsCustomerLog.MODULE_ATTACHMENT,
e.getValue().getFileName(), BmsCustomerLog.OP_DELETE, null);
}
}
}
/* ============================== 套餐绑定 ============================== */
@Override
public void recordPriceSetBind(BmsCustomer customer, BmsCustomerPriceSet existing,
BmsCustomerPriceSet bind, BmsPriceSetOption newSet)
{
if (bind == null || bind.getCustomerId() == null || newSet == null)
{
return;
}
List<BmsCustomerLog.FieldChange> changes = new ArrayList<>();
changes.add(new BmsCustomerLog.FieldChange("priceSetName", "套餐",
existing == null ? "" : nz(existing.getPriceSetName()), nz(newSet.getPriceSetName())));
changes.add(new BmsCustomerLog.FieldChange("bindPriority", "优先级",
existing == null ? "" : numText(existing.getBindPriority()), numText(bind.getBindPriority())));
changes.add(new BmsCustomerLog.FieldChange("prBegindate", "生效日期",
existing == null ? "" : dateText(existing.getPrBegindate()), dateText(bind.getPrBegindate())));
changes.add(new BmsCustomerLog.FieldChange("prEnddate", "失效日期",
existing == null ? "长期" : dateTextOrLong(existing.getPrEnddate()), dateTextOrLong(bind.getPrEnddate())));
changes.add(new BmsCustomerLog.FieldChange("priceSetNote", "备注",
existing == null ? "" : nz(existing.getPriceSetNote()), nz(bind.getPriceSetNote())));
List<BmsCustomerLog.FieldChange> realChanges = new ArrayList<>();
for (BmsCustomerLog.FieldChange c : changes)
{
if (!Objects.equals(emptyToEmpty(c.getOldValue()), emptyToEmpty(c.getNewValue())))
{
realChanges.add(c);
}
}
saveLog(bind.getCustomerId(), customer == null ? null : customer.getCustomerCode(),
customer == null ? null : customer.getCustomerName(),
BmsCustomerLog.MODULE_PRICE_SET, newSet.getPriceSetName(),
existing == null ? BmsCustomerLog.OP_INSERT : BmsCustomerLog.OP_UPDATE, realChanges);
}
@Override
public void recordPriceSetUnbind(BmsCustomerPriceSet bind)
{
if (bind == null || bind.getCustomerId() == null)
{
return;
}
saveLog(bind.getCustomerId(), bind.getCustomerCode(), bind.getCustomerName(),
BmsCustomerLog.MODULE_PRICE_SET, bind.getPriceSetName(),
BmsCustomerLog.OP_DELETE, null);
}
/* ============================== 查询 ============================== */
@Override
public List<BmsCustomerLog> selectByCustomerId(Long customerId)
{
@@ -145,12 +471,18 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
return list;
}
private void saveLog(BmsCustomer customer, String operationType, List<BmsCustomerLog.FieldChange> changes)
/* ============================== 内部工具 ============================== */
private void saveLog(Long customerId, String customerCode, String customerName,
String module, String bizName, String operationType,
List<BmsCustomerLog.FieldChange> changes)
{
BmsCustomerLog log = new BmsCustomerLog();
log.setCustomerId(customer.getCustomerId());
log.setCustomerCode(customer.getCustomerCode());
log.setCustomerName(customer.getCustomerName());
log.setCustomerId(customerId);
log.setCustomerCode(customerCode);
log.setCustomerName(customerName);
log.setBizModule(module);
log.setBizName(bizName);
log.setOperationType(operationType);
if (changes != null)
{
@@ -170,6 +502,88 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
bmsCustomerLogMapper.insertBmsCustomerLog(log);
}
/** 新增场景:取所有非空字段作为初始值 */
private List<BmsCustomerLog.FieldChange> beanInsertChanges(Object bean, LinkedHashMap<String, String> fields)
{
List<BmsCustomerLog.FieldChange> changes = new ArrayList<>();
BeanWrapper bw = new BeanWrapperImpl(bean);
for (Map.Entry<String, String> f : fields.entrySet())
{
String value = displayValue(bw, f.getKey());
if (value != null && !value.isEmpty())
{
changes.add(new BmsCustomerLog.FieldChange(f.getKey(), f.getValue(), "", value));
}
}
return changes;
}
/** 修改场景:逐字段比对,返回变化项 */
private List<BmsCustomerLog.FieldChange> beanDiff(Object oldBean, Object newBean,
LinkedHashMap<String, String> fields)
{
List<BmsCustomerLog.FieldChange> changes = new ArrayList<>();
BeanWrapper oldBw = new BeanWrapperImpl(oldBean);
BeanWrapper newBw = new BeanWrapperImpl(newBean);
for (Map.Entry<String, String> f : fields.entrySet())
{
Object newRaw = newBw.getPropertyValue(f.getKey());
// 与 update 动态 SQL 保持一致:新值为 null 的字段本次不落库,不参与比对
if (newRaw == null)
{
continue;
}
Object oldRaw = oldBw.getPropertyValue(f.getKey());
if (!sameValue(oldRaw, newRaw))
{
changes.add(new BmsCustomerLog.FieldChange(f.getKey(), f.getValue(),
nz(displayValue(oldBw, f.getKey())), nz(displayValue(newBw, f.getKey()))));
}
}
return changes;
}
/** 字段值 -> 日志展示文本(字典翻译/日期格式化) */
private String displayValue(BeanWrapper bw, String field)
{
Object raw = bw.getPropertyValue(field);
if (raw == null)
{
return "";
}
if (raw instanceof Date)
{
return DATE_FMT.get().format((Date) raw);
}
String text = raw.toString();
if (text.isEmpty())
{
return "";
}
Map<String, String> dict = FIELD_DICTS.get(field);
if (dict != null)
{
String translated = dict.get(text);
return translated != null ? translated : text;
}
return text;
}
private static List<BmsCustomerAttachment> safe(List<BmsCustomerAttachment> list)
{
return list == null ? List.of() : list;
}
private static String emptyToEmpty(String s)
{
return s == null ? "" : s;
}
private static String nz(String s)
{
return s == null ? "" : s;
}
/** 人员字段展示:姓名(工号),缺姓名时只显示工号 */
private static String userDisplay(String code, String name)
{
@@ -195,6 +609,16 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
return num == null ? "" : num.toString();
}
private static String dateText(Date date)
{
return date == null ? "" : DATE_FMT.get().format(date);
}
private static String dateTextOrLong(Date date)
{
return date == null ? "长期" : DATE_FMT.get().format(date);
}
private static String trimToNull(String s)
{
if (s == null)
@@ -205,18 +629,32 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
return t.isEmpty() ? null : t;
}
/** 数值按大小比较(规避 BigDecimal 精度差异),其余按字符串比较 */
/** 数值按大小比较(规避 BigDecimal 精度差异),日期按时间比较,其余按字符串比较 */
private static boolean sameValue(Object a, Object b)
{
if (a instanceof BigDecimal && b instanceof BigDecimal)
{
return ((BigDecimal) a).compareTo((BigDecimal) b) == 0;
}
return Objects.equals(a == null ? null : a.toString(), b == null ? null : b.toString());
if (a instanceof Date && b instanceof Date)
{
return ((Date) a).getTime() == ((Date) b).getTime();
}
String sa = a == null ? null : a.toString();
String sb = b == null ? null : b.toString();
if ("".equals(sa))
{
sa = null;
}
if ("".equals(sb))
{
sb = null;
}
return Objects.equals(sa, sb);
}
/**
* 字段定义
* 主表字段定义
*/
private static final class FieldDef
{
@@ -9,6 +9,7 @@ import com.bms.customer.customerinfo.domain.BmsCustomer;
import com.bms.customer.customerinfo.domain.BmsCustomerPriceSet;
import com.bms.customer.customerinfo.domain.BmsPriceSetOption;
import com.bms.customer.customerinfo.mapper.BmsCustomerPriceSetMapper;
import com.bms.customer.customerinfo.service.IBmsCustomerLogService;
import com.bms.customer.customerinfo.service.IBmsCustomerPriceSetService;
import com.bms.customer.customerinfo.service.IBmsCustomerService;
@@ -27,6 +28,9 @@ public class BmsCustomerPriceSetServiceImpl implements IBmsCustomerPriceSetServi
@Autowired
private IBmsCustomerService customerService;
@Autowired
private IBmsCustomerLogService customerLogService;
@Override
public List<BmsCustomerPriceSet> selectBindList(Long customerId)
{
@@ -85,19 +89,37 @@ public class BmsCustomerPriceSetServiceImpl implements IBmsCustomerPriceSetServi
bind.setCustomerName(customer.getCustomerName());
BmsCustomerPriceSet existing = bindMapper.selectBindByCustomerId(bind.getCustomerId());
// selectBindByCustomerId 未关联套餐表,补取旧套餐名用于日志展示
if (existing != null && existing.getPriceSetId() != null)
{
BmsPriceSetOption oldSet = bindMapper.selectPriceSetOptionById(existing.getPriceSetId());
if (oldSet != null)
{
existing.setPriceSetName(oldSet.getPriceSetName());
}
}
int rows;
try
{
if (existing != null)
{
bind.setCustomerPricesetId(existing.getCustomerPricesetId());
return bindMapper.updateBind(bind);
rows = bindMapper.updateBind(bind);
}
else
{
rows = bindMapper.insertBind(bind);
}
return bindMapper.insertBind(bind);
}
catch (DuplicateKeyException e)
{
throw new ServiceException("该客户已存在套餐绑定,请勿重复绑定");
}
if (rows > 0)
{
customerLogService.recordPriceSetBind(customer, existing, bind, set);
}
return rows;
}
@Override
@@ -107,6 +129,24 @@ public class BmsCustomerPriceSetServiceImpl implements IBmsCustomerPriceSetServi
{
throw new ServiceException("请选择要解绑的记录");
}
return bindMapper.deleteBindByIds(customerPricesetIds);
// 删除前逐个取快照,用于解绑日志
List<BmsCustomerPriceSet> snapshots = new java.util.ArrayList<>();
for (Long id : customerPricesetIds)
{
BmsCustomerPriceSet snapshot = bindMapper.selectBindById(id);
if (snapshot != null)
{
snapshots.add(snapshot);
}
}
int rows = bindMapper.deleteBindByIds(customerPricesetIds);
if (rows > 0)
{
for (BmsCustomerPriceSet snapshot : snapshots)
{
customerLogService.recordPriceSetUnbind(snapshot);
}
}
return rows;
}
}
@@ -98,6 +98,15 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
*/
@Override
public void saveBmsCustomerAttachments(Long customerId, List<BmsCustomerAttachment> attachmentList)
{
saveBmsCustomerAttachments(customerId, attachmentList, false);
}
/**
* 批量保存客户附件。
* @param logInsert true=随客户新建上传,逐文件记新增日志;false=编辑页全量重建,日志由重建差异统一记录
*/
private void saveBmsCustomerAttachments(Long customerId, List<BmsCustomerAttachment> attachmentList, boolean logInsert)
{
if (attachmentList == null || attachmentList.isEmpty())
{
@@ -123,6 +132,10 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
item.setCreateBy(user.getUserName());
item.setCreateTime(DateUtils.getNowDate());
bmsCustomerMapper.insertBmsCustomerAttachment(item);
if (logInsert)
{
customerLogService.recordAttachmentInsert(item);
}
}
}
}
@@ -167,7 +180,12 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
{
bmsCustomerCompany.setDelFlag("0");
}
return bmsCustomerMapper.insertBmsCustomerCompany(bmsCustomerCompany);
int rows = bmsCustomerMapper.insertBmsCustomerCompany(bmsCustomerCompany);
if (rows > 0)
{
customerLogService.recordCompanyInsert(bmsCustomerCompany);
}
return rows;
}
/**
@@ -176,10 +194,17 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
@Override
public int updateBmsCustomerCompany(BmsCustomerCompany bmsCustomerCompany)
{
BmsCustomerCompany old = bmsCustomerCompany.getCompanyId() == null ? null
: bmsCustomerMapper.selectBmsCustomerCompanyByCompanyId(bmsCustomerCompany.getCompanyId());
SysUser user = SecurityUtils.getLoginUser().getUser();
bmsCustomerCompany.setUpdateBy(user.getUserName());
bmsCustomerCompany.setUpdateTime(DateUtils.getNowDate());
return bmsCustomerMapper.updateBmsCustomerCompany(bmsCustomerCompany);
int rows = bmsCustomerMapper.updateBmsCustomerCompany(bmsCustomerCompany);
if (rows > 0)
{
customerLogService.recordCompanyUpdate(old, bmsCustomerCompany);
}
return rows;
}
/**
@@ -191,7 +216,12 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
int rows = 0;
for (Long companyId : companyIds)
{
BmsCustomerCompany snapshot = bmsCustomerMapper.selectBmsCustomerCompanyByCompanyId(companyId);
rows += bmsCustomerMapper.deleteBmsCustomerCompanyByCompanyId(companyId);
if (snapshot != null)
{
customerLogService.recordCompanyDelete(snapshot);
}
}
return rows;
}
@@ -216,15 +246,18 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
}
if (item.getCompanyId() != null)
{
BmsCustomerCompany old = bmsCustomerMapper.selectBmsCustomerCompanyByCompanyId(item.getCompanyId());
item.setUpdateBy(user.getUserName());
item.setUpdateTime(DateUtils.getNowDate());
bmsCustomerMapper.updateBmsCustomerCompany(item);
customerLogService.recordCompanyUpdate(old, item);
}
else
{
item.setCreateBy(user.getUserName());
item.setCreateTime(DateUtils.getNowDate());
bmsCustomerMapper.insertBmsCustomerCompany(item);
customerLogService.recordCompanyInsert(item);
}
}
}
@@ -245,7 +278,7 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
int rows = bmsCustomerMapper.insertBmsCustomer(bmsCustomer);
if (rows > 0)
{
saveBmsCustomerAttachments(bmsCustomer.getCustomerId(), bmsCustomer.getAttachmentList());
saveBmsCustomerAttachments(bmsCustomer.getCustomerId(), bmsCustomer.getAttachmentList(), true);
saveBmsCustomerCompanies(bmsCustomer.getCustomerId(), bmsCustomer.getCompanyList());
saveBmsCustomerContacts(bmsCustomer.getCustomerId(), bmsCustomer.getContactList());
// 新建客户即初始化默认CNY账户:余额0、总额度1000 CNY,写INIT流水
@@ -271,6 +304,11 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
bmsCustomer.setUpdateBy(user.getUserName());
// 修改前先取旧值快照,用于业务日志记录字段级变更
BmsCustomer oldCustomer = bmsCustomerMapper.selectBmsCustomerByCustomerId(bmsCustomer.getCustomerId());
// 附件重建前取旧档案附件快照,重建后按文件差异记业务日志
BmsCustomerAttachment attachmentQuery = new BmsCustomerAttachment();
attachmentQuery.setCustomerId(bmsCustomer.getCustomerId());
attachmentQuery.setBizType(BmsCustomerAttachment.BIZ_TYPE_CUSTOMER);
List<BmsCustomerAttachment> oldAttachments = bmsCustomerMapper.selectBmsCustomerAttachmentList(attachmentQuery);
// 仅重建客户档案模块的附件,收款水单等其他业务模块的附件保留不动
bmsCustomerMapper.deleteBmsCustomerProfileAttachmentByCustomerId(bmsCustomer.getCustomerId());
if (bmsCustomer.getAttachmentList() != null)
@@ -286,10 +324,12 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
// 联系人采用增量 upsert
saveBmsCustomerContacts(bmsCustomer.getCustomerId(), bmsCustomer.getContactList());
int rows = bmsCustomerMapper.updateBmsCustomer(bmsCustomer);
// 业务日志:修改(字段级 修改前→修改后;无实际变更时不记录)
if (rows > 0)
{
// 业务日志:主表字段级修改(无实际变更时不记录)
customerLogService.recordUpdate(oldCustomer, bmsCustomer);
// 业务日志:附件新增/删除/修改差异
customerLogService.recordAttachmentRebuild(oldAttachments, bmsCustomer.getAttachmentList());
}
return rows;
}
@@ -384,7 +424,12 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
{
bmsCustomerContact.setDelFlag("0");
}
return bmsCustomerMapper.insertBmsCustomerContact(bmsCustomerContact);
int rows = bmsCustomerMapper.insertBmsCustomerContact(bmsCustomerContact);
if (rows > 0)
{
customerLogService.recordContactInsert(bmsCustomerContact);
}
return rows;
}
/**
@@ -393,10 +438,17 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
@Override
public int updateBmsCustomerContact(BmsCustomerContact bmsCustomerContact)
{
BmsCustomerContact old = bmsCustomerContact.getContactId() == null ? null
: bmsCustomerMapper.selectBmsCustomerContactByContactId(bmsCustomerContact.getContactId());
SysUser user = SecurityUtils.getLoginUser().getUser();
bmsCustomerContact.setUpdateBy(user.getUserName());
bmsCustomerContact.setUpdateTime(DateUtils.getNowDate());
return bmsCustomerMapper.updateBmsCustomerContact(bmsCustomerContact);
int rows = bmsCustomerMapper.updateBmsCustomerContact(bmsCustomerContact);
if (rows > 0)
{
customerLogService.recordContactUpdate(old, bmsCustomerContact);
}
return rows;
}
/**
@@ -408,7 +460,12 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
int rows = 0;
for (Long contactId : contactIds)
{
BmsCustomerContact snapshot = bmsCustomerMapper.selectBmsCustomerContactByContactId(contactId);
rows += bmsCustomerMapper.deleteBmsCustomerContactByContactId(contactId);
if (snapshot != null)
{
customerLogService.recordContactDelete(snapshot);
}
}
return rows;
}
@@ -433,15 +490,18 @@ public class BmsCustomerServiceImpl implements IBmsCustomerService
}
if (item.getContactId() != null)
{
BmsCustomerContact old = bmsCustomerMapper.selectBmsCustomerContactByContactId(item.getContactId());
item.setUpdateBy(user.getUserName());
item.setUpdateTime(DateUtils.getNowDate());
bmsCustomerMapper.updateBmsCustomerContact(item);
customerLogService.recordContactUpdate(old, item);
}
else
{
item.setCreateBy(user.getUserName());
item.setCreateTime(DateUtils.getNowDate());
bmsCustomerMapper.insertBmsCustomerContact(item);
customerLogService.recordContactInsert(item);
}
}
}