Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
commit
5851bcb479
|
@ -62,6 +62,7 @@
|
|||
<jsch.version>0.1.55</jsch.version>
|
||||
<tika-core.version>2.9.1</tika-core.version>
|
||||
<ip2region.version>2.7.0</ip2region.version>
|
||||
<bizlog-sdk.version>3.0.6</bizlog-sdk.version>
|
||||
<!-- 三方云服务相关 -->
|
||||
<okio.version>3.5.0</okio.version>
|
||||
<okhttp3.version>4.11.0</okhttp3.version>
|
||||
|
@ -99,6 +100,17 @@
|
|||
<artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.mouzt</groupId>
|
||||
<artifactId>bizlog-sdk</artifactId>
|
||||
<version>${bizlog-sdk.version}</version>
|
||||
<exclusions>
|
||||
<exclusion> <!-- 排除掉springboot依赖使用项目的 -->
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-dict</artifactId>
|
||||
|
|
|
@ -177,4 +177,14 @@ public class DateUtils {
|
|||
return LocalDateTimeUtil.isSameDay(date, LocalDateTime.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否昨天
|
||||
*
|
||||
* @param date 日期
|
||||
* @return 是否
|
||||
*/
|
||||
public static boolean isYesterday(LocalDateTime date) {
|
||||
return LocalDateTimeUtil.isSameDay(date, LocalDateTime.now().minusDays(1));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package cn.iocoder.yudao.module.crm.enums;
|
||||
|
||||
/**
|
||||
* CRM 操作日志枚举
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
public interface LogRecordConstants {
|
||||
|
||||
//======================= 客户模块类型 =======================
|
||||
// TODO puhui999: 确保模块命名方式为 module + 子模块名称的方式。统一定义模块名称是为了方便查询各自记录的操作日志,列如说:查询客户【张三的操作日志】就可以 module + bizId
|
||||
String CRM_LEADS = "CRM-线索";
|
||||
String CRM_CUSTOMER = "CRM-客户";
|
||||
String CRM_CONTACT = "CRM-联系人";
|
||||
String CRM_BUSINESS = "CRM-商机";
|
||||
String CRM_CONTRACT = "CRM-合同";
|
||||
String CRM_PRODUCT = "CRM-产品";
|
||||
String CRM_RECEIVABLE = "CRM-回款";
|
||||
String CRM_RECEIVABLE_PLAN = "CRM-回款计划";
|
||||
|
||||
//======================= 客户转移操作日志 =======================
|
||||
|
||||
String TRANSFER_CUSTOMER_LOG_SUCCESS = "把客户【{{#crmCustomer.name}}】的负责人从【{getAdminUserById{#crmCustomer.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】";
|
||||
String TRANSFER_CUSTOMER_LOG_FAIL = "";
|
||||
|
||||
}
|
|
@ -22,7 +22,9 @@ public enum CrmBizTypeEnum implements IntArrayValuable {
|
|||
CRM_CONTACT(3, "联系人"),
|
||||
CRM_BUSINESS(4, "商机"),
|
||||
CRM_CONTRACT(5, "合同"),
|
||||
CRM_PRODUCT(6, "产品")
|
||||
CRM_PRODUCT(6, "产品"),
|
||||
CRM_RECEIVABLE(7, "回款"),
|
||||
CRM_RECEIVABLE_PLAN(8, "回款计划")
|
||||
;
|
||||
|
||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmBizTypeEnum::getType).toArray();
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -122,7 +122,7 @@ public class CrmBusinessController {
|
|||
@Operation(summary = "获得商机分页,基于指定客户")
|
||||
public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessPageByCustomer(@Valid CrmBusinessPageReqVO pageReqVO) {
|
||||
Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空");
|
||||
PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByCustomer(pageReqVO, getLoginUserId());
|
||||
PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByCustomerId(pageReqVO);
|
||||
// 处理客户名称回显
|
||||
// TODO @ljlleo:可以使用 CollectionUtils.convertSet 替代常用的 stream 操作,更简洁一点;下面几个也是哈;
|
||||
Set<Long> customerIds = pageResult.getList().stream()
|
||||
|
|
|
@ -24,7 +24,4 @@ public class CrmBusinessPageReqVO extends PageParam {
|
|||
@InEnum(CrmSceneTypeEnum.class)
|
||||
private Integer sceneType; // 场景类型,为 null 时则表示全部
|
||||
|
||||
@Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
|
||||
private Boolean pool; // null 则表示为不是公海数据
|
||||
|
||||
}
|
||||
|
|
|
@ -2,16 +2,15 @@ package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
|
|||
|
||||
import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - 商机转移 Request VO")
|
||||
@Data
|
||||
public class CrmBusinessTransferReqVO {
|
||||
|
||||
@Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
|
||||
@NotNull(message = "联系人编号不能为空")
|
||||
@NotNull(message = "商机编号不能为空")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
|
|
|
@ -88,4 +88,12 @@ public class CrmClueController {
|
|||
ExcelUtils.write(response, "线索.xls", "数据", CrmClueExcelVO.class, datas);
|
||||
}
|
||||
|
||||
@PutMapping("/transfer")
|
||||
@Operation(summary = "线索转移")
|
||||
@PreAuthorize("@ss.hasPermission('crm:clue:update')")
|
||||
public CommonResult<Boolean> transfer(@Valid @RequestBody CrmClueTransferReqVO reqVO) {
|
||||
clueService.transferClue(reqVO, getLoginUserId());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package cn.iocoder.yudao.module.crm.controller.admin.clue.vo;
|
||||
|
||||
import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - 线索转移 Request VO")
|
||||
@Data
|
||||
public class CrmClueTransferReqVO {
|
||||
|
||||
@Schema(description = "线索编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
|
||||
@NotNull(message = "线索编号不能为空")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 新负责人的用户编号
|
||||
*/
|
||||
@Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
|
||||
@NotNull(message = "新负责人的用户编号不能为空")
|
||||
private Long newOwnerUserId;
|
||||
|
||||
/**
|
||||
* 老负责人加入团队后的权限级别。如果 null 说明移除
|
||||
*
|
||||
* 关联 {@link CrmPermissionLevelEnum}
|
||||
*/
|
||||
@Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
private Integer oldOwnerPermissionLevel;
|
||||
|
||||
}
|
|
@ -9,7 +9,7 @@ import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
|||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*;
|
||||
import cn.iocoder.yudao.module.crm.convert.contact.ContactConvert;
|
||||
import cn.iocoder.yudao.module.crm.convert.contact.CrmContactConvert;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
|
||||
import cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants;
|
||||
|
@ -100,7 +100,7 @@ public class CrmContactController {
|
|||
// 3. 直属上级
|
||||
List<CrmContactDO> parentContactList = contactService.getContactList(
|
||||
Collections.singletonList(contact.getParentId()), getLoginUserId());
|
||||
return success(ContactConvert.INSTANCE.convert(contact, userMap, customerList, parentContactList));
|
||||
return success(CrmContactConvert.INSTANCE.convert(contact, userMap, customerList, parentContactList));
|
||||
}
|
||||
|
||||
@GetMapping("/simple-all-list")
|
||||
|
@ -110,7 +110,7 @@ public class CrmContactController {
|
|||
CrmContactPageReqVO pageReqVO = new CrmContactPageReqVO();
|
||||
pageReqVO.setPageSize(PAGE_SIZE_NONE);
|
||||
List<CrmContactDO> list = contactService.getContactPage(pageReqVO, getLoginUserId()).getList();
|
||||
return success(ContactConvert.INSTANCE.convertAllList(list));
|
||||
return success(CrmContactConvert.INSTANCE.convertAllList(list));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
|
@ -125,7 +125,7 @@ public class CrmContactController {
|
|||
@Operation(summary = "获得联系人分页,基于指定客户")
|
||||
public CommonResult<PageResult<CrmContactRespVO>> getContactPageByCustomer(@Valid CrmContactPageReqVO pageVO) {
|
||||
Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空");
|
||||
PageResult<CrmContactDO> pageResult = contactService.getContactPageByCustomerId(pageVO, getLoginUserId());
|
||||
PageResult<CrmContactDO> pageResult = contactService.getContactPageByCustomerId(pageVO);
|
||||
return success(convertDetailContactPage(pageResult));
|
||||
}
|
||||
|
||||
|
@ -161,7 +161,15 @@ public class CrmContactController {
|
|||
// 3. 直属上级
|
||||
List<CrmContactDO> parentContactList = contactService.getContactList(
|
||||
convertSet(contactList, CrmContactDO::getParentId), getLoginUserId());
|
||||
return ContactConvert.INSTANCE.convertPage(pageResult, userMap, crmCustomerDOList, parentContactList);
|
||||
return CrmContactConvert.INSTANCE.convertPage(pageResult, userMap, crmCustomerDOList, parentContactList);
|
||||
}
|
||||
|
||||
@PutMapping("/transfer")
|
||||
@Operation(summary = "联系人转移")
|
||||
@PreAuthorize("@ss.hasPermission('crm:contact:update')")
|
||||
public CommonResult<Boolean> transfer(@Valid @RequestBody CrmContactTransferReqVO reqVO) {
|
||||
contactService.transferContact(reqVO, getLoginUserId());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -39,7 +39,4 @@ public class CrmContactPageReqVO extends PageParam {
|
|||
@InEnum(CrmSceneTypeEnum.class)
|
||||
private Integer sceneType; // 场景类型,为 null 时则表示全部
|
||||
|
||||
@Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
|
||||
private Boolean pool; // null 则表示为不是公海数据
|
||||
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
|||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.*;
|
||||
import cn.iocoder.yudao.module.crm.convert.contract.ContractConvert;
|
||||
import cn.iocoder.yudao.module.crm.convert.contract.CrmContractConvert;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
|
||||
import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
|
||||
|
@ -80,7 +80,7 @@ public class CrmContractController {
|
|||
@PreAuthorize("@ss.hasPermission('crm:contract:query')")
|
||||
public CommonResult<ContractRespVO> getContract(@RequestParam("id") Long id) {
|
||||
CrmContractDO contract = contractService.getContract(id);
|
||||
return success(ContractConvert.INSTANCE.convert(contract));
|
||||
return success(CrmContractConvert.INSTANCE.convert(contract));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
|
@ -95,7 +95,7 @@ public class CrmContractController {
|
|||
@Operation(summary = "获得联系人分页,基于指定客户")
|
||||
public CommonResult<PageResult<ContractRespVO>> getContractPageByCustomer(@Valid CrmContractPageReqVO pageVO) {
|
||||
Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空");
|
||||
PageResult<CrmContractDO> pageResult = contractService.getContractPageByCustomer(pageVO, getLoginUserId());
|
||||
PageResult<CrmContractDO> pageResult = contractService.getContractPageByCustomerId(pageVO);
|
||||
return success(convertDetailContractPage(pageResult));
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ public class CrmContractController {
|
|||
PageResult<CrmContractDO> pageResult = contractService.getContractPage(exportReqVO, getLoginUserId());
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "合同.xls", "数据", CrmContractExcelVO.class,
|
||||
ContractConvert.INSTANCE.convertList02(pageResult.getList()));
|
||||
CrmContractConvert.INSTANCE.convertList02(pageResult.getList()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -128,7 +128,7 @@ public class CrmContractController {
|
|||
// 2. 获取创建人、负责人列表
|
||||
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(contactList,
|
||||
contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId())));
|
||||
return ContractConvert.INSTANCE.convertPage(pageResult, userMap, customerList);
|
||||
return CrmContractConvert.INSTANCE.convertPage(pageResult, userMap, customerList);
|
||||
}
|
||||
|
||||
@PutMapping("/transfer")
|
||||
|
|
|
@ -30,7 +30,4 @@ public class CrmContractPageReqVO extends PageParam {
|
|||
@InEnum(CrmSceneTypeEnum.class)
|
||||
private Integer sceneType; // 场景类型,为 null 时则表示全部
|
||||
|
||||
@Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
|
||||
private Boolean pool; // null 则表示为不是公海数据 TODO @puhui999:合同没有公海。目前只有【客户】【线索】有公海,其它都没
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
### 请求 /update
|
||||
GET {{baseUrl}}/crm/customer/page?pageNo=1&pageSize=10&name="张三"
|
||||
### 请求 /transfer
|
||||
PUT {{baseUrl}}/crm/customer/transfer
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
{
|
||||
"id": 10,
|
||||
"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)
|
||||
|
|
|
@ -11,20 +11,22 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
|
|||
import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
|
||||
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
||||
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
||||
import cn.iocoder.yudao.module.system.api.logger.OperateLogApi;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Parameters;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import org.mapstruct.ap.internal.util.Collections;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -36,6 +38,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
|
|||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CUSTOMER;
|
||||
|
||||
@Tag(name = "管理后台 - CRM 客户")
|
||||
@RestController
|
||||
|
@ -50,6 +53,8 @@ public class CrmCustomerController {
|
|||
private DeptApi deptApi;
|
||||
@Resource
|
||||
private AdminUserApi adminUserApi;
|
||||
@Resource
|
||||
private OperateLogApi operateLogApi;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建客户")
|
||||
|
@ -59,7 +64,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,13 +128,28 @@ public class CrmCustomerController {
|
|||
}
|
||||
|
||||
@PutMapping("/transfer")
|
||||
@Operation(summary = "客户转移")
|
||||
//@Operation(summary = "客户转移")
|
||||
@PreAuthorize("@ss.hasPermission('crm:customer:update')")
|
||||
public CommonResult<Boolean> transfer(@Valid @RequestBody CrmCustomerTransferReqVO reqVO) {
|
||||
customerService.transferCustomer(reqVO, getLoginUserId());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/operate-log")
|
||||
@Operation(summary = "获得客户操作日志")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('crm:customer:query')")
|
||||
public CommonResult<List<OperateLogV2RespDTO>> getOperateLog(@RequestParam("id") Long id) {
|
||||
// 1. 获取客户
|
||||
CrmCustomerDO customer = customerService.getCustomer(id);
|
||||
if (customer == null) {
|
||||
return success(null);
|
||||
}
|
||||
|
||||
// 2. 获取操作日志
|
||||
return success(operateLogApi.getOperateLogByModuleAndBizId(CRM_CUSTOMER, id));
|
||||
}
|
||||
|
||||
// TODO @Joey:单独建一个属于自己业务的 ReqVO;因为前端如果模拟请求,是不是可以更新其它字段了;
|
||||
@PutMapping("/lock")
|
||||
@Operation(summary = "锁定/解锁客户")
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -2,16 +2,15 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
|
|||
|
||||
import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - CRM 客户转移 Request VO")
|
||||
@Data
|
||||
public class CrmCustomerTransferReqVO {
|
||||
|
||||
@Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
|
||||
@NotNull(message = "联系人编号不能为空")
|
||||
@NotNull(message = "客户编号不能为空")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
|
|
|
@ -7,10 +7,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|||
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableRespVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.*;
|
||||
import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivableConvert;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
|
||||
|
@ -36,6 +33,7 @@ import java.util.Map;
|
|||
import java.util.stream.Stream;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
|
@ -94,7 +92,7 @@ public class CrmReceivableController {
|
|||
@Operation(summary = "获得回款分页")
|
||||
@PreAuthorize("@ss.hasPermission('crm:receivable:query')")
|
||||
public CommonResult<PageResult<CrmReceivableRespVO>> getReceivablePage(@Valid CrmReceivablePageReqVO pageReqVO) {
|
||||
PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePage(pageReqVO);
|
||||
PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePage(pageReqVO, getLoginUserId());
|
||||
return success(convertDetailReceivablePage(pageResult));
|
||||
}
|
||||
|
||||
|
@ -102,7 +100,7 @@ public class CrmReceivableController {
|
|||
@Operation(summary = "获得回款分页,基于指定客户")
|
||||
public CommonResult<PageResult<CrmReceivableRespVO>> getReceivablePageByCustomer(@Valid CrmReceivablePageReqVO pageReqVO) {
|
||||
Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空");
|
||||
PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePageByCustomer(pageReqVO);
|
||||
PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePageByCustomerId(pageReqVO);
|
||||
return success(convertDetailReceivablePage(pageResult));
|
||||
}
|
||||
|
||||
|
@ -113,7 +111,8 @@ public class CrmReceivableController {
|
|||
@OperateLog(type = EXPORT)
|
||||
public void exportReceivableExcel(@Valid CrmReceivablePageReqVO exportReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePage(exportReqVO);
|
||||
exportReqVO.setPageSize(PAGE_SIZE_NONE);
|
||||
PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePage(exportReqVO, getLoginUserId());
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "回款.xls", "数据", CrmReceivableRespVO.class,
|
||||
convertDetailReceivablePage(pageResult).getList());
|
||||
|
@ -142,4 +141,12 @@ public class CrmReceivableController {
|
|||
return CrmReceivableConvert.INSTANCE.convertPage(pageResult, userMap, customerList, contractList);
|
||||
}
|
||||
|
||||
@PutMapping("/transfer")
|
||||
@Operation(summary = "回款转移")
|
||||
@PreAuthorize("@ss.hasPermission('crm:receivable:update')")
|
||||
public CommonResult<Boolean> transfer(@Valid @RequestBody CrmReceivableTransferReqVO reqVO) {
|
||||
receivableService.transferReceivable(reqVO, getLoginUserId());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,10 +7,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|||
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanRespVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.*;
|
||||
import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivablePlanConvert;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
|
||||
|
@ -38,6 +35,7 @@ import java.util.Map;
|
|||
import java.util.stream.Stream;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
|
@ -65,7 +63,7 @@ public class CrmReceivablePlanController {
|
|||
@Operation(summary = "创建回款计划")
|
||||
@PreAuthorize("@ss.hasPermission('crm:receivable-plan:create')")
|
||||
public CommonResult<Long> createReceivablePlan(@Valid @RequestBody CrmReceivablePlanCreateReqVO createReqVO) {
|
||||
return success(receivablePlanService.createReceivablePlan(createReqVO));
|
||||
return success(receivablePlanService.createReceivablePlan(createReqVO, getLoginUserId()));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
|
@ -98,7 +96,7 @@ public class CrmReceivablePlanController {
|
|||
@Operation(summary = "获得回款计划分页")
|
||||
@PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')")
|
||||
public CommonResult<PageResult<CrmReceivablePlanRespVO>> getReceivablePlanPage(@Valid CrmReceivablePlanPageReqVO pageReqVO) {
|
||||
PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(pageReqVO);
|
||||
PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(pageReqVO, getLoginUserId());
|
||||
return success(convertDetailReceivablePlanPage(pageResult));
|
||||
}
|
||||
|
||||
|
@ -106,7 +104,7 @@ public class CrmReceivablePlanController {
|
|||
@Operation(summary = "获得回款计划分页,基于指定客户")
|
||||
public CommonResult<PageResult<CrmReceivablePlanRespVO>> getReceivablePlanPageByCustomer(@Valid CrmReceivablePlanPageReqVO pageReqVO) {
|
||||
Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空");
|
||||
PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPageByCustomer(pageReqVO);
|
||||
PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPageByCustomerId(pageReqVO);
|
||||
return success(convertDetailReceivablePlanPage(pageResult));
|
||||
}
|
||||
|
||||
|
@ -117,7 +115,8 @@ public class CrmReceivablePlanController {
|
|||
@OperateLog(type = EXPORT)
|
||||
public void exportReceivablePlanExcel(@Valid CrmReceivablePlanPageReqVO exportReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(exportReqVO);
|
||||
exportReqVO.setPageSize(PAGE_SIZE_NONE);
|
||||
PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(exportReqVO, getLoginUserId());
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "回款计划.xls", "数据", CrmReceivablePlanRespVO.class,
|
||||
convertDetailReceivablePlanPage(pageResult).getList());
|
||||
|
@ -149,4 +148,12 @@ public class CrmReceivablePlanController {
|
|||
return CrmReceivablePlanConvert.INSTANCE.convertPage(pageResult, userMap, customerList, contractList, receivableList);
|
||||
}
|
||||
|
||||
@PutMapping("/transfer")
|
||||
@Operation(summary = "回款计划转移")
|
||||
@PreAuthorize("@ss.hasPermission('crm:receivable-plan:update')")
|
||||
public CommonResult<Boolean> transfer(@Valid @RequestBody CrmReceivablePlanTransferReqVO reqVO) {
|
||||
receivablePlanService.transferReceivablePlan(reqVO, getLoginUserId());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,7 +25,4 @@ public class CrmReceivablePlanPageReqVO extends PageParam {
|
|||
@InEnum(CrmSceneTypeEnum.class)
|
||||
private Integer sceneType; // 场景类型,为 null 时则表示全部
|
||||
|
||||
@Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
|
||||
private Boolean pool; // null 则表示为不是公海数据
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan;
|
||||
|
||||
import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - CRM 回款计划转移 Request VO")
|
||||
@Data
|
||||
public class CrmReceivablePlanTransferReqVO {
|
||||
|
||||
@Schema(description = "回款计划编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
|
||||
@NotNull(message = "回款计划编号不能为空")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 新负责人的用户编号
|
||||
*/
|
||||
@Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
|
||||
@NotNull(message = "新负责人的用户编号不能为空")
|
||||
private Long newOwnerUserId;
|
||||
|
||||
/**
|
||||
* 老负责人加入团队后的权限级别。如果 null 说明移除
|
||||
*
|
||||
* 关联 {@link CrmPermissionLevelEnum}
|
||||
*/
|
||||
@Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
private Integer oldOwnerPermissionLevel;
|
||||
|
||||
}
|
|
@ -27,7 +27,4 @@ public class CrmReceivablePageReqVO extends PageParam {
|
|||
@InEnum(CrmSceneTypeEnum.class)
|
||||
private Integer sceneType; // 场景类型,为 null 时则表示全部
|
||||
|
||||
@Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
|
||||
private Boolean pool; // null 则表示为不是公海数据
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable;
|
||||
|
||||
import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - CRM 回款转移 Request VO")
|
||||
@Data
|
||||
public class CrmReceivableTransferReqVO {
|
||||
|
||||
@Schema(description = "回款编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
|
||||
@NotNull(message = "回款编号不能为空")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 新负责人的用户编号
|
||||
*/
|
||||
@Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
|
||||
@NotNull(message = "新负责人的用户编号不能为空")
|
||||
private Long newOwnerUserId;
|
||||
|
||||
/**
|
||||
* 老负责人加入团队后的权限级别。如果 null 说明移除
|
||||
*
|
||||
* 关联 {@link CrmPermissionLevelEnum}
|
||||
*/
|
||||
@Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
private Integer oldOwnerPermissionLevel;
|
||||
|
||||
}
|
|
@ -1,13 +1,14 @@
|
|||
package cn.iocoder.yudao.module.crm.convert.clue;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.*;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO;
|
||||
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 线索 Convert
|
||||
|
@ -29,4 +30,7 @@ public interface CrmClueConvert {
|
|||
|
||||
List<CrmClueExcelVO> convertList02(List<CrmClueDO> list);
|
||||
|
||||
@Mapping(target = "bizId", source = "reqVO.id")
|
||||
CrmPermissionTransferReqBO convert(CrmClueTransferReqVO reqVO, Long userId);
|
||||
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferRe
|
|||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -26,9 +25,9 @@ import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAnd
|
|||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface ContactConvert {
|
||||
public interface CrmContactConvert {
|
||||
|
||||
ContactConvert INSTANCE = Mappers.getMapper(ContactConvert.class);
|
||||
CrmContactConvert INSTANCE = Mappers.getMapper(CrmContactConvert.class);
|
||||
|
||||
CrmContactDO convert(CrmContactCreateReqVO bean);
|
||||
|
||||
|
@ -48,10 +47,7 @@ public interface ContactConvert {
|
|||
|
||||
List<CrmContactSimpleRespVO> convertAllList(List<CrmContactDO> list);
|
||||
|
||||
@Mappings({
|
||||
@Mapping(target = "bizId", source = "reqVO.id"),
|
||||
@Mapping(target = "newOwnerUserId", source = "reqVO.id")
|
||||
})
|
||||
@Mapping(target = "bizId", source = "reqVO.id")
|
||||
CrmPermissionTransferReqBO convert(CrmContactTransferReqVO reqVO, Long userId);
|
||||
|
||||
/**
|
|
@ -8,7 +8,6 @@ import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferRe
|
|||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -23,9 +22,9 @@ import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAnd
|
|||
* @author dhb52
|
||||
*/
|
||||
@Mapper
|
||||
public interface ContractConvert {
|
||||
public interface CrmContractConvert {
|
||||
|
||||
ContractConvert INSTANCE = Mappers.getMapper(ContractConvert.class);
|
||||
CrmContractConvert INSTANCE = Mappers.getMapper(CrmContractConvert.class);
|
||||
|
||||
CrmContractDO convert(CrmContractCreateReqVO bean);
|
||||
|
||||
|
@ -39,10 +38,7 @@ public interface ContractConvert {
|
|||
|
||||
List<CrmContractExcelVO> convertList02(List<CrmContractDO> list);
|
||||
|
||||
@Mappings({
|
||||
@Mapping(target = "bizId", source = "reqVO.id"),
|
||||
@Mapping(target = "newOwnerUserId", source = "reqVO.id")
|
||||
})
|
||||
@Mapping(target = "bizId", source = "reqVO.id")
|
||||
CrmPermissionTransferReqBO convert(CrmContractTransferReqVO reqVO, Long userId);
|
||||
|
||||
default PageResult<ContractRespVO> convertPage(PageResult<CrmContractDO> pageResult, Map<Long, AdminUserRespDTO> userMap,
|
|
@ -3,12 +3,15 @@ package cn.iocoder.yudao.module.crm.convert.receivable;
|
|||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableRespVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableTransferReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO;
|
||||
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -58,4 +61,7 @@ public interface CrmReceivableConvert {
|
|||
findAndThen(userMap, Long.parseLong(receivable.getCreator()), user -> receivable.setCreatorName(user.getNickname()));
|
||||
}
|
||||
|
||||
@Mapping(target = "bizId", source = "reqVO.id")
|
||||
CrmPermissionTransferReqBO convert(CrmReceivableTransferReqVO reqVO, Long userId);
|
||||
|
||||
}
|
||||
|
|
|
@ -3,13 +3,16 @@ package cn.iocoder.yudao.module.crm.convert.receivable;
|
|||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanRespVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanTransferReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO;
|
||||
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -63,4 +66,7 @@ public interface CrmReceivablePlanConvert {
|
|||
findAndThen(userMap, Long.parseLong(receivablePlan.getCreator()), user -> receivablePlan.setCreatorName(user.getNickname()));
|
||||
}
|
||||
|
||||
@Mapping(target = "bizId", source = "reqVO.id")
|
||||
CrmPermissionTransferReqBO convert(CrmReceivablePlanTransferReqVO reqVO, Long userId);
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.mysql.business;
|
|||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
|
||||
|
@ -27,14 +28,23 @@ public interface CrmBusinessMapper extends BaseMapperX<CrmBusinessDO> {
|
|||
.set(CrmBusinessDO::getOwnerUserId, ownerUserId));
|
||||
}
|
||||
|
||||
default PageResult<CrmBusinessDO> selectPageByCustomerId(CrmBusinessPageReqVO pageReqVO) {
|
||||
return selectPage(pageReqVO, new LambdaQueryWrapperX<CrmBusinessDO>()
|
||||
.eq(CrmBusinessDO::getCustomerId, pageReqVO.getCustomerId()) // 指定客户编号
|
||||
.likeIfPresent(CrmBusinessDO::getName, pageReqVO.getName())
|
||||
.orderByDesc(CrmBusinessDO::getId));
|
||||
}
|
||||
|
||||
default PageResult<CrmBusinessDO> selectPage(CrmBusinessPageReqVO pageReqVO, Long userId) {
|
||||
MPJLambdaWrapperX<CrmBusinessDO> query = new MPJLambdaWrapperX<>();
|
||||
// 拼接数据权限的查询条件
|
||||
CrmQueryWrapperUtils.builderPageQuery(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), CrmBusinessDO::getId,
|
||||
userId, pageReqVO.getSceneType(), pageReqVO.getPool());
|
||||
boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(),
|
||||
CrmBusinessDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE);
|
||||
if (!condition) {
|
||||
return PageResult.empty();
|
||||
}
|
||||
// 拼接自身的查询条件
|
||||
query.selectAll(CrmBusinessDO.class)
|
||||
.eqIfPresent(CrmBusinessDO::getCustomerId, pageReqVO.getCustomerId()) // 指定客户编号
|
||||
.likeIfPresent(CrmBusinessDO::getName, pageReqVO.getName())
|
||||
.orderByDesc(CrmBusinessDO::getId);
|
||||
return selectJoinPage(pageReqVO, CrmBusinessDO.class, query);
|
||||
|
@ -43,7 +53,7 @@ public interface CrmBusinessMapper extends BaseMapperX<CrmBusinessDO> {
|
|||
default List<CrmBusinessDO> selectBatchIds(Collection<Long> ids, Long userId) {
|
||||
MPJLambdaWrapperX<CrmBusinessDO> query = new MPJLambdaWrapperX<>();
|
||||
// 拼接数据权限的查询条件
|
||||
CrmQueryWrapperUtils.builderListQueryBatch(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), ids, userId);
|
||||
CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), ids, userId);
|
||||
return selectJoinList(CrmBusinessDO.class, query);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,8 +30,11 @@ public interface CrmClueMapper extends BaseMapperX<CrmClueDO> {
|
|||
default PageResult<CrmClueDO> selectPage(CrmCluePageReqVO pageReqVO, Long userId) {
|
||||
MPJLambdaWrapperX<CrmClueDO> query = new MPJLambdaWrapperX<>();
|
||||
// 拼接数据权限的查询条件
|
||||
CrmQueryWrapperUtils.builderPageQuery(query, CrmBizTypeEnum.CRM_LEADS.getType(), CrmClueDO::getId,
|
||||
userId, pageReqVO.getSceneType(), pageReqVO.getPool());
|
||||
boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(),
|
||||
CrmClueDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool());
|
||||
if (!condition) {
|
||||
return PageResult.empty();
|
||||
}
|
||||
// 拼接自身的查询条件
|
||||
query.selectAll(CrmClueDO.class)
|
||||
.likeIfPresent(CrmClueDO::getName, pageReqVO.getName())
|
||||
|
@ -44,7 +47,7 @@ public interface CrmClueMapper extends BaseMapperX<CrmClueDO> {
|
|||
default List<CrmClueDO> selectBatchIds(Collection<Long> ids, Long userId) {
|
||||
MPJLambdaWrapperX<CrmClueDO> query = new MPJLambdaWrapperX<>();
|
||||
// 拼接数据权限的查询条件
|
||||
CrmQueryWrapperUtils.builderListQueryBatch(query, CrmBizTypeEnum.CRM_LEADS.getType(), ids, userId);
|
||||
CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), ids, userId);
|
||||
return selectJoinList(CrmClueDO.class, query);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.mysql.contact;
|
|||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
|
||||
|
@ -27,14 +28,28 @@ public interface CrmContactMapper extends BaseMapperX<CrmContactDO> {
|
|||
.set(CrmContactDO::getOwnerUserId, ownerUserId));
|
||||
}
|
||||
|
||||
default PageResult<CrmContactDO> selectPageByCustomerId(CrmContactPageReqVO pageVO) {
|
||||
return selectPage(pageVO, new LambdaQueryWrapperX<CrmContactDO>()
|
||||
.eq(CrmContactDO::getCustomerId, pageVO.getCustomerId()) // 指定客户编号
|
||||
.likeIfPresent(CrmContactDO::getName, pageVO.getName())
|
||||
.eqIfPresent(CrmContactDO::getMobile, pageVO.getMobile())
|
||||
.eqIfPresent(CrmContactDO::getTelephone, pageVO.getTelephone())
|
||||
.eqIfPresent(CrmContactDO::getEmail, pageVO.getEmail())
|
||||
.eqIfPresent(CrmContactDO::getQq, pageVO.getQq())
|
||||
.eqIfPresent(CrmContactDO::getWechat, pageVO.getWechat())
|
||||
.orderByDesc(CrmContactDO::getId));
|
||||
}
|
||||
|
||||
default PageResult<CrmContactDO> selectPage(CrmContactPageReqVO pageReqVO, Long userId) {
|
||||
MPJLambdaWrapperX<CrmContactDO> query = new MPJLambdaWrapperX<>();
|
||||
// 拼接数据权限的查询条件
|
||||
CrmQueryWrapperUtils.builderPageQuery(query, CrmBizTypeEnum.CRM_CONTACT.getType(), CrmContactDO::getId,
|
||||
userId, pageReqVO.getSceneType(), pageReqVO.getPool());
|
||||
boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(),
|
||||
CrmContactDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE);
|
||||
if (!condition) {
|
||||
return PageResult.empty();
|
||||
}
|
||||
// 拼接自身的查询条件
|
||||
query.selectAll(CrmContactDO.class)
|
||||
.eqIfPresent(CrmContactDO::getCustomerId, pageReqVO.getCustomerId()) // 指定客户编号
|
||||
.likeIfPresent(CrmContactDO::getName, pageReqVO.getName())
|
||||
.eqIfPresent(CrmContactDO::getMobile, pageReqVO.getMobile())
|
||||
.eqIfPresent(CrmContactDO::getTelephone, pageReqVO.getTelephone())
|
||||
|
@ -48,7 +63,7 @@ public interface CrmContactMapper extends BaseMapperX<CrmContactDO> {
|
|||
default List<CrmContactDO> selectBatchIds(Collection<Long> ids, Long userId) {
|
||||
MPJLambdaWrapperX<CrmContactDO> query = new MPJLambdaWrapperX<>();
|
||||
// 拼接数据权限的查询条件
|
||||
CrmQueryWrapperUtils.builderListQueryBatch(query, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId);
|
||||
CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId);
|
||||
return selectJoinList(CrmContactDO.class, query);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.mysql.contract;
|
|||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
|
||||
|
@ -27,13 +28,26 @@ public interface CrmContractMapper extends BaseMapperX<CrmContractDO> {
|
|||
.set(CrmContractDO::getOwnerUserId, ownerUserId));
|
||||
}
|
||||
|
||||
default PageResult<CrmContractDO> selectPageByCustomerId(CrmContractPageReqVO pageReqVO) {
|
||||
return selectPage(pageReqVO, new LambdaQueryWrapperX<CrmContractDO>()
|
||||
.eq(CrmContractDO::getCustomerId, pageReqVO.getCustomerId())
|
||||
.likeIfPresent(CrmContractDO::getNo, pageReqVO.getNo())
|
||||
.likeIfPresent(CrmContractDO::getName, pageReqVO.getName())
|
||||
.eqIfPresent(CrmContractDO::getCustomerId, pageReqVO.getCustomerId())
|
||||
.eqIfPresent(CrmContractDO::getBusinessId, pageReqVO.getBusinessId())
|
||||
.orderByDesc(CrmContractDO::getId));
|
||||
}
|
||||
|
||||
default PageResult<CrmContractDO> selectPage(CrmContractPageReqVO pageReqVO, Long userId) {
|
||||
MPJLambdaWrapperX<CrmContractDO> mpjLambdaWrapperX = new MPJLambdaWrapperX<>();
|
||||
// 构建数据权限连表条件
|
||||
CrmQueryWrapperUtils.builderPageQuery(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), CrmContractDO::getId,
|
||||
userId, pageReqVO.getSceneType(), pageReqVO.getPool());
|
||||
// 拼接数据权限的查询条件
|
||||
boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(),
|
||||
CrmContractDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE);
|
||||
if (!condition) {
|
||||
return PageResult.empty();
|
||||
}
|
||||
// 拼接自身的查询条件
|
||||
mpjLambdaWrapperX.selectAll(CrmContractDO.class)
|
||||
.eqIfPresent(CrmContractDO::getCustomerId, pageReqVO.getCustomerId())
|
||||
.likeIfPresent(CrmContractDO::getNo, pageReqVO.getNo())
|
||||
.likeIfPresent(CrmContractDO::getName, pageReqVO.getName())
|
||||
.eqIfPresent(CrmContractDO::getCustomerId, pageReqVO.getCustomerId())
|
||||
|
@ -45,7 +59,7 @@ public interface CrmContractMapper extends BaseMapperX<CrmContractDO> {
|
|||
default List<CrmContractDO> selectBatchIds(Collection<Long> ids, Long userId) {
|
||||
MPJLambdaWrapperX<CrmContractDO> mpjLambdaWrapperX = new MPJLambdaWrapperX<>();
|
||||
// 构建数据权限连表条件
|
||||
CrmQueryWrapperUtils.builderListQueryBatch(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId);
|
||||
CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId);
|
||||
return selectJoinList(CrmContractDO.class, mpjLambdaWrapperX);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,8 +30,11 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> {
|
|||
default PageResult<CrmCustomerDO> selectPage(CrmCustomerPageReqVO pageReqVO, Long userId) {
|
||||
MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>();
|
||||
// 拼接数据权限的查询条件
|
||||
CrmQueryWrapperUtils.builderPageQuery(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId,
|
||||
userId, pageReqVO.getSceneType(), pageReqVO.getPool());
|
||||
boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(),
|
||||
CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool());
|
||||
if (!condition) {
|
||||
return PageResult.empty();
|
||||
}
|
||||
// 拼接自身的查询条件
|
||||
query.selectAll(CrmCustomerDO.class)
|
||||
.likeIfPresent(CrmCustomerDO::getName, pageReqVO.getName())
|
||||
|
@ -45,7 +48,7 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> {
|
|||
default List<CrmCustomerDO> selectBatchIds(Collection<Long> ids, Long userId) {
|
||||
MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>();
|
||||
// 拼接数据权限的查询条件
|
||||
CrmQueryWrapperUtils.builderListQueryBatch(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), ids, userId);
|
||||
CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), ids, userId);
|
||||
return selectJoinList(CrmCustomerDO.class, query);
|
||||
}
|
||||
|
||||
|
|
|
@ -46,4 +46,10 @@ public interface CrmPermissionMapper extends BaseMapperX<CrmPermissionDO> {
|
|||
.eq(CrmPermissionDO::getId, id).eq(CrmPermissionDO::getUserId, userId));
|
||||
}
|
||||
|
||||
default int deletePermission(Integer bizType, Long bizId) {
|
||||
return delete(new LambdaQueryWrapperX<CrmPermissionDO>()
|
||||
.eq(CrmPermissionDO::getBizType, bizType)
|
||||
.eq(CrmPermissionDO::getBizId, bizId));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,10 +3,17 @@ package cn.iocoder.yudao.module.crm.dal.mysql.receivable;
|
|||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO;
|
||||
import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 回款 Mapper
|
||||
*
|
||||
|
@ -15,15 +22,13 @@ import org.apache.ibatis.annotations.Mapper;
|
|||
@Mapper
|
||||
public interface CrmReceivableMapper extends BaseMapperX<CrmReceivableDO> {
|
||||
|
||||
default PageResult<CrmReceivableDO> selectPage(CrmReceivablePageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<CrmReceivableDO>()
|
||||
.eqIfPresent(CrmReceivableDO::getNo, reqVO.getNo())
|
||||
.eqIfPresent(CrmReceivableDO::getPlanId, reqVO.getPlanId())
|
||||
.eqIfPresent(CrmReceivableDO::getCustomerId, reqVO.getCustomerId())
|
||||
.orderByDesc(CrmReceivableDO::getId));
|
||||
default int updateOwnerUserIdById(Long id, Long ownerUserId) {
|
||||
return update(new LambdaUpdateWrapper<CrmReceivableDO>()
|
||||
.eq(CrmReceivableDO::getId, id)
|
||||
.set(CrmReceivableDO::getOwnerUserId, ownerUserId));
|
||||
}
|
||||
|
||||
default PageResult<CrmReceivableDO> selectPageByCustomer(CrmReceivablePageReqVO reqVO) {
|
||||
default PageResult<CrmReceivableDO> selectPageByCustomerId(CrmReceivablePageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<CrmReceivableDO>()
|
||||
.eq(CrmReceivableDO::getCustomerId, reqVO.getCustomerId()) // 必须传递
|
||||
.eqIfPresent(CrmReceivableDO::getNo, reqVO.getNo())
|
||||
|
@ -31,4 +36,27 @@ public interface CrmReceivableMapper extends BaseMapperX<CrmReceivableDO> {
|
|||
.orderByDesc(CrmReceivableDO::getId));
|
||||
}
|
||||
|
||||
default PageResult<CrmReceivableDO> selectPage(CrmReceivablePageReqVO pageReqVO, Long userId) {
|
||||
MPJLambdaWrapperX<CrmReceivableDO> query = new MPJLambdaWrapperX<>();
|
||||
// 拼接数据权限的查询条件
|
||||
boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(),
|
||||
CrmReceivableDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE);
|
||||
if (!condition) {
|
||||
return PageResult.empty();
|
||||
}
|
||||
// 拼接自身的查询条件
|
||||
query.selectAll(CrmReceivableDO.class)
|
||||
.eqIfPresent(CrmReceivableDO::getNo, pageReqVO.getNo())
|
||||
.eqIfPresent(CrmReceivableDO::getPlanId, pageReqVO.getPlanId())
|
||||
.orderByDesc(CrmReceivableDO::getId);
|
||||
return selectJoinPage(pageReqVO, CrmReceivableDO.class, query);
|
||||
}
|
||||
|
||||
default List<CrmReceivableDO> selectBatchIds(Collection<Long> ids, Long userId) {
|
||||
MPJLambdaWrapperX<CrmReceivableDO> query = new MPJLambdaWrapperX<>();
|
||||
// 拼接数据权限的查询条件
|
||||
CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), ids, userId);
|
||||
return selectJoinList(CrmReceivableDO.class, query);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,10 +3,17 @@ package cn.iocoder.yudao.module.crm.dal.mysql.receivable;
|
|||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO;
|
||||
import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 回款计划 Mapper
|
||||
*
|
||||
|
@ -15,18 +22,40 @@ import org.apache.ibatis.annotations.Mapper;
|
|||
@Mapper
|
||||
public interface CrmReceivablePlanMapper extends BaseMapperX<CrmReceivablePlanDO> {
|
||||
|
||||
default PageResult<CrmReceivablePlanDO> selectPage(CrmReceivablePlanPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<CrmReceivablePlanDO>()
|
||||
.eqIfPresent(CrmReceivablePlanDO::getCustomerId, reqVO.getCustomerId())
|
||||
.eqIfPresent(CrmReceivablePlanDO::getContractId, reqVO.getContractId())
|
||||
.orderByDesc(CrmReceivablePlanDO::getId));
|
||||
default int updateOwnerUserIdById(Long id, Long ownerUserId) {
|
||||
return update(new LambdaUpdateWrapper<CrmReceivablePlanDO>()
|
||||
.eq(CrmReceivablePlanDO::getId, id)
|
||||
.set(CrmReceivablePlanDO::getOwnerUserId, ownerUserId));
|
||||
}
|
||||
|
||||
default PageResult<CrmReceivablePlanDO> selectPageByCustomer(CrmReceivablePlanPageReqVO reqVO) {
|
||||
default PageResult<CrmReceivablePlanDO> selectPageByCustomerId(CrmReceivablePlanPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<CrmReceivablePlanDO>()
|
||||
.eq(CrmReceivablePlanDO::getCustomerId, reqVO.getCustomerId()) // 必须传递
|
||||
.eqIfPresent(CrmReceivablePlanDO::getContractId, reqVO.getContractId())
|
||||
.orderByDesc(CrmReceivablePlanDO::getId));
|
||||
}
|
||||
|
||||
default PageResult<CrmReceivablePlanDO> selectPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId) {
|
||||
MPJLambdaWrapperX<CrmReceivablePlanDO> query = new MPJLambdaWrapperX<>();
|
||||
// 拼接数据权限的查询条件
|
||||
boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(),
|
||||
CrmReceivablePlanDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE);
|
||||
if (!condition) {
|
||||
return PageResult.empty();
|
||||
}
|
||||
// 拼接自身的查询条件
|
||||
query.selectAll(CrmReceivablePlanDO.class)
|
||||
.eqIfPresent(CrmReceivablePlanDO::getCustomerId, pageReqVO.getCustomerId())
|
||||
.eqIfPresent(CrmReceivablePlanDO::getContractId, pageReqVO.getContractId())
|
||||
.orderByDesc(CrmReceivablePlanDO::getId);
|
||||
return selectJoinPage(pageReqVO, CrmReceivablePlanDO.class, query);
|
||||
}
|
||||
|
||||
default List<CrmReceivablePlanDO> selectBatchIds(Collection<Long> ids, Long userId) {
|
||||
MPJLambdaWrapperX<CrmReceivablePlanDO> query = new MPJLambdaWrapperX<>();
|
||||
// 拼接数据权限的查询条件
|
||||
CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), ids, userId);
|
||||
return selectJoinList(CrmReceivablePlanDO.class, query);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 "";
|
||||
}
|
||||
}
|
|
@ -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 "";
|
||||
}
|
||||
}
|
|
@ -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 "";
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
package cn.iocoder.yudao.module.crm.framework.bizlog;
|
|
@ -75,10 +75,9 @@ public interface CrmBusinessService {
|
|||
* 数据权限:基于 {@link CrmCustomerDO} 读取
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @param userId 用户编号
|
||||
* @return 联系人分页
|
||||
*/
|
||||
PageResult<CrmBusinessDO> getBusinessPageByCustomer(CrmBusinessPageReqVO pageReqVO, Long userId);
|
||||
PageResult<CrmBusinessDO> getBusinessPageByCustomerId(CrmBusinessPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 商机转移
|
||||
|
|
|
@ -111,11 +111,9 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public PageResult<CrmBusinessDO> getBusinessPageByCustomer(CrmBusinessPageReqVO pageReqVO, Long userId) {
|
||||
// 校验客户存在 TODO @puhui999:这里不校验
|
||||
customerService.validateCustomer(pageReqVO.getCustomerId());
|
||||
// TODO @puhui999:感觉这里貌似不太复用用 selectPage,因为他可能没商机权限,只是因为能看 customer,所以可以看到列表
|
||||
return businessMapper.selectPage(pageReqVO, userId);
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageReqVO.customerId", level = CrmPermissionLevelEnum.READ)
|
||||
public PageResult<CrmBusinessDO> getBusinessPageByCustomerId(CrmBusinessPageReqVO pageReqVO) {
|
||||
return businessMapper.selectPageByCustomerId(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -127,7 +125,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
|||
// 2.1 数据权限转移
|
||||
crmPermissionService.transferPermission(
|
||||
CrmBusinessConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()));
|
||||
|
||||
// 2.2 设置新的负责人
|
||||
businessMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.crm.service.clue;
|
|||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueCreateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO;
|
||||
import jakarta.validation.Valid;
|
||||
|
@ -64,4 +65,12 @@ public interface CrmClueService {
|
|||
*/
|
||||
PageResult<CrmClueDO> getCluePage(CrmCluePageReqVO pageReqVO, Long userId);
|
||||
|
||||
/**
|
||||
* 线索转移
|
||||
*
|
||||
* @param reqVO 请求
|
||||
* @param userId 用户编号
|
||||
*/
|
||||
void transferClue(CrmClueTransferReqVO reqVO, Long userId);
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import cn.hutool.core.collection.ListUtil;
|
|||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueCreateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.convert.clue.CrmClueConvert;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO;
|
||||
|
@ -101,4 +102,18 @@ public class CrmClueServiceImpl implements CrmClueService {
|
|||
return clueMapper.selectPage(pageReqVO, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferClue(CrmClueTransferReqVO reqVO, Long userId) {
|
||||
// 1 校验线索是否存在
|
||||
validateClueExists(reqVO.getId());
|
||||
|
||||
// 2.1 数据权限转移
|
||||
crmPermissionService.transferPermission(
|
||||
CrmClueConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_LEADS.getType()));
|
||||
// 2.2 设置新的负责人
|
||||
clueMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
|
||||
|
||||
// 3. TODO 记录转移日志
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,8 +3,10 @@ package cn.iocoder.yudao.module.crm.service.contact;
|
|||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactCreateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.util.Collection;
|
||||
|
@ -71,12 +73,19 @@ public interface CrmContactService {
|
|||
/**
|
||||
* 获得联系人分页
|
||||
*
|
||||
* 数据权限:基于 {@link CrmContactDO}
|
||||
* 数据权限:基于 {@link CrmCustomerDO}
|
||||
*
|
||||
* @param pageVO 分页查询
|
||||
* @param userId 用户编号
|
||||
* @return 联系人分页
|
||||
*/
|
||||
PageResult<CrmContactDO> getContactPageByCustomerId(CrmContactPageReqVO pageVO, Long userId);
|
||||
PageResult<CrmContactDO> getContactPageByCustomerId(CrmContactPageReqVO pageVO);
|
||||
|
||||
/**
|
||||
* 联系人转移
|
||||
*
|
||||
* @param reqVO 请求
|
||||
* @param userId 用户编号
|
||||
*/
|
||||
void transferContact(CrmContactTransferReqVO reqVO, Long userId);
|
||||
|
||||
}
|
||||
|
|
|
@ -3,11 +3,8 @@ package cn.iocoder.yudao.module.crm.service.contact;
|
|||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBaseVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactCreateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.convert.contact.ContactConvert;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*;
|
||||
import cn.iocoder.yudao.module.crm.convert.contact.CrmContactConvert;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper;
|
||||
import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
|
||||
|
@ -56,7 +53,7 @@ public class CrmContactServiceImpl implements CrmContactService {
|
|||
// 1.1 校验
|
||||
validateRelationDataExists(createReqVO);
|
||||
// 1.2 插入
|
||||
CrmContactDO contact = ContactConvert.INSTANCE.convert(createReqVO);
|
||||
CrmContactDO contact = CrmContactConvert.INSTANCE.convert(createReqVO);
|
||||
contactMapper.insert(contact);
|
||||
|
||||
// 2. 创建数据权限
|
||||
|
@ -73,7 +70,7 @@ public class CrmContactServiceImpl implements CrmContactService {
|
|||
validateContactExists(updateReqVO.getId());
|
||||
validateRelationDataExists(updateReqVO);
|
||||
// 2. 更新
|
||||
CrmContactDO updateObj = ContactConvert.INSTANCE.convert(updateReqVO);
|
||||
CrmContactDO updateObj = CrmContactConvert.INSTANCE.convert(updateReqVO);
|
||||
contactMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
|
@ -134,11 +131,23 @@ public class CrmContactServiceImpl implements CrmContactService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public PageResult<CrmContactDO> getContactPageByCustomerId(CrmContactPageReqVO pageVO, Long userId) {
|
||||
// 校验用户存在
|
||||
customerService.validateCustomer(pageVO.getCustomerId());
|
||||
// TODO @puhui999:getBusinessPageByCustomer 同理
|
||||
return contactMapper.selectPage(pageVO, userId);
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageVO.customerId", level = CrmPermissionLevelEnum.READ)
|
||||
public PageResult<CrmContactDO> getContactPageByCustomerId(CrmContactPageReqVO pageVO) {
|
||||
return contactMapper.selectPageByCustomerId(pageVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferContact(CrmContactTransferReqVO reqVO, Long userId) {
|
||||
// 1 校验联系人是否存在
|
||||
validateContactExists(reqVO.getId());
|
||||
|
||||
// 2.1 数据权限转移
|
||||
crmPermissionService.transferPermission(
|
||||
CrmContactConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTACT.getType()));
|
||||
// 2.2 设置新的负责人
|
||||
contactMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
|
||||
|
||||
// 3. TODO 记录转移日志
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -75,12 +75,9 @@ public interface CrmContractService {
|
|||
* 数据权限:基于 {@link CrmCustomerDO} 读取
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @param userId 用户编号
|
||||
* @return 联系人分页
|
||||
*/
|
||||
default PageResult<CrmContractDO> getContractPageByCustomer(CrmContractPageReqVO pageReqVO, Long userId) {
|
||||
return getContractPage(pageReqVO, userId);
|
||||
}
|
||||
PageResult<CrmContractDO> getContractPageByCustomerId(CrmContractPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 合同转移
|
||||
|
|
|
@ -7,7 +7,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractCreat
|
|||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.convert.contract.ContractConvert;
|
||||
import cn.iocoder.yudao.module.crm.convert.contract.CrmContractConvert;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper;
|
||||
import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
|
||||
|
@ -44,7 +44,7 @@ public class CrmContractServiceImpl implements CrmContractService {
|
|||
@Override
|
||||
public Long createContract(CrmContractCreateReqVO createReqVO, Long userId) {
|
||||
// 插入
|
||||
CrmContractDO contract = ContractConvert.INSTANCE.convert(createReqVO);
|
||||
CrmContractDO contract = CrmContractConvert.INSTANCE.convert(createReqVO);
|
||||
contractMapper.insert(contract);
|
||||
|
||||
// 创建数据权限
|
||||
|
@ -61,7 +61,7 @@ public class CrmContractServiceImpl implements CrmContractService {
|
|||
// 校验存在
|
||||
validateContractExists(updateReqVO.getId());
|
||||
// 更新
|
||||
CrmContractDO updateObj = ContractConvert.INSTANCE.convert(updateReqVO);
|
||||
CrmContractDO updateObj = CrmContractConvert.INSTANCE.convert(updateReqVO);
|
||||
contractMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
|
@ -104,6 +104,12 @@ public class CrmContractServiceImpl implements CrmContractService {
|
|||
return contractMapper.selectPage(pageReqVO, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageReqVO.customerId", level = CrmPermissionLevelEnum.READ)
|
||||
public PageResult<CrmContractDO> getContractPageByCustomerId(CrmContractPageReqVO pageReqVO) {
|
||||
return contractMapper.selectPageByCustomerId(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void transferContract(CrmContractTransferReqVO reqVO, Long userId) {
|
||||
|
@ -112,7 +118,7 @@ public class CrmContractServiceImpl implements CrmContractService {
|
|||
|
||||
// 2.1 数据权限转移
|
||||
crmPermissionService.transferPermission(
|
||||
ContractConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType()));
|
||||
CrmContractConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType()));
|
||||
// 2.2 设置负责人
|
||||
contractMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -15,6 +16,9 @@ import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission;
|
|||
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;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
@ -24,6 +28,8 @@ import java.util.*;
|
|||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
|
||||
import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CUSTOMER;
|
||||
import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.TRANSFER_CUSTOMER_LOG_SUCCESS;
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
/**
|
||||
|
@ -59,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);
|
||||
|
@ -82,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
|
||||
|
@ -114,7 +125,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
|
|||
*/
|
||||
@Override
|
||||
public void validateCustomer(Long customerId) {
|
||||
// TODO puhui999: 不返回客户不走校验应该可行
|
||||
// 校验客户是否存在
|
||||
if (customerId == null) {
|
||||
throw exception(CUSTOMER_NOT_EXISTS);
|
||||
|
@ -127,11 +137,13 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
|
|||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@LogRecord(success = TRANSFER_CUSTOMER_LOG_SUCCESS, type = CRM_CUSTOMER, subType = "客户转移", bizNo = "{{#reqVO.id}}")
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER)
|
||||
public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) {
|
||||
// 1. 校验客户是否存在
|
||||
validateCustomer(reqVO.getId());
|
||||
|
||||
// 添加 crmCustomer 到日志上下文 TODO 日志记录放在 service 里是因为已经过了权限校验查询时不用走两次校验
|
||||
LogRecordContext.putVariable("crmCustomer", customerMapper.selectById(reqVO.getId()));
|
||||
// 2.1 数据权限转移
|
||||
crmPermissionService.transferPermission(
|
||||
CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()));
|
||||
|
|
|
@ -138,15 +138,13 @@ public class CrmPermissionServiceImpl implements CrmPermissionService {
|
|||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deletePermission(Integer bizType, Long bizId) {
|
||||
// TODO @puhui999:这种直接写条件删除;不需要先查询,再删除
|
||||
List<CrmPermissionDO> permissionList = crmPermissionMapper.selectByBizTypeAndBizId(bizType, bizId);
|
||||
if (CollUtil.isEmpty(permissionList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 删除数据权限
|
||||
crmPermissionMapper.deleteBatchIds(convertSet(permissionList, CrmPermissionDO::getId));
|
||||
int deletedCol = crmPermissionMapper.deletePermission(bizType, bizId);
|
||||
if (deletedCol == 0) {
|
||||
throw exception(CRM_PERMISSION_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -3,11 +3,12 @@ package cn.iocoder.yudao.module.crm.service.receivable;
|
|||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanTransferReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -24,7 +25,7 @@ public interface CrmReceivablePlanService {
|
|||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createReceivablePlan(@Valid CrmReceivablePlanCreateReqVO createReqVO);
|
||||
Long createReceivablePlan(@Valid CrmReceivablePlanCreateReqVO createReqVO, Long userId);
|
||||
|
||||
/**
|
||||
* 更新回款计划
|
||||
|
@ -62,9 +63,10 @@ public interface CrmReceivablePlanService {
|
|||
* 数据权限:基于 {@link CrmReceivablePlanDO} 读取
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @param userId 用户编号
|
||||
* @return 回款计划分页
|
||||
*/
|
||||
PageResult<CrmReceivablePlanDO> getReceivablePlanPage(CrmReceivablePlanPageReqVO pageReqVO);
|
||||
PageResult<CrmReceivablePlanDO> getReceivablePlanPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId);
|
||||
|
||||
/**
|
||||
* 获得回款计划分页,基于指定客户
|
||||
|
@ -74,6 +76,14 @@ public interface CrmReceivablePlanService {
|
|||
* @param pageReqVO 分页查询
|
||||
* @return 回款计划分页
|
||||
*/
|
||||
PageResult<CrmReceivablePlanDO> getReceivablePlanPageByCustomer(CrmReceivablePlanPageReqVO pageReqVO);
|
||||
PageResult<CrmReceivablePlanDO> getReceivablePlanPageByCustomerId(CrmReceivablePlanPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 回款计划转移
|
||||
*
|
||||
* @param reqVO 请求
|
||||
* @param userId 用户编号
|
||||
*/
|
||||
void transferReceivablePlan(CrmReceivablePlanTransferReqVO reqVO, Long userId);
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import cn.hutool.core.util.ObjectUtil;
|
|||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanTransferReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivablePlanConvert;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
|
||||
|
@ -17,10 +18,12 @@ import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
|
|||
import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission;
|
||||
import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
|
||||
import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
|
||||
import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
|
||||
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -28,7 +31,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU
|
|||
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
|
||||
|
||||
// TODO @liuhongfeng:参考 CrmReceivableServiceImpl 写的 todo 哈;
|
||||
// TODO @puhui999:数据权限
|
||||
|
||||
/**
|
||||
* 回款计划 Service 实现类
|
||||
*
|
||||
|
@ -45,9 +48,11 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
|
|||
private CrmContractService contractService;
|
||||
@Resource
|
||||
private CrmCustomerService customerService;
|
||||
@Resource
|
||||
private CrmPermissionService crmPermissionService;
|
||||
|
||||
@Override
|
||||
public Long createReceivablePlan(CrmReceivablePlanCreateReqVO createReqVO) {
|
||||
public Long createReceivablePlan(CrmReceivablePlanCreateReqVO createReqVO, Long userId) {
|
||||
// 插入
|
||||
CrmReceivablePlanDO receivablePlan = CrmReceivablePlanConvert.INSTANCE.convert(createReqVO);
|
||||
receivablePlan.setFinishStatus(false);
|
||||
|
@ -55,29 +60,33 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
|
|||
checkReceivablePlan(receivablePlan);
|
||||
|
||||
receivablePlanMapper.insert(receivablePlan);
|
||||
// 创建数据权限
|
||||
crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType())
|
||||
.setBizId(receivablePlan.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
|
||||
// 返回
|
||||
return receivablePlan.getId();
|
||||
}
|
||||
|
||||
private void checkReceivablePlan(CrmReceivablePlanDO receivablePlan) {
|
||||
|
||||
if(ObjectUtil.isNull(receivablePlan.getContractId())){
|
||||
if (ObjectUtil.isNull(receivablePlan.getContractId())) {
|
||||
throw exception(CONTRACT_NOT_EXISTS);
|
||||
}
|
||||
|
||||
CrmContractDO contract = contractService.getContract(receivablePlan.getContractId());
|
||||
if(ObjectUtil.isNull(contract)){
|
||||
if (ObjectUtil.isNull(contract)) {
|
||||
throw exception(CONTRACT_NOT_EXISTS);
|
||||
}
|
||||
|
||||
CrmCustomerDO customer = customerService.getCustomer(receivablePlan.getCustomerId());
|
||||
if(ObjectUtil.isNull(customer)){
|
||||
if (ObjectUtil.isNull(customer)) {
|
||||
throw exception(CUSTOMER_NOT_EXISTS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
|
||||
public void updateReceivablePlan(CrmReceivablePlanUpdateReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateReceivablePlanExists(updateReqVO.getId());
|
||||
|
@ -88,6 +97,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
|
|||
}
|
||||
|
||||
@Override
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
|
||||
public void deleteReceivablePlan(Long id) {
|
||||
// 校验存在
|
||||
validateReceivablePlanExists(id);
|
||||
|
@ -102,6 +112,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
|
|||
}
|
||||
|
||||
@Override
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#id", level = CrmPermissionLevelEnum.READ)
|
||||
public CrmReceivablePlanDO getReceivablePlan(Long id) {
|
||||
return receivablePlanMapper.selectById(id);
|
||||
}
|
||||
|
@ -115,14 +126,28 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public PageResult<CrmReceivablePlanDO> getReceivablePlanPage(CrmReceivablePlanPageReqVO pageReqVO) {
|
||||
return receivablePlanMapper.selectPage(pageReqVO);
|
||||
public PageResult<CrmReceivablePlanDO> getReceivablePlanPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId) {
|
||||
return receivablePlanMapper.selectPage(pageReqVO, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageReqVO.customerId", level = CrmPermissionLevelEnum.READ)
|
||||
public PageResult<CrmReceivablePlanDO> getReceivablePlanPageByCustomer(CrmReceivablePlanPageReqVO pageReqVO) {
|
||||
return receivablePlanMapper.selectPageByCustomer(pageReqVO);
|
||||
public PageResult<CrmReceivablePlanDO> getReceivablePlanPageByCustomerId(CrmReceivablePlanPageReqVO pageReqVO) {
|
||||
return receivablePlanMapper.selectPageByCustomerId(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferReceivablePlan(CrmReceivablePlanTransferReqVO reqVO, Long userId) {
|
||||
// 1 校验回款计划是否存在
|
||||
validateReceivablePlanExists(reqVO.getId());
|
||||
|
||||
// 2.1 数据权限转移
|
||||
crmPermissionService.transferPermission(
|
||||
CrmReceivablePlanConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType()));
|
||||
// 2.2 设置新的负责人
|
||||
receivablePlanMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
|
||||
|
||||
// 3. TODO 记录转移日志
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,11 +3,12 @@ package cn.iocoder.yudao.module.crm.service.receivable;
|
|||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableTransferReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -62,9 +63,10 @@ public interface CrmReceivableService {
|
|||
* 数据权限:基于 {@link CrmReceivableDO} 读取
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @param userId 用户编号
|
||||
* @return 回款分页
|
||||
*/
|
||||
PageResult<CrmReceivableDO> getReceivablePage(CrmReceivablePageReqVO pageReqVO);
|
||||
PageResult<CrmReceivableDO> getReceivablePage(CrmReceivablePageReqVO pageReqVO, Long userId);
|
||||
|
||||
/**
|
||||
* 获得回款分页,基于指定客户
|
||||
|
@ -74,6 +76,14 @@ public interface CrmReceivableService {
|
|||
* @param pageReqVO 分页查询
|
||||
* @return 回款分页
|
||||
*/
|
||||
PageResult<CrmReceivableDO> getReceivablePageByCustomer(CrmReceivablePageReqVO pageReqVO);
|
||||
PageResult<CrmReceivableDO> getReceivablePageByCustomerId(CrmReceivablePageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 回款转移
|
||||
*
|
||||
* @param reqVO 请求
|
||||
* @param userId 用户编号
|
||||
*/
|
||||
void transferReceivable(CrmReceivableTransferReqVO reqVO, Long userId);
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
|||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableTransferReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivableConvert;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
|
||||
|
@ -20,10 +21,11 @@ import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
|
|||
import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission;
|
||||
import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
|
||||
import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
|
||||
import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -48,6 +50,8 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
|
|||
private CrmCustomerService customerService;
|
||||
@Resource
|
||||
private CrmReceivablePlanService receivablePlanService;
|
||||
@Resource
|
||||
private CrmPermissionService crmPermissionService;
|
||||
|
||||
// TODO @liuhongfeng:创建还款后,是不是什么时候,要更新 plan?
|
||||
@Override
|
||||
|
@ -70,22 +74,22 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
|
|||
// TODO @liuhongfeng:这里的括号要注意排版;
|
||||
private void checkReceivable(CrmReceivableDO receivable) {
|
||||
// TODO @liuhongfeng:这个放在参数校验合适
|
||||
if(ObjectUtil.isNull(receivable.getContractId())){
|
||||
if (ObjectUtil.isNull(receivable.getContractId())) {
|
||||
throw exception(CONTRACT_NOT_EXISTS);
|
||||
}
|
||||
|
||||
CrmContractDO contract = contractService.getContract(receivable.getContractId());
|
||||
if(ObjectUtil.isNull(contract)){
|
||||
if (ObjectUtil.isNull(contract)) {
|
||||
throw exception(CONTRACT_NOT_EXISTS);
|
||||
}
|
||||
|
||||
CrmCustomerDO customer = customerService.getCustomer(receivable.getCustomerId());
|
||||
if(ObjectUtil.isNull(customer)){
|
||||
if (ObjectUtil.isNull(customer)) {
|
||||
throw exception(CUSTOMER_NOT_EXISTS);
|
||||
}
|
||||
|
||||
CrmReceivablePlanDO receivablePlan = receivablePlanService.getReceivablePlan(receivable.getPlanId());
|
||||
if(ObjectUtil.isNull(receivablePlan)){
|
||||
if (ObjectUtil.isNull(receivablePlan)) {
|
||||
throw exception(RECEIVABLE_PLAN_NOT_EXISTS);
|
||||
}
|
||||
|
||||
|
@ -129,16 +133,29 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
|
|||
return receivableMapper.selectBatchIds(ids);
|
||||
}
|
||||
|
||||
// TODO @芋艿:数据权限
|
||||
@Override
|
||||
public PageResult<CrmReceivableDO> getReceivablePage(CrmReceivablePageReqVO pageReqVO) {
|
||||
return receivableMapper.selectPage(pageReqVO);
|
||||
public PageResult<CrmReceivableDO> getReceivablePage(CrmReceivablePageReqVO pageReqVO, Long userId) {
|
||||
return receivableMapper.selectPage(pageReqVO, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageReqVO.customerId", level = CrmPermissionLevelEnum.READ)
|
||||
public PageResult<CrmReceivableDO> getReceivablePageByCustomer(CrmReceivablePageReqVO pageReqVO) {
|
||||
return receivableMapper.selectPageByCustomer(pageReqVO);
|
||||
public PageResult<CrmReceivableDO> getReceivablePageByCustomerId(CrmReceivablePageReqVO pageReqVO) {
|
||||
return receivableMapper.selectPageByCustomerId(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferReceivable(CrmReceivableTransferReqVO reqVO, Long userId) {
|
||||
// 1 校验回款是否存在
|
||||
validateReceivableExists(reqVO.getId());
|
||||
|
||||
// 2.1 数据权限转移
|
||||
crmPermissionService.transferPermission(
|
||||
CrmReceivableConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_RECEIVABLE.getType()));
|
||||
// 2.2 设置新的负责人
|
||||
receivableMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
|
||||
|
||||
// 3. TODO 记录转移日志
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import cn.hutool.extra.spring.SpringUtil;
|
|||
import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
|
||||
import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum;
|
||||
import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
|
@ -17,7 +18,7 @@ import java.util.List;
|
|||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
|
||||
/**
|
||||
* CRM 分页查询工具类
|
||||
* CRM 查询工具类
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
|
@ -26,17 +27,17 @@ public class CrmQueryWrapperUtils {
|
|||
/**
|
||||
* 构造 CRM 数据类型数据分页查询条件
|
||||
*
|
||||
* @param query 连表查询对象
|
||||
* @param bizType 数据类型 {@link CrmBizTypeEnum}
|
||||
* @param bizId 数据编号
|
||||
* @param userId 用户编号
|
||||
* @param sceneType 场景类型
|
||||
* @param pool 公海
|
||||
* @param query 连表查询对象
|
||||
* @param bizType 数据类型 {@link CrmBizTypeEnum}
|
||||
* @param bizId 数据编号
|
||||
* @param userId 用户编号
|
||||
* @param sceneType 场景类型
|
||||
* @param pool 公海
|
||||
* @return 是否 (是:需要执行查询,否:不需要查询调用方法直接返回空)
|
||||
*/
|
||||
// TODO @puhui999:bizId 直接传递会不会简单点
|
||||
// TODO @puhui999:builderPageQuery 应该不仅仅适合于分页查询,应该适用于所有的查询;可以改成 appendPermissionCondition
|
||||
public static <T extends MPJLambdaWrapper<?>, S> void builderPageQuery(T query, Integer bizType, SFunction<S, ?> bizId,
|
||||
Long userId, Integer sceneType, Boolean pool) {
|
||||
// TODO @puhui999:bizId 直接传递会不会简单点 回复:还是需要 SFunction 因为分页连表时不知道 bizId 是多少
|
||||
public static <T extends MPJLambdaWrapper<?>, S> boolean appendPermissionCondition(T query, Integer bizType, SFunction<S, ?> bizId,
|
||||
Long userId, Integer sceneType, Boolean pool) {
|
||||
// 1. 构建数据权限连表条件
|
||||
if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE)) { // 管理员不需要数据权限
|
||||
query.innerJoin(CrmPermissionDO.class, on ->
|
||||
|
@ -48,52 +49,55 @@ public class CrmQueryWrapperUtils {
|
|||
query.eq("owner_user_id", userId);
|
||||
}
|
||||
// 2.2 场景二:我参与的数据
|
||||
// TODO @puhui999:参与,指的是有读写权限噢;可以把 1. 的合并到 2.2 里;因为 2.1 不需要;
|
||||
if (CrmSceneTypeEnum.isInvolved(sceneType)) {
|
||||
query.ne("owner_user_id", userId);
|
||||
query
|
||||
.ne("owner_user_id", userId)
|
||||
.and(q -> q.eq(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.READ.getLevel())
|
||||
.or()
|
||||
.eq(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.WRITE.getLevel()));
|
||||
|
||||
}
|
||||
// 2.3 场景三:下属负责的数据
|
||||
if (CrmSceneTypeEnum.isSubordinate(sceneType)) {
|
||||
List<AdminUserRespDTO> subordinateUsers = getAdminUserApi().getUserListBySubordinate(userId);
|
||||
// TODO @puhui999:如果为空,不拼接,就是查询了所有数据呀?
|
||||
if (CollUtil.isNotEmpty(subordinateUsers)) {
|
||||
query.in("owner_user_id", convertSet(subordinateUsers, AdminUserRespDTO::getId));
|
||||
if (CollUtil.isEmpty(subordinateUsers)) {
|
||||
return false;
|
||||
}
|
||||
query.in("owner_user_id", convertSet(subordinateUsers, AdminUserRespDTO::getId));
|
||||
}
|
||||
|
||||
// 2. 拼接公海的查询条件
|
||||
// 3. 拼接公海的查询条件
|
||||
if (ObjUtil.equal(pool, Boolean.TRUE)) { // 情况一:公海
|
||||
query.isNull("owner_user_id");
|
||||
} else { // 情况二:不是公海
|
||||
query.isNotNull("owner_user_id");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造 CRM 数据类型批量数据查询条件
|
||||
*
|
||||
* @param query 连表查询对象
|
||||
* @param bizType 数据类型 {@link CrmBizTypeEnum}
|
||||
* @param bizIds 数据编号
|
||||
* @param userId 用户编号
|
||||
* @param query 连表查询对象
|
||||
* @param bizType 数据类型 {@link CrmBizTypeEnum}
|
||||
* @param bizIds 数据编号
|
||||
* @param userId 用户编号
|
||||
*/
|
||||
// TODO @puhui999:可以改成 appendPermissionCondition
|
||||
// TODO @puhui999:S 是不是可以删除
|
||||
public static <T extends MPJLambdaWrapper<?>, S> void builderListQueryBatch(T query, Integer bizType, Collection<Long> bizIds, Long userId) {
|
||||
// TODO @puhui999:这里先 if return 简单点
|
||||
if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE)) { // 管理员不需要数据权限
|
||||
query.innerJoin(CrmPermissionDO.class, on ->
|
||||
on.eq(CrmPermissionDO::getBizType, bizType).in(CrmPermissionDO::getBizId, bizIds)
|
||||
.in(CollUtil.isNotEmpty(bizIds), CrmPermissionDO::getUserId, userId));
|
||||
public static <T extends MPJLambdaWrapper<?>> void appendPermissionCondition(T query, Integer bizType, Collection<Long> bizIds, Long userId) {
|
||||
if (ObjUtil.equal(validateAdminUser(userId), Boolean.TRUE)) {// 管理员不需要数据权限
|
||||
return;
|
||||
}
|
||||
|
||||
query.innerJoin(CrmPermissionDO.class, on ->
|
||||
on.eq(CrmPermissionDO::getBizType, bizType).in(CrmPermissionDO::getBizId, bizIds)
|
||||
.in(CollUtil.isNotEmpty(bizIds), CrmPermissionDO::getUserId, userId));
|
||||
}
|
||||
|
||||
// TODO @puhui999:需要加个变量,不用每次都拿哈;
|
||||
private static AdminUserApi getAdminUserApi() {
|
||||
return SpringUtil.getBean(AdminUserApi.class);
|
||||
return AdminUserApiHolder.ADMIN_USER_API;
|
||||
}
|
||||
|
||||
// TODO @puhui999:需要实现;
|
||||
/**
|
||||
* 校验用户是否是管理员
|
||||
*
|
||||
|
@ -101,7 +105,27 @@ public class CrmQueryWrapperUtils {
|
|||
* @return 是/否
|
||||
*/
|
||||
private static boolean validateAdminUser(Long userId) {
|
||||
// TODO 查询权限配置表用户的角色信息
|
||||
//CrmPermissionConfig permissionConfig = crmPermissionConfigService.getPermissionConfigByUserId(userId);
|
||||
//if (permissionConfig == null) {
|
||||
// return false;
|
||||
//}
|
||||
//// 校验是否为管理员
|
||||
//if (permissionConfig.getIsAdmin()){
|
||||
// return true;
|
||||
//}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 静态内部类实现 AdminUserApi 单例获取
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
private static class AdminUserApiHolder {
|
||||
|
||||
private static final AdminUserApi ADMIN_USER_API = SpringUtil.getBean(AdminUserApi.class);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,12 +7,12 @@ import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceiv
|
|||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivablePlanMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
|
||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
|
@ -22,6 +22,7 @@ import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.RECEIVABLE_PL
|
|||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
// TODO 芋艿:后续,需要补充测试用例
|
||||
|
||||
/**
|
||||
* {@link CrmReceivablePlanServiceImpl} 的单元测试类
|
||||
*
|
||||
|
@ -43,7 +44,7 @@ public class CrmCrmReceivablePlanServiceImplTest extends BaseDbUnitTest {
|
|||
CrmReceivablePlanCreateReqVO reqVO = randomPojo(CrmReceivablePlanCreateReqVO.class);
|
||||
|
||||
// 调用
|
||||
Long receivablePlanId = receivablePlanService.createReceivablePlan(reqVO);
|
||||
Long receivablePlanId = receivablePlanService.createReceivablePlan(reqVO, 1L);
|
||||
// 断言
|
||||
assertNotNull(receivablePlanId);
|
||||
// 校验记录的属性是否正确
|
||||
|
@ -87,8 +88,8 @@ public class CrmCrmReceivablePlanServiceImplTest extends BaseDbUnitTest {
|
|||
|
||||
// 调用
|
||||
receivablePlanService.deleteReceivablePlan(id);
|
||||
// 校验数据不存在了
|
||||
assertNull(crmReceivablePlanMapper.selectById(id));
|
||||
// 校验数据不存在了
|
||||
assertNull(crmReceivablePlanMapper.selectById(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -103,34 +104,34 @@ public class CrmCrmReceivablePlanServiceImplTest extends BaseDbUnitTest {
|
|||
@Test
|
||||
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
|
||||
public void testGetReceivablePlanPage() {
|
||||
// mock 数据
|
||||
CrmReceivablePlanDO dbReceivablePlan = randomPojo(CrmReceivablePlanDO.class, o -> { // 等会查询到
|
||||
o.setPeriod(null);
|
||||
o.setReturnTime(null);
|
||||
o.setRemindDays(null);
|
||||
o.setRemindTime(null);
|
||||
o.setCustomerId(null);
|
||||
o.setContractId(null);
|
||||
o.setOwnerUserId(null);
|
||||
o.setRemark(null);
|
||||
o.setCreateTime(null);
|
||||
});
|
||||
crmReceivablePlanMapper.insert(dbReceivablePlan);
|
||||
// 测试 customerId 不匹配
|
||||
crmReceivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setCustomerId(null)));
|
||||
// 测试 contractId 不匹配
|
||||
crmReceivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setContractId(null)));
|
||||
// 准备参数
|
||||
CrmReceivablePlanPageReqVO reqVO = new CrmReceivablePlanPageReqVO();
|
||||
reqVO.setCustomerId(null);
|
||||
reqVO.setContractId(null);
|
||||
|
||||
// 调用
|
||||
PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
assertPojoEquals(dbReceivablePlan, pageResult.getList().get(0));
|
||||
// mock 数据
|
||||
CrmReceivablePlanDO dbReceivablePlan = randomPojo(CrmReceivablePlanDO.class, o -> { // 等会查询到
|
||||
o.setPeriod(null);
|
||||
o.setReturnTime(null);
|
||||
o.setRemindDays(null);
|
||||
o.setRemindTime(null);
|
||||
o.setCustomerId(null);
|
||||
o.setContractId(null);
|
||||
o.setOwnerUserId(null);
|
||||
o.setRemark(null);
|
||||
o.setCreateTime(null);
|
||||
});
|
||||
crmReceivablePlanMapper.insert(dbReceivablePlan);
|
||||
// 测试 customerId 不匹配
|
||||
crmReceivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setCustomerId(null)));
|
||||
// 测试 contractId 不匹配
|
||||
crmReceivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setContractId(null)));
|
||||
// 准备参数
|
||||
CrmReceivablePlanPageReqVO reqVO = new CrmReceivablePlanPageReqVO();
|
||||
reqVO.setCustomerId(null);
|
||||
reqVO.setContractId(null);
|
||||
reqVO.setPageSize(PAGE_SIZE_NONE);
|
||||
// 调用
|
||||
PageResult<CrmReceivablePlanDO> pageResult = receivablePlanService.getReceivablePlanPage(reqVO, 1L);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
assertPojoEquals(dbReceivablePlan, pageResult.getList().get(0));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,12 +7,11 @@ import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.Crm
|
|||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivableMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
|
@ -133,7 +132,7 @@ public class CrmCrmReceivableServiceImplTest extends BaseDbUnitTest {
|
|||
reqVO.setCustomerId(null);
|
||||
|
||||
// 调用
|
||||
PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePage(reqVO);
|
||||
PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePage(reqVO, 1L);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
|
|
|
@ -63,7 +63,7 @@ export function export${simpleClassName}Excel(params) {
|
|||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
## 特殊:主子表专属逻辑 TODO @puhui999:下面方法的【空格】不太对
|
||||
## 特殊:主子表专属逻辑
|
||||
#foreach ($subTable in $subTables)
|
||||
#set ($index = $foreach.count - 1)
|
||||
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
|
||||
|
@ -76,7 +76,7 @@ export function export${simpleClassName}Excel(params) {
|
|||
|
||||
// ==================== 子表($subTable.classComment) ====================
|
||||
## 情况一:MASTER_ERP 时,需要分查询页子表
|
||||
#if ( $table.templateType == 11 )
|
||||
#if ($table.templateType == 11)
|
||||
// 获得${subTable.classComment}分页
|
||||
export function get${subSimpleClassName}Page(params) {
|
||||
return request({
|
||||
|
@ -87,7 +87,7 @@ export function export${simpleClassName}Excel(params) {
|
|||
}
|
||||
## 情况二:非 MASTER_ERP 时,需要列表查询子表
|
||||
#else
|
||||
#if ( $subTable.subJoinMany )
|
||||
#if ($subTable.subJoinMany)
|
||||
// 获得${subTable.classComment}列表
|
||||
export function get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaField}) {
|
||||
return request({
|
||||
|
@ -106,7 +106,7 @@ export function export${simpleClassName}Excel(params) {
|
|||
#end
|
||||
#end
|
||||
## 特殊:MASTER_ERP 时,支持单个的新增、修改、删除操作
|
||||
#if ( $table.templateType == 11 )
|
||||
#if ($table.templateType == 11)
|
||||
// 新增${subTable.classComment}
|
||||
export function create${subSimpleClassName}(data) {
|
||||
return request({
|
||||
|
@ -115,7 +115,6 @@ export function export${simpleClassName}Excel(params) {
|
|||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改${subTable.classComment}
|
||||
export function update${subSimpleClassName}(data) {
|
||||
return request({
|
||||
|
@ -124,7 +123,6 @@ export function export${simpleClassName}Excel(params) {
|
|||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除${subTable.classComment}
|
||||
export function delete${subSimpleClassName}(id) {
|
||||
return request({
|
||||
|
@ -132,7 +130,6 @@ export function export${simpleClassName}Excel(params) {
|
|||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 获得${subTable.classComment}
|
||||
export function get${subSimpleClassName}(id) {
|
||||
return request({
|
||||
|
|
|
@ -1,18 +1,25 @@
|
|||
package cn.iocoder.yudao.module.product.controller.app.category;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.product.controller.app.category.vo.AppCategoryRespVO;
|
||||
import cn.iocoder.yudao.module.product.convert.category.ProductCategoryConvert;
|
||||
import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
|
||||
import cn.iocoder.yudao.module.product.service.category.ProductCategoryService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
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 jakarta.annotation.Resource;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -32,7 +39,19 @@ public class AppCategoryController {
|
|||
public CommonResult<List<AppCategoryRespVO>> getProductCategoryList() {
|
||||
List<ProductCategoryDO> list = categoryService.getEnableCategoryList();
|
||||
list.sort(Comparator.comparing(ProductCategoryDO::getSort));
|
||||
return success(ProductCategoryConvert.INSTANCE.convertList03(list));
|
||||
return success(BeanUtils.toBean(list, AppCategoryRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/list-by-ids")
|
||||
@Operation(summary = "获得商品分类列表,指定编号")
|
||||
@Parameter(name = "ids", description = "商品分类编号数组", required = true)
|
||||
public CommonResult<List<AppCategoryRespVO>> getProductCategoryList(@RequestParam("ids") List<Long> ids) {
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return success(Collections.emptyList());
|
||||
}
|
||||
List<ProductCategoryDO> list = categoryService.getEnableCategoryList(ids);
|
||||
list.sort(Comparator.comparing(ProductCategoryDO::getSort));
|
||||
return success(BeanUtils.toBean(list, AppCategoryRespVO.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -42,14 +42,6 @@ public class AppFavoriteController {
|
|||
return success(productFavoriteService.createFavorite(getLoginUserId(), reqVO.getSpuId()));
|
||||
}
|
||||
|
||||
@PostMapping(value = "/create-list")
|
||||
@Operation(summary = "添加多个商品收藏")
|
||||
@PreAuthenticated
|
||||
public CommonResult<Boolean> createFavoriteList(@RequestBody @Valid AppFavoriteBatchReqVO reqVO) {
|
||||
// todo @jason:待实现;如果有已经收藏的,不用报错,忽略即可;
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping(value = "/delete")
|
||||
@Operation(summary = "取消单个商品收藏")
|
||||
@PreAuthenticated
|
||||
|
@ -58,15 +50,6 @@ public class AppFavoriteController {
|
|||
return success(Boolean.TRUE);
|
||||
}
|
||||
|
||||
@DeleteMapping(value = "/delete-list")
|
||||
@Operation(summary = "取消多个商品收藏")
|
||||
@PreAuthenticated
|
||||
public CommonResult<Boolean> deleteFavoriteList(@RequestBody @Valid AppFavoriteBatchReqVO reqVO) {
|
||||
// todo @jason:待实现
|
||||
// productFavoriteService.deleteFavorite(getLoginUserId(), reqVO.getSpuId());
|
||||
return success(Boolean.TRUE);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/page")
|
||||
@Operation(summary = "获得商品收藏分页")
|
||||
@PreAuthenticated
|
||||
|
|
|
@ -78,9 +78,7 @@ public class AppProductSpuController {
|
|||
|
||||
@GetMapping("/list-by-ids")
|
||||
@Operation(summary = "获得商品 SPU 列表")
|
||||
@Parameters({
|
||||
@Parameter(name = "ids", description = "编号列表", required = true)
|
||||
})
|
||||
@Parameter(name = "ids", description = "编号列表", required = true)
|
||||
public CommonResult<List<AppProductSpuPageRespVO>> getSpuList(@RequestParam("ids") Set<Long> ids) {
|
||||
List<ProductSpuDO> list = productSpuService.getSpuList(ids);
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
|
|
|
@ -18,6 +18,7 @@ public class AppProductSpuPageReqVO extends PageParam {
|
|||
|
||||
public static final String SORT_FIELD_PRICE = "price";
|
||||
public static final String SORT_FIELD_SALES_COUNT = "salesCount";
|
||||
public static final String SORT_FIELD_CREATE_TIME = "createTime";
|
||||
|
||||
public static final String RECOMMEND_TYPE_HOT = "hot";
|
||||
public static final String RECOMMEND_TYPE_BENEFIT = "benefit";
|
||||
|
|
|
@ -28,5 +28,4 @@ public interface ProductCategoryConvert {
|
|||
|
||||
List<ProductCategoryRespVO> convertList(List<ProductCategoryDO> list);
|
||||
|
||||
List<AppCategoryRespVO> convertList03(List<ProductCategoryDO> list);
|
||||
}
|
||||
|
|
|
@ -84,26 +84,27 @@ public interface ProductCommentConvert {
|
|||
return divide.intValue();
|
||||
}
|
||||
|
||||
ProductCommentDO convert(ProductCommentCreateReqDTO createReqDTO);
|
||||
|
||||
@Mapping(target = "scores",
|
||||
expression = "java(convertScores(createReqDTO.getDescriptionScores(), createReqDTO.getBenefitScores()))")
|
||||
default ProductCommentDO convert(ProductCommentCreateReqDTO createReqDTO, ProductSpuDO spuDO, ProductSkuDO skuDO, MemberUserRespDTO user) {
|
||||
ProductCommentDO commentDO = convert(createReqDTO);
|
||||
ProductCommentDO convert(ProductCommentCreateReqDTO createReqDTO);
|
||||
|
||||
default ProductCommentDO convert(ProductCommentCreateReqDTO createReqDTO,
|
||||
ProductSpuDO spu, ProductSkuDO sku, MemberUserRespDTO user) {
|
||||
ProductCommentDO comment = convert(createReqDTO).setReplyStatus(false);
|
||||
if (user != null) {
|
||||
commentDO.setUserId(user.getId());
|
||||
commentDO.setUserNickname(user.getNickname());
|
||||
commentDO.setUserAvatar(user.getAvatar());
|
||||
comment.setUserId(user.getId());
|
||||
comment.setUserNickname(user.getNickname());
|
||||
comment.setUserAvatar(user.getAvatar());
|
||||
}
|
||||
if (spuDO != null) {
|
||||
commentDO.setSpuId(spuDO.getId());
|
||||
commentDO.setSpuName(spuDO.getName());
|
||||
if (spu != null) {
|
||||
comment.setSpuId(spu.getId());
|
||||
comment.setSpuName(spu.getName());
|
||||
}
|
||||
if (skuDO != null) {
|
||||
commentDO.setSkuPicUrl(skuDO.getPicUrl());
|
||||
commentDO.setSkuProperties(skuDO.getProperties());
|
||||
if (sku != null) {
|
||||
comment.setSkuPicUrl(sku.getPicUrl());
|
||||
comment.setSkuProperties(sku.getProperties());
|
||||
}
|
||||
return commentDO;
|
||||
return comment;
|
||||
}
|
||||
|
||||
@Mapping(target = "visible", constant = "true")
|
||||
|
|
|
@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCateg
|
|||
import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -32,4 +33,10 @@ public interface ProductCategoryMapper extends BaseMapperX<ProductCategoryDO> {
|
|||
return selectList(ProductCategoryDO::getStatus, status);
|
||||
}
|
||||
|
||||
default List<ProductCategoryDO> selectListByIdAndStatus(Collection<Long> ids, Integer status) {
|
||||
return selectList(new LambdaQueryWrapperX<ProductCategoryDO>()
|
||||
.in(ProductCategoryDO::getId, ids)
|
||||
.eq(ProductCategoryDO::getStatus, status));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -84,6 +84,9 @@ public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> {
|
|||
} else if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_PRICE)) {
|
||||
query.orderBy(true, pageReqVO.getSortAsc(), ProductSpuDO::getPrice)
|
||||
.orderByDesc(ProductSpuDO::getSort).orderByDesc(ProductSpuDO::getId);
|
||||
} else if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_CREATE_TIME)) {
|
||||
query.orderBy(true, pageReqVO.getSortAsc(), ProductSpuDO::getCreateTime)
|
||||
.orderByDesc(ProductSpuDO::getSort).orderByDesc(ProductSpuDO::getId);
|
||||
} else {
|
||||
query.orderByDesc(ProductSpuDO::getSort).orderByDesc(ProductSpuDO::getId);
|
||||
}
|
||||
|
|
|
@ -76,6 +76,14 @@ public interface ProductCategoryService {
|
|||
*/
|
||||
List<ProductCategoryDO> getEnableCategoryList();
|
||||
|
||||
/**
|
||||
* 获得开启状态的商品分类列表,指定编号
|
||||
*
|
||||
* @param ids 商品分类编号数组
|
||||
* @return 商品分类列表
|
||||
*/
|
||||
List<ProductCategoryDO> getEnableCategoryList(List<Long> ids);
|
||||
|
||||
/**
|
||||
* 校验商品分类是否有效。如下情况,视为无效:
|
||||
* 1. 商品分类编号不存在
|
||||
|
@ -84,4 +92,5 @@ public interface ProductCategoryService {
|
|||
* @param ids 商品分类编号数组
|
||||
*/
|
||||
void validateCategoryList(Collection<Long> ids);
|
||||
|
||||
}
|
||||
|
|
|
@ -170,4 +170,9 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
|
|||
return productCategoryMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProductCategoryDO> getEnableCategoryList(List<Long> ids) {
|
||||
return productCategoryMapper.selectListByIdAndStatus(ids, CommonStatusEnum.ENABLE.getStatus());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,11 +7,10 @@ import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivity
|
|||
import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
|
||||
import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINATION_RECORD_NOT_EXISTS;
|
||||
|
||||
|
@ -25,21 +24,21 @@ import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINA
|
|||
public class CombinationRecordApiImpl implements CombinationRecordApi {
|
||||
|
||||
@Resource
|
||||
private CombinationRecordService recordService;
|
||||
private CombinationRecordService combinationRecordService;
|
||||
|
||||
@Override
|
||||
public void validateCombinationRecord(Long userId, Long activityId, Long headId, Long skuId, Integer count) {
|
||||
recordService.validateCombinationRecord(userId, activityId, headId, skuId, count);
|
||||
combinationRecordService.validateCombinationRecord(userId, activityId, headId, skuId, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CombinationRecordCreateRespDTO createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) {
|
||||
return CombinationActivityConvert.INSTANCE.convert4(recordService.createCombinationRecord(reqDTO));
|
||||
return CombinationActivityConvert.INSTANCE.convert4(combinationRecordService.createCombinationRecord(reqDTO));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCombinationRecordSuccess(Long userId, Long orderId) {
|
||||
CombinationRecordDO record = recordService.getCombinationRecord(userId, orderId);
|
||||
CombinationRecordDO record = combinationRecordService.getCombinationRecord(userId, orderId);
|
||||
if (record == null) {
|
||||
throw exception(COMBINATION_RECORD_NOT_EXISTS);
|
||||
}
|
||||
|
@ -48,7 +47,7 @@ public class CombinationRecordApiImpl implements CombinationRecordApi {
|
|||
|
||||
@Override
|
||||
public CombinationValidateJoinRespDTO validateJoinCombination(Long userId, Long activityId, Long headId, Long skuId, Integer count) {
|
||||
return recordService.validateJoinCombination(userId, activityId, headId, skuId, count);
|
||||
return combinationRecordService.validateJoinCombination(userId, activityId, headId, skuId, count);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.controller.app.coupon;
|
|||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.*;
|
||||
import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert;
|
||||
|
@ -59,7 +60,8 @@ public class AppCouponController {
|
|||
@Operation(summary = "获得匹配指定商品的优惠劵列表", description = "用于下单页,展示优惠劵列表")
|
||||
public CommonResult<List<AppCouponMatchRespVO>> getMatchCouponList(AppCouponMatchReqVO matchReqVO) {
|
||||
// todo: 优化:优惠金额倒序
|
||||
return success(CouponConvert.INSTANCE.convertList(couponService.getMatchCouponList(getLoginUserId(), matchReqVO)));
|
||||
List<CouponDO> list = couponService.getMatchCouponList(getLoginUserId(), matchReqVO);
|
||||
return success(BeanUtils.toBean(list, AppCouponMatchRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
|
@ -68,7 +70,16 @@ public class AppCouponController {
|
|||
public CommonResult<PageResult<AppCouponRespVO>> getCouponPage(AppCouponPageReqVO pageReqVO) {
|
||||
PageResult<CouponDO> pageResult = couponService.getCouponPage(
|
||||
CouponConvert.INSTANCE.convert(pageReqVO, Collections.singleton(getLoginUserId())));
|
||||
return success(CouponConvert.INSTANCE.convertAppPage(pageResult));
|
||||
return success(BeanUtils.toBean(pageResult, AppCouponRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得优惠劵")
|
||||
@Parameter(name = "id", description = "优惠劵编号", required = true, example = "1024")
|
||||
@PreAuthenticated
|
||||
public CommonResult<AppCouponRespVO> getCoupon(@RequestParam("id") Long id) {
|
||||
CouponDO coupon = couponService.getCoupon(getLoginUserId(), id);
|
||||
return success(BeanUtils.toBean(coupon, AppCouponRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping(value = "/get-unused-count")
|
||||
|
|
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.controller.app.coupon;
|
|||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
|
||||
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
|
||||
|
@ -43,6 +44,20 @@ public class AppCouponTemplateController {
|
|||
@Resource
|
||||
private ProductSpuApi productSpuApi;
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得优惠劵模版")
|
||||
@Parameter(name = "id", description = "优惠券模板编号", required = true, example = "1024")
|
||||
public CommonResult<AppCouponTemplateRespVO> getCouponTemplate(Long id) {
|
||||
CouponTemplateDO template = couponTemplateService.getCouponTemplate(id);
|
||||
if (template == null) {
|
||||
return success(null);
|
||||
}
|
||||
// 处理是否可领取
|
||||
Map<Long, Boolean> canCanTakeMap = couponService.getUserCanCanTakeMap(getLoginUserId(), List.of(template));
|
||||
return success(BeanUtils.toBean(template, AppCouponTemplateRespVO.class)
|
||||
.setCanTake(canCanTakeMap.get(template.getId())));
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "获得优惠劵模版列表")
|
||||
@Parameters({
|
||||
|
|
|
@ -5,6 +5,7 @@ import lombok.Data;
|
|||
|
||||
import jakarta.validation.constraints.Min;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "用户 App - 优惠劵 Response VO")
|
||||
@Data
|
||||
|
@ -19,10 +20,15 @@ public class AppCouponRespVO {
|
|||
@Schema(description = "优惠劵状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") // 参见 CouponStatusEnum 枚举
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否设置满多少金额可用", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
|
||||
// 单位:分;0 - 不限制
|
||||
@Schema(description = "是否设置满多少金额可用", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") // 单位:分;0 - 不限制
|
||||
private Integer usePrice;
|
||||
|
||||
@Schema(description = "商品范围", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer productScope;
|
||||
|
||||
@Schema(description = "商品范围编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private List<Long> productScopeValues;
|
||||
|
||||
@Schema(description = "固定日期 - 生效开始时间")
|
||||
private LocalDateTime validStartTime;
|
||||
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
package cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.Min;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "用户 App - 优惠劵模板 Response VO")
|
||||
@Data
|
||||
|
@ -19,10 +23,15 @@ public class AppCouponTemplateRespVO {
|
|||
@Schema(description = "每人限领个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "66") // -1 - 则表示不限制
|
||||
private Integer takeLimitCount;
|
||||
|
||||
@Schema(description = "是否设置满多少金额可用", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
|
||||
// 单位:分;0 - 不限制
|
||||
@Schema(description = "是否设置满多少金额可用", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") // 单位:分;0 - 不限制
|
||||
private Integer usePrice;
|
||||
|
||||
@Schema(description = "商品范围", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer productScope;
|
||||
|
||||
@Schema(description = "商品范围编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private List<Long> productScopeValues;
|
||||
|
||||
@Schema(description = "生效日期类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer validityType;
|
||||
|
||||
|
|
|
@ -58,8 +58,4 @@ public interface CouponConvert {
|
|||
|
||||
CouponPageReqVO convert(AppCouponPageReqVO pageReqVO, Collection<Long> userIds);
|
||||
|
||||
PageResult<AppCouponRespVO> convertAppPage(PageResult<CouponDO> pageResult);
|
||||
|
||||
List<AppCouponMatchRespVO> convertList(List<CouponDO> list);
|
||||
|
||||
}
|
||||
|
|
|
@ -168,4 +168,13 @@ public interface CouponService {
|
|||
*/
|
||||
Map<Long, Boolean> getUserCanCanTakeMap(Long userId, List<CouponTemplateDO> templates);
|
||||
|
||||
/**
|
||||
* 获得优惠劵
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param id 编号
|
||||
* @return 优惠劵
|
||||
*/
|
||||
CouponDO getCoupon(Long userId, Long id);
|
||||
|
||||
}
|
||||
|
|
|
@ -315,6 +315,11 @@ public class CouponServiceImpl implements CouponService {
|
|||
userIds.removeIf(userId -> MapUtil.getInt(userTakeCountMap, userId, 0) >= couponTemplate.getTakeLimitCount());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CouponDO getCoupon(Long userId, Long id) {
|
||||
return couponMapper.selectByIdAndUserId(id, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得自身的代理对象,解决 AOP 生效问题
|
||||
*
|
||||
|
|
|
@ -14,26 +14,21 @@ public class AfterSaleLogRespVO {
|
|||
private Long id;
|
||||
|
||||
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22634")
|
||||
@NotNull(message = "用户编号不能为空")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@NotNull(message = "用户类型不能为空")
|
||||
private Integer userType;
|
||||
|
||||
@Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3023")
|
||||
@NotNull(message = "售后编号不能为空")
|
||||
private Long afterSaleId;
|
||||
|
||||
@Schema(description = "售后状态(之前)", example = "2")
|
||||
private Integer beforeStatus;
|
||||
|
||||
@Schema(description = "售后状态(之后)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "售后状态(之后)不能为空")
|
||||
private Integer afterStatus;
|
||||
|
||||
@Schema(description = "操作明细", requiredMode = Schema.RequiredMode.REQUIRED, example = "维权完成,退款金额:¥37776.00")
|
||||
@NotNull(message = "操作明细不能为空")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
|
|
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.controller.app.aftersale;
|
|||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.log.AfterSaleLogRespVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleCreateReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleDeliveryReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleRespVO;
|
||||
|
@ -17,6 +18,8 @@ import org.springframework.web.bind.annotation.*;
|
|||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package cn.iocoder.yudao.module.trade.controller.app.aftersale;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.log.AppAfterSaleLogRespVO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleLogDO;
|
||||
import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleLogService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
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;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - 售后日志")
|
||||
@RestController
|
||||
@RequestMapping("/trade/after-sale-log")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class AppAfterSaleLogController {
|
||||
|
||||
@Resource
|
||||
private AfterSaleLogService afterSaleLogService;
|
||||
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "获得售后日志列表")
|
||||
@Parameter(name = "afterSaleId", description = "售后编号", required = true, example = "1")
|
||||
public CommonResult<List<AppAfterSaleLogRespVO>> getAfterSaleLogList(
|
||||
@RequestParam("afterSaleId") Long afterSaleId) {
|
||||
List<AfterSaleLogDO> logs = afterSaleLogService.getAfterSaleLogList(afterSaleId);
|
||||
return success(BeanUtils.toBean(logs, AppAfterSaleLogRespVO.class));
|
||||
}
|
||||
|
||||
}
|
|
@ -35,6 +35,12 @@ public class AppAfterSaleRespVO {
|
|||
@Schema(description = "补充凭证图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private List<String> applyPicUrls;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
// ========== 交易订单相关 ==========
|
||||
|
||||
@Schema(description = "交易订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.log;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - App 交易售后日志 Response VO")
|
||||
@Data
|
||||
public class AppAfterSaleLogRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20669")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "操作明细", requiredMode = Schema.RequiredMode.REQUIRED, example = "维权完成,退款金额:¥37776.00")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
|
@ -97,7 +97,7 @@ public class AppTradeOrderController {
|
|||
@GetMapping("/get-express-track-list")
|
||||
@Operation(summary = "获得交易订单的物流轨迹")
|
||||
@Parameter(name = "id", description = "交易订单编号")
|
||||
public CommonResult<List<?>> getOrderExpressTrackList(@RequestParam("id") Long id) {
|
||||
public CommonResult<List<AppOrderExpressTrackRespDTO>> getOrderExpressTrackList(@RequestParam("id") Long id) {
|
||||
return success(TradeOrderConvert.INSTANCE.convertList02(
|
||||
tradeOrderQueryService.getExpressTrackList(id, getLoginUserId())));
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cn.iocoder.yudao.module.trade.controller.app.order.vo;
|
||||
|
||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderRefundStatusEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
|
@ -20,6 +21,9 @@ public class AppTradeOrderDetailRespVO {
|
|||
@Schema(description = "订单流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1146347329394184195")
|
||||
private String no;
|
||||
|
||||
@Schema(description = "订单类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "下单时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
|
@ -118,6 +122,12 @@ public class AppTradeOrderDetailRespVO {
|
|||
|
||||
// ========== 售后基本信息 ==========
|
||||
|
||||
@Schema(description = "售后状态", example = "0")
|
||||
private Integer refundStatus;
|
||||
|
||||
@Schema(description = "退款金额,单位:分", example = "100")
|
||||
private Integer refundPrice;
|
||||
|
||||
// ========== 营销基本信息 ==========
|
||||
|
||||
@Schema(description = "优惠劵编号", example = "1024")
|
||||
|
|
|
@ -206,7 +206,8 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService {
|
|||
|
||||
/**
|
||||
* 查询物流轨迹
|
||||
* 加个 spring 缓存,30 分钟;主要考虑及时性要求不高,但是每次调用需要钱;TODO @艿艿:这个时间不会搞了。。。交给你了哈哈哈
|
||||
*
|
||||
* 缓存的目的:考虑及时性要求不高,但是每次调用需要钱
|
||||
*
|
||||
* @param code 快递公司编码
|
||||
* @param logisticsNo 发货快递单号
|
||||
|
@ -216,7 +217,6 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService {
|
|||
@Cacheable(cacheNames = RedisKeyConstants.EXPRESS_TRACK, key = "#code + '-' + #logisticsNo + '-' + #receiverMobile",
|
||||
condition = "#result != null")
|
||||
public List<ExpressTrackRespDTO> getExpressTrackList(String code, String logisticsNo, String receiverMobile) {
|
||||
// 查询物流轨迹
|
||||
return expressClientFactory.getDefaultExpressClient().getExpressTrackList(
|
||||
new ExpressTrackQueryReqDTO().setExpressCode(code).setLogisticsNo(logisticsNo)
|
||||
.setPhone(receiverMobile));
|
||||
|
|
|
@ -20,6 +20,9 @@ public class AppMemberUserInfoRespVO {
|
|||
@Schema(description = "用户手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300")
|
||||
private String mobile;
|
||||
|
||||
@Schema(description = "用户性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer sex;
|
||||
|
||||
@Schema(description = "积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
private Integer point;
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package cn.iocoder.yudao.module.member.controller.app.user.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.system.enums.common.SexEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.URL;
|
||||
|
@ -15,4 +17,7 @@ public class AppMemberUserUpdateReqVO {
|
|||
@URL(message = "头像必须是 URL 格式")
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer sex;
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
|
|||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
||||
import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordRespVO;
|
||||
import cn.iocoder.yudao.module.member.controller.app.signin.vo.record.AppMemberSignInRecordRespVO;
|
||||
import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInConfigDO;
|
||||
|
@ -47,10 +48,9 @@ public interface MemberSignInRecordConvert {
|
|||
// 1. 计算是第几天签到
|
||||
configs.sort(Comparator.comparing(MemberSignInConfigDO::getDay));
|
||||
MemberSignInConfigDO lastConfig = CollUtil.getLast(configs); // 最大签到天数配置
|
||||
// 1.2. 计算今天是第几天签到
|
||||
// 1.2. 计算今天是第几天签到 (只有连续签到才加否则重置为 1)
|
||||
int day = 1;
|
||||
// TODO @puhui999:要判断是不是昨天签到的;是否是昨天的判断,可以抽个方法到 util 里
|
||||
if (lastRecord != null) {
|
||||
if (lastRecord != null && DateUtils.isYesterday(lastRecord.getCreateTime())) {
|
||||
day = lastRecord.getDay() + 1;
|
||||
}
|
||||
// 1.3 判断是否超出了最大签到配置
|
||||
|
|
|
@ -19,14 +19,12 @@ import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum;
|
|||
import cn.iocoder.yudao.module.member.service.level.MemberLevelService;
|
||||
import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService;
|
||||
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -77,50 +75,15 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService
|
|||
}
|
||||
summary.setTodaySignIn(DateUtils.isToday(lastRecord.getCreateTime()));
|
||||
|
||||
// 4. 校验今天是否签到,没有签到则直接返回
|
||||
// 4.1 校验今天是否签到,没有签到则直接返回
|
||||
if (!summary.getTodaySignIn()) {
|
||||
return summary;
|
||||
}
|
||||
// 4.1. 判断连续签到天数
|
||||
// TODO @puhui999:连续签到,可以基于 lastRecord 的 day 和当前时间判断呀?按 day 统计连续签到天数可能不准确
|
||||
// 1. day 只是记录第几天签到的有可能不连续,比如第一次签到是周一,第二次签到是周三这样 lastRecord 的 day 为 2 但是并不是连续的两天
|
||||
// 2. day 超出签到规则的最大天数会重置到从第一天开始签到(我理解为开始下一轮,类似一周签到七天七天结束下周又从周一开始签到)
|
||||
// 1. 回复:周三签到,day 要归 1 呀。连续签到哈;
|
||||
List<MemberSignInRecordDO> signInRecords = signInRecordMapper.selectListByUserId(userId);
|
||||
signInRecords.sort(Comparator.comparing(MemberSignInRecordDO::getCreateTime).reversed()); // 根据签到时间倒序
|
||||
summary.setContinuousDay(calculateConsecutiveDays(signInRecords));
|
||||
// 4.2 连续签到天数
|
||||
summary.setContinuousDay(lastRecord.getDay());
|
||||
return summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算连续签到天数
|
||||
*
|
||||
* @param signInRecords 签到记录列表
|
||||
* @return int 连续签到天数
|
||||
*/
|
||||
public int calculateConsecutiveDays(List<MemberSignInRecordDO> signInRecords) {
|
||||
int consecutiveDays = 1; // 初始连续天数为1
|
||||
LocalDate previousDate = null;
|
||||
|
||||
for (MemberSignInRecordDO record : signInRecords) {
|
||||
LocalDate currentDate = record.getCreateTime().toLocalDate();
|
||||
|
||||
if (previousDate != null) {
|
||||
// 检查相邻两个日期是否连续
|
||||
if (currentDate.minusDays(1).isEqual(previousDate)) {
|
||||
consecutiveDays++;
|
||||
} else {
|
||||
// 如果日期不连续,停止遍历
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
previousDate = currentDate;
|
||||
}
|
||||
|
||||
return consecutiveDays;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<MemberSignInRecordDO> getSignInRecordPage(MemberSignInRecordPageReqVO pageReqVO) {
|
||||
// 根据用户昵称查询出用户ids
|
||||
|
|
|
@ -7,6 +7,7 @@ import cn.hutool.core.util.ObjectUtil;
|
|||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserPageReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserResetPasswordReqVO;
|
||||
|
@ -128,8 +129,8 @@ public class MemberUserServiceImpl implements MemberUserService {
|
|||
|
||||
@Override
|
||||
public void updateUser(Long userId, AppMemberUserUpdateReqVO reqVO) {
|
||||
memberUserMapper.updateById(new MemberUserDO().setId(userId)
|
||||
.setNickname(reqVO.getNickname()).setAvatar(reqVO.getAvatar()));
|
||||
MemberUserDO updateObj = BeanUtils.toBean(reqVO, MemberUserDO.class).setId(userId);
|
||||
memberUserMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -22,6 +22,23 @@
|
|||
<artifactId>yudao-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Springboot-注解-通用操作日志组件 -->
|
||||
<!-- 此组件解决的问题是: 「谁」在「什么时间」对「什么」做了「什么事」 -->
|
||||
<dependency>
|
||||
<groupId>io.github.mouzt</groupId>
|
||||
<artifactId>bizlog-sdk</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--工具类相关-->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 参数校验 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package cn.iocoder.yudao.module.system.api.logger;
|
||||
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
|
||||
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 操作日志 API 接口
|
||||
*
|
||||
|
@ -18,4 +20,13 @@ public interface OperateLogApi {
|
|||
*/
|
||||
void createOperateLog(@Valid OperateLogCreateReqDTO createReqDTO);
|
||||
|
||||
/**
|
||||
* 获取指定模块的指定数据的操作日志
|
||||
*
|
||||
* @param module 操作模块
|
||||
* @param bizId 操作模块编号
|
||||
* @return 操作日志
|
||||
*/
|
||||
List<OperateLogV2RespDTO> getOperateLogByModuleAndBizId(String module, Long bizId);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
package cn.iocoder.yudao.module.system.api.logger.dto;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
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.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
|
||||
|
||||
/**
|
||||
* 系统操作日志 Resp DTO
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Data
|
||||
public class OperateLogV2RespDTO {
|
||||
|
||||
/**
|
||||
* 链路追踪编号
|
||||
*
|
||||
* 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。
|
||||
*/
|
||||
private String traceId;
|
||||
/**
|
||||
* 用户编号
|
||||
*
|
||||
* 关联 MemberUserDO 的 id 属性,或者 AdminUserDO 的 id 属性
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 用户类型
|
||||
*
|
||||
* 关联 {@link UserTypeEnum}
|
||||
*/
|
||||
private Integer userType;
|
||||
/**
|
||||
* 操作模块
|
||||
*/
|
||||
private String module;
|
||||
/**
|
||||
* 操作名
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 操作模块业务编号
|
||||
*/
|
||||
private Long bizId;
|
||||
/**
|
||||
* 操作内容,记录整个操作的明细
|
||||
* 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。
|
||||
*/
|
||||
private String content;
|
||||
/**
|
||||
* 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 )
|
||||
* 例如说,记录订单编号,{ orderId: "1"}
|
||||
*/
|
||||
private String extra;
|
||||
|
||||
/**
|
||||
* 请求方法名
|
||||
*/
|
||||
private String requestMethod;
|
||||
/**
|
||||
* 请求地址
|
||||
*/
|
||||
private String requestUrl;
|
||||
/**
|
||||
* 用户 IP
|
||||
*/
|
||||
private String userIp;
|
||||
/**
|
||||
* 浏览器 UA
|
||||
*/
|
||||
private String userAgent;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
// TODO puhui999: 木得效果怎么肥事
|
||||
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
|
||||
private LocalDateTime createTime;
|
||||
/**
|
||||
* 创建者,关联 AdminUserDO#getId
|
||||
*/
|
||||
private String creator;
|
||||
/**
|
||||
* 创建者名称
|
||||
*/
|
||||
private String creatorName;
|
||||
|
||||
}
|
|
@ -1,11 +1,23 @@
|
|||
package cn.iocoder.yudao.module.system.api.logger;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import cn.iocoder.yudao.module.system.service.logger.OperateLogService;
|
||||
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
|
||||
|
||||
/**
|
||||
* 操作日志 API 实现类
|
||||
|
@ -18,10 +30,31 @@ public class OperateLogApiImpl implements OperateLogApi {
|
|||
|
||||
@Resource
|
||||
private OperateLogService operateLogService;
|
||||
@Resource
|
||||
private AdminUserService adminUserService;
|
||||
|
||||
@Override
|
||||
public void createOperateLog(OperateLogCreateReqDTO createReqDTO) {
|
||||
operateLogService.createOperateLog(createReqDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OperateLogV2RespDTO> getOperateLogByModuleAndBizId(String module, Long bizId) {
|
||||
List<OperateLogV2DO> logList = operateLogService.getOperateLogByModuleAndBizId(module, bizId);
|
||||
if (CollUtil.isEmpty(logList)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 获取用户
|
||||
List<AdminUserDO> userList = adminUserService.getUserList(convertSet(logList, item -> Long.parseLong(item.getCreator())));
|
||||
Map<Long, AdminUserDO> userMap = convertMap(userList, AdminUserDO::getId);
|
||||
return convertList(logList, item -> {
|
||||
OperateLogV2RespDTO bean = BeanUtils.toBean(item, OperateLogV2RespDTO.class);
|
||||
findAndThen(userMap, Long.parseLong(item.getCreator()), user -> {
|
||||
bean.setCreatorName(user.getNickname());
|
||||
});
|
||||
return bean;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
package cn.iocoder.yudao.module.system.dal.dataobject.logger;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 操作日志表 V2
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "system_operate_log_v2", autoResultMap = true)
|
||||
@KeySequence("system_operate_log_seq_v2") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class OperateLogV2DO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 日志主键
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 链路追踪编号
|
||||
*
|
||||
* 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。
|
||||
*/
|
||||
private String traceId;
|
||||
/**
|
||||
* 用户编号
|
||||
*
|
||||
* 关联 MemberUserDO 的 id 属性,或者 AdminUserDO 的 id 属性
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 用户类型
|
||||
*
|
||||
* 关联 {@link UserTypeEnum}
|
||||
*/
|
||||
private Integer userType;
|
||||
/**
|
||||
* 操作模块
|
||||
*/
|
||||
private String module;
|
||||
/**
|
||||
* 操作名
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 操作模块业务编号
|
||||
*/
|
||||
private Long bizId;
|
||||
/**
|
||||
* 操作内容,记录整个操作的明细
|
||||
* 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。
|
||||
*/
|
||||
private String content;
|
||||
/**
|
||||
* 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 )
|
||||
* 例如说,记录订单编号,{ orderId: "1"}
|
||||
*/
|
||||
private String extra;
|
||||
/**
|
||||
* 请求方法名
|
||||
*/
|
||||
private String requestMethod;
|
||||
/**
|
||||
* 请求地址
|
||||
*/
|
||||
private String requestUrl;
|
||||
/**
|
||||
* 用户 IP
|
||||
*/
|
||||
private String userIp;
|
||||
/**
|
||||
* 浏览器 UA
|
||||
*/
|
||||
private String userAgent;
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package cn.iocoder.yudao.module.system.dal.mysql.logger;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface OperateLogV2Mapper extends BaseMapperX<OperateLogV2DO> {
|
||||
|
||||
default PageResult<OperateLogV2DO> selectPage(OperateLogPageReqVO reqVO, Collection<Long> userIds) {
|
||||
LambdaQueryWrapperX<OperateLogV2DO> query = new LambdaQueryWrapperX<OperateLogV2DO>()
|
||||
.likeIfPresent(OperateLogV2DO::getModule, reqVO.getModule())
|
||||
.inIfPresent(OperateLogV2DO::getUserId, userIds);
|
||||
query.orderByDesc(OperateLogV2DO::getId); // 降序
|
||||
return selectPage(reqVO, query);
|
||||
}
|
||||
|
||||
default List<OperateLogV2DO> selectListByModuleAndBizId(String module, Long bizId) {
|
||||
return selectList(new LambdaQueryWrapperX<OperateLogV2DO>()
|
||||
.eq(OperateLogV2DO::getModule, module)
|
||||
.eq(OperateLogV2DO::getBizId, bizId)
|
||||
.orderByDesc(OperateLogV2DO::getCreateTime));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package cn.iocoder.yudao.module.system.framework.bizlog.config;
|
||||
|
||||
import com.mzt.logapi.starter.annotation.EnableLogRecord;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* mzt-biz-log 配置类
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableLogRecord(tenant = "") // 貌似用不上 tenant 这玩意给个空好啦
|
||||
public class YudaoOperateLogV2Configuration {
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package cn.iocoder.yudao.module.system.framework.bizlog.function;
|
||||
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import com.mzt.logapi.service.IParseFunction;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 自定义函数-通过用户编号获取用户信息
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class AdminUserParseFunction implements IParseFunction {
|
||||
|
||||
@Resource
|
||||
private AdminUserApi adminUserApi;
|
||||
|
||||
@Override
|
||||
public String functionName() {
|
||||
return "getAdminUserById";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apply(Object value) {
|
||||
if (value == null) {
|
||||
//log.warn("(getAdminUserById) 解析异常参数为 null");
|
||||
return "";
|
||||
}
|
||||
if (StrUtil.isEmpty(value.toString())) {
|
||||
//log.warn("(getAdminUserById) 解析异常参数为空");
|
||||
return "";
|
||||
}
|
||||
|
||||
// 获取用户信息
|
||||
AdminUserRespDTO user = adminUserApi.getUser(Long.parseLong(value.toString()));
|
||||
if (user == null) {
|
||||
log.warn("(getAdminUserById) 获取用户信息失败,参数为:{}", value);
|
||||
return "";
|
||||
}
|
||||
// 返回格式 芋道源码(13888888888)
|
||||
String nickname = user.getNickname();
|
||||
if (ObjUtil.isNotEmpty(user.getMobile())) {
|
||||
return nickname.concat("(").concat(user.getMobile()).concat(")");
|
||||
}
|
||||
return nickname;
|
||||
}
|
||||
}
|
|
@ -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()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
package cn.iocoder.yudao.module.system.framework.bizlog;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue