Browse Source

系统操作日志:集成 mzt-biz-log 4

puhui999 1 year ago
parent
commit
3c74b22933
12 changed files with 224 additions and 17 deletions
  1. 1 2
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java
  2. 4 0
      yudao-module-crm/yudao-module-crm-biz/pom.xml
  3. 4 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http
  4. 2 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java
  5. 24 5
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerBaseVO.java
  6. 46 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmIndustryParseFunction.java
  7. 46 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmLevelParseFunction.java
  8. 46 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmSourceParseFunction.java
  9. 1 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/package-info.java
  10. 11 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
  11. 0 5
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AdminUserParseFunction.java
  12. 39 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AreaParseFunction.java

+ 1 - 2
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java

@@ -20,8 +20,7 @@ public interface LogRecordConstants {
 
     //======================= 客户转移操作日志 =======================
 
-    String TRANSFER_CUSTOMER_LOG_SUCCESS = "把客户【{{#crmCustomer == null ? '' : #crmCustomer.name}}】负责人从" +
-            "【{getAdminUserById{#crmCustomer == null ? '' : #crmCustomer.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】";
+    String TRANSFER_CUSTOMER_LOG_SUCCESS = "把客户【{{#crmCustomer.name}}】的负责人从【{getAdminUserById{#crmCustomer.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】";
     String TRANSFER_CUSTOMER_LOG_FAIL = "";
 
 }

+ 4 - 0
yudao-module-crm/yudao-module-crm-biz/pom.xml

@@ -60,6 +60,10 @@
             <groupId>cn.iocoder.boot</groupId>
             <artifactId>yudao-spring-boot-starter-excel</artifactId>
         </dependency>
+        <dependency>
+            <groupId>cn.iocoder.boot</groupId>
+            <artifactId>yudao-spring-boot-starter-biz-dict</artifactId>
+        </dependency>
 
         <!-- Test 测试相关 -->
         <dependency>

+ 4 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http

@@ -9,4 +9,8 @@ tenant-id: {{adminTenentId}}
   "newOwnerUserId": 127
 }
 
+### 自定义日志记录结果
+### 操作日志 ===> OperateLogV2CreateReqBO(traceId=, userId=1, userType=2, module=CRM-客户, name=客户转移, bizId=10, content=把客户【张三】的负责人从【芋道源码(15612345678)】变更为了【tttt】, requestMethod=PUT, requestUrl=/admin-api/crm/customer/transfer, userIp=127.0.0.1, userAgent=Apache-HttpClient/4.5.14 (Java/17.0.9))
 
+### diff 日志
+### | 操作日志 ===> OperateLogV2CreateReqBO(traceId=, userId=1, userType=2, module=CRM-客户, name=更新客户, bizId=11, content=更新了客户【所属行业】从【H 住宿和餐饮业】修改为【D 电力、热力、燃气及水生产和供应业】;【客户等级】从【C (非优先客户)】修改为【A (重点客户)】;【客户来源】从【线上咨询】修改为【预约上门】, requestMethod=PUT, requestUrl=/admin-api/crm/customer/update, userIp=0:0:0:0:0:0:0:1, userAgent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36)

+ 2 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java

@@ -59,7 +59,7 @@ public class CrmCustomerController {
     }
 
     @PutMapping("/update")
-    @Operation(summary = "更新客户")
+    //@Operation(summary = "更新客户")
     @PreAuthorize("@ss.hasPermission('crm:customer:update')")
     public CommonResult<Boolean> updateCustomer(@Valid @RequestBody CrmCustomerUpdateReqVO updateReqVO) {
         customerService.updateCustomer(updateReqVO);
@@ -123,6 +123,7 @@ public class CrmCustomerController {
     }
 
     @PutMapping("/transfer")
+    //@Operation(summary = "客户转移")
     @PreAuthorize("@ss.hasPermission('crm:customer:update')")
     public CommonResult<Boolean> transfer(@Valid @RequestBody CrmCustomerTransferReqVO reqVO) {
         customerService.transferCustomer(reqVO, getLoginUserId());

+ 24 - 5
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerBaseVO.java

@@ -3,17 +3,20 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
 import cn.iocoder.yudao.framework.common.validation.InEnum;
 import cn.iocoder.yudao.framework.common.validation.Mobile;
 import cn.iocoder.yudao.framework.common.validation.Telephone;
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
 import cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLevelEnum;
+import com.mzt.logapi.starter.annotation.DiffLogField;
 import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
 import jakarta.validation.constraints.Email;
 import jakarta.validation.constraints.NotEmpty;
 import jakarta.validation.constraints.Size;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
 import java.time.LocalDateTime;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY;
 
 /**
  * 客户 Base VO,提供给添加、修改、详细的子 VO 使用
@@ -23,57 +26,73 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 public class CrmCustomerBaseVO {
 
     @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
+    @DiffLogField(name = "客户名称")
     @NotEmpty(message = "客户名称不能为空")
     private String name;
 
     @Schema(description = "所属行业", example = "1")
+    @DiffLogField(name = "所属行业", function = "getIndustryById")
+    @DictFormat(CRM_CUSTOMER_INDUSTRY)
     private Integer industryId;
 
     @Schema(description = "客户等级", example = "2")
+    @DiffLogField(name = "客户等级", function = "getLevel")
     @InEnum(CrmCustomerLevelEnum.class)
     private Integer level;
 
     @Schema(description = "客户来源", example = "3")
+    @DiffLogField(name = "客户来源", function = "getSource")
     private Integer source;
 
     @Schema(description = "手机", example = "18000000000")
+    @DiffLogField(name = "手机")
     @Mobile
     private String mobile;
 
     @Schema(description = "电话", example = "18000000000")
+    @DiffLogField(name = "电话")
     @Telephone
     private String telephone;
 
     @Schema(description = "网址", example = "https://www.baidu.com")
+    @DiffLogField(name = "网址")
     private String website;
 
     @Schema(description = "QQ", example = "123456789")
+    @DiffLogField(name = "QQ")
     @Size(max = 20, message = "QQ长度不能超过 20 个字符")
     private String qq;
 
-    @Schema(description = "wechat", example = "123456789")
+    @Schema(description = "微信", example = "123456789")
+    @DiffLogField(name = "微信")
     @Size(max = 255, message = "微信长度不能超过 255 个字符")
     private String wechat;
 
-    @Schema(description = "email", example = "123456789@qq.com")
+    @Schema(description = "邮箱", example = "123456789@qq.com")
+    @DiffLogField(name = "邮箱")
     @Email(message = "邮箱格式不正确")
     @Size(max = 255, message = "邮箱长度不能超过 255 个字符")
     private String email;
 
     @Schema(description = "客户描述", example = "任意文字")
+    @DiffLogField(name = "客户描述")
     @Size(max = 4096, message = "客户描述长度不能超过 4096 个字符")
     private String description;
 
     @Schema(description = "备注", example = "随便")
+    @DiffLogField(name = "备注")
     private String remark;
 
     @Schema(description = "地区编号", example = "20158")
+    @DiffLogField(name = "地区编号", function = "getAreaById")
     private Integer areaId;
 
     @Schema(description = "详细地址", example = "北京市海淀区")
+    @DiffLogField(name = "详细地址")
     private String detailAddress;
 
     @Schema(description = "下次联系时间")
+    @DiffLogField(name = "下次联系时间")
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime contactNextTime;
 

+ 46 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmIndustryParseFunction.java

@@ -0,0 +1,46 @@
+package cn.iocoder.yudao.module.crm.framework.bizlog.function;
+
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
+import com.mzt.logapi.service.IParseFunction;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY;
+
+/**
+ * 自定义函数-通过行业编号获取行业信息
+ *
+ * @author HUIHUI
+ */
+@Slf4j
+@Component
+public class CrmIndustryParseFunction implements IParseFunction {
+
+    @Override
+    public boolean executeBefore() {
+        return true; // 先转换值后对比
+    }
+
+    @Override
+    public String functionName() {
+        return "getIndustryById";
+    }
+
+    @Override
+    public String apply(Object value) {
+        if (value == null) {
+            return "";
+        }
+        if (StrUtil.isEmpty(value.toString())) {
+            return "";
+        }
+
+        // 获取行业信息
+        try {
+            return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_INDUSTRY, value.toString());
+        } catch (Exception ignored) {
+        }
+        return "";
+    }
+}

+ 46 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmLevelParseFunction.java

@@ -0,0 +1,46 @@
+package cn.iocoder.yudao.module.crm.framework.bizlog.function;
+
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
+import com.mzt.logapi.service.IParseFunction;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_LEVEL;
+
+/**
+ * 自定义函数-通过客户等级编号获取客户等级信息
+ *
+ * @author HUIHUI
+ */
+@Slf4j
+@Component
+public class CrmLevelParseFunction implements IParseFunction {
+
+    @Override
+    public boolean executeBefore() {
+        return true; // 先转换值后对比
+    }
+
+    @Override
+    public String functionName() {
+        return "getLevel";
+    }
+
+    @Override
+    public String apply(Object value) {
+        if (value == null) {
+            return "";
+        }
+        if (StrUtil.isEmpty(value.toString())) {
+            return "";
+        }
+
+        // 获取客户等级信息
+        try {
+            return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_LEVEL, value.toString());
+        } catch (Exception ignored) {
+        }
+        return "";
+    }
+}

+ 46 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmSourceParseFunction.java

@@ -0,0 +1,46 @@
+package cn.iocoder.yudao.module.crm.framework.bizlog.function;
+
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
+import com.mzt.logapi.service.IParseFunction;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_SOURCE;
+
+/**
+ * 自定义函数-通过客户来源编号获取客户来源信息
+ *
+ * @author HUIHUI
+ */
+@Slf4j
+@Component
+public class CrmSourceParseFunction implements IParseFunction {
+
+    @Override
+    public boolean executeBefore() {
+        return true; // 先转换值后对比
+    }
+
+    @Override
+    public String functionName() {
+        return "getSource";
+    }
+
+    @Override
+    public String apply(Object value) {
+        if (value == null) {
+            return "";
+        }
+        if (StrUtil.isEmpty(value.toString())) {
+            return "";
+        }
+
+        // 获取客户来源信息
+        try {
+            return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_SOURCE, value.toString());
+        } catch (Exception ignored) {
+        }
+        return "";
+    }
+}

+ 1 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/package-info.java

@@ -0,0 +1 @@
+package cn.iocoder.yudao.module.crm.framework.bizlog;

+ 11 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.service.customer;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerCreateReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO;
@@ -16,6 +17,7 @@ import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import com.mzt.logapi.context.LogRecordContext;
+import com.mzt.logapi.service.impl.DiffParseFunction;
 import com.mzt.logapi.starter.annotation.LogRecord;
 import jakarta.annotation.Resource;
 import org.springframework.stereotype.Service;
@@ -63,11 +65,14 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
 
     @Override
     @Transactional(rollbackFor = Exception.class)
+    @LogRecord(success = "更新了客户{_DIFF{#updateReqVO}}", type = CRM_CUSTOMER, subType = "更新客户", bizNo = "{{#updateReqVO.id}}")
     @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
     public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) {
         // 校验存在
-        validateCustomerExists(updateReqVO.getId());
+        CrmCustomerDO oldCustomerDO = validateCustomerExists(updateReqVO.getId());
 
+        // __DIFF 函数传递了一个参数,传递的参数是修改之后的对象,这种方式需要在方法内部向 LogRecordContext 中 put 一个变量,代表是之前的对象,这个对象可以是null
+        LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomerDO, CrmCustomerUpdateReqVO.class));
         // 更新
         CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO);
         customerMapper.updateById(updateObj);
@@ -86,10 +91,12 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
         crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id);
     }
 
-    private void validateCustomerExists(Long id) {
-        if (customerMapper.selectById(id) == null) {
+    private CrmCustomerDO validateCustomerExists(Long id) {
+        CrmCustomerDO customerDO = customerMapper.selectById(id);
+        if (customerDO == null) {
             throw exception(CUSTOMER_NOT_EXISTS);
         }
+        return customerDO;
     }
 
     @Override
@@ -135,7 +142,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
     public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) {
         // 1. 校验客户是否存在
         validateCustomer(reqVO.getId());
-        // 添加 crmCustomer 到日志上下文
+        // 添加 crmCustomer 到日志上下文 TODO 日志记录放在 service 里是因为已经过了权限校验查询时不用走两次校验
         LogRecordContext.putVariable("crmCustomer", customerMapper.selectById(reqVO.getId()));
         // 2.1 数据权限转移
         crmPermissionService.transferPermission(

+ 0 - 5
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AdminUserParseFunction.java

@@ -21,11 +21,6 @@ public class AdminUserParseFunction implements IParseFunction {
     @Resource
     private AdminUserApi adminUserApi;
 
-    @Override
-    public boolean executeBefore() {
-        return true;
-    }
-
     @Override
     public String functionName() {
         return "getAdminUserById";

+ 39 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AreaParseFunction.java

@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.system.framework.bizlog.function;
+
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
+import com.mzt.logapi.service.IParseFunction;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+/**
+ * 自定义函数-通过区域编号获取区域信息
+ *
+ * @author HUIHUI
+ */
+@Slf4j
+@Component
+public class AreaParseFunction implements IParseFunction {
+
+    @Override
+    public boolean executeBefore() {
+        return true; // 先转换值后对比
+    }
+
+    @Override
+    public String functionName() {
+        return "getAreaById";
+    }
+
+    @Override
+    public String apply(Object value) {
+        if (value == null) {
+            return "";
+        }
+        if (StrUtil.isEmpty(value.toString())) {
+            return "";
+        }
+
+        return AreaUtils.format(Integer.parseInt(value.toString()));
+    }
+}