签约目标;线索

This commit is contained in:
DB 2024-02-19 18:27:26 +08:00
parent 0d443be4bc
commit 32ab3e1782
30 changed files with 1440 additions and 21 deletions

View File

@ -40,17 +40,17 @@ public class CpopGenerator {
/**
* 输出路径
*/
private static final String EXPORT_URL = "/Cpop-Mini";
private static final String EXPORT_URL = "/Cpop-Oam";
/**
* 模块
*/
private static final String EXPORT_ITEM = "mini";
private static final String EXPORT_ITEM = "oam";
/**
* 表前缀
*/
private static final String TABLE_PREFIX = "cp_mini_";
private static final String TABLE_PREFIX = "cp_oam_";
/**
* 主入口

View File

@ -52,18 +52,18 @@ public class CpopWxPayTests {
WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount();
//退款金额(单位分)
//int refund = order.getTotalAmount().scaleByPowerOfTen(2).intValue();
int refund = 8400;
int refund = 1;
amount.setRefund(refund)
.setTotal(refund)
.setCurrency("CNY");
request.setTransactionId("4200002111202402019716818254")
request.setTransactionId("4200002123202402194880609914")
//.setOutTradeNo("1000000000202401121937112562856")
//.setTransactionId(order.getOutOrderNo())
//.setOutTradeNo(order.getId())
.setNotifyUrl(wxPayProperties.getNotifyRefund())
.setOutRefundNo(IdUtil.getSnowflakeNextIdStr())
.setSubMchid("1661323640")
.setReason("先学后付重复核销退款")
.setSubMchid("1618925571")
.setReason("先学后付测试退款")
.setAmount(amount);
WxPayRefundV3Result result = wxPayService.refundV3(request);
System.out.println(result);
@ -137,7 +137,7 @@ public class CpopWxPayTests {
public void getOrderInfo() throws WxPayException {
WxPayConfig config = wxPayService.getConfig();
config.setSubMchId("1661323640");
WxPayOrderQueryResult wxPayOrderQueryResult = wxPayService.queryOrder("4200002122202402014187762767", null);
WxPayOrderQueryResult wxPayOrderQueryResult = wxPayService.queryOrder("4200002096202402199975156147", null);
System.out.println(JSONObject.toJSONString(wxPayOrderQueryResult));
}

View File

@ -119,7 +119,7 @@ xss:
# 排除链接(多个用逗号分隔)
excludes:
# 匹配链接
urlPatterns: /oam/*
urlPatterns: /*
logging:
level:

View File

@ -277,18 +277,21 @@ public class CpopEasyLearnTest {
public void queryOrderAndSharing() throws WxPayException {
WxPayService wxPayService = wxPayHandler.getWxPayService(null, "1661323640");
WxPayOrderQueryRequest wxPayOrderQueryRequest = new WxPayOrderQueryRequest();
wxPayOrderQueryRequest.setTransactionId("4200002116202402013721924373");
WxPayConfig config = wxPayService.getConfig();
config.setAppId("wx1eb0e5fb7dac3c05");
wxPayService.setConfig(config);
wxPayOrderQueryRequest.setTransactionId("4200002096202402199975156147");
WxPayOrderQueryResult wxPayOrderQueryResult = wxPayService.queryOrder(wxPayOrderQueryRequest);
ProfitSharingService profitSharingService = wxPayService.getProfitSharingService();
ProfitSharingV3Result profitSharingV3Result = profitSharingService.profitSharingQueryV3("1752967538354028544", "4200002116202402013721924373", "1661323640");
//ProfitSharingService profitSharingService = wxPayService.getProfitSharingService();
//ProfitSharingV3Result profitSharingV3Result = profitSharingService.profitSharingQueryV3("1752967538354028544", "4200002116202402013721924373", "1661323640");
System.out.println(JSONObject.toJSONString(wxPayOrderQueryResult));
System.out.println(JSONObject.toJSONString(profitSharingV3Result));
//System.out.println(JSONObject.toJSONString(profitSharingV3Result));
}
@Test
public void queryServiceOrder() throws WxPayException {
WxPayService wxPayService = wxPayHandler.getWxPayService();
WxPartnerPayScoreResult wxPartnerPayScoreResult = wxPayService.getPartnerPayScoreService().queryServiceOrder("00003053000000169450961228104460", "1661323640", "1736629608413073418", null);
WxPartnerPayScoreResult wxPartnerPayScoreResult = wxPayService.getPartnerPayScoreService().queryServiceOrder("00003053000000169450961228104460", "1661323640", "1759141081982881793", null);
System.out.println(JSONObject.toJSONString(wxPartnerPayScoreResult));
}
@ -313,10 +316,10 @@ public class CpopEasyLearnTest {
@Test
public void getWxPayPlan() {
WxPayService wxPayService = wxPayHandler.getWxPayService(null,"1661323640");
WxPayService wxPayService = wxPayHandler.getWxPayService(null,"1618925571");
PartnerUserSignPlanEntity result = null;
try {
result = wxPayService.getPartnerPayScoreSignPlanService().queryUserSignPlans("1736679801829396540", "1661323640");
result = wxPayService.getPartnerPayScoreSignPlanService().queryUserSignPlans("1759141081982881794", "1618925571");
System.out.println(JSONObject.toJSONString(result));
} catch (WxPayException e) {
throw new RuntimeException(e);
@ -325,8 +328,8 @@ public class CpopEasyLearnTest {
@Test
public void queryOrder() throws WxPayException {
WxPayService wxPayService = wxPayHandler.getWxPayService(null, "1661323640");
WxPayOrderQueryResult wxPayOrderQueryResult = wxPayService.queryOrder("4200002115202401300171921108",null);
WxPayService wxPayService = wxPayHandler.getWxPayService(null, "1618925571");
WxPayOrderQueryResult wxPayOrderQueryResult = wxPayService.queryOrder("4200002123202402194880609914",null);
System.out.println(JSONObject.toJSONString(wxPayOrderQueryResult));
}

View File

@ -1,8 +1,13 @@
package com.cpop.oam.web;
import cn.hutool.poi.excel.ExcelDateUtil;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.cpop.common.utils.StringUtils;
import com.cpop.common.utils.bean.BeanUtils;
import com.cpop.core.base.entity.LoginUser;
import com.cpop.core.base.enums.UserType;
@ -11,7 +16,9 @@ import com.cpop.core.base.table.SysUser;
import com.cpop.core.mapper.CoreMapper;
import com.cpop.core.utils.SecurityUtils;
import com.cpop.core.utils.SpringUtils;
import com.cpop.core.utils.file.FileUtils;
import com.cpop.core.utils.uuid.IdUtils;
import com.cpop.oam.business.dto.DataImportDto;
import com.cpop.oam.business.entity.Dept;
import com.cpop.oam.business.entity.Staff;
import com.cpop.oam.business.entity.StaffMidDept;
@ -23,10 +30,15 @@ import com.mybatisflex.core.row.Db;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpExternalContactService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpDepart;
import me.chanjar.weixin.cp.bean.WxCpUser;
import me.chanjar.weixin.cp.bean.export.WxCpExportRequest;
import me.chanjar.weixin.cp.bean.export.WxCpExportResult;
import me.chanjar.weixin.cp.bean.external.WxCpUserExternalGroupChatInfo;
import me.chanjar.weixin.cp.bean.external.WxCpUserExternalGroupChatList;
import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactBatchInfo;
import me.chanjar.weixin.cp.bean.user.WxCpDeptUserResult;
import org.apache.commons.codec.binary.Base64;
import org.junit.jupiter.api.Test;
@ -37,6 +49,8 @@ import org.springframework.web.client.RestTemplate;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
@ -46,7 +60,7 @@ import java.util.stream.Collectors;
* @createTime 2023/10/12 15:19
* @description 企业微信Api测试
*/
@SpringBootTest
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Slf4j
public class CpopWxCpTests {
@ -373,4 +387,118 @@ public class CpopWxCpTests {
private List<Long> order;
}
/**
* 获取线索
* @author DB
* @since 2024/2/18
*/
@Test
public void getClueList() throws WxErrorException {
WxCpService cpService = WxCpConfiguration.getCpService(1000024);
WxCpExternalContactService externalContactService = cpService.getExternalContactService();
String[] userIds = {"YiHaiNan","ChenShuJie","ChenWei","GuTingTing","9106a48341c538f2f634343241c7e37a","LanShengYao","LiMei","LiuYe","MaYaLan","NiXuMei","PanYanXia","YangTingHong","ZhangCongTang","ZhaoSuMin"};
List<WxCpExternalContactBatchInfo.ExternalContactInfo> externalData = getExternalData(null,externalContactService, null, userIds);
List<ExportClueData> exportClueDataList = new ArrayList<>();
externalData.forEach(item->{
ExportClueData exportClueData = new ExportClueData();
exportClueData.setType(item.getExternalContact().getType() == 1 ? "微信用户" : "企业微信用户");
exportClueData.setUserid(item.getFollowInfo().getUserId());
exportClueData.setName(item.getExternalContact().getName());
exportClueData.setExternalUserid(item.getExternalContact().getExternalUserId());
exportClueDataList.add(exportClueData);
});
List<ExportClueData> filterExportClueDataList = new ArrayList<>();
exportClueDataList.stream().collect(Collectors.groupingBy(ExportClueData::getExternalUserid))
.forEach((key, value) ->{
if(value.size() > 1){
filterExportClueDataList.add(value.get(0));
}
});
Map<String, ExportClueData> externalUserMap = filterExportClueDataList.stream().collect(Collectors.toMap(ExportClueData::getExternalUserid, item -> item));
WxCpUserExternalGroupChatList wxCpUserExternalGroupChatList = externalContactService.listGroupChat(1000, null, 0, userIds);
wxCpUserExternalGroupChatList.getGroupChatList().forEach(item->{
try {
WxCpUserExternalGroupChatInfo groupChatInfo = externalContactService.getGroupChat(item.getChatId(), 1);
WxCpUserExternalGroupChatInfo.GroupChat groupChat = groupChatInfo.getGroupChat();
List<String> collect = groupChat.getMemberList().stream().map(WxCpUserExternalGroupChatInfo.GroupMember::getUserId).collect(Collectors.toList());
collect.forEach(inner->{
ExportClueData exportClueData = externalUserMap.get(inner);
if (exportClueData != null){
exportClueData.setGroupName(groupChatInfo.getGroupChat().getName());
}
});
} catch (WxErrorException e) {
throw new RuntimeException(e);
}
});
File file = new File("D:\\Lost\\桌面\\线索池数据.xlsx");
EasyExcel.write(file, ExportClueData.class)
.sheet("已知线索池")
.doWrite(() -> {
// 分页查询数据
return filterExportClueDataList;
});
}
private List<WxCpExternalContactBatchInfo.ExternalContactInfo> getExternalData(List<WxCpExternalContactBatchInfo.ExternalContactInfo> allExternalContactList, WxCpExternalContactService externalContactService, String nextCursor, String[] userIds) throws WxErrorException {
WxCpExternalContactBatchInfo contactDetailBatch = externalContactService.getContactDetailBatch(userIds, nextCursor, null);
List<WxCpExternalContactBatchInfo.ExternalContactInfo> externalContactList = contactDetailBatch.getExternalContactList();
if (allExternalContactList != null){
allExternalContactList.addAll(externalContactList);
} else {
allExternalContactList = externalContactList;
}
if (StringUtils.isNotBlank(contactDetailBatch.getNextCursor())) {
return getExternalData(allExternalContactList, externalContactService, contactDetailBatch.getNextCursor(), userIds);
} else {
return allExternalContactList;
}
}
@Data
public class ExportClueData{
/**
* 联系人名称
*/
@ExcelProperty(value = "联系人名称")
private String name;
/**
* 客户群名
*/
@ExcelProperty(value = "客户群名")
private String groupName;
/**
* 联系人类型
*/
@ExcelProperty(value = "联系人类型")
private String type;
/**
* 联系人userid
*/
@ExcelProperty(value = "联系人userid")
@JSONField(name = "external_userid")
private String externalUserid;
/**
* 系统微信用户id
*/
@ExcelProperty(value = "系统微信用户id")
private String userid;
/**
* 校区名
*/
@ExcelProperty(value = "校区名")
private String storeName;
/**
* 校区id
*/
@ExcelProperty(value = "校区id")
private String storeId;
}
}

View File

@ -0,0 +1,112 @@
package com.cpop.oam.business.bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotEmpty;
import java.util.List;
/**
* @author DB
* @version 1.0.0
* @since 2024-02-19 15:39
*/
@Data
@Accessors(chain = true)
@ApiModel(value = "SignGoalBo对象", description = "签约指标")
public class SignGoalBo {
/**
* 主键
*/
@ApiModelProperty(value = "主键")
private String id;
/**
* 员工id
*/
@ApiModelProperty(value = "员工id")
private String staffId;
/**
* 签约区域集合
*/
@NotEmpty(message = "签约区域集合不能为空")
@ApiModelProperty(value = "签约区域集合")
private List<String> signAreaList;
/**
* 一月目标
*/
@ApiModelProperty(value = "一月目标")
private Integer janGoal;
/**
* 二月目标
*/
@ApiModelProperty(value = "二月目标")
private Integer febGoal;
/**
* 三月目标
*/
@ApiModelProperty(value = "三月目标")
private Integer marGoal;
/**
* 四月目标
*/
@ApiModelProperty(value = "四月目标")
private Integer aprGoal;
/**
* 五月目标
*/
@ApiModelProperty(value = "五月目标")
private Integer mayGoal;
/**
* 六月目标
*/
@ApiModelProperty(value = "六月目标")
private Integer junGoal;
/**
* 七月目标
*/
@ApiModelProperty(value = "七月目标")
private Integer julGoal;
/**
* 八月目标
*/
@ApiModelProperty(value = "八月目标")
private Integer augGoal;
/**
* 九月目标
*/
@ApiModelProperty(value = "九月目标")
private Integer sepGoal;
/**
* 十月目标
*/
@ApiModelProperty(value = "十月目标")
private Integer octGoal;
/**
* 十一月目标
*/
@ApiModelProperty(value = "十一月目标")
private Integer novGoal;
/**
* 十二月目标
*/
@ApiModelProperty(value = "十二月目标")
private Integer decGoal;
}

View File

@ -0,0 +1,34 @@
package com.cpop.oam.business.bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* @author DB
* @version 1.0.0
* @since 2024-02-19 15:30
*/
@Data
@Accessors(chain = true)
@ApiModel(value = "SignGoalConfigInfoBo对象", description = "签约指标配置信息")
public class SignGoalConfigInfoBo {
/**
* 跟进间隔
*/
@NotNull(message = "跟进间隔不能为空")
@ApiModelProperty(value = "跟进间隔",required = true)
private String followUpInterval;
/**
* 签约间隔
*/
@NotNull(message = "签约间隔不能为空")
@ApiModelProperty(value = "签约间隔",required = true)
private String signInterval;
}

View File

@ -0,0 +1,48 @@
package com.cpop.oam.business.controller.backstage;
import com.cpop.core.base.R;
import com.cpop.oam.business.vo.SignGoalPageVo;
import com.mybatisflex.core.paginate.Page;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import com.cpop.oam.business.entity.Clue;
import com.cpop.oam.business.service.ClueService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import java.io.Serializable;
import java.util.List;
/**
* 线索表 控制层
*
* @author DB
* @since 2024-02-19
*/
@RestController
@Api(tags = "线索接口")
@RequestMapping("/backstage/clue")
public class BackstageClueController {
@Autowired
private ClueService clueService;
/**
* 个人线索分页
* @author DB
* @since 2024/2/19
* @return R<Page<SignGoalPageVo>>
*/
@ApiOperation("个人线索分页")
@GetMapping("/getPersonCluePage")
public R<Page<SignGoalPageVo>> getPersonCluePage(@ApiParam(value = "地区") @RequestParam(value = "city", required = false) String city,
@ApiParam(value = "品牌") @RequestParam(value = "brandId", required = false) String brandId,
@ApiParam(value = "校区") @RequestParam(value = "storeId", required = false) String storeId,
@ApiParam(value = "负责人或手机号") @RequestParam(value = "chargeOrPhone", required = false) String chargeOrPhone,
@ApiParam(value = "员工id") @RequestParam(value = "staffId", required = false) String staffId,
@ApiParam(value = "签约月份") @RequestParam(value = "signMonth", required = false) String signMonth) {
Page<SignGoalPageVo> pageVo = clueService.getPersonCluePage(city, brandId, storeId, chargeOrPhone, staffId, signMonth);
return R.ok(pageVo);
}
}

View File

@ -0,0 +1,195 @@
package com.cpop.oam.business.controller.backstage;
import com.cpop.common.utils.StringUtils;
import com.cpop.common.utils.bean.BeanUtils;
import com.cpop.core.annontation.OperationLog;
import com.cpop.core.base.R;
import com.cpop.core.base.enums.OperationLogEnum;
import com.cpop.core.base.exception.ServiceException;
import com.cpop.core.base.table.SysConfig;
import com.cpop.core.service.CoreService;
import com.cpop.core.service.RedisService;
import com.cpop.core.utils.SpringUtils;
import com.cpop.oam.business.bo.*;
import com.cpop.oam.business.service.CommonService;
import com.cpop.oam.business.service.SignAreaService;
import com.cpop.oam.business.vo.ConfigInfoVo;
import com.cpop.oam.business.vo.SignGoalConfigInfoVo;
import com.cpop.oam.business.vo.SignGoalPageVo;
import com.cpop.oam.business.vo.StaffPageVo;
import com.cpop.oam.framework.constant.OamConfigKey;
import com.cpop.oam.framework.enums.OamConfigEnum;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.DbChain;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.beans.factory.annotation.Autowired;
import com.cpop.oam.business.entity.SignGoal;
import com.cpop.oam.business.service.SignGoalService;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.cpop.core.base.table.table.SysConfigTableDef.SYS_CONFIG;
import static com.cpop.oam.business.entity.table.SignAreaTableDef.SIGN_AREA;
/**
* 签约目标表 控制层
*
* @author DB
* @since 2024-02-19
*/
@RestController
@Api(tags = "签约目标接口")
@RequestMapping("/backstage/signGoal")
public class BackstageSignGoalController {
@Autowired
private SignGoalService signGoalService;
/**
* 签约指标分页
* @author DB
* @since 2024/2/19
* @return R<Page<SignGoalPageVo>>
*/
@ApiOperation("签约指标分页")
@GetMapping("/getSignGoalPage")
public R<Page<SignGoalPageVo>> getSignGoalPage() {
Page<SignGoalPageVo> pageVo = signGoalService.getSignGoalPage();
return R.ok(pageVo);
}
/**
* 设置签约间隔配置信息
* @author DB
* @since 2024/2/19
* @param bo 请求参数
* @return R<Void>
*/
@ApiOperation("设置签约间隔配置信息")
@PutMapping("/setSignConfigInfo")
public R<Void> setSignConfigInfo(@RequestBody @Validated SignGoalConfigInfoBo bo) {
CoreService coreService = SpringUtils.getBean(CoreService.class);
CommonService commonService = SpringUtils.getBean(CommonService.class);
// 遍历属性名与值
try {
for (Field field : bo.getClass().getDeclaredFields()) {
field.setAccessible(true);
// 获取枚举
OamConfigEnum sysConfigEnum = OamConfigEnum.matchField(field.getName());
if (null != sysConfigEnum) {
SysConfig sysConfig = new SysConfig();
sysConfig.setConfigName(sysConfigEnum.getName())
.setConfigKey(sysConfigEnum.getKey())
.setConfigValue(field.get(bo).toString());
// 修改
if (DbChain.table(SYS_CONFIG)
.where(SYS_CONFIG.CONFIG_KEY.eq(sysConfig.getConfigKey()))
.count() > 0) {
coreService.updateConfig(sysConfig);
} else {
coreService.insertConfig(sysConfig);
}
// 更新缓存
SpringUtils.getBean(RedisService.class).setCacheObject(commonService.getCacheKey(sysConfigEnum.getKey()), sysConfig.getConfigValue());
}
}
} catch (IllegalAccessException e) {
throw new ServiceException("设置签约间隔配置信息失败,请联系相关人员!");
}
return R.ok();
}
/**
* 获取签约间隔配置信息
* @author DB
* @since 2024/2/19
* @return R<SignGoalConfigInfoVo>
*/
@ApiOperation("获取签约间隔配置信息")
@GetMapping("/getSignConfigInfo")
public R<SignGoalConfigInfoVo> getSignConfigInfo() {
RedisService redisService = SpringUtils.getBean(RedisService.class);
CoreService coreService = SpringUtils.getBean(CoreService.class);
CommonService commonService = SpringUtils.getBean(CommonService.class);
Map<String, String> configMap = new HashMap<>(8);
Arrays.asList(OamConfigKey.SIGN_GOAL).forEach(item -> {
String cacheInfo = redisService.getCacheObject(commonService.getCacheKey(item));
if (StringUtils.isNotBlank(cacheInfo)) {
// 获取枚举
OamConfigEnum sysConfigEnum = OamConfigEnum.matchKey(item);
configMap.put(sysConfigEnum.getField(), cacheInfo);
} else {
// 查询系统
SysConfig sysConfig = coreService.selectConfigByKey(item);
if (null != sysConfig) {
// 获取枚举
OamConfigEnum sysConfigEnum = OamConfigEnum.matchKey(item);
configMap.put(sysConfigEnum.getField(), sysConfig.getConfigValue());
}
}
});
SignGoalConfigInfoVo signGoalConfigInfoVo = new SignGoalConfigInfoVo();
BeanUtils.mapToObj(configMap, signGoalConfigInfoVo);
return R.ok(signGoalConfigInfoVo);
}
/**
* 新增签约指标
* @author DB
* @since 2024/2/19
* @param bo 请求参数
* @return R<Void>
*/
@ApiOperation("新增签约指标")
@PostMapping("/insertSignGoal")
public R<Void> insertSignGoal(@RequestBody @Validated SignGoalBo bo) {
signGoalService.insertSignGoal(bo);
return R.ok();
}
/**
* 修改签约指标
* @author DB
* @since 2024/2/19
* @param bo 请求参数
* @return R<Void>
*/
@ApiOperation("修改签约指标")
@PutMapping("/updateSignGoal")
public R<Void> updateSignGoal(@RequestBody @Validated SignGoalBo bo) {
signGoalService.updateSignGoal(bo);
return R.ok();
}
/**
* 删除签约指标
* @author DB
* @since 2024/2/19
* @param id 主键
* @return R<Void>
*/
@ApiOperation("删除签约指标")
@DeleteMapping("/removeSignGoal/{id}")
public R<Void> removeSignGoal(@PathVariable String id) {
signGoalService.removeById(id);
SpringUtils.getBean(SignAreaService.class).remove(QueryWrapper.create().where(SIGN_AREA.SIGN_GOAL_ID.eq(id)));
return R.ok();
}
}

View File

@ -0,0 +1,82 @@
package com.cpop.oam.business.entity;
import com.cpop.core.base.entity.BaseEntity;
import com.cpop.core.base.entity.BaseInsertListener;
import com.cpop.core.base.entity.BaseUpdateListener;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.Table;
import java.io.Serializable;
import java.time.LocalDateTime;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.experimental.Accessors;
/**
* 线索表 实体类
*
* @author DB
* @since 2024-02-19
*/
@Data
@EqualsAndHashCode(callSuper=false)
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@Table(value = "cp_oam_clue", onInsert = BaseInsertListener.class, onUpdate = BaseUpdateListener.class, mapperGenerateEnable = false)
public class Clue extends BaseEntity implements Serializable {
/**
* 主键
*/
@Id
private String id;
/**
* 校区id
*/
private String storeId;
/**
* 城市(地区)
*/
private String city;
/**
* 负责员工id
*/
private String responsibleStaffId;
/**
* 开发员工id
*/
private String devStaffId;
/**
* 最后跟进时间
*/
private LocalDateTime lastFollowUpTime;
/**
* 最后跟进内容
*/
private String lastFollowUpContent;
/**
* 接受时间
*/
private LocalDateTime receiptTime;
/**
* 是否删除(0否1是)
*/
@Column(isLogicDelete = true)
private Boolean isDelete;
}

View File

@ -0,0 +1,50 @@
package com.cpop.oam.business.entity;
import com.cpop.core.base.entity.BaseEntity;
import com.cpop.core.base.entity.BaseInsertListener;
import com.cpop.core.base.entity.BaseUpdateListener;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.Table;
import java.io.Serializable;
import java.time.LocalDateTime;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.experimental.Accessors;
/**
* 签约目标区域表 实体类
*
* @author DB
* @since 2024-02-19
*/
@Data
@EqualsAndHashCode(callSuper=false)
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@Table(value = "cp_oam_sign_area", onInsert = BaseInsertListener.class, onUpdate = BaseUpdateListener.class, mapperGenerateEnable = false)
public class SignArea extends BaseEntity implements Serializable {
/**
* 主键
*/
@Id
private String id;
/**
* 签约目标id
*/
private String signGoalId;
/**
* 城市
*/
private String city;
}

View File

@ -0,0 +1,177 @@
package com.cpop.oam.business.entity;
import com.cpop.core.base.entity.BaseEntity;
import com.cpop.core.base.entity.BaseInsertListener;
import com.cpop.core.base.entity.BaseUpdateListener;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.Table;
import java.io.Serializable;
import java.time.LocalDateTime;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.experimental.Accessors;
/**
* 签约目标表 实体类
*
* @author DB
* @since 2024-02-19
*/
@Data
@EqualsAndHashCode(callSuper=false)
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@Table(value = "cp_oam_sign_goal", onInsert = BaseInsertListener.class, onUpdate = BaseUpdateListener.class, mapperGenerateEnable = false)
public class SignGoal extends BaseEntity implements Serializable {
/**
* 主键
*/
@Id
private String id;
/**
* 员工id
*/
private String staffId;
/**
* 年份
*/
private Integer year;
/**
* 一月目标
*/
private Integer janGoal;
/**
* 一月完成
*/
private Integer janFinish;
/**
* 二月目标
*/
private Integer febGoal;
/**
* 二月完成
*/
private Integer febFinish;
/**
* 三月目标
*/
private Integer marGoal;
/**
* 三月完成
*/
private Integer marFinish;
/**
* 四月目标
*/
private Integer aprGoal;
/**
* 四月完成
*/
private Integer aprFinish;
/**
* 五月目标
*/
private Integer mayGoal;
/**
* 五月完成
*/
private Integer mayFinish;
/**
* 六月目标
*/
private Integer junGoal;
/**
* 六月完成
*/
private Integer junFinish;
/**
* 七月目标
*/
private Integer julGoal;
/**
* 七月完成
*/
private Integer julFinish;
/**
* 八月目标
*/
private Integer augGoal;
/**
* 八月完成
*/
private Integer augFinish;
/**
* 九月目标
*/
private Integer sepGoal;
/**
* 九月完成
*/
private Integer sepFinish;
/**
* 十月目标
*/
private Integer octGoal;
/**
* 十月完成
*/
private Integer octFinish;
/**
* 十一月目标
*/
private Integer novGoal;
/**
* 十一月完成
*/
private Integer novFinish;
/**
* 十二月目标
*/
private Integer decGoal;
/**
* 十二月完成
*/
private Integer decFinish;
/**
* 逻辑删除(0否1是)
*/
@Column(isLogicDelete = true)
private Boolean isDelete;
}

View File

@ -0,0 +1,14 @@
package com.cpop.oam.business.mapper;
import com.mybatisflex.core.BaseMapper;
import com.cpop.oam.business.entity.Clue;
/**
* 线索表 映射层
*
* @author DB
* @since 2024-02-19
*/
public interface ClueMapper extends BaseMapper<Clue> {
}

View File

@ -0,0 +1,14 @@
package com.cpop.oam.business.mapper;
import com.mybatisflex.core.BaseMapper;
import com.cpop.oam.business.entity.SignArea;
/**
* 签约目标区域表 映射层
*
* @author DB
* @since 2024-02-19
*/
public interface SignAreaMapper extends BaseMapper<SignArea> {
}

View File

@ -0,0 +1,14 @@
package com.cpop.oam.business.mapper;
import com.mybatisflex.core.BaseMapper;
import com.cpop.oam.business.entity.SignGoal;
/**
* 签约目标表 映射层
*
* @author DB
* @since 2024-02-19
*/
public interface SignGoalMapper extends BaseMapper<SignGoal> {
}

View File

@ -0,0 +1,23 @@
package com.cpop.oam.business.service;
import com.cpop.oam.business.vo.SignGoalPageVo;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.service.IService;
import com.cpop.oam.business.entity.Clue;
/**
* 线索表 服务层
*
* @author DB
* @since 2024-02-19
*/
public interface ClueService extends IService<Clue> {
/**
* 个人线索分页
* @author DB
* @since 2024/2/19
* @return R<Page<SignGoalPageVo>>
*/
Page<SignGoalPageVo> getPersonCluePage(String city, String brandId, String storeId, String chargeOrPhone, String staffId, String signMonth);
}

View File

@ -0,0 +1,14 @@
package com.cpop.oam.business.service;
import com.mybatisflex.core.service.IService;
import com.cpop.oam.business.entity.SignArea;
/**
* 签约目标区域表 服务层
*
* @author DB
* @since 2024-02-19
*/
public interface SignAreaService extends IService<SignArea> {
}

View File

@ -0,0 +1,40 @@
package com.cpop.oam.business.service;
import com.cpop.oam.business.bo.SignGoalBo;
import com.cpop.oam.business.vo.SignGoalPageVo;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.service.IService;
import com.cpop.oam.business.entity.SignGoal;
/**
* 签约目标表 服务层
*
* @author DB
* @since 2024-02-19
*/
public interface SignGoalService extends IService<SignGoal> {
/**
* 签约指标分页
* @author DB
* @since 2024/2/19
* @return R<Page<SignGoalPageVo>>
*/
Page<SignGoalPageVo> getSignGoalPage();
/**
* 新增签约指标
* @author DB
* @since 2024/2/19
* @param bo 请求参数
*/
void insertSignGoal(SignGoalBo bo);
/**
* 修改签约指标
* @author DB
* @since 2024/2/19
* @param bo 请求参数
*/
void updateSignGoal(SignGoalBo bo);
}

View File

@ -0,0 +1,30 @@
package com.cpop.oam.business.service.impl;
import com.cpop.oam.business.vo.SignGoalPageVo;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.cpop.oam.business.entity.Clue;
import com.cpop.oam.business.mapper.ClueMapper;
import com.cpop.oam.business.service.ClueService;
import org.springframework.stereotype.Service;
/**
* 线索表 服务层实现
*
* @author DB
* @since 2024-02-19
*/
@Service("clueService")
public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements ClueService {
/**
* 个人线索分页
* @author DB
* @since 2024/2/19
* @return R<Page<SignGoalPageVo>>
*/
@Override
public Page<SignGoalPageVo> getPersonCluePage(String city, String brandId, String storeId, String chargeOrPhone, String staffId, String signMonth) {
return null;
}
}

View File

@ -14,6 +14,7 @@ import com.cpop.oam.business.vo.ConfigInfoVo;
import com.cpop.oam.framework.constant.OamConfigKey;
import com.cpop.oam.framework.enums.OamConfigEnum;
import org.apache.commons.lang3.ArrayUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
@ -43,7 +44,11 @@ public class CommonServiceImpl implements CommonService {
*/
@Override
public void loadingConfigCache() {
String[] keys = ArrayUtils.addAll(OamConfigKey.WORK_WX_INFO, OamConfigKey.DEMAND_TO_TASK);
List<String> keys = new ArrayList<>(Arrays.asList(OamConfigKey.WORK_WX_INFO));
List<String> demandToTask = Arrays.asList(OamConfigKey.DEMAND_TO_TASK);
keys.addAll(demandToTask);
List<String> signGoalList = Arrays.asList(OamConfigKey.SIGN_GOAL);
keys.addAll(signGoalList);
// 加载OAM配置参数
List<SysConfig> configsList = DbChain.table(SYS_CONFIG)
.select(SYS_CONFIG.ALL_COLUMNS)

View File

@ -0,0 +1,18 @@
package com.cpop.oam.business.service.impl;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.cpop.oam.business.entity.SignArea;
import com.cpop.oam.business.mapper.SignAreaMapper;
import com.cpop.oam.business.service.SignAreaService;
import org.springframework.stereotype.Service;
/**
* 签约目标区域表 服务层实现
*
* @author DB
* @since 2024-02-19
*/
@Service("signAreaService")
public class SignAreaServiceImpl extends ServiceImpl<SignAreaMapper, SignArea> implements SignAreaService {
}

View File

@ -0,0 +1,115 @@
package com.cpop.oam.business.service.impl;
import com.cpop.common.utils.bean.BeanUtils;
import com.cpop.core.base.entity.PageDomain;
import com.cpop.core.base.exception.ServiceException;
import com.cpop.core.utils.SpringUtils;
import com.cpop.core.utils.sql.SqlUtils;
import com.cpop.oam.business.bo.SignGoalBo;
import com.cpop.oam.business.entity.SignArea;
import com.cpop.oam.business.service.SignAreaService;
import com.cpop.oam.business.vo.SignGoalPageVo;
import com.cpop.system.business.vo.StoreRenewPageVo;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.cpop.oam.business.entity.SignGoal;
import com.cpop.oam.business.mapper.SignGoalMapper;
import com.cpop.oam.business.service.SignGoalService;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import static com.cpop.oam.business.entity.table.SignAreaTableDef.SIGN_AREA;
import static com.cpop.oam.business.entity.table.SignGoalTableDef.SIGN_GOAL;
import static com.cpop.oam.business.entity.table.StaffTableDef.STAFF;
import static com.mybatisflex.core.query.QueryMethods.*;
/**
* 签约目标表 服务层实现
*
* @author DB
* @since 2024-02-19
*/
@Service("signGoalService")
public class SignGoalServiceImpl extends ServiceImpl<SignGoalMapper, SignGoal> implements SignGoalService {
/**
* 签约指标分页
* @author DB
* @since 2024/2/19
* @return R<Page<SignGoalPageVo>>
*/
@Override
public Page<SignGoalPageVo> getSignGoalPage() {
PageDomain pageDomain = SqlUtils.getInstance().getPageDomain();
return this.mapper.paginateAs(Page.of(pageDomain.getPageNum(),pageDomain.getPageSize()),
QueryWrapper.create()
.select(SIGN_GOAL.ID,SIGN_GOAL.YEAR,SIGN_GOAL.JAN_GOAL,SIGN_GOAL.JAN_FINISH,SIGN_GOAL.FEB_GOAL,SIGN_GOAL.FEB_FINISH,SIGN_GOAL.MAR_GOAL,SIGN_GOAL.MAR_FINISH,
SIGN_GOAL.APR_GOAL,SIGN_GOAL.APR_FINISH,SIGN_GOAL.MAY_GOAL,SIGN_GOAL.MAY_FINISH,SIGN_GOAL.JUN_GOAL,SIGN_GOAL.JUN_FINISH,SIGN_GOAL.JUL_GOAL,
SIGN_GOAL.JUL_FINISH,SIGN_GOAL.AUG_GOAL,SIGN_GOAL.AUG_FINISH,SIGN_GOAL.SEP_GOAL,SIGN_GOAL.SEP_FINISH,SIGN_GOAL.OCT_GOAL,SIGN_GOAL.OCT_FINISH,
SIGN_GOAL.NOV_GOAL,SIGN_GOAL.NOV_FINISH,SIGN_GOAL.DEC_GOAL,SIGN_GOAL.DEC_FINISH)
.select(STAFF.NAME.as(SignGoalPageVo::getStaffName))
.from(SIGN_GOAL)
.leftJoin(STAFF).on(STAFF.ID.eq(SIGN_GOAL.STAFF_ID)),
SignGoalPageVo.class,
//子查询
item -> item.field(SignGoalPageVo::getSignArea)
.queryWrapper(signArea -> queryChain()
.select(SIGN_AREA.CITY.as(SignGoalPageVo::getSignArea))
.from(SIGN_AREA)
.where(SIGN_AREA.SIGN_GOAL_ID.eq(signArea.getId()))));
}
/**
* 新增签约指标
* @author DB
* @since 2024/2/19
* @param bo 请求参数
*/
@Override
public void insertSignGoal(SignGoalBo bo) {
//检查用户是否存在
int year = LocalDate.now().getYear();
if (this.count(QueryWrapper.create().where(SIGN_GOAL.YEAR.eq(year))
.and(SIGN_GOAL.STAFF_ID.eq(bo.getStaffId()))) > 0) {
throw new ServiceException("该员工已存在签约指标");
} else {
SignGoal signGoal = BeanUtils.mapToClass(bo, SignGoal.class);
signGoal.setYear(year);
this.save(signGoal);
//新增签约区域
List<SignArea> signAreas = new ArrayList<>();
bo.getSignAreaList().forEach(item->{
SignArea signArea = new SignArea().setSignGoalId(signGoal.getId()).setCity(item);
signAreas.add(signArea);
});
SpringUtils.getBean(SignAreaService.class).saveBatch(signAreas);
}
}
/**
* 修改签约指标
* @author DB
* @since 2024/2/19
* @param bo 请求参数
*/
@Override
public void updateSignGoal(SignGoalBo bo) {
//修改签约指标
SignGoal signGoal = BeanUtils.mapToClass(bo, SignGoal.class);
this.updateById(signGoal);
List<SignArea> signAreas = new ArrayList<>();
bo.getSignAreaList().forEach(item->{
SignArea signArea = new SignArea().setSignGoalId(signGoal.getId()).setCity(item);
signAreas.add(signArea);
});
SignAreaService signAreaService = SpringUtils.getBean(SignAreaService.class);
//先删后存
signAreaService.updateChain().where(SIGN_AREA.SIGN_GOAL_ID.eq(signGoal.getId())).remove();
signAreaService.saveBatch(signAreas);
}
}

View File

@ -0,0 +1,46 @@
package com.cpop.oam.business.vo;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.experimental.Accessors;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* @author DB
* @version 1.0.0
* @since 2024-02-19 18:08
*/
@Data
@Accessors(chain = true)
@ApiModel(value = "线索分页返回对象")
public class CluePageVo {
private String storeId;
private String storeName;
private String brandName;
private String city;
/**
* 店铺/校区地址
*/
private String storeAddr;
/**
* 负责人
*/
private String personCharge;
/**
* 手机号
*/
private String phone;
private LocalDateTime createTime;
private LocalDate updateTime;
}

View File

@ -0,0 +1,32 @@
package com.cpop.oam.business.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
/**
* @author DB
* @version 1.0.0
* @since 2024-02-19 16:47
*/
@Data
@Accessors(chain = true)
@ApiModel(value = "SignGoalConfigInfoVo对象", description = "签约指标配置信息")
public class SignGoalConfigInfoVo {
/**
* 跟进间隔
*/
@ApiModelProperty(value = "跟进间隔")
private String followUpInterval;
/**
* 签约间隔
*/
@ApiModelProperty(value = "签约间隔")
private String signInterval;
}

View File

@ -0,0 +1,188 @@
package com.cpop.oam.business.vo;
import com.mybatisflex.annotation.Id;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
/**
* @author DB
* @version 1.0.0
* @since 2024-02-19 14:45
*/
@Data
@Accessors(chain = true)
@ApiModel(value = "SignGoalPageVo对象", description = "签约目标分页对象")
public class SignGoalPageVo {
/**
* 主键
*/
@ApiModelProperty(value = "主键")
private String id;
/**
* 员工名
*/
@ApiModelProperty(value = "员工名")
private String staffName;
/**
* 签约区域
*/
@ApiModelProperty(value = "签约区域")
private List<String> signArea;
/**
* 年份
*/
@ApiModelProperty(value = "年份")
private Integer year;
/**
* 一月目标
*/
@ApiModelProperty(value = "一月目标")
private Integer janGoal;
/**
* 一月完成
*/
@ApiModelProperty(value = "一月完成")
private Integer janFinish;
/**
* 二月目标
*/
@ApiModelProperty(value = "二月目标")
private Integer febGoal;
/**
* 二月完成
*/
@ApiModelProperty(value = "二月完成")
private Integer febFinish;
/**
* 三月目标
*/
@ApiModelProperty(value = "三月目标")
private Integer marGoal;
/**
* 三月完成
*/
@ApiModelProperty(value = "三月完成")
private Integer marFinish;
/**
* 四月目标
*/
@ApiModelProperty(value = "四月目标")
private Integer aprGoal;
/**
* 四月完成
*/
@ApiModelProperty(value = "四月完成")
private Integer aprFinish;
/**
* 五月目标
*/
@ApiModelProperty(value = "五月目标")
private Integer mayGoal;
/**
* 五月完成
*/
@ApiModelProperty(value = "五月完成")
private Integer mayFinish;
/**
* 六月目标
*/
@ApiModelProperty(value = "六月目标")
private Integer junGoal;
/**
* 六月完成
*/
@ApiModelProperty(value = "六月完成")
private Integer junFinish;
/**
* 七月目标
*/
@ApiModelProperty(value = "七月目标")
private Integer julGoal;
/**
* 七月完成
*/
@ApiModelProperty(value = "七月完成")
private Integer julFinish;
/**
* 八月目标
*/
@ApiModelProperty(value = "八月目标")
private Integer augGoal;
/**
* 八月完成
*/
@ApiModelProperty(value = "八月完成")
private Integer augFinish;
/**
* 九月目标
*/
@ApiModelProperty(value = "九月目标")
private Integer sepGoal;
/**
* 九月完成
*/
@ApiModelProperty(value = "九月完成")
private Integer sepFinish;
/**
* 十月目标
*/
@ApiModelProperty(value = "十月目标")
private Integer octGoal;
/**
* 十月完成
*/
@ApiModelProperty(value = "十月完成")
private Integer octFinish;
/**
* 十一月目标
*/
@ApiModelProperty(value = "十一月目标")
private Integer novGoal;
/**
* 十一月完成
*/
@ApiModelProperty(value = "十一月完成")
private Integer novFinish;
/**
* 十二月目标
*/
@ApiModelProperty(value = "十二月目标")
private Integer decGoal;
/**
* 十二月完成
*/
@ApiModelProperty(value = "十二月完成")
private Integer decFinish;
}

View File

@ -21,4 +21,9 @@ public interface OamConfigKey {
* 需求转任务配置信息
*/
String[] DEMAND_TO_TASK = {OamConfigEnum.DEMAND_TO_TASK_BRAND.getKey(), OamConfigEnum.DEMAND_TO_TASK_STORE.getKey()};
/**
* 签约指标配置
*/
String[] SIGN_GOAL = {OamConfigEnum.FOLLOW_UP_INTERVAL.getKey(), OamConfigEnum.SIGN_INTERVAL.getKey()};
}

View File

@ -28,7 +28,18 @@ public enum OamConfigEnum {
/**
* 需求转任务主体校区
*/
DEMAND_TO_TASK_STORE("需求转任务主体校区", "DemandToTaskStore", "oamDemandToTaskStore", true);
DEMAND_TO_TASK_STORE("需求转任务主体校区", "DemandToTaskStore", "oamDemandToTaskStore", true),
/**
* 跟进间隔
*/
FOLLOW_UP_INTERVAL("跟进间隔", "FollowUpInterval", "followUpInterval", true),
/**
* 签约间隔
*/
SIGN_INTERVAL("签约间隔", "SignInterval", "signInterval", true),
;
/**
* 配置名

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cpop.oam.business.mapper.ClueMapper">
</mapper>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cpop.oam.business.mapper.SignAreaMapper">
</mapper>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cpop.oam.business.mapper.SignGoalMapper">
</mapper>