feat: customer contact log

This commit is contained in:
AgAngle
2025-04-01 15:10:53 +08:00
committed by jianxing
parent 25bc44cabe
commit 02efd3ef1c
9 changed files with 193 additions and 46 deletions

View File

@@ -0,0 +1,47 @@
package io.cordys.crm.customer.service;
import io.cordys.common.constants.BusinessModuleField;
import io.cordys.common.constants.FormKey;
import io.cordys.common.dto.JsonDifferenceDTO;
import io.cordys.crm.customer.domain.Customer;
import io.cordys.crm.system.service.BaseModuleLogService;
import io.cordys.mybatis.BaseMapper;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@Transactional(rollbackFor = Exception.class)
public class CustomerContactLogService extends BaseModuleLogService {
@Resource
private BaseMapper<Customer> customerMapper;
@Override
public void handleLogField(List<JsonDifferenceDTO> differenceDTOS, String orgId) {
super.handleModuleLogField(differenceDTOS, orgId, FormKey.CONTACT.getKey());
for (JsonDifferenceDTO differ : differenceDTOS) {
if (StringUtils.equals(differ.getColumn(), BusinessModuleField.CUSTOMER_CONTACT_OWNER.getBusinessKey())) {
setUserFieldName(differ);
}
if (StringUtils.equals(differ.getColumn(), BusinessModuleField.CUSTOMER_CONTACT_CUSTOMER.getBusinessKey())) {
if (differ.getOldValue() != null) {
Customer customer = customerMapper.selectByPrimaryKey(differ.getOldValue().toString());
if (customer != null) {
differ.setOldValueName(customer.getName());
}
}
if (differ.getNewValue() != null) {
Customer customer = customerMapper.selectByPrimaryKey(differ.getNewValue().toString());
if (customer != null) {
differ.setNewValueName(customer.getName());
}
}
}
}
}
}

View File

@@ -3,11 +3,11 @@ package io.cordys.crm.system.controller;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.cordys.common.constants.PermissionConstants;
import io.cordys.common.dto.JsonDifferenceDTO;
import io.cordys.common.pager.PageUtils;
import io.cordys.common.pager.Pager;
import io.cordys.context.OrganizationContext;
import io.cordys.crm.system.dto.request.OperationLogRequest;
import io.cordys.crm.system.dto.response.OperationLogDetailResponse;
import io.cordys.crm.system.dto.response.OperationLogResponse;
import io.cordys.crm.system.service.SysOperationLogService;
import io.swagger.v3.oas.annotations.Operation;
@@ -38,7 +38,7 @@ public class OperationLogController {
@GetMapping("/detail/{id}")
@Operation(summary = "系统管理-操作日志-详情")
@RequiresPermissions(PermissionConstants.OPERATION_LOG_READ)
public List<JsonDifferenceDTO> logDetail(@PathVariable String id) {
public OperationLogDetailResponse logDetail(@PathVariable String id) {
return sysOperationLogService.getLogDetail(id, OrganizationContext.getOrganizationId());
}
}

View File

@@ -0,0 +1,39 @@
package io.cordys.crm.system.dto.response;
import io.cordys.common.dto.JsonDifferenceDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
@Data
public class OperationLogDetailResponse implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "id")
private String id;
@Schema(description = "操作人")
private String operator;
@Schema(description = "操作人名称")
private String operatorName;
@Schema(description = "操作时间")
private Long createTime;
@Schema(description = "操作对象")
private String module;
@Schema(description = "操作类型")
private String type;
@Schema(description = "资源名称")
private String resourceName;
@Schema(description = "字段差异")
private List<JsonDifferenceDTO> diffs = List.of();
}

View File

@@ -17,6 +17,9 @@ public class OperationLogResponse implements Serializable {
@Schema(description = "操作人")
private String operator;
@Schema(description = "操作人名称")
private String operatorName;
@Schema(description = "操作时间")
private Long createTime;

View File

@@ -20,6 +20,13 @@ public abstract class BaseModuleLogService {
abstract public void handleLogField(List<JsonDifferenceDTO> differenceDTOS, String orgId);
/**
* 处理非业务字段的自定义字段
* 同时会翻译其他字段的 ColumnName
* @param differenceDTOS
* @param orgId
* @param formKey
*/
protected void handleModuleLogField(List<JsonDifferenceDTO> differenceDTOS, String orgId, String formKey) {
ModuleFormConfigDTO customerFormConfig = CommonBeanFactory.getBean(ModuleFormCacheService.class)
.getBusinessFormConfig(formKey, orgId);
@@ -59,14 +66,23 @@ public abstract class BaseModuleLogService {
// 设置字段值名称
setColumnValueName(optionMap, differ);
} else {
//主表字段
differ.setColumnName(Translator.get("log." + differ.getColumn()));
differ.setOldValueName(differ.getOldValue());
differ.setNewValueName(differ.getNewValue());
translatorDifferInfo(differ);
}
});
}
/**
* 翻译字段名称
* 赋值旧值名称和新值名称
* @param differ
*/
public static void translatorDifferInfo(JsonDifferenceDTO differ) {
//主表字段
differ.setColumnName(Translator.get("log." + differ.getColumn()));
differ.setOldValueName(differ.getOldValue());
differ.setNewValueName(differ.getNewValue());
}
private void setColumnValueName(Map<String, List<OptionDTO>> optionMap, JsonDifferenceDTO differ) {
List<OptionDTO> options = optionMap.get(differ.getColumn());
if (options == null) {

View File

@@ -1,16 +1,22 @@
package io.cordys.crm.system.service;
import io.cordys.aspectj.constants.LogModule;
import io.cordys.common.util.CommonBeanFactory;
import io.cordys.crm.customer.service.CustomerContactLogService;
import io.cordys.crm.customer.service.CustomerLogService;
import java.util.HashMap;
public class ModuleLogServiceFactory {
private static final HashMap<String, BaseModuleLogService> logServiceMap = new HashMap<>();
static {
logServiceMap.put(LogModule.CUSTOMER, CommonBeanFactory.getBean(CustomerLogService.class));
logServiceMap.put(LogModule.CUSTOMER_CONTACT, CommonBeanFactory.getBean(CustomerContactLogService.class));
}
public static BaseModuleLogService getModuleLogService(String type) {
switch (type) {
case "CUSTOMER":
return CommonBeanFactory.getBean(CustomerLogService.class);
default:
return null;
}
return logServiceMap.get(type);
}
}

View File

@@ -3,11 +3,14 @@ package io.cordys.crm.system.service;
import io.cordys.common.dto.JsonDifferenceDTO;
import io.cordys.common.dto.OptionDTO;
import io.cordys.common.exception.GenericException;
import io.cordys.common.service.BaseService;
import io.cordys.common.util.BeanUtils;
import io.cordys.common.util.JsonDifferenceUtils;
import io.cordys.common.util.Translator;
import io.cordys.crm.system.domain.OperationLog;
import io.cordys.crm.system.domain.OperationLogBlob;
import io.cordys.crm.system.dto.request.OperationLogRequest;
import io.cordys.crm.system.dto.response.OperationLogDetailResponse;
import io.cordys.crm.system.dto.response.OperationLogResponse;
import io.cordys.crm.system.mapper.ExtOperationLogMapper;
import io.cordys.crm.system.mapper.ExtUserMapper;
@@ -39,6 +42,8 @@ public class SysOperationLogService {
private BaseMapper<OperationLogBlob> operationLogBlobMapper;
@Resource
private BaseMapper<OperationLog> operationLogMapper;
@Resource
private BaseService baseService;
/**
* 操作日志列表查询
@@ -65,7 +70,7 @@ public class SysOperationLogService {
Map<String, String> userMap = userList.stream()
.collect(Collectors.toMap(OptionDTO::getId, OptionDTO::getName));
list.forEach(item -> item.setOperator(userMap.getOrDefault(item.getOperator(), StringUtils.EMPTY)));
list.forEach(item -> item.setOperatorName(userMap.getOrDefault(item.getOperator(), StringUtils.EMPTY)));
}
}
@@ -87,40 +92,65 @@ public class SysOperationLogService {
* @param id 日志ID
* @return 日志详情
*/
public List<JsonDifferenceDTO> getLogDetail(String id, String orgId) {
List<JsonDifferenceDTO> differenceDTOS = new ArrayList<>();
Optional.ofNullable(operationLogBlobMapper.selectByPrimaryKey(id))
.ifPresent(operationLog -> {
String oldString = new String(
Optional.ofNullable(operationLog.getOriginalValue()).orElse(new byte[0]),
StandardCharsets.UTF_8
);
String newString = new String(
Optional.ofNullable(operationLog.getModifiedValue()).orElse(new byte[0]),
StandardCharsets.UTF_8
);
public OperationLogDetailResponse getLogDetail(String id, String orgId) {
OperationLog operationLog = operationLogMapper.selectByPrimaryKey(id);
OperationLogDetailResponse logResponse = BeanUtils.copyBean(new OperationLogDetailResponse(), operationLog);
logResponse.setOperator(operationLog.getCreateUser());
logResponse.setOperatorName(baseService.getUserName(logResponse.getOperator()));
try {
JsonDifferenceUtils.compareJson(oldString, newString, differenceDTOS);
if (CollectionUtils.isNotEmpty(differenceDTOS)) {
OperationLog log = operationLogMapper.selectByPrimaryKey(id);
BaseModuleLogService moduleLogService = ModuleLogServiceFactory.getModuleLogService(log.getModule());
if (moduleLogService != null) {
moduleLogService.handleLogField(differenceDTOS, orgId);
} else {
differenceDTOS.forEach(differ -> {
differ.setColumnName(Translator.get("log." + differ.getColumn()));
differ.setOldValueName(differ.getOldValue());
differ.setNewValueName(differ.getNewValue());
});
}
OperationLogBlob operationLogBlob = operationLogBlobMapper.selectByPrimaryKey(id);
if (operationLogBlob == null) {
return logResponse;
}
}
} catch (Exception e) {
throw new GenericException(Translator.get("data_parsing_exception"));
String oldString = new String(
Optional.ofNullable(operationLogBlob.getOriginalValue()).orElse(new byte[0]),
StandardCharsets.UTF_8
);
String newString = new String(
Optional.ofNullable(operationLogBlob.getModifiedValue()).orElse(new byte[0]),
StandardCharsets.UTF_8
);
try {
List<JsonDifferenceDTO> differenceDTOS = new ArrayList<>();
JsonDifferenceUtils.compareJson(oldString, newString, differenceDTOS);
// 过滤掉组织ID等字段
differenceDTOS = filterIgnoreFields(differenceDTOS);
if (CollectionUtils.isNotEmpty(differenceDTOS)) {
OperationLog log = operationLogMapper.selectByPrimaryKey(id);
BaseModuleLogService moduleLogService = ModuleLogServiceFactory.getModuleLogService(log.getModule());
if (moduleLogService != null) {
moduleLogService.handleLogField(differenceDTOS, orgId);
} else {
differenceDTOS.forEach(differ -> BaseModuleLogService.translatorDifferInfo(differ));
}
}
logResponse.setDiffs(differenceDTOS);
} catch (Exception e) {
throw new GenericException(Translator.get("data_parsing_exception"));
}
return logResponse;
}
/**
* 过滤掉日志对比无需显示的字段
* 例如organizationId
* @param differenceDTOS
* @return
*/
private List<JsonDifferenceDTO> filterIgnoreFields(List<JsonDifferenceDTO> differenceDTOS) {
differenceDTOS = differenceDTOS.stream()
.filter(differ -> {
if (StringUtils.equalsAny(differ.getColumn(),
"organizationId", "createUser", "updateUser", "createTime", "updateTime")) {
return false;
}
});
return true;
}).toList();
return differenceDTOS;
}
}

View File

@@ -318,4 +318,7 @@ http_result_forbidden=permission authentication failure
# Log
log.name=Name
log.updateTime=Update time
log.owner=Owner
log.owner=Owner
log.internal=System internal
log.dataScope=Data scope
log.description=Description

View File

@@ -322,4 +322,7 @@ http_result_forbidden=权限认证失败
# 日志
log.name=名称
log.updateTime=更新时间
log.owner=负责人
log.owner=负责人
log.internal=系统内置
log.dataScope=数据范围
log.description=描述