refactor(bpm): 重构回款结算接口并添加客户转移功能
- 重构了 BpmOAReceiptService 接口,使用 ReceiptSettlementVO 替代 LocalDateTime[] 参数 - 添加了客户转移相关的 API 和服务实现 - 优化了销售业绩结算相关的数据结构和接口 - 调整了权限控制相关的配置
This commit is contained in:
parent
f3f91f7350
commit
1f65ca883c
@ -145,7 +145,7 @@ public class WxMpMsgTemplateUtils {
|
||||
message.setJumpWxMaFlag(true);
|
||||
message.setMiniProgramState(dto.getMiniProgramState());
|
||||
message.setPage(dto.getPage());
|
||||
message.setSocialType(SocialTypeEnum.WECHAT_MINI_APP.getType());
|
||||
message.setSocialType(SocialTypeEnum.WECHAT_MINI_APP_CRM.getType());
|
||||
return message;
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,7 @@
|
||||
package cn.iocoder.yudao.module.bpm.api.oa;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.BpmOAReceiptDTO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.BpmOAReceiptVO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.ReceiptSettlementDTO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.ReceiptStatisticsDTO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.*;
|
||||
import cn.iocoder.yudao.module.bpm.enums.ApiConstants;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@ -36,7 +33,7 @@ public interface BpmOAReceiptApi {
|
||||
CommonResult<List<ReceiptStatisticsDTO>> getContractStatistics(@RequestParam("userId") List<Long> userIds,
|
||||
@RequestParam(name = "createTime", required = false) LocalDateTime[] createTime);
|
||||
|
||||
@GetMapping(PREFIX + "/getReceiptSettlement")
|
||||
@PostMapping(PREFIX + "/getReceiptSettlement")
|
||||
@Operation(summary = "获取用户回款结算信息")
|
||||
CommonResult<List<ReceiptSettlementDTO>> getReceiptSettlement(@RequestParam(name = "times", required = false) LocalDateTime[] times);
|
||||
CommonResult<List<ReceiptSettlementDTO>> getReceiptSettlement(@RequestBody ReceiptSettlementVO vo);
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
package cn.iocoder.yudao.module.bpm.api.oa.vo.receipt;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class ReceiptSettlementVO {
|
||||
@Schema(description = "时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
}
|
@ -2,14 +2,12 @@ package cn.iocoder.yudao.module.bpm.api.oa;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.BpmOAReceiptDTO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.BpmOAReceiptVO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.ReceiptSettlementDTO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.ReceiptStatisticsDTO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.*;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt.ReceiptStatisticsVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAReceiptDO;
|
||||
import cn.iocoder.yudao.module.bpm.service.oa.BpmOAReceiptService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@ -48,7 +46,7 @@ public class BpmOAReceiptApiImpl implements BpmOAReceiptApi{
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<List<ReceiptSettlementDTO>> getReceiptSettlement(LocalDateTime[] times) {
|
||||
return success(receiptService.getReceiptSettlement(times));
|
||||
public CommonResult<List<ReceiptSettlementDTO>> getReceiptSettlement(ReceiptSettlementVO vo) {
|
||||
return success(receiptService.getReceiptSettlement(vo));
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ 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.MPJLambdaWrapperX;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.ReceiptSettlementDTO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.ReceiptSettlementVO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.ReceiptStatisticsDTO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt.BpmOAReceiptPageReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt.BpmOAReceiptRespVO;
|
||||
@ -50,8 +51,7 @@ public interface BpmOAReceiptMapper extends BaseMapperX<BpmOAReceiptDO> {
|
||||
/**
|
||||
* 获取用户结算回款信息
|
||||
*
|
||||
* @param times
|
||||
* @return
|
||||
*/
|
||||
List<ReceiptSettlementDTO> getReceiptSettlement(@Param("times") LocalDateTime[] times);
|
||||
List<ReceiptSettlementDTO> getReceiptSettlement(@Param("vo") ReceiptSettlementVO vo);
|
||||
}
|
||||
|
@ -272,11 +272,13 @@ public class BpmOAContractServiceImpl extends BpmOABaseService implements BpmOAC
|
||||
List<Long> userIds = new ArrayList<>();
|
||||
if ("my".equals(pageReqVO.getRelation())) {
|
||||
userIds.add(getLoginUserId());
|
||||
}else if ("sub".equals(pageReqVO.getRelation())){
|
||||
} else if ("sub".equals(pageReqVO.getRelation())) {
|
||||
// 查询当前用户 所有下级用户编号
|
||||
userIds.addAll(userLiveTreeApi.getItemIdsByUserId(getLoginUserId()).getCheckedData());
|
||||
}
|
||||
|
||||
if (CollUtil.isEmpty(userIds)) {
|
||||
return PageResult.empty();
|
||||
}
|
||||
return contractMapper.selectPage(pageReqVO, userIds);
|
||||
}
|
||||
|
||||
@ -327,9 +329,10 @@ public class BpmOAContractServiceImpl extends BpmOABaseService implements BpmOAC
|
||||
|
||||
@Override
|
||||
public List<BpmOAContractDO> getContractList(BpmOAContractVO respVO) {
|
||||
|
||||
Date[] dateArray = new Date[]{respVO.getStarTime(), respVO.getEndTime()};
|
||||
|
||||
if (CollUtil.isEmpty(respVO.getUserId())) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return contractMapper.selectList(new LambdaQueryWrapperX<BpmOAContractDO>()
|
||||
.inIfPresent(BpmOAContractDO::getUserId, respVO.getUserId())
|
||||
.eqIfPresent(BpmOAContractDO::getContractType, respVO.getContractType())
|
||||
@ -370,30 +373,30 @@ public class BpmOAContractServiceImpl extends BpmOABaseService implements BpmOAC
|
||||
}
|
||||
|
||||
private void createContractProductList(Long contractId, List<CrmContractProductVO> list) {
|
||||
List<StoreProductAttrValueApiVO> storeProductAttrValueList = new ArrayList<>();
|
||||
if (CollUtil.isNotEmpty(list)) {
|
||||
List<Long> productIds = list.stream().map(CrmContractProductVO::getProductId).collect(Collectors.toList());
|
||||
List<String> productAttrUnique = list.stream().map(CrmContractProductVO::getProductAttrUnique).collect(Collectors.toList());
|
||||
storeProductAttrValueList = storeProductAttrValueApi.getStoreProductAttrValueList(new StoreProductAttrValueApiDTO()
|
||||
.setProductIds(productIds)
|
||||
.setUniques(productAttrUnique)).getCheckedData();
|
||||
}
|
||||
Map<String, List<StoreProductAttrValueApiVO>> map = storeProductAttrValueList.stream().collect(Collectors.groupingBy(a -> a.getProductId() + "_" + a.getUnique()));
|
||||
list.forEach(o -> {
|
||||
o.setContractId(contractId);
|
||||
//库存处理
|
||||
List<StoreProductAttrValueApiVO> storeProductAttrValueApiVOS = map.get(o.getProductId() + "_" + o.getProductAttrUnique());
|
||||
|
||||
int count = 0;
|
||||
if (CollUtil.isNotEmpty(storeProductAttrValueApiVOS)) {
|
||||
count = storeProductAttrValueApiVOS.stream().mapToInt(StoreProductAttrValueApiVO::getStock).sum();
|
||||
}
|
||||
if (NumberUtil.compare(count, o.getNums()) < 0) {
|
||||
throw exception(new ErrorCode(202408250, "该商品ID:" + o.getProductId() + "库存不足"));
|
||||
}
|
||||
// TODO: 2024/11/21 这里的库存扣件完后 - 如果审批不通过 库存退回
|
||||
this.decProductStock(o.getNums(), o.getProductId(), o.getProductAttrUnique());
|
||||
});
|
||||
// List<StoreProductAttrValueApiVO> storeProductAttrValueList = new ArrayList<>();
|
||||
// if (CollUtil.isNotEmpty(list)) {
|
||||
// List<Long> productIds = list.stream().map(CrmContractProductVO::getProductId).collect(Collectors.toList());
|
||||
// List<String> productAttrUnique = list.stream().map(CrmContractProductVO::getProductAttrUnique).collect(Collectors.toList());
|
||||
// storeProductAttrValueList = storeProductAttrValueApi.getStoreProductAttrValueList(new StoreProductAttrValueApiDTO()
|
||||
// .setProductIds(productIds)
|
||||
// .setUniques(productAttrUnique)).getCheckedData();
|
||||
// }
|
||||
// Map<String, List<StoreProductAttrValueApiVO>> map = storeProductAttrValueList.stream().collect(Collectors.groupingBy(a -> a.getProductId() + "_" + a.getUnique()));
|
||||
// list.forEach(o -> {
|
||||
// o.setContractId(contractId);
|
||||
// //库存处理
|
||||
// List<StoreProductAttrValueApiVO> storeProductAttrValueApiVOS = map.get(o.getProductId() + "_" + o.getProductAttrUnique());
|
||||
//
|
||||
// int count = 0;
|
||||
// if (CollUtil.isNotEmpty(storeProductAttrValueApiVOS)) {
|
||||
// count = storeProductAttrValueApiVOS.stream().mapToInt(StoreProductAttrValueApiVO::getStock).sum();
|
||||
// }
|
||||
// if (NumberUtil.compare(count, o.getNums()) < 0) {
|
||||
// throw exception(new ErrorCode(202408250, "该商品ID:" + o.getProductId() + "库存不足"));
|
||||
// }
|
||||
// // TODO: 2024/11/21 这里的库存扣件完后 - 如果审批不通过 库存退回
|
||||
// this.decProductStock(o.getNums(), o.getProductId(), o.getProductAttrUnique());
|
||||
// });
|
||||
|
||||
contractApi.createProduct(BeanUtils.toBean(list, CrmContractProductDTO.class));
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.bpm.service.oa;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.BpmOAReceiptVO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.ReceiptSettlementDTO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.ReceiptSettlementVO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.ReceiptStatisticsDTO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt.BpmOAReceiptCreateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt.BpmOAReceiptPageReqVO;
|
||||
@ -86,8 +87,8 @@ public interface BpmOAReceiptService {
|
||||
/**
|
||||
* 获取用户结算回款信息
|
||||
*
|
||||
* @param times
|
||||
* @param vo
|
||||
* @return
|
||||
*/
|
||||
List<ReceiptSettlementDTO> getReceiptSettlement(LocalDateTime[] times);
|
||||
List<ReceiptSettlementDTO> getReceiptSettlement(ReceiptSettlementVO vo);
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.oa;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.BpmOAReceiptVO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.ReceiptSettlementDTO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.ReceiptSettlementVO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.ReceiptStatisticsDTO;
|
||||
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
|
||||
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
|
||||
@ -30,11 +32,7 @@ import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
@ -44,11 +42,10 @@ import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_RECEIPT_NO
|
||||
* OA 回款申请 Service 实现类
|
||||
*
|
||||
* @author 符溶馨
|
||||
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class BpmOAReceiptServiceImpl extends BpmOABaseService implements BpmOAReceiptService{
|
||||
public class BpmOAReceiptServiceImpl extends BpmOABaseService implements BpmOAReceiptService {
|
||||
|
||||
/**
|
||||
* OA 退款对应的流程定义 KEY
|
||||
@ -80,7 +77,7 @@ public class BpmOAReceiptServiceImpl extends BpmOABaseService implements BpmOARe
|
||||
BpmOAReceiptDO receipt = BeanUtils.toBean(createReqVO, BpmOAReceiptDO.class)
|
||||
.setUserId(userId)
|
||||
.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
|
||||
receiptMapper.insert(receipt) ;
|
||||
receiptMapper.insert(receipt);
|
||||
|
||||
// 发起 BPM 流程
|
||||
Map<String, Object> processInstanceVariables = new HashMap<>();
|
||||
@ -97,10 +94,10 @@ public class BpmOAReceiptServiceImpl extends BpmOABaseService implements BpmOARe
|
||||
historyProcessInstanceService.createHistoryProcessInstance(processInstanceId, createReqVO.getProcessInstanceId());
|
||||
}
|
||||
|
||||
List<UploadUserFile> fileItems = createReqVO.getFileItems() ;
|
||||
List<UploadUserFile> fileItems = createReqVO.getFileItems();
|
||||
//这里的逻辑,如果fileItems不为空,且有数据,那么说明是上传了附件的,则需要更工作流文件表对应的实例Id
|
||||
if (fileItems != null && !fileItems.isEmpty()) {
|
||||
uploadBpmFileProcessInstanceId(processInstanceId,fileItems) ;
|
||||
uploadBpmFileProcessInstanceId(processInstanceId, fileItems);
|
||||
}
|
||||
|
||||
return receipt.getId();
|
||||
@ -152,11 +149,13 @@ public class BpmOAReceiptServiceImpl extends BpmOABaseService implements BpmOARe
|
||||
List<Long> userIds = new ArrayList<>();
|
||||
if ("my".equals(pageReqVO.getRelation())) {
|
||||
userIds.add(getLoginUserId());
|
||||
}else if ("sub".equals(pageReqVO.getRelation())){
|
||||
} else if ("sub".equals(pageReqVO.getRelation())) {
|
||||
// 查询当前用户 所有下级用户编号
|
||||
userIds.addAll(userLiveTreeApi.getItemIdsByUserId(getLoginUserId()).getCheckedData());
|
||||
}
|
||||
|
||||
if (CollUtil.isEmpty(userIds)) {
|
||||
return PageResult.empty();
|
||||
}
|
||||
return receiptMapper.selectReceiptPage(pageReqVO, userIds);
|
||||
}
|
||||
|
||||
@ -171,7 +170,9 @@ public class BpmOAReceiptServiceImpl extends BpmOABaseService implements BpmOARe
|
||||
|
||||
@Override
|
||||
public List<BpmOAReceiptDO> getReceiptList(BpmOAReceiptVO respVO) {
|
||||
|
||||
if (CollUtil.isEmpty(respVO.getUserId())) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return receiptMapper.selectList(new LambdaQueryWrapperX<BpmOAReceiptDO>()
|
||||
.inIfPresent(BpmOAReceiptDO::getUserId, respVO.getUserId())
|
||||
.eq(BpmOAReceiptDO::getResult, BpmProcessInstanceResultEnum.APPROVE.getResult())
|
||||
@ -185,8 +186,8 @@ public class BpmOAReceiptServiceImpl extends BpmOABaseService implements BpmOARe
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ReceiptSettlementDTO> getReceiptSettlement(LocalDateTime[] times) {
|
||||
return receiptMapper.getReceiptSettlement(times);
|
||||
public List<ReceiptSettlementDTO> getReceiptSettlement(ReceiptSettlementVO vo) {
|
||||
return receiptMapper.getReceiptSettlement(vo);
|
||||
}
|
||||
|
||||
public static BigDecimal calculatePercentageChange(Object today, Object yesterday) {
|
||||
|
@ -69,12 +69,12 @@
|
||||
WHERE
|
||||
deleted = 0
|
||||
AND result = 2
|
||||
<if test="times != null and times.length > 0">
|
||||
<if test="times[0] != null">
|
||||
and create_time >= #{times[0]}
|
||||
<if test="vo.createTime != null and vo.createTime.length > 0">
|
||||
<if test="vo.createTime[0] != null">
|
||||
and create_time >= #{vo.createTime[0]}
|
||||
</if>
|
||||
<if test="times[1] != null">
|
||||
and create_time <= #{times[1]}
|
||||
<if test="vo.createTime[1] != null">
|
||||
and create_time <= #{vo.createTime[1]}
|
||||
</if>
|
||||
</if>
|
||||
GROUP BY user_id
|
||||
|
@ -15,4 +15,6 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode INVOICE_NOT_EXISTS = new ErrorCode(200008, "发票不存在");
|
||||
ErrorCode ACHIEVEMENT_NOT_EXISTS = new ErrorCode(200009, "业绩目标不存在");
|
||||
ErrorCode NOT_EDITABLE_UNTIL_SALES_TARGET_HAS_BEEN_APPLIED = new ErrorCode(200010, "未申请销售目标前不可编辑");
|
||||
ErrorCode THIS_CUSTOMER_ALREADY_EXISTS_IN_THE_SYSTEM_AND_CANNOT_BE_ENTERED_REPEATEDLY = new ErrorCode(200011, "系统已存在该客户,不可重复录入");
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.crmbusiness.vo.CrmBusinessPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.crmbusiness.vo.CrmBusinessRespVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.crmbusiness.vo.CrmBusinessSaveReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.crmbusiness.vo.CrmBusinessTransferVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.crmcustomer.vo.CrmCustomerTransferVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.crmbusiness.CrmBusinessProductDO;
|
||||
import cn.iocoder.yudao.module.crm.service.crmbusiness.CrmBusinessService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@ -62,6 +64,13 @@ public class CrmBusinessController {
|
||||
return success(businessService.getBusiness(id));
|
||||
}
|
||||
|
||||
@PostMapping("/transfer")
|
||||
@Operation(summary = "转移商机")
|
||||
public CommonResult<Boolean> transferBusiness(@Valid @RequestBody CrmBusinessTransferVO transferVO) {
|
||||
businessService.transfer(transferVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得商机分页")
|
||||
// @PreAuthorize("@ss.hasPermission('crm:business:query')")
|
||||
|
@ -0,0 +1,23 @@
|
||||
package cn.iocoder.yudao.module.crm.controller.admin.crmbusiness.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Schema(description = "管理后台 - 客户转移 VO")
|
||||
@Data
|
||||
public class CrmBusinessTransferVO {
|
||||
|
||||
@Schema(description = "商机ID")
|
||||
private List<Long> businessIds;
|
||||
|
||||
@Schema(description = "接受员工ID")
|
||||
private List<Long> ownerAdminIds;
|
||||
|
||||
@Schema(description = "分配方式")
|
||||
private Integer averageType;
|
||||
|
||||
|
||||
}
|
@ -41,7 +41,6 @@ public class SalesPerformanceSettlementController {
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新销售业绩结算记录")
|
||||
@PreAuthorize("@ss.hasPermission('crm:sales-performance-settlement:update')")
|
||||
public CommonResult<Boolean> updateSalesPerformanceSettlement(@Valid @RequestBody SalesPerformanceSettlementSaveReqVO updateReqVO) {
|
||||
salesPerformanceSettlementService.updateSalesPerformanceSettlement(updateReqVO);
|
||||
return success(true);
|
||||
@ -67,7 +66,6 @@ public class SalesPerformanceSettlementController {
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得销售业绩结算记录分页")
|
||||
@PreAuthorize("@ss.hasPermission('crm:sales-performance-settlement:query')")
|
||||
public CommonResult<PageResult<SalesPerformanceSettlementRespVO>> getSalesPerformanceSettlementPage(@Valid SalesPerformanceSettlementPageReqVO pageReqVO) {
|
||||
PageResult<SalesPerformanceSettlementDO> pageResult = salesPerformanceSettlementService.getSalesPerformanceSettlementPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, SalesPerformanceSettlementRespVO.class));
|
||||
|
@ -1,13 +1,15 @@
|
||||
package cn.iocoder.yudao.module.crm.controller.admin.salesperformancesettlement.vo;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import java.math.BigDecimal;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@ -59,6 +61,12 @@ public class SalesPerformanceSettlementPageReqVO extends PageParam {
|
||||
@Schema(description = "是否可以确认 0否 1是")
|
||||
private Integer canConfirmFlag;
|
||||
|
||||
@Schema(description = "评分状态 0待评分 1已评分")
|
||||
private Integer scoreStatus;
|
||||
|
||||
@Schema(description = "结算状态 0待结算 1已结算(待评分) 2已结算")
|
||||
private Integer settlementStatus;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
@ -66,4 +74,7 @@ public class SalesPerformanceSettlementPageReqVO extends PageParam {
|
||||
@Schema(description = "用户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "27486")
|
||||
private String nickname;
|
||||
|
||||
@Schema(description = "用户ids", example = "27486")
|
||||
private List<Long> userIds;
|
||||
|
||||
}
|
||||
|
@ -44,6 +44,12 @@ public class SalesPerformanceSettlementRespVO {
|
||||
@Schema(description = "实际销售额")
|
||||
private Integer actualSale;
|
||||
|
||||
@Schema(description = "回款目标")
|
||||
private BigDecimal paymentTarget;
|
||||
|
||||
@Schema(description = "销售目标")
|
||||
private Integer saleTarget;
|
||||
|
||||
@Schema(description = "评分")
|
||||
private BigDecimal score;
|
||||
|
||||
@ -68,6 +74,12 @@ public class SalesPerformanceSettlementRespVO {
|
||||
@Schema(description = "是否可以确认 0否 1是")
|
||||
private Integer canConfirmFlag;
|
||||
|
||||
@Schema(description = "评分状态 0待评分 1已评分")
|
||||
private Integer scoreStatus;
|
||||
|
||||
@Schema(description = "结算状态 0待结算 1已结算(待评分) 2已结算")
|
||||
private Integer settlementStatus;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
@ -59,4 +59,9 @@ public class SalesPerformanceSettlementSaveReqVO {
|
||||
@Schema(description = "是否可以确认 0否 1是")
|
||||
private Integer canConfirmFlag;
|
||||
|
||||
@Schema(description = "评分状态 0待评分 1已评分")
|
||||
private Integer scoreStatus;
|
||||
|
||||
@Schema(description = "结算状态 0待结算 1已结算(待评分) 2已结算")
|
||||
private Integer settlementStatus;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
@ -86,9 +87,28 @@ public class SalesPerformanceSettlementDO extends BaseDO {
|
||||
* 是否可以确认 0否 1是
|
||||
*/
|
||||
private Integer canConfirmFlag;
|
||||
/**
|
||||
* 评分状态 0待评分 1已评分
|
||||
*/
|
||||
private Integer scoreStatus;
|
||||
/**
|
||||
* 结算状态 0待结算 1已结算(待评分) 2已结算
|
||||
*/
|
||||
private Integer settlementStatus;
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String nickname;
|
||||
|
||||
/**
|
||||
* 回款目标
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private BigDecimal paymentTarget;
|
||||
/**
|
||||
* 销售目标
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private Integer saleTarget;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
||||
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
|
||||
import cn.iocoder.yudao.module.system.api.mail.MailSendApi;
|
||||
import cn.iocoder.yudao.module.system.api.notice.NoticeApi;
|
||||
import cn.iocoder.yudao.module.system.api.permission.RoleApi;
|
||||
import cn.iocoder.yudao.module.system.api.sms.SmsSendApi;
|
||||
import cn.iocoder.yudao.module.system.api.subscribe.SubscribeMessageSendApi;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
@ -18,6 +19,6 @@ import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableFeignClients(clients = {DeptApi.class, DictDataApi.class, AdminUserApi.class, StoreProductApi.class, StoreProductAttrValueApi.class, SmsSendApi.class, MailSendApi.class, NoticeApi.class,
|
||||
BpmOAContractApi.class, BpmOAReceiptApi.class, BpmOASalesPerformanceApi.class, AdminOauthUserOtherInfoApi.class, SubscribeMessageSendApi.class})
|
||||
BpmOAContractApi.class, BpmOAReceiptApi.class, BpmOASalesPerformanceApi.class, AdminOauthUserOtherInfoApi.class, SubscribeMessageSendApi.class, RoleApi.class})
|
||||
public class RpcConfiguration {
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
package cn.iocoder.yudao.module.crm.job.salesperformance;
|
||||
|
||||
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
|
||||
import cn.iocoder.yudao.module.crm.service.salesperformancesettlement.SalesPerformanceSettlementService;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.handler.annotation.XxlJob;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class AutoConfirmJob {
|
||||
|
||||
// TODO: 2024/11/04 - 每个月月初03号 未确认的 自动确认上个月的结算记录
|
||||
@Resource
|
||||
private SalesPerformanceSettlementService salesPerformanceSettlementService;
|
||||
|
||||
@XxlJob("autoConfirmJob")
|
||||
@TenantJob // --- ⚠️ 这个注解 会将租户列表拉出来 完了后逐个租户执行 定时任务需要注意
|
||||
public ReturnT<String> execute() {
|
||||
log.info("开始 自动确认");
|
||||
salesPerformanceSettlementService.autoConfirmJob();
|
||||
log.info("结束 自动确认");
|
||||
return ReturnT.SUCCESS;
|
||||
}
|
||||
}
|
@ -357,11 +357,6 @@ public class CrmAchievementServiceImpl implements CrmAchievementService {
|
||||
.setStarTime(starTime)
|
||||
.setEndTime(endTime)).getCheckedData();
|
||||
|
||||
// List<CrmContractReceivablesDO> crmContractReceivablesDOS = contractReceivablesMapper
|
||||
// .selectList(new LambdaQueryWrapper<CrmContractReceivablesDO>()
|
||||
// .in(CrmContractReceivablesDO::getOwnerUserId, userIds)
|
||||
// .eq(CrmContractReceivablesDO::getCheckStatus, ContractStatusEnum.STATUS_2.getValue())
|
||||
// .between(CrmContractReceivablesDO::getReturnTime, starTime, endTime));
|
||||
BigDecimal receivablesSuccessMoney = BigDecimal.ZERO;
|
||||
if (CollectionUtil.isNotEmpty(receiptDTOS)) {
|
||||
receivablesSuccessMoney = receiptDTOS
|
||||
|
@ -198,6 +198,9 @@ public class AchievementServiceImpl implements AchievementService {
|
||||
} else if (RelationEnum.SUB.getValue().equals(relation)) {
|
||||
userIds = userLiveTreeService.getItemIdsByUserId(userId);
|
||||
}
|
||||
if (CollUtil.isEmpty(userIds)){
|
||||
return Collections.emptyList();
|
||||
}
|
||||
//合同目标
|
||||
List<CrmAchievementDO> crmAchievementDO = achievementMapper.selectList(new LambdaQueryWrapperX<CrmAchievementDO>()
|
||||
.eq(CrmAchievementDO::getType, FlowStepEnum.TYPE_2.getValue())
|
||||
@ -364,6 +367,9 @@ public class AchievementServiceImpl implements AchievementService {
|
||||
} else if (RelationEnum.SUB.getValue().equals(relation)) {
|
||||
userIds = userLiveTreeService.getItemIdsByUserId(userId);
|
||||
}
|
||||
if (CollUtil.isEmpty(userIds)){
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<SalesVO> salesVOS = new ArrayList<>();
|
||||
int i = 1;
|
||||
while (i <= 12) {
|
||||
|
@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.crmbusiness.vo.CrmBusinessPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.crmbusiness.vo.CrmBusinessRespVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.crmbusiness.vo.CrmBusinessSaveReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.crmbusiness.vo.CrmBusinessTransferVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.crmbusiness.CrmBusinessProductDO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
@ -65,4 +66,10 @@ public interface CrmBusinessService {
|
||||
*/
|
||||
List<CrmBusinessProductDO> getBusinessProductListByBusinessId(Long businessId);
|
||||
|
||||
/**
|
||||
* 转移商机
|
||||
*
|
||||
* @param transferVO
|
||||
*/
|
||||
void transfer(@Valid CrmBusinessTransferVO transferVO);
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package cn.iocoder.yudao.module.crm.service.crmbusiness;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.ShopCommonEnum;
|
||||
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
|
||||
@ -8,7 +10,7 @@ import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.crmbusiness.vo.CrmBusinessPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.crmbusiness.vo.CrmBusinessRespVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.crmbusiness.vo.CrmBusinessSaveReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.crmclues.vo.CrmCluesRespVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.crmbusiness.vo.CrmBusinessTransferVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.crmbusiness.CrmBusinessDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.crmbusiness.CrmBusinessProductDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.crmcustomer.CrmCustomerDO;
|
||||
@ -17,13 +19,13 @@ import cn.iocoder.yudao.module.crm.dal.mysql.crmbusiness.CrmBusinessMapper;
|
||||
import cn.iocoder.yudao.module.crm.dal.mysql.crmbusiness.CrmBusinessProductMapper;
|
||||
import cn.iocoder.yudao.module.crm.dal.mysql.crmcustomer.CrmCustomerMapper;
|
||||
import cn.iocoder.yudao.module.crm.dal.mysql.crmrecord.CrmRecordMapper;
|
||||
import cn.iocoder.yudao.module.crm.service.crmoperatelog.CrmOperatelogService;
|
||||
import cn.iocoder.yudao.module.crm.service.userlivetree.UserLiveTreeService;
|
||||
import cn.iocoder.yudao.module.hrm.enums.RelationEnum;
|
||||
import cn.iocoder.yudao.module.hrm.enums.TypesEnum;
|
||||
import cn.iocoder.yudao.module.product.api.storeproductattrvalue.StoreProductAttrValueApi;
|
||||
import cn.iocoder.yudao.module.product.api.storeproductattrvalue.dto.StoreProductAttrValueApiDTO;
|
||||
import cn.iocoder.yudao.module.product.api.storeproductattrvalue.vo.StoreProductAttrValueApiVO;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -34,6 +36,7 @@ import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
@ -61,6 +64,8 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
||||
private CrmRecordMapper crmRecordMapper;
|
||||
@Resource
|
||||
private UserLiveTreeService userLiveTreeService;
|
||||
@Resource
|
||||
private CrmOperatelogService crmOperatelogService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@ -130,7 +135,9 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
||||
} else if (RelationEnum.SUB.getValue().equals(pageReqVO.getRelation())) {
|
||||
ids = userLiveTreeService.getItemIdsByUserId(adminId);
|
||||
}
|
||||
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return PageResult.empty();
|
||||
}
|
||||
IPage mpPage = MyBatisUtils.buildPage(pageReqVO);
|
||||
IPage<CrmBusinessRespVO> page = businessMapper.selectPageList(mpPage, pageReqVO, ids);
|
||||
return new PageResult<>(page.getRecords(), page.getTotal());
|
||||
@ -160,6 +167,44 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
||||
return businessProductDOS;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void transfer(CrmBusinessTransferVO transferVO) {
|
||||
//客户
|
||||
List<CrmBusinessDO> crmBusinessDOS = businessMapper.selectBatchIds(transferVO.getBusinessIds());
|
||||
if (crmBusinessDOS == null || crmBusinessDOS.isEmpty()) {
|
||||
throw exception(new ErrorCode(202409091, "商机信息不存在"));
|
||||
}
|
||||
|
||||
int adminCount = transferVO.getOwnerAdminIds().size();
|
||||
int i = 0;
|
||||
List<CrmBusinessDO> businessUpdateList = new ArrayList<>();
|
||||
for (CrmBusinessDO businessDO : crmBusinessDOS) {
|
||||
Long adminId;
|
||||
if (ShopCommonEnum.AVG_1.getValue().equals(transferVO.getAverageType())) {
|
||||
//平均分配
|
||||
adminId = transferVO.getOwnerAdminIds().get(i);
|
||||
if (i == (adminCount - 1)) {
|
||||
i = 0;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
//随机分配
|
||||
Random random = new Random();
|
||||
int num = random.nextInt(adminCount);
|
||||
adminId = transferVO.getOwnerAdminIds().get(num);
|
||||
}
|
||||
businessDO.setOwnerUserId(adminId);
|
||||
businessUpdateList.add(businessDO);
|
||||
//处理日志
|
||||
crmOperatelogService.createLog("转移商机", businessDO.getCustomerId(), 0L, 0L);
|
||||
}
|
||||
if (CollUtil.isNotEmpty(businessUpdateList)) {
|
||||
businessMapper.updateBatch(businessUpdateList);
|
||||
}
|
||||
}
|
||||
|
||||
private void createBusinessProductList(Long businessId, List<CrmBusinessProductDO> list) {
|
||||
list.forEach(o -> o.setBusinessId(businessId));
|
||||
businessProductMapper.insertBatch(list);
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.crm.service.crmclues;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.ShopCommonEnum;
|
||||
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||
@ -40,6 +41,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.CLUES_NOT_EXISTS;
|
||||
import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.THIS_CUSTOMER_ALREADY_EXISTS_IN_THE_SYSTEM_AND_CANNOT_BE_ENTERED_REPEATEDLY;
|
||||
|
||||
/**
|
||||
* 线索 Service 实现类
|
||||
@ -118,7 +120,9 @@ public class CrmCluesServiceImpl implements CrmCluesService {
|
||||
} else if (RelationEnum.SUB.getValue().equals(pageReqVO.getRelation())) {
|
||||
ids = userLiveTreeService.getItemIdsByUserId(adminId);
|
||||
}
|
||||
|
||||
if (CollUtil.isEmpty(ids)){
|
||||
return PageResult.empty();
|
||||
}
|
||||
IPage mpPage = MyBatisUtils.buildPage(pageReqVO);
|
||||
IPage<CrmCluesRespVO> page = cluesMapper.selectPageList(mpPage, pageReqVO, ids);
|
||||
return new PageResult<>(page.getRecords(), page.getTotal());
|
||||
@ -157,13 +161,18 @@ public class CrmCluesServiceImpl implements CrmCluesService {
|
||||
if(CluesStatusEnum.STATUS_1.getValue().equals(crmCluesDO.getStatus())){
|
||||
throw exception(new ErrorCode(202411160,"已经转化成客户!"));
|
||||
}
|
||||
// 判断客户名称是否唯一
|
||||
Long count = customerMapper.selectCount(new LambdaQueryWrapper<CrmCustomerDO>()
|
||||
.eq(CrmCustomerDO::getName, createReqVO.getName()));
|
||||
if (count > 0) {
|
||||
throw exception(THIS_CUSTOMER_ALREADY_EXISTS_IN_THE_SYSTEM_AND_CANNOT_BE_ENTERED_REPEATEDLY);
|
||||
}
|
||||
createReqVO.setId(null);
|
||||
CrmCustomerDO customerDO = BeanUtils.toBean(createReqVO, CrmCustomerDO.class);
|
||||
customerDO.setOwnerUserId(SecurityFrameworkUtils.getLoginUserId());
|
||||
customerDO.setNextTime(LocalDateTime.now());
|
||||
customerDO.setCollectTime(LocalDateTime.now());
|
||||
customerMapper.insert(customerDO);
|
||||
|
||||
//更新线索
|
||||
crmCluesDO.setStatus(CluesStatusEnum.STATUS_1.getValue());
|
||||
crmCluesDO.setCustomerId(customerDO.getId());
|
||||
|
@ -408,30 +408,30 @@ public class CrmContractServiceImpl implements CrmContractService {
|
||||
}
|
||||
|
||||
private void createContractProductList(Long contractId, List<CrmContractProductDO> list) {
|
||||
List<StoreProductAttrValueApiVO> storeProductAttrValueList = new ArrayList<>();
|
||||
if (CollUtil.isNotEmpty(list)) {
|
||||
List<Long> productIds = list.stream().map(CrmContractProductDO::getProductId).collect(Collectors.toList());
|
||||
List<String> productAttrUnique = list.stream().map(CrmContractProductDO::getProductAttrUnique).collect(Collectors.toList());
|
||||
storeProductAttrValueList = storeProductAttrValueApi.getStoreProductAttrValueList(new StoreProductAttrValueApiDTO()
|
||||
.setProductIds(productIds)
|
||||
.setUniques(productAttrUnique)).getCheckedData();
|
||||
}
|
||||
Map<String, List<StoreProductAttrValueApiVO>> map = storeProductAttrValueList.stream().collect(Collectors.groupingBy(a -> a.getProductId() + "_" + a.getUnique()));
|
||||
list.forEach(o -> {
|
||||
o.setContractId(contractId);
|
||||
//库存处理
|
||||
List<StoreProductAttrValueApiVO> storeProductAttrValueApiVOS = map.get(o.getProductId() + "_" + o.getProductAttrUnique());
|
||||
|
||||
int count = 0;
|
||||
if (CollUtil.isNotEmpty(storeProductAttrValueApiVOS)) {
|
||||
count = storeProductAttrValueApiVOS.stream().mapToInt(StoreProductAttrValueApiVO::getStock).sum();
|
||||
}
|
||||
if (NumberUtil.compare(count, o.getNums()) < 0) {
|
||||
throw exception(new ErrorCode(202408250, "该商品ID:" + o.getProductId() + "库存不足"));
|
||||
}
|
||||
// TODO: 2024/11/21 这里的库存扣件完后 - 如果审批不通过 库存退回
|
||||
this.decProductStock(o.getNums(), o.getProductId(), o.getProductAttrUnique());
|
||||
});
|
||||
// List<StoreProductAttrValueApiVO> storeProductAttrValueList = new ArrayList<>();
|
||||
// if (CollUtil.isNotEmpty(list)) {
|
||||
// List<Long> productIds = list.stream().map(CrmContractProductDO::getProductId).collect(Collectors.toList());
|
||||
// List<String> productAttrUnique = list.stream().map(CrmContractProductDO::getProductAttrUnique).collect(Collectors.toList());
|
||||
// storeProductAttrValueList = storeProductAttrValueApi.getStoreProductAttrValueList(new StoreProductAttrValueApiDTO()
|
||||
// .setProductIds(productIds)
|
||||
// .setUniques(productAttrUnique)).getCheckedData();
|
||||
// }
|
||||
// Map<String, List<StoreProductAttrValueApiVO>> map = storeProductAttrValueList.stream().collect(Collectors.groupingBy(a -> a.getProductId() + "_" + a.getUnique()));
|
||||
// list.forEach(o -> {
|
||||
// o.setContractId(contractId);
|
||||
// //库存处理
|
||||
// List<StoreProductAttrValueApiVO> storeProductAttrValueApiVOS = map.get(o.getProductId() + "_" + o.getProductAttrUnique());
|
||||
//
|
||||
// int count = 0;
|
||||
// if (CollUtil.isNotEmpty(storeProductAttrValueApiVOS)) {
|
||||
// count = storeProductAttrValueApiVOS.stream().mapToInt(StoreProductAttrValueApiVO::getStock).sum();
|
||||
// }
|
||||
// if (NumberUtil.compare(count, o.getNums()) < 0) {
|
||||
// throw exception(new ErrorCode(202408250, "该商品ID:" + o.getProductId() + "库存不足"));
|
||||
// }
|
||||
// // TODO: 2024/11/21 这里的库存扣件完后 - 如果审批不通过 库存退回
|
||||
// this.decProductStock(o.getNums(), o.getProductId(), o.getProductAttrUnique());
|
||||
// });
|
||||
|
||||
contractProductMapper.insertBatch(list);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.crm.service.crmcontractreceivables;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.lang.PatternPool;
|
||||
import cn.hutool.core.util.ReUtil;
|
||||
@ -186,6 +187,9 @@ public class CrmContractReceivablesServiceImpl implements CrmContractReceivables
|
||||
} else if (RelationEnum.SUB.getValue().equals(pageReqVO.getRelation())) {
|
||||
ids = userLiveTreeService.getItemIdsByUserId(loginAdminId);
|
||||
}
|
||||
if (CollUtil.isEmpty(ids)){
|
||||
return PageResult.empty();
|
||||
}
|
||||
pageReqVO.setLoginAdminId(loginAdminId);
|
||||
IPage mpPage = MyBatisUtils.buildPage(pageReqVO);
|
||||
IPage<CrmContractReceivablesRespVO> pageResult = contractReceivablesMapper.selectPageList(mpPage, pageReqVO, ids);
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.crm.service.crmcustomer;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.ShopCommonEnum;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
@ -49,6 +50,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS;
|
||||
import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.THIS_CUSTOMER_ALREADY_EXISTS_IN_THE_SYSTEM_AND_CANNOT_BE_ENTERED_REPEATEDLY;
|
||||
|
||||
/**
|
||||
* 客户 Service 实现类
|
||||
@ -87,8 +89,13 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createCustomer(CrmCustomerSaveReqVO createReqVO) {
|
||||
|
||||
|
||||
// 插入
|
||||
// 判断客户名称是否唯一
|
||||
Long count = customerMapper.selectCount(new LambdaQueryWrapper<CrmCustomerDO>()
|
||||
.eq(CrmCustomerDO::getName, createReqVO.getName()));
|
||||
if (count > 0) {
|
||||
throw exception(THIS_CUSTOMER_ALREADY_EXISTS_IN_THE_SYSTEM_AND_CANNOT_BE_ENTERED_REPEATEDLY);
|
||||
}
|
||||
CrmCustomerDO customer = BeanUtils.toBean(createReqVO, CrmCustomerDO.class);
|
||||
customer.setCollectTime(LocalDateTime.now());
|
||||
customer.setFollowTime(LocalDateTime.now());
|
||||
@ -245,6 +252,9 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
|
||||
ids = userLiveTreeService.getItemIdsByUserId(adminId);
|
||||
}
|
||||
}
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return PageResult.empty();
|
||||
}
|
||||
return customerMapper.selectPage(pageReqVO, ids);
|
||||
}
|
||||
|
||||
@ -262,6 +272,9 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
|
||||
ids = userLiveTreeService.getItemIdsByUserId(adminId);
|
||||
}
|
||||
}
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return PageResult.empty();
|
||||
}
|
||||
IPage mpPage = MyBatisUtils.buildPage(pageReqVO);
|
||||
IPage<CrmCustomerRespVO> pageResult = customerMapper.selectPageList(mpPage, pageReqVO, ids);
|
||||
return new PageResult<>(pageResult.getRecords(), pageResult.getTotal());
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.crm.service.crmcustomercontacts;
|
||||
|
||||
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.framework.mybatis.core.util.MyBatisUtils;
|
||||
@ -91,6 +92,9 @@ public class CrmCustomerContactsServiceImpl implements CrmCustomerContactsServic
|
||||
} else if (RelationEnum.SUB.getValue().equals(pageReqVO.getRelation())) {
|
||||
ids = userLiveTreeService.getItemIdsByUserId(adminId);
|
||||
}
|
||||
if (CollUtil.isEmpty(ids)){
|
||||
return PageResult.empty();
|
||||
}
|
||||
IPage mpPage = MyBatisUtils.buildPage(pageReqVO);
|
||||
IPage<CrmCustomerContactsRespVO> pageResult = customerContactsMapper.selectPageList(mpPage, pageReqVO, ids);
|
||||
return new PageResult<>(pageResult.getRecords(), pageResult.getTotal());
|
||||
|
@ -1,9 +1,11 @@
|
||||
package cn.iocoder.yudao.module.crm.service.crmindex;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.enums.ShopCommonEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.BpmOAContractApi;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.BpmOAReceiptApi;
|
||||
@ -101,7 +103,9 @@ public class CrmIndexServiceImpl implements CrmIndexService {
|
||||
ids = userLiveTreeService.getItemIdsByUserId(adminId);
|
||||
}
|
||||
}
|
||||
|
||||
if (CollUtil.isEmpty(ids)){
|
||||
return BrieCountVO.builder().build();
|
||||
}
|
||||
Long count01 = businessMapper.selectCount(new LambdaQueryWrapper<CrmBusinessDO>()
|
||||
.in(!ids.isEmpty(), CrmBusinessDO::getOwnerUserId, ids)
|
||||
.between(CrmBusinessDO::getCreateTime, todayStart, todayEnd));
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.crm.service.crminvoice;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.ShopCommonEnum;
|
||||
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||
@ -181,6 +182,9 @@ public class CrmInvoiceServiceImpl implements CrmInvoiceService {
|
||||
} else if (RelationEnum.SUB.getValue().equals(pageReqVO.getRelation())) {
|
||||
ids = userLiveTreeService.getItemIdsByUserId(loginAdminId);
|
||||
}
|
||||
if (CollUtil.isEmpty(ids)){
|
||||
return PageResult.empty();
|
||||
}
|
||||
PageResult<CrmInvoiceRespVO> pageResult = invoiceMapper.selectPage2(pageReqVO, ids);
|
||||
for (CrmInvoiceRespVO respVO : pageResult.getList()) {
|
||||
List<String> adminIds = StrUtil.split(respVO.getFlowAdminId(), ",");
|
||||
|
@ -43,7 +43,6 @@ import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.RECORD_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
@ -71,6 +70,7 @@ public class CrmRecordServiceImpl implements CrmRecordService {
|
||||
private DictDataApi dictDataApi;
|
||||
@Resource
|
||||
private UserLiveTreeService userLiveTreeService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createRecord(CrmRecordSaveReqVO createReqVO) {
|
||||
@ -156,7 +156,7 @@ public class CrmRecordServiceImpl implements CrmRecordService {
|
||||
List<CrmRecordUserDO> crmRecordUserDOS = crmRecordUserMapper.selectList(new LambdaQueryWrapper<CrmRecordUserDO>().eq(CrmRecordUserDO::getRecordId, id));
|
||||
crmRecordUserMapper.delete(new LambdaQueryWrapper<CrmRecordUserDO>().eq(CrmRecordUserDO::getRecordId, id).eq(CrmRecordUserDO::getUserId, adminId));
|
||||
// 删除如果是最后一个的话删除一下
|
||||
if (crmRecordUserDOS.size() == 1 && adminId.equals(crmRecordUserDOS.get(0).getUserId())){
|
||||
if (crmRecordUserDOS.size() == 1 && adminId.equals(crmRecordUserDOS.get(0).getUserId())) {
|
||||
recordMapper.deleteById(id);
|
||||
}
|
||||
}
|
||||
|
@ -63,4 +63,9 @@ public interface SalesPerformanceSettlementService extends IService<SalesPerform
|
||||
* 生成下一个月的业绩
|
||||
*/
|
||||
void generateSalesPerformanceJob();
|
||||
|
||||
/**
|
||||
* 自动确认上个月的业绩
|
||||
*/
|
||||
void autoConfirmJob();
|
||||
}
|
||||
|
@ -11,10 +11,12 @@ import cn.iocoder.yudao.framework.common.util.number.BigDecimalUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
|
||||
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.BpmOAContractApi;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.BpmOAReceiptApi;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.BpmOASalesPerformanceApi;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.ReceiptSettlementDTO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.ReceiptSettlementVO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.salesperformance.SalesPerformanceDTO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.salesperformancesettlement.vo.SalesPerformanceSettlementPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.salesperformancesettlement.vo.SalesPerformanceSettlementSaveReqVO;
|
||||
@ -31,12 +33,14 @@ import cn.iocoder.yudao.module.hrm.api.crmcontract.dto.CrmContractProductSettlem
|
||||
import cn.iocoder.yudao.module.system.api.auth.AdminOauthUserOtherInfoApi;
|
||||
import cn.iocoder.yudao.module.system.api.auth.dto.AdminOauthUserOtherInfoApiDTO;
|
||||
import cn.iocoder.yudao.module.system.api.auth.vo.AdminOauthUserOtherInfoApiVO;
|
||||
import cn.iocoder.yudao.module.system.api.permission.RoleApi;
|
||||
import cn.iocoder.yudao.module.system.api.subscribe.SubscribeMessageSendApi;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.ibatis.ognl.Ognl;
|
||||
import org.apache.ibatis.ognl.OgnlException;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -60,6 +64,7 @@ import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.NOT_EDITABLE_
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class SalesPerformanceSettlementServiceImpl extends ServiceImpl<SalesPerformanceSettlementMapper, SalesPerformanceSettlementDO> implements SalesPerformanceSettlementService {
|
||||
|
||||
@Resource
|
||||
@ -84,6 +89,8 @@ public class SalesPerformanceSettlementServiceImpl extends ServiceImpl<SalesPerf
|
||||
private AdminUserApi adminUserApi;
|
||||
@Resource
|
||||
private BpmOAContractApi bpmOAContractApi;
|
||||
@Resource
|
||||
private RoleApi roleApi;
|
||||
|
||||
//百分比
|
||||
private static final BigDecimal PERCENTAGE = new BigDecimal("0.01");
|
||||
@ -120,8 +127,8 @@ public class SalesPerformanceSettlementServiceImpl extends ServiceImpl<SalesPerf
|
||||
// 未申请销售目标前不可编辑
|
||||
throw exception(NOT_EDITABLE_UNTIL_SALES_TARGET_HAS_BEEN_APPLIED);
|
||||
}
|
||||
BigDecimal saleScore = BigDecimal.valueOf(updateObj.getActualSale())
|
||||
.divide(BigDecimal.valueOf(salesPerformanceDTO.getSaleTarget()), 2, RoundingMode.HALF_UP);
|
||||
BigDecimal saleScore = (salesPerformanceDTO.getSaleTarget() == null || salesPerformanceDTO.getSaleTarget() == 0) ? BigDecimal.ZERO :
|
||||
(BigDecimal.valueOf(updateObj.getActualSale()).divide(BigDecimal.valueOf(salesPerformanceDTO.getSaleTarget()), 2, RoundingMode.HALF_UP));
|
||||
saleScore = (saleScore.compareTo(BigDecimal.ONE) >= 0) ? salesPerformanceWeight.getSaleWeight() :
|
||||
salesPerformanceWeight.getSaleWeight().multiply(saleScore);
|
||||
// 销售任务最终得分
|
||||
@ -133,8 +140,8 @@ public class SalesPerformanceSettlementServiceImpl extends ServiceImpl<SalesPerf
|
||||
// 未申请销售目标前不可编辑
|
||||
throw exception(NOT_EDITABLE_UNTIL_SALES_TARGET_HAS_BEEN_APPLIED);
|
||||
}
|
||||
BigDecimal paymentScore = updateObj.getActualPayment()
|
||||
.divide(salesPerformanceDTO.getPaymentTarget(), 2, RoundingMode.HALF_UP);
|
||||
BigDecimal paymentScore = BigDecimalUtil.isEqZero(salesPerformanceDTO.getPaymentTarget()) ? BigDecimal.ZERO :
|
||||
(updateObj.getActualPayment().divide(salesPerformanceDTO.getPaymentTarget(), 2, RoundingMode.HALF_UP));
|
||||
paymentScore = (paymentScore.compareTo(BigDecimal.ONE) >= 0) ? salesPerformanceWeight.getPaymentWeight() :
|
||||
salesPerformanceWeight.getPaymentWeight().multiply(paymentScore);
|
||||
// 回款任务最终得分
|
||||
@ -149,6 +156,11 @@ public class SalesPerformanceSettlementServiceImpl extends ServiceImpl<SalesPerf
|
||||
// 回款任务最终得分
|
||||
updateObj.setScoreTask(score);
|
||||
changeFlag = true;
|
||||
// --
|
||||
updateObj.setScoreStatus(1);
|
||||
if (salesPerformanceSettlementDO.getSettlementStatus() == 1) {
|
||||
updateObj.setSettlementStatus(2);
|
||||
}
|
||||
}
|
||||
if (changeFlag) {
|
||||
// 重新计算 -
|
||||
@ -179,19 +191,26 @@ public class SalesPerformanceSettlementServiceImpl extends ServiceImpl<SalesPerf
|
||||
|
||||
@Override
|
||||
public PageResult<SalesPerformanceSettlementDO> getSalesPerformanceSettlementPage(SalesPerformanceSettlementPageReqVO pageReqVO) {
|
||||
Long userId = SecurityFrameworkUtils.getLoginUserId();
|
||||
// -- 这里要做什么? 要筛选出可见范围 - 但是crm用户不和system 用户 结构一体 - 所以 需要从代码中来区分 - 我们设定一个角色 可以看全部内容 - 完了后 其他的用户只能看自己以及下级的信息 通过pid 和 id来判断
|
||||
// 那么怎么获取到这个用户有没有包含这个角色呢?
|
||||
boolean calculator = roleApi.validCalculator(userId).getCheckedData();
|
||||
if (!calculator) {
|
||||
List<Long> userIds = userLiveTreeService.getItemIdsByUserId(userId);
|
||||
userIds.add(userId);
|
||||
pageReqVO.setUserIds(userIds);
|
||||
}
|
||||
IPage<SalesPerformanceSettlementDO> pageResult = salesPerformanceSettlementMapper.getSalesPerformanceSettlementPage(pageReqVO, MyBatisUtils.buildPage(pageReqVO));
|
||||
return new PageResult<>(pageResult.getRecords(), pageResult.getTotal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void settlement() {
|
||||
// LocalDateTime now = LocalDateTime.now().minusMonths(1L);
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
LocalDateTime now = LocalDateTime.now().minusMonths(1L);
|
||||
String year = String.valueOf(now.getYear());
|
||||
String month = String.format("%02d", now.getMonthValue());
|
||||
// 获取CRM用户一下
|
||||
// List<UserLiveTreeListVO> userLiveList = userLiveTreeService.getUserLiveList();
|
||||
List<UserLiveTreeListVO> userLiveList = Arrays.asList(new UserLiveTreeListVO().setUserId(152L));
|
||||
List<UserLiveTreeListVO> userLiveList = userLiveTreeService.getUserLiveList();
|
||||
// 计算当前月所有销售的 销售额 - 销售台数
|
||||
// -- 合同产品数量 (后续可能需要根据不同的产品来定目标 - 所以这里 我们预判下 - 将合同对应的projectId也查询出来 好方便后续做产品区分)
|
||||
List<CrmContractProductSettlementDTO> contractProductSettlementDTOList = crmContractService.getContractProductSettlement();
|
||||
@ -204,7 +223,9 @@ public class SalesPerformanceSettlementServiceImpl extends ServiceImpl<SalesPerf
|
||||
LocalDateTime beginTime = LocalDateTimeUtils.beginOfMonth(now);
|
||||
LocalDateTime endTime = LocalDateTimeUtils.endOfMonth(now);
|
||||
LocalDateTime[] times = {beginTime, endTime};
|
||||
List<ReceiptSettlementDTO> receiptSettlementList = receiptApi.getReceiptSettlement(times).getCheckedData();
|
||||
ReceiptSettlementVO receiptSettlementVO = new ReceiptSettlementVO();
|
||||
receiptSettlementVO.setCreateTime(times);
|
||||
List<ReceiptSettlementDTO> receiptSettlementList = receiptApi.getReceiptSettlement(receiptSettlementVO).getCheckedData();
|
||||
receiptSettlementList = CollUtil.isEmpty(receiptSettlementList) ? Collections.emptyList() : receiptSettlementList;
|
||||
Map<Long, BigDecimal> receiptSettlementMap = receiptSettlementList.stream()
|
||||
.collect(Collectors.toMap(ReceiptSettlementDTO::getUserId, ReceiptSettlementDTO::getMoney));
|
||||
@ -232,20 +253,25 @@ public class SalesPerformanceSettlementServiceImpl extends ServiceImpl<SalesPerf
|
||||
salesPerformanceSettlementDO.setActualSale(productMap.getOrDefault(vo.getUserId(), 0));
|
||||
salesPerformanceSettlementDO.setActualPayment(receiptSettlementMap.getOrDefault(vo.getUserId(), BigDecimal.ZERO));
|
||||
SalesPerformanceDTO salesPerformanceDTO = salesPerformanceMap.get(vo.getUserId());
|
||||
if (salesPerformanceDTO == null) {
|
||||
continue;
|
||||
}
|
||||
// 计算得分
|
||||
if (salesPerformanceWeight != null) {
|
||||
// -- 如果实际/目标>0则拿到全额的权重
|
||||
// ----------- 销售任务得分计算 -----------
|
||||
BigDecimal saleScore = BigDecimal.valueOf(salesPerformanceSettlementDO.getActualSale())
|
||||
.divide(BigDecimal.valueOf(salesPerformanceDTO.getSaleTarget()), 2, RoundingMode.HALF_UP);
|
||||
BigDecimal saleScore = (salesPerformanceDTO.getSaleTarget() == null || salesPerformanceDTO.getSaleTarget() == 0) ? BigDecimal.ZERO :
|
||||
(BigDecimal.valueOf(salesPerformanceSettlementDO.getActualSale())
|
||||
.divide(BigDecimal.valueOf(salesPerformanceDTO.getSaleTarget()), 2, RoundingMode.HALF_UP));
|
||||
saleScore = (saleScore.compareTo(BigDecimal.ONE) >= 0) ? salesPerformanceWeight.getSaleWeight() :
|
||||
salesPerformanceWeight.getSaleWeight().multiply(saleScore);
|
||||
// 销售任务最终得分
|
||||
salesPerformanceSettlementDO.setSaleTask(saleScore);
|
||||
|
||||
// ----------- 回款任务得分计算 -----------
|
||||
BigDecimal paymentScore = salesPerformanceSettlementDO.getActualPayment()
|
||||
.divide(salesPerformanceDTO.getPaymentTarget(), 2, RoundingMode.HALF_UP);
|
||||
BigDecimal paymentScore = BigDecimalUtil.isEqZero(salesPerformanceDTO.getPaymentTarget()) ? BigDecimal.ZERO :
|
||||
(salesPerformanceSettlementDO.getActualPayment()
|
||||
.divide(salesPerformanceDTO.getPaymentTarget(), 2, RoundingMode.HALF_UP));
|
||||
paymentScore = (paymentScore.compareTo(BigDecimal.ONE) >= 0) ? salesPerformanceWeight.getPaymentWeight() :
|
||||
salesPerformanceWeight.getPaymentWeight().multiply(paymentScore);
|
||||
// 回款任务最终得分
|
||||
@ -272,6 +298,7 @@ public class SalesPerformanceSettlementServiceImpl extends ServiceImpl<SalesPerf
|
||||
}
|
||||
}
|
||||
salesPerformanceSettlementDO.setCanConfirmFlag(1);
|
||||
salesPerformanceSettlementDO.setSettlementStatus(salesPerformanceSettlementDO.getScoreStatus() == 1 ? 2 : 1);
|
||||
}
|
||||
list.add(salesPerformanceSettlementDO);
|
||||
}
|
||||
@ -286,7 +313,8 @@ public class SalesPerformanceSettlementServiceImpl extends ServiceImpl<SalesPerf
|
||||
List<AdminOauthUserOtherInfoApiVO> adminOauthUserOtherInfoApiVOS = adminOauthUserOtherInfoApi.getOpenIdByCondition(
|
||||
new AdminOauthUserOtherInfoApiDTO().setUserIds(userIds)
|
||||
.setSocialType(SocialTypeEnum.WECHAT_MP.getType())).getCheckedData();
|
||||
|
||||
log.info("用户列表:{}", userIds);
|
||||
log.info("用户三方账号列表:{}", adminOauthUserOtherInfoApiVOS);
|
||||
// - 结算完毕 - 通知所有填写申请到crm用户确认
|
||||
for (AdminOauthUserOtherInfoApiVO adminOauthUserOtherInfoApiVO : adminOauthUserOtherInfoApiVOS) {
|
||||
SubscribeMessageReqDTO dto = new WxMpMsgTemplateUtils().convertPerformanceResultConfirmationReminder(new PerformanceResultConfirmationReminderDTO()
|
||||
@ -321,6 +349,16 @@ public class SalesPerformanceSettlementServiceImpl extends ServiceImpl<SalesPerf
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void autoConfirmJob() {
|
||||
LocalDateTime now = LocalDateTime.now().minusMonths(1L);
|
||||
salesPerformanceSettlementMapper.update(new SalesPerformanceSettlementDO().setConfirmFlag(1),
|
||||
new LambdaQueryWrapper<SalesPerformanceSettlementDO>()
|
||||
.eq(SalesPerformanceSettlementDO::getYear, String.valueOf(now.getYear()))
|
||||
.eq(SalesPerformanceSettlementDO::getMonth, String.format("%02d", now.getMonthValue()))
|
||||
.eq(SalesPerformanceSettlementDO::getConfirmFlag, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* 表达式 10<=n && n<=20
|
||||
*
|
||||
|
@ -34,7 +34,7 @@
|
||||
and a.is_end = #{dto.isEnd}
|
||||
</if>
|
||||
<if test="dto.customerName != null and dto.customerName != ''">
|
||||
and b.name = #{dto.customerName}
|
||||
and b.name like concat('%', #{dto.customerName}, '%')=
|
||||
</if>
|
||||
<if test="dto.customerId != null">
|
||||
and a.customer_id = #{dto.customerId}
|
||||
|
@ -13,15 +13,24 @@
|
||||
resultType="cn.iocoder.yudao.module.crm.dal.dataobject.salesperformancesettlement.SalesPerformanceSettlementDO">
|
||||
select
|
||||
a.*,
|
||||
b.nickname
|
||||
b.nickname,
|
||||
c.payment_target as paymentTarget,
|
||||
c.sale_target as saleTarget
|
||||
from crm_sales_performance_settlement as a
|
||||
left join system_users as b on a.user_id = b.id
|
||||
left join bpm_oa_sales_performance as c on a.sales_performance_id = c.id
|
||||
<where>
|
||||
a.deleted = 0
|
||||
and b.deleted = 0
|
||||
<if test="vo.userId != null">
|
||||
and a.user_id = #{vo.userId}
|
||||
</if>
|
||||
<if test="vo.userIds != null and vo.userIds.size() > 0">
|
||||
and a.user_id in
|
||||
<foreach collection="vo.userIds" item="userId" open="(" separator="," close=")">
|
||||
#{userId}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="vo.year != null and vo.year != ''">
|
||||
and a.year = #{vo.year}
|
||||
</if>
|
||||
@ -31,15 +40,24 @@
|
||||
<if test="vo.nickname != null and vo.nickname != ''">
|
||||
and b.nickname like concat('%', #{vo.nickname}, '%')
|
||||
</if>
|
||||
<if test="vo.scoreStatus != null">
|
||||
and a.score_status = #{vo.scoreStatus}
|
||||
</if>
|
||||
<if test="vo.settlementStatus != null">
|
||||
and a.settlement_status = #{vo.settlementStatus}
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
<select id="getSalesPerformanceSettlement"
|
||||
resultType="cn.iocoder.yudao.module.crm.dal.dataobject.salesperformancesettlement.SalesPerformanceSettlementDO">
|
||||
select
|
||||
a.*,
|
||||
b.nickname
|
||||
b.nickname,
|
||||
c.payment_target as paymentTarget,
|
||||
c.sale_target as saleTarget
|
||||
from crm_sales_performance_settlement as a
|
||||
left join system_users as b on a.user_id = b.id
|
||||
left join bpm_oa_sales_performance as c on a.sales_performance_id = c.id
|
||||
<where>
|
||||
a.deleted = 0
|
||||
and b.deleted = 0
|
||||
|
@ -22,4 +22,10 @@ public interface RoleApi {
|
||||
@Parameter(name = "ids", description = "角色编号数组", example = "1,2", required = true)
|
||||
CommonResult<Boolean> validRoleList(@RequestParam("ids") Collection<Long> ids);
|
||||
|
||||
|
||||
@GetMapping(PREFIX + "/validCalculator")
|
||||
@Operation(summary = "校验角色是否包含销售业绩核算员")
|
||||
@Parameter(name = "userId", description = "用户id", example = "2", required = true)
|
||||
CommonResult<Boolean> validCalculator(@RequestParam("userId") Long userId);
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.module.system.api.permission;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
|
||||
import cn.iocoder.yudao.module.system.service.permission.RoleService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
@ -16,10 +17,19 @@ public class RoleApiImpl implements RoleApi {
|
||||
|
||||
@Resource
|
||||
private RoleService roleService;
|
||||
@Resource
|
||||
private PermissionService permissionService;
|
||||
private static final String ROLE = "calculator";
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> validRoleList(Collection<Long> ids) {
|
||||
roleService.validateRoleList(ids);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> validCalculator(Long userId) {
|
||||
boolean flag = permissionService.hasAnyRoles(userId, ROLE);
|
||||
return success(flag);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user