Merge #128 into master from cc_20250512_uploadRentContract
feat:租赁合同新增审批记录
* cc_20250512_uploadRentContract: (100 commits squashed)
- fix:计划闭店时间修改
- Merge branch 'cc_20250922_closeStore_w' into cc_20250514_common_bak
- feat:新签调整
- Merge branch 'cc_20260506_newsign' into cc_20250514_common_bak
# Conflicts:
#	coolstore-partner-common/src/main/java/com/cool/store/enums/UserRoleEnum.java
- fix:闭店信息新增初审、复审、终审时间字段;闭店管理列表新增返回字段
- Merge branch 'cc_20250922_closeStore_w' into cc_20250514_common_bak
- feat:招商
- Merge branch 'cc_20260506_newsign' into cc_20250514_common_bak
# Conflicts:
#	coolstore-partner-common/src/main/java/com/cool/store/enums/UserRoleEnum.java
- feat:招商
- feat:招商
- feat:招商
- fix:删除字段
- Merge branch 'cc_20250922_closeStore_w' into cc_20250514_common_bak
- feat:招商
- Merge branch 'cc_20260506_newsign' into cc_20250514_common_bak
- Merge remote-tracking branch 'origin/cc_20250514_common_bak' into cc_20250514_common_bak
- feat:数据同步 名称新增MX 等前缀
- feat:上海魔盒未来食品有限公司
- fix:修改查询逻辑
- Merge branch 'cc_20260428_store_report' into cc_20250514_common_bak
# Conflicts:
#	coolstore-partner-web/src/main/java/com/cool/store/job/XxlJobHandler.java
- feat:id
- Merge branch 'cc_20260506_newsign' into cc_20250514_common_bak
- Merge remote-tracking branch 'origin/cc_20250514_common_bak' into cc_20250514_common_bak
- Merge branch 'cc_20260507_smz' into cc_20250514_common_bak
# Conflicts:
#	coolstore-partner-service/src/main/java/com/cool/store/service/impl/SyncDataServiceImpl.java
- Merge remote-tracking branch 'origin/cc_20250514_common_bak' into cc_20250514_common_bak
- feat:翻新
- feat:用户列表为空
- Merge branch 'cc_20260427_rnewal' into cc_20250514_common_bak
- feat:用户列表为空
- Merge branch 'cc_20260427_rnewal' into cc_20250514_common_bak
- feat:RenewalRenovateApprovalVO
- Merge branch 'cc_20260427_rnewal' into cc_20250514_common_bak
- feat:招商副总裁
- Merge branch 'cc_20260427_rnewal' into cc_20250514_common_bak
# Conflicts:
#	coolstore-partner-common/src/main/java/com/cool/store/enums/point/ShopSubStageStatusEnum.java
- feat:招商副总裁审核
- Merge branch 'cc_20260506_newsign' into cc_20250514_common_bak
- feat:费用单调整
- feat:招商经理
- feat:招商经理
- Merge branch 'cc_20260506_newsign' into cc_20250514_common_bak
- feat:费用调整
- Merge branch 'master' into cc_20260226_fix
- fix:bug修复
- fix:未开业门店试营业日期
- Merge branch 'cc_20260508_open_store_req' into cc_20250514_common_bak
# Conflicts:
#	coolstore-partner-dao/src/main/java/com/cool/store/dao/StoreDao.java
#	coolstore-partner-dao/src/main/java/com/cool/store/mapper/StoreMapper.java
#	coolstore-partner-dao/src/main/resources/mapper/StoreMapper.xml
#	coolstore-partner-web/src/main/java/com/cool/store/job/XxlJobHandler.java
- feat:新增审批
- fix:开业日期报备不同步门店状态
- Merge branch 'cc_20260508_open_store_req' into cc_20250514_common_bak
- fix:字段名称修改
- Merge branch 'cc_20250922_closeStore_w' into cc_20250514_common_bak
- fix:闭店中止新增审批记录
- Merge branch 'cc_20250922_closeStore_w' into cc_20250514_common_bak
- feat:费用调整单
- feat:招商大区总审核 或者 分部内勤审核 其他状态不能审核
- Merge branch 'cc_20260506_newsign' into cc_20250514_common_bak
- feat:调整单
- feat:SHOP_SUB_STAGE_STATUS_150_5
- Merge branch 'cc_20260506_newsign' into cc_20250514_common_bak
- fix:试营业测试接口
- Merge remote-tracking branch 'origin/cc_20250514_common_bak' into cc_20250514_common_bak
- Merge branch 'master' into cc_20250514_common_bak
- feat:page
- feat:自动分账
- Merge branch 'master' into cc_20250514_common_bak
- fix:私域二维码门店绑定关系缓存改为7天
- Merge branch 'cc_20260226_fix' into cc_20250514_common_bak
- feat:getAuthRegionIdAndSubRegionIdExcludeStoreByUserId 优化开店管理查询
- Merge branch 'cc_20260509_fix' into cc_20250514_common_bak
- fix:修改门店开业日期判断条件修改
- Merge branch 'cc_20260508_open_store_req' into cc_20250514_common_bak
- feat:填写添加门店
- feat:建店代办处理
- Merge branch 'cc_20260506_newsign' into cc_20250514_common_bak
- Merge branch 'cc_20260508_adjustment' into cc_20250514_common_bak
- feat:userAuthMappingService
- feat:addShopDecorationLog
- Merge branch 'cc_20260506_newsign' into cc_20250514_common_bak
- feat:待采购确认 审批流程
- feat:问题修复
- Merge branch 'cc_20260511_fix' into cc_20250514_common_bak
# Conflicts:
#	coolstore-partner-dao/src/main/java/com/cool/store/dao/ShopStageInfoDAO.java
#	coolstore-partner-dao/src/main/java/com/cool/store/dao/StoreDao.java
#	coolstore-partner-dao/src/main/java/com/cool/store/mapper/ShopStageInfoMapper.java
#	coolstore-partner-dao/src/main/java/com/cool/store/mapper/StoreMapper.java
#	coolstore-partner-dao/src/main/resources/mapper/ShopStageInfoMapper.xml
#	coolstore-partner-dao/src/main/resources/mapper/StoreMapper.xml
#	coolstore-partner-service/src/main/java/com/cool/store/service/impl/PointServiceImpl.java
#	coolstore-partner-service/src/main/java/com/cool/store/service/impl/SignFranchiseServiceImpl.java
#	coolstore-partner-web/src/main/java/com/cool/store/job/XxlJobHandler.java
- feat:问题修复
- feat:问题修复
- feat:流水查询条件
- Merge branch 'master' into cc_20260508_adjustment
- feat:费用流水筛选条件
- fix:歇业管理逻辑修改
- Merge branch 'cc_20260508_adjustment' into cc_20250514_common_bak
- feat:getAdjustAmount
- Merge branch 'cc_20260511_close_up_modify' into cc_20260408_close_up
# Conflicts:
#	coolstore-partner-common/src/main/java/com/cool/store/enums/ErrorCodeEnum.java
#	coolstore-partner-common/src/main/java/com/cool/store/enums/RocketMqGroupEnum.java
#	coolstore-partner-common/src/main/java/com/cool/store/enums/RocketMqTagEnum.java
#	coolstore-partner-common/src/main/java/com/cool/store/enums/closeup/CloseUpPlatformEnum.java
#	coolstore-partner-dao/src/main/java/com/cool/store/dao/closeup/CloseUpPlatformDAO.java
#	coolstore-partner-dao/src/main/java/com/cool/store/mapper/StoreMapper.java
#	coolstore-partner-dao/src/main/java/com/cool/store/mapper/closeup/CloseUpPlatformMapper.java
#	coolstore-partner-dao/src/main/resources/mapper/StoreMapper.xml
#	coolstore-partner-dao/src/main/resources/mapper/closeup/CloseUpApplyFormMapper.xml
#	coolstore-partner-dao/src/main/resources/mapper/closeup/CloseUpPlatformMapper.xml
#	coolstore-partner-model/src/main/java/com/cool/store/entity/closeup/CloseUpApplyFormDO.java
#	coolstore-partner-model/src/main/java/com/cool/store/entity/closeup/CloseUpPlatformDO.java
#	coolstore-partner-service/src/main/java/com/cool/store/mq/consumer/ConsumerClient.java
#	coolstore-partner-service/src/main/java/com/cool/store/service/closeup/CloseUpService.java
#	coolstore-partner-service/src/main/java/com/cool/store/service/closeup/impl/CloseUpServiceImpl.java
#	coolstore-partner-web/src/main/java/com/cool/store/controller/webb/PCTestController.java
#	coolstore-partner-web/src/main/java/com/cool/store/job/XxlJobHandler.java
#	coolstore-partner-web/src/main/resources/application-ab.properties
#	coolstore-partner-web/src/main/resources/application-local.properties
#	coolstore-partner-web/src/main/resources/application-online.properties
#	coolstore-partner-web/src/main/resources/application-test.properties
- fix:合并冲突
- Merge branch 'cc_20260408_close_up' into cc_20250514_common_bak
# Conflicts:
#	coolstore-partner-common/src/main/java/com/cool/store/enums/ErrorCodeEnum.java
#	coolstore-partner-dao/src/main/java/com/cool/store/dao/StoreDao.java
#	coolstore-partner-service/src/main/java/com/cool/store/service/closeup/impl/CloseUpServiceImpl.java
#	coolstore-partner-web/src/main/java/com/cool/store/controller/webb/PCTestController.java
#	coolstore-partner-web/src/main/java/com/cool/store/job/XxlJobHandler.java
- fix:合并冲突
- Merge branch 'cc_20260508_adjustment' into cc_20250514_common_bak
- Merge branch 'master' into cc_20260408_close_up
- fix:火码歇业时机修改
- Merge branch 'cc_20260408_close_up' into cc_20250514_common_bak
- feat:租赁合同新增审批记录
- Merge branch 'master' into cc_20250512_uploadRentContract
# Conflicts:
#	coolstore-partner-service/src/main/java/com/cool/store/service/closeup/impl/CloseUpServiceImpl.java
#	coolstore-partner-service/src/main/java/com/cool/store/service/impl/PointServiceImpl.java
#	coolstore-partner-web/src/main/java/com/cool/store/controller/webb/PCTestController.java
- feat:merge冲突
- feat:merge冲突
Signed-off-by: 正新 <accounts_6964c7bcd2a2c377c5bbd01b@mail.teambition.com>
Merged-by: 正新 <accounts_6964c7bcd2a2c377c5bbd01b@mail.teambition.com>
CR-link: https://codeup.aliyun.com/692ea314dec569489f6f167c/hangzhou/java/custom_zxjp/change/128
This commit is contained in:
@@ -34,4 +34,5 @@ public class WechatMpProperties {
|
||||
* 发送模板消息的URL
|
||||
*/
|
||||
private String sendTemplateMessageUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send";
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.cool.store.handler;
|
||||
|
||||
import com.alibaba.excel.write.handler.RowWriteHandler;
|
||||
import com.alibaba.excel.write.handler.WriteHandler;
|
||||
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
|
||||
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
|
||||
public class TitleWriteHandler implements RowWriteHandler {
|
||||
|
||||
private final String title;
|
||||
|
||||
public TitleWriteHandler(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex, Integer relativeRowIndex, Boolean isHead) {
|
||||
if (rowIndex == 0 && !isHead) {
|
||||
// 创建第一行(index=0)
|
||||
Sheet sheet = writeSheetHolder.getSheet();
|
||||
Row row = sheet.createRow(0);
|
||||
|
||||
// 创建单元格并设置标题内容
|
||||
Cell cell = row.createCell(0);
|
||||
cell.setCellValue(title);
|
||||
|
||||
// 合并第一行的所有列(假设最多有10列)
|
||||
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 9));
|
||||
|
||||
// 设置字体样式(可选)
|
||||
Workbook workbook = writeSheetHolder.getSheet().getWorkbook();
|
||||
CellStyle cellStyle = workbook.createCellStyle();
|
||||
Font font = workbook.createFont();
|
||||
font.setBold(true);
|
||||
font.setFontHeightInPoints((short) 16);
|
||||
cellStyle.setFont(font);
|
||||
cellStyle.setAlignment(HorizontalAlignment.CENTER);
|
||||
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
cell.setCellStyle(cellStyle);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer integer, Boolean aBoolean) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer integer, Boolean aBoolean) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -174,7 +174,9 @@ public class WalletHttpClientRest {
|
||||
throw new ServiceException(ErrorCodeEnum.WALLET_API_ERROR, msg);
|
||||
} else if (code == 610 || msg.equals("支付密码不正确")) {
|
||||
throw new ServiceException(ErrorCodeEnum.PASSWORD_ERROR);
|
||||
} else {
|
||||
} else if (code == 611) {
|
||||
throw new ServiceException(ErrorCodeEnum.WALLET_OPEN_ACCOUNT_NO_BALANCE);
|
||||
}else {
|
||||
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR,
|
||||
"code: " + code + ", msg: " + msg);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.cool.store.dto.wx.PhoneInfoDTO;
|
||||
import com.cool.store.enums.ErrorCodeEnum;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.mq.util.HttpRestTemplateService;
|
||||
import com.cool.store.utils.CommonContextUtil;
|
||||
import com.cool.store.utils.RedisUtilPool;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -16,6 +17,7 @@ import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author zhangchenbiao
|
||||
@@ -47,6 +49,11 @@ public class WechatRest {
|
||||
|
||||
String GET_MINIAPP_URL_LINK = "https://api.weixin.qq.com/wxa/generate_urllink?access_token=%s";
|
||||
|
||||
/**
|
||||
* 生成小程序二维码
|
||||
*/
|
||||
String GET_MINIAPP_QR_CODE = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s";
|
||||
|
||||
|
||||
public CodeSessionDTO miniProgramJsCodeSession(String appId, String secret, String jsCode){
|
||||
log.info("WechatRest#miniProgramJsCodeSession, jsCode:{}", jsCode);
|
||||
@@ -138,4 +145,44 @@ public class WechatRest {
|
||||
return null;
|
||||
}
|
||||
|
||||
public byte[] createQrCode(String accessToken, String page, String scene, String width) {
|
||||
String reqUrl = String.format(GET_MINIAPP_QR_CODE, accessToken);
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
body.put("page", page);
|
||||
body.put("scene", scene);
|
||||
body.put("env_version", CommonContextUtil.getProfileName().equals("online") ? "release" : "trial");
|
||||
if (StringUtils.isNotBlank(width)) {
|
||||
body.put("width", width);
|
||||
}
|
||||
try {
|
||||
// 直接使用 byte[] 接收二进制图片数据
|
||||
byte[] result = httpRestTemplateService.postForObject(reqUrl, body, byte[].class);
|
||||
if (result == null || result.length == 0) {
|
||||
log.error("二维码生成失败, 返回数据为空");
|
||||
return null;
|
||||
}
|
||||
// 检查是否是图片格式:PNG开头是 89 50 4E 47,JPEG开头是 FF D8 FF
|
||||
boolean isImage = (result.length > 4 &&
|
||||
// PNG: 89 50 4E 47 (即 0x89 'P' 'N' 'G')
|
||||
(result[0] == (byte) 0x89 && result[1] == 0x50 && result[2] == 0x4E && result[3] == 0x47) ||
|
||||
// JPEG: FF D8 FF
|
||||
(result[0] == (byte) 0xFF && result[1] == (byte) 0xD8 && result[2] == (byte) 0xFF));
|
||||
if (!isImage) {
|
||||
// 不是图片,说明返回的是错误JSON
|
||||
String response = new String(result);
|
||||
log.error("二维码生成失败, response:{}", response);
|
||||
JSONObject jsonObject = JSONObject.parseObject(response);
|
||||
if ("40001".equals(jsonObject.getString("errcode"))) {
|
||||
throw new ServiceException(ErrorCodeEnum.WX_ACCESS_TOKEN_INVALID);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return result;
|
||||
} catch (ServiceException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
log.error("二维码生成失败", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.cool.store.mq.consumer.listener.*;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Map;
|
||||
@@ -24,6 +25,7 @@ import java.util.Properties;
|
||||
* @date 2021-12-21 11:35
|
||||
*/
|
||||
@Configuration
|
||||
@Lazy
|
||||
public class ConsumerClient {
|
||||
|
||||
@Resource
|
||||
@@ -41,6 +43,10 @@ public class ConsumerClient {
|
||||
@Resource
|
||||
private TpPenaltyAppealListener tpPenaltyAppealListener;
|
||||
@Resource
|
||||
private ExamAutoSubmitListener examAutoSubmitListener;
|
||||
@Resource
|
||||
private ExamAutoEndListener examAutoEndListener;
|
||||
@Resource
|
||||
private CloseUpApplyStoreUpdateListener closeUpApplyStoreUpdateListener;
|
||||
@Resource
|
||||
private CloseUpPlanOpenStoreListener closeUpPlanOpenStoreListener;
|
||||
@@ -149,6 +155,32 @@ public class ConsumerClient {
|
||||
return consumerBean;
|
||||
}
|
||||
|
||||
@Bean(initMethod = "start", destroyMethod = "shutdown")
|
||||
public ConsumerBean examAutoSubmit() {
|
||||
RocketMqGroupEnum groupEnum = RocketMqGroupEnum.EXAM_AUTO_SUBMIT;
|
||||
ConsumerBean consumerBean = new ConsumerBean();
|
||||
//配置文件
|
||||
Properties properties = getCommonProperties(groupEnum);
|
||||
consumerBean.setProperties(properties);
|
||||
Map<Subscription, MessageListener> commonSubscriptionTable = getCommonSubscriptionTable(groupEnum, examAutoSubmitListener);
|
||||
//订阅多个topic如上面设置
|
||||
consumerBean.setSubscriptionTable(commonSubscriptionTable);
|
||||
return consumerBean;
|
||||
}
|
||||
|
||||
@Bean(initMethod = "start", destroyMethod = "shutdown")
|
||||
public ConsumerBean examAutoEnd() {
|
||||
RocketMqGroupEnum groupEnum = RocketMqGroupEnum.EXAM_AUTO_END;
|
||||
ConsumerBean consumerBean = new ConsumerBean();
|
||||
//配置文件
|
||||
Properties properties = getCommonProperties(groupEnum);
|
||||
consumerBean.setProperties(properties);
|
||||
Map<Subscription, MessageListener> commonSubscriptionTable = getCommonSubscriptionTable(groupEnum, examAutoEndListener);
|
||||
//订阅多个topic如上面设置
|
||||
consumerBean.setSubscriptionTable(commonSubscriptionTable);
|
||||
return consumerBean;
|
||||
}
|
||||
|
||||
@Bean(initMethod = "start", destroyMethod = "shutdown")
|
||||
public ConsumerBean closeUpApplyStoreUpdate() {
|
||||
RocketMqGroupEnum groupEnum = RocketMqGroupEnum.CLOSE_UP_APPLY_STORE_UPDATE;
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.cool.store.mq.consumer.listener;
|
||||
|
||||
import com.aliyun.openservices.ons.api.Action;
|
||||
import com.aliyun.openservices.ons.api.ConsumeContext;
|
||||
import com.aliyun.openservices.ons.api.Message;
|
||||
import com.aliyun.openservices.ons.api.MessageListener;
|
||||
import com.cool.store.constants.CommonConstants;
|
||||
import com.cool.store.service.exam.ExamInfoService;
|
||||
import com.cool.store.utils.RedisUtilPool;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 考试自动结束消费者监听器
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ExamAutoEndListener implements MessageListener {
|
||||
|
||||
@Resource
|
||||
private RedisUtilPool redisUtilPool;
|
||||
@Resource
|
||||
private ExamInfoService examInfoService;
|
||||
|
||||
@Override
|
||||
public Action consume(Message message, ConsumeContext context) {
|
||||
String text = new String(message.getBody());
|
||||
if (StringUtils.isBlank(text)) {
|
||||
log.info("消息体为空,tag:{},messageId:{}", message.getTag(), message.getMsgID());
|
||||
return Action.CommitMessage;
|
||||
}
|
||||
String lockKey = "ExamAutoEndListener:" + message.getMsgID();
|
||||
boolean lock = redisUtilPool.setNxExpire(lockKey, message.getMsgID(), CommonConstants.NORMAL_LOCK_TIMES);
|
||||
if (lock) {
|
||||
try {
|
||||
Long examId = Long.valueOf(text);
|
||||
examInfoService.autoEndExam(examId);
|
||||
} catch (Exception e) {
|
||||
log.error("ExamAutoEndListener consume error", e);
|
||||
return Action.ReconsumeLater;
|
||||
} finally {
|
||||
redisUtilPool.delKey(lockKey);
|
||||
}
|
||||
log.info("消费成功,tag:{},messageId:{},examId={}", message.getTag(), message.getMsgID(), text);
|
||||
return Action.CommitMessage;
|
||||
}
|
||||
return Action.ReconsumeLater;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.cool.store.mq.consumer.listener;
|
||||
|
||||
import com.aliyun.openservices.ons.api.Action;
|
||||
import com.aliyun.openservices.ons.api.ConsumeContext;
|
||||
import com.aliyun.openservices.ons.api.Message;
|
||||
import com.aliyun.openservices.ons.api.MessageListener;
|
||||
import com.cool.store.constants.CommonConstants;
|
||||
import com.cool.store.service.exam.ExamAttemptService;
|
||||
import com.cool.store.utils.RedisUtilPool;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 考试自动提交消费者监听器
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ExamAutoSubmitListener implements MessageListener {
|
||||
|
||||
@Resource
|
||||
private RedisUtilPool redisUtilPool;
|
||||
@Resource
|
||||
private ExamAttemptService examAttemptService;
|
||||
|
||||
@Override
|
||||
public Action consume(Message message, ConsumeContext context) {
|
||||
String text = new String(message.getBody());
|
||||
if (StringUtils.isBlank(text)) {
|
||||
log.info("消息体为空,tag:{},messageId:{}", message.getTag(), message.getMsgID());
|
||||
return Action.CommitMessage;
|
||||
}
|
||||
String lockKey = "ExamAutoSubmitListener:" + message.getMsgID();
|
||||
boolean lock = redisUtilPool.setNxExpire(lockKey, message.getMsgID(), CommonConstants.NORMAL_LOCK_TIMES);
|
||||
if (lock) {
|
||||
try {
|
||||
Long attemptId = Long.valueOf(text);
|
||||
examAttemptService.autoSubmit(attemptId);
|
||||
} catch (Exception e) {
|
||||
log.error("ExamAutoSubmitListener consume error", e);
|
||||
return Action.ReconsumeLater;
|
||||
} finally {
|
||||
redisUtilPool.delKey(lockKey);
|
||||
}
|
||||
log.info("消费成功,tag:{},messageId:{},attemptId={}", message.getTag(), message.getMsgID(), text);
|
||||
return Action.CommitMessage;
|
||||
}
|
||||
return Action.ReconsumeLater;
|
||||
}
|
||||
}
|
||||
@@ -87,5 +87,11 @@ public interface AdjustmentOrderService {
|
||||
*/
|
||||
Long pageCount(AdjustmentOrderPageRequest request,LoginUserInfo user);
|
||||
|
||||
/**
|
||||
* 审批调整单
|
||||
* @param request 审批请求
|
||||
* @return 是否成功
|
||||
*/
|
||||
Boolean approval(AdjustmentApprovalRequest request);
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ public interface AuditOpeningOperationPlanService {
|
||||
* @Date: 2024/4/23
|
||||
* @description:审核方案
|
||||
*/
|
||||
|
||||
@Deprecated
|
||||
Boolean auditPlan(OpeningOperationPlanAuditRequest openingOperationPlanAuditRequest, LoginUserInfo user);
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import com.cool.store.request.*;
|
||||
import com.cool.store.request.order.PCStoreOrderQueryRequest;
|
||||
import com.cool.store.request.tp.TpScoreJournalQueryRequest;
|
||||
import com.cool.store.request.visit.VisitRecordQueryRequest;
|
||||
import com.cool.store.request.visit.VisitRecordQueryRequest;
|
||||
import com.cool.store.response.BranchShopResponse;
|
||||
import com.cool.store.response.FranchiseReportResponse;
|
||||
import com.cool.store.response.ShopReportResponse;
|
||||
@@ -42,6 +41,7 @@ public interface ExportRealizeService {
|
||||
void exportVisitRecord(VisitRecordQueryRequest request, ImportTaskDO importTaskDO);
|
||||
|
||||
void exportOrderRecord(PCStoreOrderQueryRequest request, ImportTaskDO importTaskDO);
|
||||
|
||||
void exportPoint(AllPointPageRequest request, ImportTaskDO importTaskDO);
|
||||
void myExportPoint(PointPageRequest request, String userId, ImportTaskDO importTaskDO);
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ import com.cool.store.request.order.PCStoreOrderQueryRequest;
|
||||
import com.cool.store.request.tp.TpScoreJournalQueryRequest;
|
||||
import com.cool.store.request.visit.VisitRecordQueryRequest;
|
||||
import com.cool.store.request.visit.VisitRecordQueryRequest;
|
||||
import com.cool.store.request.order.PCStoreOrderQueryRequest;
|
||||
import com.cool.store.request.visit.VisitRecordQueryRequest;
|
||||
|
||||
/**
|
||||
* @Author: WangShuo
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.cool.store.service;
|
||||
|
||||
import com.cool.store.context.LoginUserInfo;
|
||||
import com.cool.store.dto.ImportReceivingBankDTO;
|
||||
import com.cool.store.entity.ImportTaskDO;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author: WangShuo
|
||||
* @Date: 2025/06/19/10:29
|
||||
* @Version 1.0
|
||||
* @注释:
|
||||
*/
|
||||
public interface ImportService {
|
||||
/**
|
||||
* 导入银行配置信息
|
||||
* @param list
|
||||
* @param originalFilename
|
||||
* @param userId
|
||||
* @param task
|
||||
* @return
|
||||
*/
|
||||
Boolean importReceivingBank(List<ImportReceivingBankDTO> list, String originalFilename, String userId,
|
||||
ImportTaskDO task);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.cool.store.service;
|
||||
|
||||
/**
|
||||
* 猎聘-招商 业务servive
|
||||
* @Author suzhuhong
|
||||
* @Date 2025/5/26 19:26
|
||||
* @Version 1.0
|
||||
*/
|
||||
public interface LiePinService {
|
||||
|
||||
|
||||
/**
|
||||
* 获取小程序跳转链接
|
||||
* @param shopCode
|
||||
* @return mobile 当前登录人手机号
|
||||
*/
|
||||
String getJumpUrl(String shopCode,String mobile,String userName);
|
||||
|
||||
/**
|
||||
* 推送门店到猎聘
|
||||
* @param shopCode
|
||||
* @return
|
||||
*/
|
||||
Long pushStoreToLiePin(String shopCode);
|
||||
|
||||
/**
|
||||
* 推送门店人员到对应门店
|
||||
* @param shopCode
|
||||
* @param mobile
|
||||
* @param userName
|
||||
* @return
|
||||
*/
|
||||
Long pushStoreEmpToLiePin(String shopCode,String mobile,String userName);
|
||||
|
||||
|
||||
}
|
||||
@@ -4,9 +4,12 @@ import com.cool.store.context.CurrentUserHolder;
|
||||
import com.cool.store.context.LoginUserInfo;
|
||||
import com.cool.store.dto.AmountDTO;
|
||||
import com.cool.store.entity.LinePayDO;
|
||||
import com.cool.store.request.FranchiseFeePayOnlineRequest;
|
||||
import com.cool.store.request.LinePaySubmitRequest;
|
||||
import com.cool.store.request.xgj.OnlinePayInfoRequest;
|
||||
import com.cool.store.request.xgj.ReceiptCallBackRequest;
|
||||
import com.cool.store.response.FranchiseFeePayInfoResponse;
|
||||
import com.cool.store.response.FranchiseFeePayOnlineResponse;
|
||||
import com.cool.store.response.bigdata.ApiResponse;
|
||||
import com.cool.store.vo.LinePayVO;
|
||||
import com.cool.store.vo.PartnerUserInfoVO;
|
||||
@@ -51,7 +54,13 @@ public interface LinePayService {
|
||||
*/
|
||||
Boolean pushPayInfo(Long shopId, LinePayDO linePayDO);
|
||||
|
||||
Boolean onlinePushPayInfo(Long shopId, LinePayDO linePayDO);
|
||||
|
||||
ApiResponse<Boolean> ReceiptCallBack(ReceiptCallBackRequest request);
|
||||
|
||||
FranchiseFeePayOnlineResponse franchiseFeePayOnline(FranchiseFeePayOnlineRequest request, String userId);
|
||||
|
||||
ApiResponse<Boolean> changeOnlinePayInfo(OnlinePayInfoRequest onlinePayInfoRequest);
|
||||
|
||||
Boolean cancelFranchiseFeePayOnline(Long id,String userId);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.cool.store.service;
|
||||
import com.cool.store.dto.BatchStatusRefreshDTO;
|
||||
import com.cool.store.dto.StatusRefreshDTO;
|
||||
import com.cool.store.request.xgj.FranchiseFeeCallBackRequest;
|
||||
import com.cool.store.request.xgj.OnlinePayInfoRequest;
|
||||
import com.cool.store.request.xgj.ReceiptCallBackRequest;
|
||||
import com.cool.store.response.bigdata.ApiResponse;
|
||||
|
||||
@@ -21,9 +22,25 @@ public interface OpenApiService {
|
||||
*/
|
||||
Boolean statusRefresh(StatusRefreshDTO statusRefreshDTO);
|
||||
|
||||
|
||||
/**
|
||||
* 线下支付收款单 回调
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
ApiResponse<Boolean> changeReceiptStatus(ReceiptCallBackRequest request);
|
||||
|
||||
/**
|
||||
* 账单收款状态及缴款金额
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
ApiResponse<Boolean> changePaymentStatus(FranchiseFeeCallBackRequest request);
|
||||
|
||||
/**
|
||||
* 线上支付 回调收款单信息 包括交易流水号 支付时间等
|
||||
* @param onlinePayInfoRequest
|
||||
* @return
|
||||
*/
|
||||
ApiResponse<Boolean> changeOnlinePayInfo(OnlinePayInfoRequest onlinePayInfoRequest);
|
||||
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ import com.cool.store.vo.OpeningOperationPlanListVO;
|
||||
import com.cool.store.vo.OpeningOperationPlanVO;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Auther: WangShuo
|
||||
|
||||
@@ -21,4 +21,13 @@ public interface OperationLogService {
|
||||
List<AuditInfoResponse> getAuditInfo(Long shopId,List<Integer> shopSubStageList);
|
||||
|
||||
Boolean batchUpdateProcessed( List<OperationLogDO> operationLogs,Long audit , String userId, String reason);
|
||||
|
||||
/**
|
||||
* 后期新增的阶段数据 对于处在阶段中的数据 可能没有提前生成审批记录 直接插入数据 且是审批完成状态
|
||||
* @param subStageStatusEnum
|
||||
* @param audit
|
||||
* @param userId
|
||||
* @param reason
|
||||
*/
|
||||
Boolean handleApproveTimeNoDate(Long shopId,ShopSubStageStatusEnum subStageStatusEnum,Long audit , String userId, String reason);
|
||||
}
|
||||
|
||||
@@ -304,7 +304,7 @@ public interface PointService {
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
Integer uploadRentContract(AddRentContractRequest request);
|
||||
Integer uploadRentContract(AddRentContractRequest request,String userId,String userName);
|
||||
|
||||
/**
|
||||
* 获取租赁合同详情
|
||||
|
||||
@@ -42,6 +42,11 @@ public interface PreparationService {
|
||||
*/
|
||||
void contractAndBuildStoreCompletion(Long shopId);
|
||||
|
||||
/**
|
||||
* 装修完成
|
||||
* @param shopId
|
||||
*/
|
||||
void decorationCompletion(Long shopId) ;
|
||||
|
||||
/**
|
||||
* 建店完成
|
||||
|
||||
@@ -4,7 +4,9 @@ import com.cool.store.dto.*;
|
||||
import com.cool.store.dto.contract.ContractCallbackDTO;
|
||||
import com.cool.store.request.AuditRequest;
|
||||
import com.cool.store.request.ZxjpApiRequest;
|
||||
import com.cool.store.request.xgj.CancelPayRequest;
|
||||
import com.cool.store.request.xgj.PushFranchiseFeeRequest;
|
||||
import com.cool.store.request.xgj.ReceiptOnlineRequest;
|
||||
import com.cool.store.request.xgj.ReceiptRequest;
|
||||
import com.cool.store.response.XgjAccessTokenDTO;
|
||||
|
||||
@@ -38,6 +40,12 @@ public interface PushService {
|
||||
* @return
|
||||
*/
|
||||
Boolean pushReceiptToXGJ(ReceiptRequest receiptRequest);
|
||||
/**
|
||||
* 推送线上支付 收款单到新管家
|
||||
* @param receiptRequest
|
||||
* @return
|
||||
*/
|
||||
Boolean pushOnlineReceiptToXGJ(ReceiptOnlineRequest receiptRequest);
|
||||
|
||||
/**
|
||||
* 推送数据到下游系统 POS
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.cool.store.service;
|
||||
|
||||
import com.cool.store.request.ReceivingBankListRequest;
|
||||
import com.cool.store.request.ReceivingBankRequest;
|
||||
import com.cool.store.response.ReceivingBankResponse;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
/**
|
||||
* @Author: WangShuo
|
||||
* @Date: 2025/06/18/17:53
|
||||
* @Version 1.0
|
||||
* @注释:
|
||||
*/
|
||||
public interface ReceivingBankService {
|
||||
|
||||
Integer submit(ReceivingBankRequest request,String userId);
|
||||
|
||||
PageInfo<ReceivingBankResponse> getByFranchiseBrandAndRegionId(ReceivingBankListRequest request);
|
||||
|
||||
//获取该门店的收款方信息
|
||||
ReceivingBankResponse getByShopId(Long shopId);
|
||||
}
|
||||
@@ -62,4 +62,8 @@ public interface StoreService {
|
||||
*/
|
||||
List<StoreUserDTO> getStoreUserPositionList(String storeId, String userName);
|
||||
|
||||
/**
|
||||
* 处理门店报表
|
||||
*/
|
||||
void saveStoreReport(String date);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,11 @@ package com.cool.store.service;
|
||||
|
||||
import com.cool.store.dto.FoodTokenDTO;
|
||||
import com.cool.store.dto.recipe.RecipeSpLaunchDTO;
|
||||
import com.cool.store.dto.GetAccessTokenDTO;
|
||||
import com.cool.store.dto.food.DishesDTO;
|
||||
|
||||
import java.util.List;
|
||||
import com.cool.store.dto.store.StoreUserPositionDTO;
|
||||
import com.cool.store.dto.store.StoreUserUpdateDTO;
|
||||
import com.cool.store.request.recipe.RevenueDataRequest;
|
||||
import com.cool.store.request.recipe.SalesVolumeDayRequest;
|
||||
@@ -26,6 +31,16 @@ public interface ThirdFoodService {
|
||||
*/
|
||||
String getFoodToken(FoodTokenDTO dto);
|
||||
|
||||
/**
|
||||
* 查询已购菜品
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
List<DishesDTO> getPurchasedDishesList(FoodTokenDTO dto);
|
||||
|
||||
List<DishesDTO> getMyDesignDishesList(FoodTokenDTO dto);
|
||||
|
||||
|
||||
/**
|
||||
* 推送门店人员信息
|
||||
* @param storeUserUpdateDTOList
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.cool.store.service;
|
||||
|
||||
import com.cool.store.request.liepin.AddStoreEmpRequest;
|
||||
import com.cool.store.request.liepin.AddStoreRequest;
|
||||
import com.cool.store.request.liepin.GetAccessTokenRequest;
|
||||
import com.cool.store.request.liepin.GetPathRequest;
|
||||
import com.cool.store.response.liepin.PathResponse;
|
||||
|
||||
/**
|
||||
* @Author suzhuhong
|
||||
* @Date 2025/5/20 15:33
|
||||
* @Version 1.0
|
||||
*/
|
||||
public interface ThirdLiePinService {
|
||||
|
||||
|
||||
/**
|
||||
* 有效期30天,调用接口时拼接在链接后面
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
String getAccessToken(GetAccessTokenRequest request);
|
||||
|
||||
/**
|
||||
* 新增门店
|
||||
* @param addStoreRequest
|
||||
* @return
|
||||
*/
|
||||
Long addStoreToLiePin(AddStoreRequest addStoreRequest);
|
||||
|
||||
/**
|
||||
* 新增门店成员
|
||||
* @param addStoreEmpRequest
|
||||
* @return
|
||||
*/
|
||||
Long addStoreEmp(AddStoreEmpRequest addStoreEmpRequest);
|
||||
|
||||
/**
|
||||
* 获取小程序调整链接
|
||||
* @param getPathRequest
|
||||
* @return
|
||||
*/
|
||||
PathResponse getPath(GetPathRequest getPathRequest);
|
||||
|
||||
/**
|
||||
* 上传图片返回地址 只有该地址薪超人能解析
|
||||
* @param ossUrl
|
||||
* @return
|
||||
*/
|
||||
String getFilePath(String ossUrl);
|
||||
|
||||
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
package com.cool.store.service;
|
||||
|
||||
import com.cool.store.dto.BigRegionUserListDTO;
|
||||
import com.cool.store.dto.UserDTO;
|
||||
import com.cool.store.entity.EnterpriseUserDO;
|
||||
import com.cool.store.entity.UserAuthMappingDO;
|
||||
import com.cool.store.enums.UserRoleEnum;
|
||||
import com.cool.store.request.SysRoleRequest;
|
||||
import com.cool.store.response.bigdata.ApiResponse;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
import java.util.List;
|
||||
@@ -132,4 +134,10 @@ public interface UserAuthMappingService {
|
||||
* @return
|
||||
*/
|
||||
List<EnterpriseUserDO> findUserListByRole(SysRoleRequest request,Boolean flag);
|
||||
|
||||
/**
|
||||
* 查询所有大区指定角色的 用户
|
||||
* @return
|
||||
*/
|
||||
ApiResponse<List<BigRegionUserListDTO>> getAllBigRegionSpecialRoleUserList(String storeCode, UserRoleEnum userRoleEnum);
|
||||
}
|
||||
|
||||
@@ -43,4 +43,13 @@ public interface WechatMiniAppService {
|
||||
* @return 用户信息VO
|
||||
*/
|
||||
PartnerUserInfoVO getUserInfoByShortTermToken(String token);
|
||||
|
||||
/**
|
||||
* 生成微信小程序二维码
|
||||
* @param page 页面路径,路径前不带/
|
||||
* @param scene 参数,必填
|
||||
* @param width 二维码的宽度
|
||||
* @return 二维码图片路径
|
||||
*/
|
||||
String createQrCode(String page, String scene, String width);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,270 @@
|
||||
package com.cool.store.service;
|
||||
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.lang.TypeReference;
|
||||
import cn.hutool.core.lang.UUID;
|
||||
import cn.hutool.core.net.url.UrlQuery;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.cool.store.dto.liepin.XbbAppInfo;
|
||||
import com.cool.store.dto.liepin.XbbEncryptedData;
|
||||
import com.cool.store.enums.ErrorCodeEnum;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.request.liepin.XbbGetRequest;
|
||||
import com.cool.store.request.liepin.XbbPostRequest;
|
||||
import com.cool.store.response.liepin.XbbResponse;
|
||||
import com.cool.store.response.oppty.OpportunityApiResponse;
|
||||
import com.cool.store.utils.hire.XbbAesUtil;
|
||||
import com.cool.store.utils.hire.XbbSignatureInfo;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author sha.li
|
||||
* @since 2025-03-28 14:53
|
||||
*/
|
||||
@Slf4j
|
||||
public class XbbApiCaller {
|
||||
|
||||
private ObjectMapper objectMapper;
|
||||
private final String domain;
|
||||
private final String appId;
|
||||
private final String secretKey;
|
||||
private final String aesSecretKey;
|
||||
|
||||
public XbbApiCaller(String domain, String appId, String secretKey, String aesSecretKey,ObjectMapper objectMapper) {
|
||||
this.domain = domain;
|
||||
this.appId = appId;
|
||||
this.secretKey = secretKey;
|
||||
this.aesSecretKey = aesSecretKey;
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送get请求
|
||||
*/
|
||||
public <T> XbbResponse<T> get(XbbGetRequest request,
|
||||
Class<T> responseDataType,String token) {
|
||||
|
||||
XbbSignatureInfo xbbSignatureInfo = XbbSignatureInfo.createGet();
|
||||
xbbSignatureInfo.setAppId(getAppId());
|
||||
xbbSignatureInfo.setUri(request.getUri());
|
||||
xbbSignatureInfo.setQueryString(UrlQuery.of(request.getQueryParam()).toString());
|
||||
xbbSignatureInfo.setRequestPayload(null);
|
||||
xbbSignatureInfo.setNonce(UUID.randomUUID().toString(true));
|
||||
xbbSignatureInfo.setTimestamp(System.currentTimeMillis());
|
||||
xbbSignatureInfo.setAesSecretkey(getAesSecretKey());
|
||||
|
||||
String getUrlTemplate = "{domain}{uri}{queryString}";
|
||||
String url = StrUtil.format(getUrlTemplate, Dict.of(
|
||||
"domain", getDomain(),
|
||||
"uri", request.getUri(),
|
||||
"queryString", StrUtil.isBlank(xbbSignatureInfo.getQueryString()) ? "" : "?" + xbbSignatureInfo.getQueryString()
|
||||
));
|
||||
HttpRequest httpRequest = HttpUtil.createGet(url).timeout(request.getRequestTimeout());
|
||||
return sendRequest("",token, responseDataType, httpRequest, xbbSignatureInfo, request.isResponseDecrypt());
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送post请求
|
||||
*/
|
||||
public <T> XbbResponse<T> post(XbbPostRequest request, Class<T> responseDataType,String token) {
|
||||
|
||||
String requestBody;
|
||||
if (request.isRequestEncrypt()) {
|
||||
Dict encryptData = Dict.of("encrypt_data", XbbAesUtil.encrypt(request.getJsonString(), getAesSecretKey()));
|
||||
requestBody = JSONUtil.toJsonStr(encryptData);
|
||||
} else {
|
||||
requestBody = request.getJsonString();
|
||||
}
|
||||
XbbSignatureInfo xbbSignatureInfo = XbbSignatureInfo.createPost();
|
||||
xbbSignatureInfo.setAppId(getAppId());
|
||||
xbbSignatureInfo.setUri(request.getUri());
|
||||
xbbSignatureInfo.setQueryString(UrlQuery.of(request.getQueryParam()).toString());
|
||||
xbbSignatureInfo.setRequestPayload(requestBody.getBytes(StandardCharsets.UTF_8));
|
||||
xbbSignatureInfo.setNonce(UUID.randomUUID().toString(true));
|
||||
xbbSignatureInfo.setTimestamp(System.currentTimeMillis());
|
||||
xbbSignatureInfo.setAesSecretkey(getAesSecretKey());
|
||||
|
||||
String postUrlTemplate = "{domain}{uri}{queryString}";
|
||||
String url = StrUtil.format(postUrlTemplate, Dict.of(
|
||||
"domain", getDomain(),
|
||||
"uri", request.getUri(),
|
||||
"queryString", StrUtil.isBlank(xbbSignatureInfo.getQueryString()) ? "" : "?" + xbbSignatureInfo.getQueryString()
|
||||
));
|
||||
HttpRequest httpRequest = HttpUtil.createPost(url).timeout(request.getRequestTimeout());
|
||||
httpRequest.body(requestBody);
|
||||
log.info("url:{} , body:{} ", url,JSONObject.toJSONString(requestBody));
|
||||
return sendRequest(requestBody,token, responseDataType, httpRequest, xbbSignatureInfo, request.isResponseDecrypt());
|
||||
}
|
||||
|
||||
|
||||
private <T> XbbResponse<T> sendRequest(String requestBody,
|
||||
String token,
|
||||
Class<T> responseDataType,
|
||||
HttpRequest httpRequest,
|
||||
XbbSignatureInfo xbbSignatureInfo,
|
||||
boolean responseDecrypt) {
|
||||
httpRequest.header("Authorization", "Bearer " + token);
|
||||
httpRequest.header("Content-Type", "application/json");
|
||||
httpRequest.header("X-App-Id", xbbSignatureInfo.getAppId());
|
||||
httpRequest.header("X-Signature", xbbSignatureInfo.toSignature());
|
||||
httpRequest.header("X-SignatureMethod", "SHA256");
|
||||
httpRequest.header("X-Nonce", xbbSignatureInfo.getNonce());
|
||||
httpRequest.header("X-Timestamp", String.valueOf(xbbSignatureInfo.getTimestamp()));
|
||||
log.info("heads:{} ", JSONObject.toJSONString(httpRequest.headers()));
|
||||
// String post = generateCurlCommand("POST", httpRequest.getUrl(), httpRequest.headers(), requestBody);
|
||||
// log.info("===={}",post);
|
||||
try (HttpResponse httpResponse = httpRequest.execute()) {
|
||||
int httpResponseStatus = httpResponse.getStatus();
|
||||
//状态码校验
|
||||
if (httpResponseStatus != 200) {
|
||||
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR,"状态码"+httpResponseStatus);
|
||||
}
|
||||
String responseBody = httpResponse.body();
|
||||
logResponse(httpRequest.getUrl(),httpResponse.getStatus(),responseBody);
|
||||
if (responseDecrypt) {
|
||||
XbbResponse<XbbEncryptedData> response = JSONUtil.toBean(responseBody, new TypeReference<XbbResponse<XbbEncryptedData>>() {
|
||||
}, false);
|
||||
String dataStr = decrypt(response.getData().getEncryptData());
|
||||
T data = JSONUtil.toBean(dataStr, responseDataType);
|
||||
return new XbbResponse<T>()
|
||||
.setCode(response.getCode())
|
||||
.setMsg(response.getMsg())
|
||||
.setSuccess(response.isSuccess())
|
||||
.setData(data);
|
||||
}
|
||||
JavaType javaType = objectMapper.getTypeFactory()
|
||||
.constructParametricType(XbbResponse.class, responseDataType);
|
||||
XbbResponse<T> apiResponse = null;
|
||||
try {
|
||||
apiResponse = objectMapper.readValue(responseBody, javaType);
|
||||
} catch (Exception e) {
|
||||
log.info("数据转换异常:{}",e.getMessage());
|
||||
}
|
||||
//业务码校验
|
||||
if (apiResponse.getCode() != 2000) {
|
||||
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR,apiResponse.getMsg());
|
||||
}
|
||||
return apiResponse;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static String generateCurlCommand(String method,
|
||||
String url,
|
||||
Map<String, List<String>> headers,
|
||||
String body) {
|
||||
StringBuilder curlCommand = new StringBuilder("curl -X ").append(method.toUpperCase()).append(" \\\n");
|
||||
|
||||
// Add URL
|
||||
curlCommand.append(" '").append(url).append("' \\\n");
|
||||
|
||||
// Add headers
|
||||
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
|
||||
curlCommand.append(" -H '")
|
||||
.append(entry.getKey())
|
||||
.append(": ")
|
||||
.append(entry.getValue().get((0)))
|
||||
.append("' \\\n");
|
||||
}
|
||||
|
||||
// Add body if present
|
||||
if (body != null && !body.isEmpty()) {
|
||||
// Escape single quotes in the body
|
||||
String escapedBody = body.replace("'", "'\\''");
|
||||
curlCommand.append(" -d '").append(escapedBody).append("'");
|
||||
}
|
||||
|
||||
return curlCommand.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录请求日志
|
||||
*/
|
||||
private void logRequest(String url, Object requestBody) {
|
||||
if (log.isInfoEnabled()) {
|
||||
try {
|
||||
log.info("\n======= 请求开始 =======\n" +
|
||||
"API地址: {}\n" +
|
||||
"请求参数: {}\n" +
|
||||
"======= 请求结束 =======",
|
||||
url,
|
||||
objectMapper.writerWithDefaultPrettyPrinter()
|
||||
.writeValueAsString(requestBody));
|
||||
} catch (JsonProcessingException e) {
|
||||
log.warn("日志JSON序列化失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录响应日志
|
||||
*/
|
||||
private void logResponse(String url, int statusCode, String responseBody) {
|
||||
if (log.isInfoEnabled()) {
|
||||
try {
|
||||
// 尝试美化JSON输出
|
||||
Object json = objectMapper.readValue(responseBody, Object.class);
|
||||
String prettyResponse = objectMapper.writerWithDefaultPrettyPrinter()
|
||||
.writeValueAsString(json);
|
||||
|
||||
log.info("\n======= 响应开始 =======\n" +
|
||||
"API地址: {}\n" +
|
||||
"HTTP状态码: {}\n" +
|
||||
"响应内容: {}\n" +
|
||||
"======= 响应结束 =======",
|
||||
url,
|
||||
statusCode,
|
||||
prettyResponse);
|
||||
} catch (Exception e) {
|
||||
// 非JSON响应或解析失败时直接输出原始内容
|
||||
log.info("\n======= 响应开始 =======\n" +
|
||||
"API地址: {}\n" +
|
||||
"HTTP状态码: {}\n" +
|
||||
"原始响应: {}\n" +
|
||||
"======= 响应结束 =======",
|
||||
url,
|
||||
statusCode,
|
||||
responseBody);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String encrypt(String data) {
|
||||
return XbbAesUtil.encrypt(data, getAesSecretKey());
|
||||
}
|
||||
|
||||
private String decrypt(String encryptData) {
|
||||
return XbbAesUtil.decrypt(encryptData, getAesSecretKey());
|
||||
}
|
||||
|
||||
public String getDomain() {
|
||||
return domain;
|
||||
}
|
||||
|
||||
public String getAppId() {
|
||||
return appId;
|
||||
}
|
||||
|
||||
public String getSecretKey() {
|
||||
return secretKey;
|
||||
}
|
||||
|
||||
public String getAesSecretKey() {
|
||||
return aesSecretKey;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.cool.store.service.approval;
|
||||
|
||||
import com.cool.store.entity.approval.CommonApprovalLogDO;
|
||||
import com.cool.store.vo.approval.ApprovalGroupedVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface CommonApprovalLogService {
|
||||
|
||||
/**
|
||||
* 插入单条审批记录(提交场景)
|
||||
*/
|
||||
void insertSingleRecord(String applicationNo, String handleUserId, String handleUserName, String nodeCode, String nodeName);
|
||||
|
||||
/**
|
||||
* 批量插入审批记录(同一批次)
|
||||
*/
|
||||
void batchInsertApprovalRecords(String applicationNo, List<CommonApprovalLogDO> records);
|
||||
|
||||
/**
|
||||
* 更新节点审批状态(权限校验 + 可选生成下一节点)
|
||||
*/
|
||||
void updateNodeApprovalStatus(String applicationNo, String currentNodeCode,
|
||||
String result, String handleUserId, String handleUserName,
|
||||
String comment, boolean generateNextNode, Long regionId);
|
||||
|
||||
/**
|
||||
* 查询某个申请的所有审批记录(按版本号分组)
|
||||
*/
|
||||
ApprovalGroupedVO getApprovalRecordsGroupedByVersion(String applicationNo);
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
package com.cool.store.service.approval.impl;
|
||||
|
||||
import com.cool.store.dao.approval.CommonApprovalLogDAO;
|
||||
import com.cool.store.dao.EnterpriseUserDAO;
|
||||
import com.cool.store.entity.EnterpriseUserDO;
|
||||
import com.cool.store.entity.approval.CommonApprovalLogDO;
|
||||
import com.cool.store.enums.UserRoleEnum;
|
||||
import com.cool.store.enums.approval.ApprovalResultEnum;
|
||||
import com.cool.store.enums.renewal.RenewalNodeEnum;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.service.UserAuthMappingService;
|
||||
import com.cool.store.service.approval.CommonApprovalLogService;
|
||||
import com.cool.store.utils.GenerateNoUtil;
|
||||
import com.cool.store.utils.poi.DateUtils;
|
||||
import com.cool.store.vo.approval.ApprovalBatchVO;
|
||||
import com.cool.store.vo.approval.ApprovalGroupedVO;
|
||||
import com.cool.store.vo.approval.ApprovalHandleVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.ListUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class CommonApprovalLogServiceImpl implements CommonApprovalLogService {
|
||||
|
||||
private final CommonApprovalLogDAO commonApprovalLogDAO;
|
||||
private final UserAuthMappingService userAuthMappingService;
|
||||
private final EnterpriseUserDAO enterpriseUserDAO;
|
||||
|
||||
@Override
|
||||
public void insertSingleRecord(String applicationNo, String handleUserId, String handleUserName, String nodeCode, String nodeName) {
|
||||
commonApprovalLogDAO.addSubmitRecord(applicationNo, handleUserId, handleUserName, nodeCode, nodeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void batchInsertApprovalRecords(String applicationNo, List<CommonApprovalLogDO> records) {
|
||||
if (CollectionUtils.isEmpty(records)) {
|
||||
return;
|
||||
}
|
||||
Long version = GenerateNoUtil.generateVersion();
|
||||
records.forEach(r -> {
|
||||
r.setApplicationNo(applicationNo);
|
||||
r.setVersion(version);
|
||||
r.setStatus("2");
|
||||
r.setSubmitType(1);
|
||||
r.setOperateTime(new Date());
|
||||
r.setDeleted(0);
|
||||
});
|
||||
commonApprovalLogDAO.batchInsertApprovalRecords(records);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateNodeApprovalStatus(String applicationNo, String currentNodeCode,
|
||||
String result, String handleUserId, String handleUserName,
|
||||
String comment, boolean generateNextNode, Long regionId) {
|
||||
// 获取当前节点所有待处理记录
|
||||
List<CommonApprovalLogDO> pendingRecords = commonApprovalLogDAO.getPendingByApplicationNoAndNodeCode(applicationNo, currentNodeCode);
|
||||
|
||||
// 检查当前操作人是否在审批列表中,如果不在则新增
|
||||
boolean isCurrentUserInList = false;
|
||||
if (CollectionUtils.isNotEmpty(pendingRecords)) {
|
||||
isCurrentUserInList = pendingRecords.stream()
|
||||
.anyMatch(record -> handleUserId.equals(record.getHandleUserId()));
|
||||
}
|
||||
|
||||
if (!isCurrentUserInList) {
|
||||
// 新增当前操作人的审批记录
|
||||
String currentNodeCodeName = RenewalNodeEnum.getNameByCode(currentNodeCode);
|
||||
Long version = null ;
|
||||
if (CollectionUtils.isNotEmpty(pendingRecords)){
|
||||
version = pendingRecords.get(0).getVersion();
|
||||
}
|
||||
|
||||
CommonApprovalLogDO newRecord = CommonApprovalLogDO.builder()
|
||||
.applicationNo(applicationNo)
|
||||
.nodeCode(currentNodeCode)
|
||||
.nodeName(currentNodeCodeName)
|
||||
.handleUserId(handleUserId)
|
||||
.handleUserName(handleUserName)
|
||||
.status("2")
|
||||
.submitType(1)
|
||||
.deleted(0)
|
||||
.operateTime(new Date())
|
||||
.build();
|
||||
commonApprovalLogDAO.addApproveRecord(newRecord.getApplicationNo(), newRecord.getNodeCode(),
|
||||
newRecord.getNodeName(), newRecord.getHandleUserId(), newRecord.getHandleUserName(),version);
|
||||
// 重新获取待处理记录
|
||||
pendingRecords = commonApprovalLogDAO.getPendingByApplicationNoAndNodeCode(applicationNo, currentNodeCode);
|
||||
}
|
||||
|
||||
// 当前节点所有审批人标记为已处理
|
||||
if (CollectionUtils.isNotEmpty(pendingRecords)) {
|
||||
Date now = new Date();
|
||||
for (CommonApprovalLogDO record : pendingRecords) {
|
||||
record.setStatus("1");
|
||||
record.setComment(comment);
|
||||
record.setOperateTime(now);
|
||||
// 仅当前操作人记录实际处理人信息
|
||||
if (record.getHandleUserId() != null && record.getHandleUserId().equals(handleUserId)) {
|
||||
record.setResult(result);
|
||||
}
|
||||
}
|
||||
commonApprovalLogDAO.batchUpdateRecords(pendingRecords);
|
||||
}
|
||||
|
||||
// 通过时生成下一节点
|
||||
if (generateNextNode && ApprovalResultEnum.PASS.getResult().equals(result)) {
|
||||
String nextNodeCode = RenewalNodeEnum.getNextNode(currentNodeCode);
|
||||
if (nextNodeCode != null) {
|
||||
RenewalNodeEnum nextNode = RenewalNodeEnum.getByCode(nextNodeCode);
|
||||
if (nextNode != null) {
|
||||
// 获取下一节点审批人
|
||||
List<String> auditUserIds = getAuditUserIds(regionId, nextNodeCode);
|
||||
List<CommonApprovalLogDO> nextRecords = new ArrayList<>();
|
||||
for (String userId : auditUserIds) {
|
||||
EnterpriseUserDO user = enterpriseUserDAO.getUserInfoById(userId);
|
||||
String userName = user != null ? user.getName() : "";
|
||||
CommonApprovalLogDO record = CommonApprovalLogDO.builder()
|
||||
.nodeCode(nextNodeCode)
|
||||
.nodeName(nextNode.getName())
|
||||
.handleUserId(userId)
|
||||
.handleUserName(userName)
|
||||
.build();
|
||||
nextRecords.add(record);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(nextRecords)) {
|
||||
batchInsertApprovalRecords(applicationNo, nextRecords);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApprovalGroupedVO getApprovalRecordsGroupedByVersion(String applicationNo) {
|
||||
List<CommonApprovalLogDO> allRecords = commonApprovalLogDAO.getByApplicationNo(applicationNo);
|
||||
ApprovalGroupedVO result = new ApprovalGroupedVO();
|
||||
result.setApplicationNo(applicationNo);
|
||||
|
||||
if (CollectionUtils.isEmpty(allRecords)) {
|
||||
result.setBatches(new ArrayList<>());
|
||||
return result;
|
||||
}
|
||||
|
||||
// 按version分组
|
||||
Map<Long, List<CommonApprovalLogDO>> versionGroups = allRecords.stream()
|
||||
.collect(Collectors.groupingBy(CommonApprovalLogDO::getVersion, LinkedHashMap::new, Collectors.toList()));
|
||||
|
||||
// 按nodeCode分组构建批次
|
||||
List<ApprovalBatchVO> batches = new ArrayList<>();
|
||||
for (Map.Entry<Long, List<CommonApprovalLogDO>> versionEntry : versionGroups.entrySet()) {
|
||||
Long version = versionEntry.getKey();
|
||||
List<CommonApprovalLogDO> versionRecords = versionEntry.getValue();
|
||||
|
||||
// 按nodeCode分组
|
||||
Map<String, List<CommonApprovalLogDO>> nodeGroups = versionRecords.stream()
|
||||
.collect(Collectors.groupingBy(CommonApprovalLogDO::getNodeCode, LinkedHashMap::new, Collectors.toList()));
|
||||
|
||||
for (Map.Entry<String, List<CommonApprovalLogDO>> nodeEntry : nodeGroups.entrySet()) {
|
||||
String nodeCode = nodeEntry.getKey();
|
||||
List<CommonApprovalLogDO> nodeRecords = nodeEntry.getValue();
|
||||
|
||||
ApprovalBatchVO batchVO = new ApprovalBatchVO();
|
||||
batchVO.setVersion(version);
|
||||
batchVO.setNodeCode(nodeCode);
|
||||
// 取第一个记录的nodeName
|
||||
batchVO.setNodeName(nodeRecords.get(0).getNodeName());
|
||||
|
||||
List<ApprovalHandleVO> handleList = nodeRecords.stream().map(r -> {
|
||||
ApprovalHandleVO handleVO = new ApprovalHandleVO();
|
||||
handleVO.setHandleUserId(r.getHandleUserId());
|
||||
handleVO.setHandleUserName(r.getHandleUserName());
|
||||
handleVO.setStatus(r.getStatus());
|
||||
handleVO.setResult(r.getResult());
|
||||
handleVO.setComment(r.getComment());
|
||||
handleVO.setSubmitType(r.getSubmitType());
|
||||
handleVO.setOperateTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,r.getOperateTime()));
|
||||
return handleVO;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
batchVO.setHandleUserIdList(handleList);
|
||||
batches.add(batchVO);
|
||||
}
|
||||
}
|
||||
|
||||
result.setBatches(batches);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据节点code获取对应的审批人ID列表
|
||||
*/
|
||||
private List<String> getAuditUserIds(Long regionId, String nodeCode) {
|
||||
UserRoleEnum roleEnum;
|
||||
switch (nodeCode) {
|
||||
case "20":
|
||||
roleEnum = UserRoleEnum.SUPERVISION;
|
||||
break;
|
||||
case "25":
|
||||
roleEnum = UserRoleEnum.OPERATION_GENERAL_CONSULTANT;
|
||||
break;
|
||||
case "30":
|
||||
roleEnum = UserRoleEnum.ENGINEER_DEP_MANAGER;
|
||||
break;
|
||||
default:
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<EnterpriseUserDO> users = userAuthMappingService.getAllUserByRoleEnumAndRegionId(roleEnum, regionId);
|
||||
return ListUtils.emptyIfNull(users).stream()
|
||||
.map(EnterpriseUserDO::getUserId)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,14 @@ package com.cool.store.service.close;
|
||||
|
||||
import com.cool.store.dto.close.CloseStoreMkUserDTO;
|
||||
import com.cool.store.dto.xgj.XgjBranchBankDTO;
|
||||
import com.cool.store.request.close.refund.CloseStoreRefundAddRequest;
|
||||
import com.cool.store.request.close.refund.CloseStoreRefundQueryRequest;
|
||||
import com.cool.store.request.close.refund.CloseStoreRefundSkipRequest;
|
||||
import com.cool.store.request.close.refund.CloseStoreRefundUpdateRequest;
|
||||
import com.cool.store.dto.xgj.XgjPartnerPageDTO;
|
||||
import com.cool.store.entity.CloseStoreRefundInfoDO;
|
||||
import com.cool.store.request.close.refund.*;
|
||||
import com.cool.store.request.xgj.XgjBankQueryRequest;
|
||||
import com.cool.store.request.close.refund.CloseStoreRefundAddRequest;
|
||||
import com.cool.store.request.close.refund.CloseStoreRefundQueryRequest;
|
||||
import com.cool.store.request.close.refund.CloseStoreRefundSkipRequest;
|
||||
import com.cool.store.request.close.refund.CloseStoreRefundUpdateRequest;
|
||||
import com.cool.store.vo.close.refund.CloseStoreRefundDetailVO;
|
||||
import com.cool.store.vo.close.refund.CloseStoreRefundListVO;
|
||||
import com.cool.store.vo.close.refund.CloseStoreRefundSimpleVO;
|
||||
|
||||
@@ -20,6 +20,11 @@ import com.cool.store.enums.close.CloseStoreSubStageStatusEnum;
|
||||
import com.cool.store.enums.close.RefundPayStatusEnum;
|
||||
import com.cool.store.enums.close.XgjRefundPayStatusEnum;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.request.close.refund.*;
|
||||
import com.cool.store.request.xgj.XgjPartnerQueryRequest;
|
||||
import com.cool.store.request.xgj.XgjPaymentRequest;
|
||||
import com.cool.store.request.xgj.XgjReimburseRequest;
|
||||
import com.cool.store.request.xgj.XgjSavePartnerRequest;
|
||||
import com.cool.store.request.close.refund.CloseStoreRefundAddRequest;
|
||||
import com.cool.store.request.close.refund.CloseStoreRefundQueryRequest;
|
||||
import com.cool.store.request.close.refund.CloseStoreRefundSkipRequest;
|
||||
|
||||
@@ -503,7 +503,8 @@ public class CloseUpServiceImpl implements CloseUpService {
|
||||
List<CloseUpPlatformDO> unClosePlatformList = list.stream()
|
||||
.filter(platformDO -> platformDO.getStatus().equals(0)
|
||||
&& platformDO.getType().equals(1)
|
||||
&& !(new Date()).before(platformDO.getTaskStartDate()))
|
||||
&& !(new Date()).before(platformDO.getTaskStartDate())
|
||||
&& Objects.nonNull(CloseUpPlatformEnum.getPlatformCodeByCode(platformDO.getCode())))
|
||||
.collect(Collectors.toList());
|
||||
if (CollectionUtils.isEmpty(unClosePlatformList)) {
|
||||
log.info("未处理的自动关闭平台为空");
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.cool.store.service.contract;
|
||||
|
||||
import com.cool.store.request.contract.ContractMasterQueryRequest;
|
||||
import com.cool.store.vo.contract.ContractMasterDetailVO;
|
||||
import com.cool.store.vo.contract.ContractMasterListVO;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
public interface ContractMasterService {
|
||||
|
||||
PageInfo<ContractMasterListVO> queryContractMasterList(ContractMasterQueryRequest request);
|
||||
|
||||
ContractMasterDetailVO getContractMasterDetail(Long contractId);
|
||||
|
||||
Boolean importContractAndCost(MultipartFile file);
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
package com.cool.store.service.contract.impl;
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.cool.store.constants.RedisConstant;
|
||||
import com.cool.store.context.CurrentUserHolder;
|
||||
import com.cool.store.context.LoginUserInfo;
|
||||
import com.cool.store.dao.EnterpriseUserDAO;
|
||||
import com.cool.store.dao.StoreDao;
|
||||
import com.cool.store.dao.contract.ContractCostDAO;
|
||||
import com.cool.store.dao.contract.ContractMasterDAO;
|
||||
import com.cool.store.entity.ImportTaskDO;
|
||||
import com.cool.store.entity.EnterpriseUserDO;
|
||||
import com.cool.store.entity.StoreDO;
|
||||
import com.cool.store.entity.contract.ContractCostDO;
|
||||
import com.cool.store.entity.contract.ContractMasterDO;
|
||||
import com.cool.store.enums.FileTypeEnum;
|
||||
import com.cool.store.enums.ImportTaskStatusEnum;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.mapper.ImportTaskMapper;
|
||||
import com.cool.store.request.contract.ContractImportRowDTO;
|
||||
import com.cool.store.request.contract.ContractMasterQueryRequest;
|
||||
import com.cool.store.service.contract.ContractMasterService;
|
||||
import com.cool.store.service.contract.listener.ContractImportListener;
|
||||
import com.cool.store.utils.RedisUtilPool;
|
||||
import com.cool.store.utils.UUIDUtils;
|
||||
import com.cool.store.utils.easyExcel.EasyExcelUtil;
|
||||
import com.cool.store.utils.poi.DateUtils;
|
||||
import com.cool.store.utils.poi.StringUtils;
|
||||
import com.cool.store.vo.contract.ContractCostVO;
|
||||
import com.cool.store.vo.contract.ContractMasterDetailVO;
|
||||
import com.cool.store.vo.contract.ContractMasterListVO;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.cool.store.utils.poi.DateUtils.SPECIAL_DATE_START_1;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class ContractMasterServiceImpl implements ContractMasterService {
|
||||
|
||||
private final ContractMasterDAO contractMasterDAO;
|
||||
private final ContractCostDAO contractCostDAO;
|
||||
private final EnterpriseUserDAO enterpriseUserDAO;
|
||||
private final ImportTaskMapper importTaskMapper;
|
||||
private final RedisUtilPool redisUtilPool;
|
||||
private final EasyExcelUtil easyExcelUtil;
|
||||
private final StoreDao storeDao;
|
||||
@Resource(name = "generalThreadPool")
|
||||
private ThreadPoolTaskExecutor executor;
|
||||
|
||||
@Value("${mybatis.configuration.variables.enterpriseId}")
|
||||
private String eid;
|
||||
|
||||
@Override
|
||||
public PageInfo<ContractMasterListVO> queryContractMasterList(ContractMasterQueryRequest request) {
|
||||
// 门店名称/编码模糊查询时需要JOIN门店表
|
||||
if (request.getStoreNameOrCode() != null && !request.getStoreNameOrCode().isEmpty()) {
|
||||
request.setQueryStore(true);
|
||||
}
|
||||
PageHelper.startPage(request.getPageNum(), request.getPageSize());
|
||||
List<ContractMasterListVO> list = contractMasterDAO.queryContractMasterList(request);
|
||||
PageInfo<ContractMasterListVO> pageInfo = new PageInfo<>(list);
|
||||
|
||||
// 批量查询创建人姓名
|
||||
fill(pageInfo.getList());
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContractMasterDetailVO getContractMasterDetail(Long contractId) {
|
||||
ContractMasterDO contractDO = contractMasterDAO.getById(contractId);
|
||||
if (contractDO == null) {
|
||||
throw new ServiceException(500, "合同不存在");
|
||||
}
|
||||
ContractMasterDetailVO detailVO = new ContractMasterDetailVO();
|
||||
detailVO.setContractId(contractDO.getId());
|
||||
detailVO.setContractType(contractDO.getContractType());
|
||||
detailVO.setContractNo(contractDO.getContractNo());
|
||||
detailVO.setStoreId(contractDO.getStoreId());
|
||||
detailVO.setStoreCode(contractDO.getStoreCode());
|
||||
detailVO.setBrandName(contractDO.getBrandName());
|
||||
detailVO.setSource(contractDO.getSource());
|
||||
detailVO.setSignForm(contractDO.getSignForm());
|
||||
detailVO.setContractYears(contractDO.getContractYears());
|
||||
detailVO.setStartDate(contractDO.getStartDate());
|
||||
detailVO.setEndDate(contractDO.getEndDate());
|
||||
detailVO.setContractStatus(contractDO.getContractStatus());
|
||||
detailVO.setCurrency(contractDO.getCurrency());
|
||||
detailVO.setSignDate(contractDO.getSignDate());
|
||||
detailVO.setRelatedContractNo(contractDO.getRelatedContractNo());
|
||||
detailVO.setRemark(contractDO.getRemark());
|
||||
detailVO.setCreatedTime(contractDO.getCreatedTime());
|
||||
|
||||
// 查询创建人姓名
|
||||
if (contractDO.getCreateUserId() != null) {
|
||||
EnterpriseUserDO user = enterpriseUserDAO.getUserInfoById(contractDO.getCreateUserId());
|
||||
if (user != null) {
|
||||
detailVO.setCreateUserName(user.getName());
|
||||
}
|
||||
}
|
||||
|
||||
// 查询费用信息
|
||||
List<ContractCostDO> costList = contractCostDAO.queryByContractNo(contractDO.getContractNo());
|
||||
if (CollectionUtils.isNotEmpty(costList)) {
|
||||
ContractCostDO cost = costList.get(0);
|
||||
ContractCostVO costVO = new ContractCostVO();
|
||||
costVO.setJoinFeeAmount(cost.getJoinFeeAmount());
|
||||
costVO.setJoinFeeFrequencyYears(cost.getJoinFeeFrequencyYears());
|
||||
costVO.setJoinFeeDiscountAmount(cost.getJoinFeeDiscountAmount());
|
||||
costVO.setJoinFeeDiscountReason(cost.getJoinFeeDiscountReason());
|
||||
costVO.setBrandUsageFeeAmount(cost.getBrandUsageFeeAmount());
|
||||
costVO.setBrandUsageFeeFrequencyYears(cost.getBrandUsageFeeFrequencyYears());
|
||||
costVO.setBrandManagementFeeAmount(cost.getBrandManagementFeeAmount());
|
||||
costVO.setBrandManagementFeeFrequencyYears(cost.getBrandManagementFeeFrequencyYears());
|
||||
costVO.setDesignFeeAmount(cost.getDesignFeeAmount());
|
||||
costVO.setSystemUsageFeeAmount(cost.getSystemUsageFeeAmount());
|
||||
costVO.setPerformanceBondAmount(cost.getPerformanceBondAmount());
|
||||
detailVO.setCostList(Collections.singletonList(costVO));
|
||||
}
|
||||
return detailVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Boolean importContractAndCost(MultipartFile file) {
|
||||
final String lockKey = RedisConstant.CONTRACT_IMPORT_LOCK;
|
||||
boolean lock = redisUtilPool.setNxExpire(lockKey, UUIDUtils.get32UUID(), 30 * 60 * 1000);
|
||||
if (!lock) {
|
||||
throw new ServiceException(500, "存在正在进行的导入任务");
|
||||
}
|
||||
ImportTaskDO importTaskDO = new ImportTaskDO();
|
||||
importTaskDO.setFileName(file.getOriginalFilename());
|
||||
importTaskDO.setFileType(FileTypeEnum.CONTRACT_IMPORT.getFileType());
|
||||
importTaskDO.setIsImport(true);
|
||||
importTaskDO.setStatus(ImportTaskStatusEnum.PROGRESS.getCode());
|
||||
importTaskDO.setCreateUserId(CurrentUserHolder.getUserId());
|
||||
importTaskDO.setCreateName(CurrentUserHolder.getUser().getName());
|
||||
importTaskDO.setCreateTime(System.currentTimeMillis());
|
||||
importTaskMapper.insert(eid, importTaskDO);
|
||||
LoginUserInfo user = CurrentUserHolder.getUser();
|
||||
try {
|
||||
byte[] excelBytes = file.getBytes();
|
||||
executor.execute(() -> importContract(excelBytes, importTaskDO, user));
|
||||
} catch (Exception e) {
|
||||
log.error("导入失败", e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void importContract(byte[] excelBytes, ImportTaskDO importTaskDO, LoginUserInfo user) {
|
||||
List<String> errorList = new ArrayList<>();
|
||||
AtomicInteger successNum = new AtomicInteger();
|
||||
AtomicInteger totalNum = new AtomicInteger();
|
||||
try {
|
||||
// 合同导入(包含费用)
|
||||
EasyExcel.read(new ByteArrayInputStream(excelBytes), ContractImportRowDTO.class,
|
||||
new ContractImportListener(contractMasterDAO, contractCostDAO, totalNum, successNum, errorList))
|
||||
.sheet(0)
|
||||
.doRead();
|
||||
} catch (Exception e) {
|
||||
log.error("合同导入失败", e);
|
||||
} finally {
|
||||
try {
|
||||
final String lockKey = RedisConstant.CONTRACT_IMPORT_LOCK;
|
||||
String value = redisUtilPool.getString(lockKey);
|
||||
if (org.apache.commons.lang3.StringUtils.isNotBlank(value)) {
|
||||
redisUtilPool.delKey(lockKey);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
log.error("释放合同导入锁异常", ex);
|
||||
}
|
||||
}
|
||||
importTaskDO.setStatus(totalNum.get() == successNum.get() ? ImportTaskStatusEnum.SUCCESS.getCode() : ImportTaskStatusEnum.PART_ERROR.getCode());
|
||||
importTaskDO.setTotalNum(totalNum.get());
|
||||
importTaskDO.setSuccessNum(successNum.get());
|
||||
if (CollectionUtils.isNotEmpty(errorList)) {
|
||||
try {
|
||||
String url = easyExcelUtil.exportExcel(String.class, errorList, null,
|
||||
FileTypeEnum.CONTRACT_ERROR_EXPORT.getDesc() + DateUtils.parseDateToStr(SPECIAL_DATE_START_1, new Date()),
|
||||
FileTypeEnum.CONTRACT_ERROR_EXPORT.getDesc() + DateUtils.parseDateToStr(SPECIAL_DATE_START_1, new Date()));
|
||||
importTaskDO.setFileUrl(url);
|
||||
} catch (Exception e) {
|
||||
log.info("导出失败列表失败 errorList:{}", errorList);
|
||||
}
|
||||
}
|
||||
importTaskMapper.update(eid, importTaskDO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量填充
|
||||
*/
|
||||
private void fill(List<ContractMasterListVO> list) {
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return;
|
||||
}
|
||||
List<String> userIds = list.stream()
|
||||
.map(ContractMasterListVO::getCreateUserId)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
List<EnterpriseUserDO> users = enterpriseUserDAO.getUserInfoByUserIds(userIds);
|
||||
Map<String, String> userNameMap = users.stream()
|
||||
.collect(Collectors.toMap(EnterpriseUserDO::getUserId, EnterpriseUserDO::getName, (a, b) -> a));
|
||||
List<String> storeCodes = list.stream().filter(x-> StringUtils.isNotBlank(x.getStoreCode()))
|
||||
.map(ContractMasterListVO::getStoreCode)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
List<StoreDO> storeList = storeDao.getStoreNumByStoreCodes(storeCodes);
|
||||
Map<String, StoreDO> storeMap = storeList.stream().collect(Collectors.toMap(StoreDO::getStoreNum, data -> data, (a, b) -> a));
|
||||
list.forEach(vo -> {
|
||||
if (vo.getCreateUserId() != null) {
|
||||
vo.setCreateUserName(userNameMap.get(vo.getCreateUserId()));
|
||||
}
|
||||
StoreDO storeDO = storeMap.get(vo.getStoreCode());
|
||||
if (storeDO!=null){
|
||||
vo.setStoreName(storeDO.getStoreName());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package com.cool.store.service.contract.listener;
|
||||
|
||||
import com.alibaba.excel.context.AnalysisContext;
|
||||
import com.alibaba.excel.metadata.CellData;
|
||||
import com.alibaba.excel.metadata.CellExtra;
|
||||
import com.alibaba.excel.read.listener.ReadListener;
|
||||
import com.cool.store.dao.contract.ContractCostDAO;
|
||||
import com.cool.store.dao.contract.ContractMasterDAO;
|
||||
import com.cool.store.entity.contract.ContractCostDO;
|
||||
import com.cool.store.entity.contract.ContractMasterDO;
|
||||
import com.cool.store.request.contract.ContractImportRowDTO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* 合同导入监听器
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class ContractImportListener implements ReadListener<ContractImportRowDTO> {
|
||||
|
||||
private final ContractMasterDAO contractMasterDAO;
|
||||
private final ContractCostDAO contractCostDAO;
|
||||
private final AtomicInteger totalNum;
|
||||
private final AtomicInteger successNum;
|
||||
private final List<String> errorList;
|
||||
|
||||
private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
|
||||
@Override
|
||||
public void onException(Exception e, AnalysisContext analysisContext) {
|
||||
log.error("合同导入失败", e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invokeHead(Map<Integer, CellData> map, AnalysisContext analysisContext) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(ContractImportRowDTO data, AnalysisContext context) {
|
||||
totalNum.incrementAndGet();
|
||||
int rowIndex = context.readRowHolder().getRowIndex();
|
||||
|
||||
if (data == null || StringUtils.isBlank(data.getContractNo())) {
|
||||
errorList.add("第" + rowIndex + "行:合同编号为空");
|
||||
return;
|
||||
}
|
||||
if (StringUtils.isBlank(data.getStoreCode())) {
|
||||
errorList.add("第" + rowIndex + "行:门店编码为空");
|
||||
return;
|
||||
}
|
||||
|
||||
ContractMasterDO contractDO = new ContractMasterDO();
|
||||
contractDO.setContractType(data.getContractType());
|
||||
contractDO.setContractNo(data.getContractNo());
|
||||
contractDO.setStoreCode(data.getStoreCode());
|
||||
contractDO.setBrandName(data.getBrandName());
|
||||
contractDO.setSource(data.getSource());
|
||||
contractDO.setSignForm(data.getSignForm());
|
||||
contractDO.setContractYears(data.getContractYears());
|
||||
contractDO.setContractStatus(data.getContractStatus());
|
||||
contractDO.setRemark(data.getRemark());
|
||||
contractDO.setRelatedContractNo(data.getRelatedContractNo());
|
||||
contractDO.setRenewalCreated(0);
|
||||
|
||||
try {
|
||||
if (StringUtils.isNotBlank(data.getStartDate())) {
|
||||
contractDO.setStartDate(dateFormat.parse(data.getStartDate()));
|
||||
}
|
||||
if (StringUtils.isNotBlank(data.getEndDate())) {
|
||||
contractDO.setEndDate(dateFormat.parse(data.getEndDate()));
|
||||
}
|
||||
if (StringUtils.isNotBlank(data.getSignDate())) {
|
||||
contractDO.setSignDate(dateFormat.parse(data.getSignDate()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorList.add("第" + rowIndex + "行:日期格式错误");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
contractMasterDAO.insertSelective(contractDO);
|
||||
|
||||
// 插入费用数据
|
||||
ContractCostDO costDO = ContractCostDO.builder()
|
||||
.contractNo(data.getContractNo())
|
||||
.joinFeeAmount(data.getJoinFeeAmount())
|
||||
.joinFeeFrequencyYears(data.getJoinFeeFrequencyYears())
|
||||
.joinFeeDiscountAmount(data.getJoinFeeDiscountAmount())
|
||||
.joinFeeDiscountReason(data.getJoinFeeDiscountReason())
|
||||
.brandUsageFeeAmount(data.getBrandUsageFeeAmount())
|
||||
.brandUsageFeeFrequencyYears(data.getBrandUsageFeeFrequencyYears())
|
||||
.brandManagementFeeAmount(data.getBrandManagementFeeAmount())
|
||||
.brandManagementFeeFrequencyYears(data.getBrandManagementFeeFrequencyYears())
|
||||
.designFeeAmount(data.getDesignFeeAmount())
|
||||
.systemUsageFeeAmount(data.getSystemUsageFeeAmount())
|
||||
.performanceBondAmount(data.getPerformanceBondAmount())
|
||||
.createdTime(new Date())
|
||||
.updatedTime(new Date())
|
||||
.build();
|
||||
contractCostDAO.insertSelective(costDO);
|
||||
|
||||
successNum.incrementAndGet();
|
||||
} catch (Exception e) {
|
||||
log.error("合同导入插入失败: contractNo={}", data.getContractNo(), e);
|
||||
errorList.add("第" + rowIndex + "行:插入失败-" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void extra(CellExtra cellExtra, AnalysisContext analysisContext) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAfterAllAnalysed(AnalysisContext context) {
|
||||
log.info("合同导入完成,总数:{}, 成功:{}", totalNum.get(), successNum.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext(AnalysisContext analysisContext) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.cool.store.service.exam;
|
||||
|
||||
import com.cool.store.dto.exam.*;
|
||||
import com.cool.store.vo.exam.ExamAttemptListVO;
|
||||
import com.cool.store.vo.exam.ExamAttemptVO;
|
||||
import com.cool.store.vo.exam.ExamPaperForAttemptVO;
|
||||
import com.cool.store.vo.exam.ExamResultVO;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
/**
|
||||
* 答卷服务接口
|
||||
*/
|
||||
public interface ExamAttemptService {
|
||||
|
||||
/**
|
||||
* 开始考试
|
||||
*/
|
||||
ExamPaperForAttemptVO startAttempt(ExamStartAttemptDTO dto);
|
||||
|
||||
/**
|
||||
* 保存答案
|
||||
*/
|
||||
void saveAnswer(ExamSubmitAnswerDTO dto);
|
||||
|
||||
/**
|
||||
* 提交试卷
|
||||
*/
|
||||
ExamResultVO submitPaper(ExamSubmitPaperDTO dto);
|
||||
|
||||
/**
|
||||
* 超时自动提交
|
||||
*/
|
||||
void autoSubmit(Long attemptId);
|
||||
|
||||
/**
|
||||
* 查看答卷详情
|
||||
*/
|
||||
ExamAttemptVO getAttemptDetail(Long attemptId);
|
||||
|
||||
/**
|
||||
* 查看考试结果
|
||||
*/
|
||||
ExamResultVO getResult(Long attemptId);
|
||||
|
||||
/**
|
||||
* 根据手机号分页查询答卷列表
|
||||
*/
|
||||
PageInfo<ExamAttemptListVO> listByMobile(String mobile, Integer pageNum, Integer pageSize);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.cool.store.service.exam;
|
||||
|
||||
import com.cool.store.dto.exam.*;
|
||||
import com.cool.store.vo.exam.ExamInfoListVO;
|
||||
import com.cool.store.vo.exam.ExamInfoVO;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
/**
|
||||
* 考试服务接口
|
||||
*/
|
||||
public interface ExamInfoService {
|
||||
|
||||
/**
|
||||
* 创建考试
|
||||
*/
|
||||
void addExam(ExamInfoAddDTO dto);
|
||||
|
||||
/**
|
||||
* 更新考试
|
||||
*/
|
||||
void updateExam(ExamInfoAddDTO dto);
|
||||
|
||||
/**
|
||||
* 发布考试
|
||||
*/
|
||||
void publishExam(Long id);
|
||||
|
||||
/**
|
||||
* 结束考试
|
||||
*/
|
||||
void endExam(Long id);
|
||||
|
||||
/**
|
||||
* 查询考试列表
|
||||
*/
|
||||
PageInfo<ExamInfoListVO> getExamList(ExamInfoListDTO dto);
|
||||
|
||||
/**
|
||||
* 查询考试详情
|
||||
*/
|
||||
ExamInfoVO getExamDetail(Long id);
|
||||
|
||||
/**
|
||||
* 通过token获取考试信息
|
||||
*/
|
||||
ExamInfoVO getExamByToken(String token);
|
||||
|
||||
/**
|
||||
* 删除考试
|
||||
*/
|
||||
void deleteExam(Long id);
|
||||
|
||||
/**
|
||||
* 自动结束考试(由延时消息触发)
|
||||
*/
|
||||
void autoEndExam(Long id);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.cool.store.service.exam;
|
||||
|
||||
import com.cool.store.dto.exam.*;
|
||||
import com.cool.store.vo.exam.ExamPaperListVO;
|
||||
import com.cool.store.vo.exam.ExamPaperVO;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
/**
|
||||
* 试卷服务接口
|
||||
*/
|
||||
public interface ExamPaperService {
|
||||
|
||||
/**
|
||||
* 新增试卷
|
||||
*/
|
||||
void addPaper(ExamPaperAddDTO dto);
|
||||
|
||||
/**
|
||||
* 更新试卷
|
||||
*/
|
||||
void updatePaper(ExamPaperAddDTO dto);
|
||||
|
||||
/**
|
||||
* 删除试卷
|
||||
*/
|
||||
void deletePaper(Long id);
|
||||
|
||||
/**
|
||||
* 查询试卷列表
|
||||
*/
|
||||
PageInfo<ExamPaperListVO> getPaperList(ExamPaperListDTO dto);
|
||||
|
||||
/**
|
||||
* 查询试卷详情
|
||||
*/
|
||||
ExamPaperVO getPaperDetail(Long id);
|
||||
|
||||
/**
|
||||
* 检查试卷是否已开始考试
|
||||
*/
|
||||
boolean hasStartedExam(Long paperId);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.cool.store.service.exam;
|
||||
|
||||
import com.cool.store.dto.exam.*;
|
||||
import com.cool.store.vo.exam.ExamQuestionListVO;
|
||||
import com.cool.store.vo.exam.ExamQuestionVO;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 题目服务接口
|
||||
*/
|
||||
public interface ExamQuestionService {
|
||||
|
||||
/**
|
||||
* 新增题目
|
||||
*/
|
||||
void addQuestion(ExamQuestionAddDTO dto);
|
||||
|
||||
/**
|
||||
* 更新题目
|
||||
*/
|
||||
void updateQuestion(ExamQuestionAddDTO dto);
|
||||
|
||||
/**
|
||||
* 批量删除题目
|
||||
*/
|
||||
void deleteQuestions(List<Long> ids);
|
||||
|
||||
/**
|
||||
* 查询题目列表
|
||||
*/
|
||||
PageInfo<ExamQuestionListVO> getQuestionList(ExamQuestionListDTO dto);
|
||||
|
||||
/**
|
||||
* 查询题目详情
|
||||
*/
|
||||
ExamQuestionVO getQuestionDetail(Long id);
|
||||
}
|
||||
@@ -0,0 +1,477 @@
|
||||
package com.cool.store.service.exam.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollStreamUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.cool.store.constants.CommonConstants;
|
||||
import com.cool.store.context.PartnerUserHolder;
|
||||
import com.cool.store.dao.exam.*;
|
||||
import com.cool.store.dto.exam.*;
|
||||
import com.cool.store.entity.exam.*;
|
||||
import com.cool.store.enums.ErrorCodeEnum;
|
||||
import com.cool.store.enums.ExamAttemptStatusEnum;
|
||||
import com.cool.store.enums.ExamInfoStatusEnum;
|
||||
import com.cool.store.enums.RocketMqTagEnum;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.mq.producer.SimpleMessageService;
|
||||
import com.cool.store.service.exam.ExamAttemptService;
|
||||
import com.cool.store.utils.BeanUtil;
|
||||
import com.cool.store.vo.exam.ExamAttemptListVO;
|
||||
import com.cool.store.vo.exam.ExamAttemptVO;
|
||||
import com.cool.store.vo.exam.ExamAnswerVO;
|
||||
import com.cool.store.vo.exam.ExamOptionVO;
|
||||
import com.cool.store.vo.exam.ExamPaperForAttemptVO;
|
||||
import com.cool.store.vo.exam.ExamResultVO;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 答卷服务实现
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class ExamAttemptServiceImpl implements ExamAttemptService {
|
||||
|
||||
private final ExamInfoDAO examInfoDAO;
|
||||
private final ExamPaperDAO examPaperDAO;
|
||||
private final ExamPaperQuestionDAO examPaperQuestionDAO;
|
||||
private final ExamAttemptDAO examAttemptDAO;
|
||||
private final ExamAttemptAnswerDAO examAttemptAnswerDAO;
|
||||
private final SimpleMessageService simpleMessageService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ExamPaperForAttemptVO startAttempt(ExamStartAttemptDTO dto) {
|
||||
// 获取当前登录用户信息
|
||||
String mobile = PartnerUserHolder.getUser().getMobile();
|
||||
// 验证考试信息
|
||||
ExamInfoDO examInfoDO = examInfoDAO.selectByToken(dto.getEntryToken());
|
||||
if (examInfoDO == null || CommonConstants.INDEX_ONE.equals(examInfoDO.getDeleted())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_TOKEN_INVALID);
|
||||
}
|
||||
|
||||
// 检查是否有进行中的答卷
|
||||
ExamAttemptDO existingAttempt = examAttemptDAO.selectInProgressByExamIdAndMobile(examInfoDO.getId(), mobile);
|
||||
if (existingAttempt != null) {
|
||||
// 检查是否已超时
|
||||
if (existingAttempt.getDeadlineTime() != null && new Date().before(existingAttempt.getDeadlineTime())) {
|
||||
// 返回继续考试的试卷信息(包含已保存的答案)
|
||||
return buildPaperForAttemptWithAnswers(examInfoDO, existingAttempt);
|
||||
}
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_ATTEMPT_EXPIRED);
|
||||
}
|
||||
|
||||
// 已参加考试
|
||||
if (examAttemptDAO.existFinishAttempt(mobile, examInfoDO.getId())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_COMPLETED);
|
||||
}
|
||||
|
||||
// 校验考试时间范围
|
||||
Date now = new Date();
|
||||
Date startTime = examInfoDO.getStartTime();
|
||||
Date endTime = examInfoDO.getEndTime();
|
||||
|
||||
// 如果开始时间不为空,校验当前时间是否已到开始时间
|
||||
if (startTime != null && now.before(startTime)) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_NOT_STARTED);
|
||||
}
|
||||
|
||||
// 如果结束时间不为空,校验当前时间是否早于结束时间
|
||||
if (endTime != null && !now.before(endTime)) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_TIME_ENDED);
|
||||
}
|
||||
|
||||
// 检查考试状态
|
||||
if (!ExamInfoStatusEnum.isPublished(examInfoDO.getStatus())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_NOT_PUBLISHED);
|
||||
}
|
||||
|
||||
// 创建新答卷
|
||||
ExamAttemptDO attemptDO = new ExamAttemptDO();
|
||||
attemptDO.setExamId(examInfoDO.getId());
|
||||
attemptDO.setPaperId(examInfoDO.getPaperId());
|
||||
attemptDO.setName(dto.getName());
|
||||
attemptDO.setMobile(mobile);
|
||||
attemptDO.setStartTime(new Date());
|
||||
Date deadline = new Date(System.currentTimeMillis() + examInfoDO.getDurationMinutes() * 60 * 1000L);
|
||||
attemptDO.setDeadlineTime(deadline);
|
||||
examAttemptDAO.insertSelective(attemptDO);
|
||||
|
||||
// 加入延时队列
|
||||
simpleMessageService.send(String.valueOf(attemptDO.getId()), RocketMqTagEnum.EXAM_AUTO_SUBMIT, deadline.getTime());
|
||||
|
||||
// 返回试卷信息
|
||||
return buildPaperForAttempt(examInfoDO, attemptDO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveAnswer(ExamSubmitAnswerDTO dto) {
|
||||
ExamAttemptDO attemptDO = getAndCheckAttempt(dto.getAttemptId());
|
||||
checkAttemptInProgress(attemptDO);
|
||||
String partnerId = PartnerUserHolder.getUser().getPartnerId();
|
||||
|
||||
// 保存或更新答案
|
||||
ExamAttemptAnswerDO answerDO = new ExamAttemptAnswerDO();
|
||||
answerDO.setAttemptId(dto.getAttemptId());
|
||||
answerDO.setPaperId(attemptDO.getPaperId());
|
||||
answerDO.setPaperQuestionId(dto.getPaperQuestionId());
|
||||
answerDO.setCreateUserId(partnerId);
|
||||
// 将答案对象转为JSON字符串存储
|
||||
if (dto.getAnswer() != null) {
|
||||
answerDO.setAnswer(JSON.toJSONString(dto.getAnswer()));
|
||||
}
|
||||
examAttemptAnswerDAO.insertOrUpdate(answerDO);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ExamResultVO submitPaper(ExamSubmitPaperDTO dto) {
|
||||
ExamAttemptDO attemptDO = getAndCheckAttempt(dto.getAttemptId());
|
||||
checkAttemptInProgress(attemptDO);
|
||||
String partnerId = PartnerUserHolder.getUser().getPartnerId();
|
||||
|
||||
// 批量保存答案
|
||||
if (CollectionUtils.isNotEmpty(dto.getAnswers())) {
|
||||
List<ExamAttemptAnswerDO> answerList = CollStreamUtil.toList(dto.getAnswers(), item -> {
|
||||
ExamAttemptAnswerDO answerDO = new ExamAttemptAnswerDO();
|
||||
answerDO.setAttemptId(dto.getAttemptId());
|
||||
answerDO.setPaperId(attemptDO.getPaperId());
|
||||
answerDO.setPaperQuestionId(item.getPaperQuestionId());
|
||||
answerDO.setCreateUserId(partnerId);
|
||||
// 将答案对象转为JSON字符串存储
|
||||
if (item.getAnswer() != null) {
|
||||
answerDO.setAnswer(JSON.toJSONString(item.getAnswer()));
|
||||
}
|
||||
return answerDO;
|
||||
});
|
||||
examAttemptAnswerDAO.batchInsertOrUpdate(answerList);
|
||||
}
|
||||
|
||||
// 自动评分
|
||||
return doScoring(attemptDO, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void autoSubmit(Long attemptId) {
|
||||
ExamAttemptDO attemptDO = examAttemptDAO.selectByPrimaryKey(attemptId);
|
||||
if (attemptDO == null || ExamAttemptStatusEnum.isCompleted(attemptDO.getStatus())) {
|
||||
return;
|
||||
}
|
||||
|
||||
doScoring(attemptDO, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExamAttemptVO getAttemptDetail(Long attemptId) {
|
||||
ExamAttemptDO attemptDO = getAndCheckAttempt(attemptId);
|
||||
|
||||
ExamAttemptVO vo = BeanUtil.toBean(attemptDO, ExamAttemptVO.class);
|
||||
|
||||
// 查询考试名称
|
||||
ExamInfoDO examInfoDO = examInfoDAO.selectByPrimaryKey(attemptDO.getExamId());
|
||||
if (examInfoDO != null) {
|
||||
vo.setExamName(examInfoDO.getExamName());
|
||||
}
|
||||
|
||||
// 查询题目和答案(批量查询)
|
||||
List<ExamPaperQuestionDO> questions = examPaperQuestionDAO.selectByPaperId(attemptDO.getPaperId());
|
||||
Map<Long, ExamAttemptAnswerDO> answerMap = examAttemptAnswerDAO.getMapByAttemptId(attemptId);
|
||||
|
||||
List<ExamAttemptVO.AnswerDetail> answers = CollStreamUtil.toList(questions, pq -> {
|
||||
ExamAttemptVO.AnswerDetail detail = new ExamAttemptVO.AnswerDetail();
|
||||
detail.setPaperQuestionId(pq.getId());
|
||||
detail.setType(pq.getType());
|
||||
detail.setQuestionStem(pq.getQuestionStem());
|
||||
if (pq.getOptions() != null) {
|
||||
detail.setOptions(JSON.parseArray(pq.getOptions(), ExamOptionVO.class));
|
||||
}
|
||||
// 将正确答案JSON字符串转为对象
|
||||
if (StringUtils.isNotBlank(pq.getAnswer())) {
|
||||
detail.setCorrectAnswer(JSON.parseObject(pq.getAnswer(), ExamAnswerVO.class));
|
||||
}
|
||||
detail.setTotalScore(pq.getScore());
|
||||
detail.setAnalysis(pq.getAnalysis());
|
||||
|
||||
ExamAttemptAnswerDO userAnswer = answerMap.get(pq.getId());
|
||||
if (userAnswer != null) {
|
||||
// 将用户答案JSON字符串转为对象
|
||||
if (StringUtils.isNotBlank(userAnswer.getAnswer())) {
|
||||
detail.setUserAnswer(JSON.parseObject(userAnswer.getAnswer(), ExamAnswerVO.class));
|
||||
}
|
||||
detail.setScore(userAnswer.getScore());
|
||||
detail.setIsCorrect(isCorrect(pq.getAnswer(), userAnswer.getAnswer(), pq.getType()));
|
||||
}
|
||||
return detail;
|
||||
});
|
||||
|
||||
vo.setAnswers(answers);
|
||||
return vo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExamResultVO getResult(Long attemptId) {
|
||||
ExamAttemptDO attemptDO = getAndCheckAttempt(attemptId);
|
||||
|
||||
// 查询试卷总分
|
||||
ExamPaperDO paperDO = examPaperDAO.selectByPrimaryKey(attemptDO.getPaperId());
|
||||
BigDecimal fullScore = paperDO != null ? paperDO.getTotalScore() : BigDecimal.ZERO;
|
||||
|
||||
// 批量查询题目和答案
|
||||
List<ExamPaperQuestionDO> questions = examPaperQuestionDAO.selectByPaperId(attemptDO.getPaperId());
|
||||
Map<Long, ExamAttemptAnswerDO> answerMap = examAttemptAnswerDAO.getMapByAttemptId(attemptId);
|
||||
|
||||
int totalCount = questions.size();
|
||||
int correctCount = 0;
|
||||
for (ExamPaperQuestionDO pq : questions) {
|
||||
ExamAttemptAnswerDO answer = answerMap.get(pq.getId());
|
||||
if (answer != null && isCorrect(pq.getAnswer(), answer.getAnswer(), pq.getType())) {
|
||||
correctCount++;
|
||||
}
|
||||
}
|
||||
|
||||
ExamResultVO vo = new ExamResultVO();
|
||||
vo.setAttemptId(attemptId);
|
||||
vo.setTotalScore(attemptDO.getTotalScore() != null ? attemptDO.getTotalScore() : BigDecimal.ZERO);
|
||||
vo.setFullScore(fullScore);
|
||||
vo.setCorrectCount(correctCount);
|
||||
vo.setTotalCount(totalCount);
|
||||
vo.setPassed(isPassed(attemptDO.getTotalScore(), fullScore));
|
||||
|
||||
return vo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageInfo<ExamAttemptListVO> listByMobile(String mobile, Integer pageNum, Integer pageSize) {
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
List<ExamAttemptDO> attemptList = examAttemptDAO.selectByMobile(mobile);
|
||||
PageInfo<ExamAttemptDO> pageInfo = new PageInfo<>(attemptList);
|
||||
|
||||
if (CollectionUtils.isEmpty(attemptList)) {
|
||||
return new PageInfo<>();
|
||||
}
|
||||
|
||||
// 批量查询考试信息,包含被删除的考试
|
||||
List<Long> examIds = CollStreamUtil.toList(attemptList, ExamAttemptDO::getExamId);
|
||||
Map<Long, ExamInfoDO> examInfoMap = examInfoDAO.getMapIncludeDeletedByIds(examIds);
|
||||
|
||||
// 批量查询试卷信息
|
||||
List<Long> paperIds = CollStreamUtil.toList(attemptList, ExamAttemptDO::getPaperId);
|
||||
Map<Long, ExamPaperDO> paperMap = examPaperDAO.getMapByIds(paperIds);
|
||||
|
||||
List<ExamAttemptListVO> voList = CollStreamUtil.toList(attemptList, attempt -> {
|
||||
ExamAttemptListVO vo = BeanUtil.toBean(attempt, ExamAttemptListVO.class);
|
||||
ExamInfoDO examInfoDO = examInfoMap.get(attempt.getExamId());
|
||||
if (examInfoDO != null) {
|
||||
vo.setExamName(examInfoDO.getExamName());
|
||||
vo.setDurationMinutes(examInfoDO.getDurationMinutes());
|
||||
vo.setEntryToken(examInfoDO.getEntryToken());
|
||||
}
|
||||
ExamPaperDO paperDO = paperMap.get(attempt.getPaperId());
|
||||
if (paperDO != null) {
|
||||
vo.setFullScore(paperDO.getTotalScore());
|
||||
}
|
||||
vo.setStatusDesc(ExamAttemptStatusEnum.isCompleted(attempt.getStatus()) ? "已完成" : "进行中");
|
||||
if (ExamAttemptStatusEnum.isCompleted(attempt.getStatus()) && paperDO != null) {
|
||||
vo.setPassed(isPassed(attempt.getTotalScore(), paperDO.getTotalScore()));
|
||||
}
|
||||
return vo;
|
||||
});
|
||||
|
||||
// 构建分页结果
|
||||
PageInfo<ExamAttemptListVO> resultPage = new PageInfo<>();
|
||||
resultPage.setList(voList);
|
||||
resultPage.setTotal(pageInfo.getTotal());
|
||||
resultPage.setPageNum(pageInfo.getPageNum());
|
||||
resultPage.setPageSize(pageInfo.getPageSize());
|
||||
resultPage.setPages(pageInfo.getPages());
|
||||
return resultPage;
|
||||
}
|
||||
|
||||
// ==================== 私有方法 ====================
|
||||
|
||||
/**
|
||||
* 获取并校验答卷
|
||||
*/
|
||||
private ExamAttemptDO getAndCheckAttempt(Long attemptId) {
|
||||
ExamAttemptDO attemptDO = examAttemptDAO.selectByPrimaryKey(attemptId);
|
||||
if (attemptDO == null) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_ATTEMPT_NOT_EXIST);
|
||||
}
|
||||
return attemptDO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验答卷是否进行中
|
||||
*/
|
||||
private void checkAttemptInProgress(ExamAttemptDO attemptDO) {
|
||||
// 检查是否已提交
|
||||
if (ExamAttemptStatusEnum.isCompleted(attemptDO.getStatus())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_ATTEMPT_ALREADY_SUBMITTED);
|
||||
}
|
||||
|
||||
// 检查是否超时
|
||||
if (attemptDO.getDeadlineTime() != null && new Date().after(attemptDO.getDeadlineTime())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_ATTEMPT_EXPIRED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行评分
|
||||
*/
|
||||
private ExamResultVO doScoring(ExamAttemptDO attemptDO, Integer submitType) {
|
||||
// 批量查询题目和答案
|
||||
List<ExamPaperQuestionDO> questions = examPaperQuestionDAO.selectByPaperId(attemptDO.getPaperId());
|
||||
Map<Long, ExamAttemptAnswerDO> answerMap = examAttemptAnswerDAO.getMapByAttemptId(attemptDO.getId());
|
||||
|
||||
BigDecimal totalScore = BigDecimal.ZERO;
|
||||
List<ExamAttemptAnswerDO> updateList = new ArrayList<>();
|
||||
|
||||
// 计算每道题得分
|
||||
for (ExamPaperQuestionDO pq : questions) {
|
||||
ExamAttemptAnswerDO answerDO = answerMap.get(pq.getId());
|
||||
if (answerDO != null) {
|
||||
BigDecimal score = calculateScore(pq, answerDO.getAnswer());
|
||||
answerDO.setScore(score);
|
||||
updateList.add(answerDO);
|
||||
totalScore = totalScore.add(score);
|
||||
}
|
||||
}
|
||||
|
||||
// 批量更新分数
|
||||
if (CollectionUtils.isNotEmpty(updateList)) {
|
||||
examAttemptAnswerDAO.batchUpdateScore(updateList);
|
||||
}
|
||||
|
||||
// 更新答卷状态
|
||||
examAttemptDAO.updateStatusAndScore(attemptDO.getId(),
|
||||
ExamAttemptStatusEnum.COMPLETED.getCode(), submitType, totalScore);
|
||||
|
||||
return getResult(attemptDO.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算单题得分
|
||||
*/
|
||||
private BigDecimal calculateScore(ExamPaperQuestionDO pq, String userAnswer) {
|
||||
if (userAnswer == null || userAnswer.isEmpty()) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
boolean correct = isCorrect(pq.getAnswer(), userAnswer, pq.getType());
|
||||
return correct ? pq.getScore() : BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断答案是否正确
|
||||
*/
|
||||
private boolean isCorrect(String correctAnswer, String userAnswer, Integer type) {
|
||||
if (correctAnswer == null || userAnswer == null) {
|
||||
return false;
|
||||
}
|
||||
// 单选和判断题直接比较 (type: 1=单选, 2=多选, 3=判断)
|
||||
if (type == null || type == 1 || type == 3) {
|
||||
return correctAnswer.trim().equalsIgnoreCase(userAnswer.trim());
|
||||
}
|
||||
// 多选题需要比较所有选项
|
||||
Set<String> correctSet = Arrays.stream(correctAnswer.split(","))
|
||||
.map(String::trim)
|
||||
.collect(Collectors.toSet());
|
||||
Set<String> userSet = Arrays.stream(userAnswer.split(","))
|
||||
.map(String::trim)
|
||||
.collect(Collectors.toSet());
|
||||
return correctSet.equals(userSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否通过(60%及格)
|
||||
*/
|
||||
private boolean isPassed(BigDecimal totalScore, BigDecimal fullScore) {
|
||||
if (totalScore == null || fullScore == null || fullScore.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return false;
|
||||
}
|
||||
return totalScore.compareTo(fullScore.multiply(new BigDecimal("0.6"))) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建答题试卷VO
|
||||
*/
|
||||
private ExamPaperForAttemptVO buildPaperForAttempt(ExamInfoDO examInfoDO, ExamAttemptDO attemptDO) {
|
||||
ExamPaperForAttemptVO vo = new ExamPaperForAttemptVO();
|
||||
vo.setAttemptId(attemptDO.getId());
|
||||
vo.setExamName(examInfoDO.getExamName());
|
||||
vo.setDurationMinutes(examInfoDO.getDurationMinutes());
|
||||
vo.setStartTime(attemptDO.getStartTime().getTime());
|
||||
vo.setDeadlineTime(attemptDO.getDeadlineTime().getTime());
|
||||
vo.setRemainingTime(attemptDO.getDeadlineTime().getTime() - System.currentTimeMillis());
|
||||
|
||||
// 查询试卷题目(不含答案)
|
||||
List<ExamPaperQuestionDO> questions = examPaperQuestionDAO.selectByPaperId(examInfoDO.getPaperId());
|
||||
|
||||
int[] sortNo = {1};
|
||||
List<ExamPaperForAttemptVO.QuestionItem> items = CollStreamUtil.toList(questions, pq -> {
|
||||
ExamPaperForAttemptVO.QuestionItem item = new ExamPaperForAttemptVO.QuestionItem();
|
||||
item.setId(pq.getId());
|
||||
item.setType(pq.getType());
|
||||
item.setQuestionStem(pq.getQuestionStem());
|
||||
if (pq.getOptions() != null) {
|
||||
item.setOptions(JSON.parseArray(pq.getOptions(), ExamOptionVO.class));
|
||||
}
|
||||
item.setScore(pq.getScore());
|
||||
item.setSortNo(sortNo[0]++);
|
||||
return item;
|
||||
});
|
||||
vo.setQuestions(items);
|
||||
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建答题试卷VO(包含已保存的答案,用于恢复考试)
|
||||
*/
|
||||
private ExamPaperForAttemptVO buildPaperForAttemptWithAnswers(ExamInfoDO examInfoDO, ExamAttemptDO attemptDO) {
|
||||
ExamPaperForAttemptVO vo = new ExamPaperForAttemptVO();
|
||||
vo.setAttemptId(attemptDO.getId());
|
||||
vo.setExamName(examInfoDO.getExamName());
|
||||
vo.setDurationMinutes(examInfoDO.getDurationMinutes());
|
||||
vo.setStartTime(attemptDO.getStartTime().getTime());
|
||||
vo.setDeadlineTime(attemptDO.getDeadlineTime().getTime());
|
||||
vo.setRemainingTime(attemptDO.getDeadlineTime().getTime() - System.currentTimeMillis());
|
||||
|
||||
// 查询试卷题目
|
||||
List<ExamPaperQuestionDO> questions = examPaperQuestionDAO.selectByPaperId(examInfoDO.getPaperId());
|
||||
// 查询已保存的答案
|
||||
Map<Long, ExamAttemptAnswerDO> answerMap = examAttemptAnswerDAO.getMapByAttemptId(attemptDO.getId());
|
||||
|
||||
int[] sortNo = {1};
|
||||
List<ExamPaperForAttemptVO.QuestionItem> items = CollStreamUtil.toList(questions, pq -> {
|
||||
ExamPaperForAttemptVO.QuestionItem item = new ExamPaperForAttemptVO.QuestionItem();
|
||||
item.setId(pq.getId());
|
||||
item.setType(pq.getType());
|
||||
item.setQuestionStem(pq.getQuestionStem());
|
||||
if (pq.getOptions() != null) {
|
||||
item.setOptions(JSON.parseArray(pq.getOptions(), ExamOptionVO.class));
|
||||
}
|
||||
item.setScore(pq.getScore());
|
||||
item.setSortNo(sortNo[0]++);
|
||||
// 设置已保存的答案
|
||||
ExamAttemptAnswerDO savedAnswer = answerMap.get(pq.getId());
|
||||
if (savedAnswer != null && StringUtils.isNotBlank(savedAnswer.getAnswer())) {
|
||||
item.setUserAnswer(JSON.parseObject(savedAnswer.getAnswer(), ExamAnswerVO.class));
|
||||
}
|
||||
return item;
|
||||
});
|
||||
vo.setQuestions(items);
|
||||
|
||||
return vo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
package com.cool.store.service.exam.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollStreamUtil;
|
||||
import com.aliyun.core.utils.StringUtils;
|
||||
import com.cool.store.constants.CommonConstants;
|
||||
import com.cool.store.context.CurrentUserHolder;
|
||||
import com.cool.store.dao.exam.ExamAttemptDAO;
|
||||
import com.cool.store.dao.exam.ExamInfoDAO;
|
||||
import com.cool.store.dao.exam.ExamPaperDAO;
|
||||
import com.cool.store.dto.exam.*;
|
||||
import com.cool.store.entity.exam.ExamInfoDO;
|
||||
import com.cool.store.entity.exam.ExamPaperDO;
|
||||
import com.cool.store.enums.ErrorCodeEnum;
|
||||
import com.cool.store.enums.ExamInfoStatusEnum;
|
||||
import com.cool.store.enums.RocketMqTagEnum;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.mq.producer.SimpleMessageService;
|
||||
import com.cool.store.service.WechatMiniAppService;
|
||||
import com.cool.store.service.exam.ExamInfoService;
|
||||
import com.cool.store.utils.BeanUtil;
|
||||
import com.cool.store.utils.UUIDUtils;
|
||||
import com.cool.store.vo.exam.ExamInfoListVO;
|
||||
import com.cool.store.vo.exam.ExamInfoVO;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 考试服务实现
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class ExamInfoServiceImpl implements ExamInfoService {
|
||||
|
||||
private final ExamInfoDAO examInfoDAO;
|
||||
private final ExamPaperDAO examPaperDAO;
|
||||
private final WechatMiniAppService wechatMiniAppService;
|
||||
private final SimpleMessageService simpleMessageService;
|
||||
private final ExamAttemptDAO examAttemptDAO;
|
||||
|
||||
@Value("${exam.qrcode.page:twelvePoints/exam/indexCode}")
|
||||
private String examQrcodePage;
|
||||
|
||||
@Override
|
||||
public void addExam(ExamInfoAddDTO dto) {
|
||||
// 检查试卷是否存在
|
||||
ExamPaperDO paperDO = examPaperDAO.selectByPrimaryKey(dto.getPaperId());
|
||||
if (paperDO == null || CommonConstants.INDEX_ONE.equals(paperDO.getDeleted())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_PAPER_NOT_EXIST);
|
||||
}
|
||||
|
||||
ExamInfoDO examInfoDO = BeanUtil.toBean(dto, ExamInfoDO.class);
|
||||
examInfoDO.setEntryToken(UUIDUtils.get8UUID());
|
||||
examInfoDO.setCreateUserId(CurrentUserHolder.getUserId());
|
||||
examInfoDAO.insertSelective(examInfoDO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateExam(ExamInfoAddDTO dto) {
|
||||
ExamInfoDO existExam = examInfoDAO.selectByPrimaryKey(dto.getId());
|
||||
if (existExam == null || CommonConstants.INDEX_ONE.equals(existExam.getDeleted())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_INFO_NOT_EXIST);
|
||||
}
|
||||
// 已发布的考试不能修改
|
||||
if (ExamInfoStatusEnum.isPublished(existExam.getStatus())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_ALREADY_PUBLISHED);
|
||||
}
|
||||
// 已结束的考试不能修改
|
||||
if (ExamInfoStatusEnum.isEnded(existExam.getStatus())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_ALREADY_ENDED);
|
||||
}
|
||||
ExamInfoDO examInfoDO = BeanUtil.toBean(dto, ExamInfoDO.class);
|
||||
examInfoDAO.updateByPrimaryKeySelective(examInfoDO);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void publishExam(Long id) {
|
||||
ExamInfoDO existExam = examInfoDAO.selectByPrimaryKey(id);
|
||||
if (existExam == null || CommonConstants.INDEX_ONE.equals(existExam.getDeleted())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_INFO_NOT_EXIST);
|
||||
}
|
||||
// 只有未发布状态可以发布
|
||||
if (!ExamInfoStatusEnum.canPublish(existExam.getStatus())) {
|
||||
if (ExamInfoStatusEnum.isPublished(existExam.getStatus())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_ALREADY_PUBLISHED);
|
||||
}
|
||||
if (ExamInfoStatusEnum.isEnded(existExam.getStatus())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_ALREADY_ENDED);
|
||||
}
|
||||
}
|
||||
// 标记试卷已开始考试
|
||||
examPaperDAO.updateStartExam(existExam.getPaperId(), 1);
|
||||
|
||||
// 生成小程序二维码
|
||||
String qrcodeUrl = null;
|
||||
try {
|
||||
qrcodeUrl = wechatMiniAppService.createQrCode(examQrcodePage, "entryToken=" + existExam.getEntryToken(), "430");
|
||||
if (StringUtils.isBlank(qrcodeUrl)) {
|
||||
log.warn("考试发布成功,但生成二维码失败,examId:{}", id);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("考试发布成功,但生成二维码异常,examId:{}", id, e);
|
||||
}
|
||||
// 合并更新状态和二维码URL
|
||||
Date now = new Date();
|
||||
ExamInfoDO update = new ExamInfoDO();
|
||||
update.setId(id);
|
||||
update.setQrcodeUrl(qrcodeUrl);
|
||||
update.setStatus(ExamInfoStatusEnum.PUBLISHED.getCode());
|
||||
update.setUpdateTime(now);
|
||||
update.setStartTime(now);
|
||||
examInfoDAO.updateByPrimaryKeySelective(update);
|
||||
|
||||
// 如果设置了结束时间,发送延时消息自动结束考试
|
||||
if (existExam.getEndTime() != null && existExam.getEndTime().after(new Date())) {
|
||||
simpleMessageService.send(String.valueOf(id), RocketMqTagEnum.EXAM_AUTO_END, existExam.getEndTime().getTime());
|
||||
log.info("考试发布成功,已设置自动结束延时消息,examId:{}, endTime:{}", id, existExam.getEndTime());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endExam(Long id) {
|
||||
ExamInfoDO existExam = examInfoDAO.selectByPrimaryKey(id);
|
||||
if (existExam == null || CommonConstants.INDEX_ONE.equals(existExam.getDeleted())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_INFO_NOT_EXIST);
|
||||
}
|
||||
// 只有已发布状态可以结束
|
||||
if (!ExamInfoStatusEnum.canEnd(existExam.getStatus())) {
|
||||
if (ExamInfoStatusEnum.isEnded(existExam.getStatus())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_ALREADY_ENDED);
|
||||
}
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_NOT_PUBLISHED);
|
||||
}
|
||||
ExamInfoDO update = new ExamInfoDO();
|
||||
update.setId(id);
|
||||
update.setStatus(ExamInfoStatusEnum.ENDED.getCode());
|
||||
update.setEndTime(new Date());
|
||||
examInfoDAO.updateByPrimaryKeySelective(update);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageInfo<ExamInfoListVO> getExamList(ExamInfoListDTO dto) {
|
||||
PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
|
||||
List<ExamInfoDO> list = examInfoDAO.selectList(dto.getStatus());
|
||||
PageInfo<ExamInfoListVO> pageInfo = BeanUtil.toPage(new PageInfo<>(list), ExamInfoListVO.class);
|
||||
// 批量查询试卷信息
|
||||
List<Long> paperIds = CollStreamUtil.toList(list, ExamInfoDO::getPaperId);
|
||||
Map<Long, ExamPaperDO> paperMap = examPaperDAO.getMapByIds(paperIds);
|
||||
List<Long> examIds = CollStreamUtil.toList(list, ExamInfoDO::getId);
|
||||
Map<Long, Long> attemptCountMap = examAttemptDAO.getAttemptCount(examIds);
|
||||
pageInfo.getList().forEach(vo -> {
|
||||
ExamPaperDO paperDO = paperMap.get(vo.getPaperId());
|
||||
if (paperDO != null) {
|
||||
vo.setPaperName(paperDO.getPaperName());
|
||||
}
|
||||
vo.setAttemptCount(attemptCountMap.getOrDefault(vo.getId(), 0L).intValue());
|
||||
});
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExamInfoVO getExamDetail(Long id) {
|
||||
ExamInfoDO examInfoDO = examInfoDAO.selectByPrimaryKey(id);
|
||||
if (examInfoDO == null || CommonConstants.INDEX_ONE.equals(examInfoDO.getDeleted())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_INFO_NOT_EXIST);
|
||||
}
|
||||
ExamInfoVO vo = BeanUtil.toBean(examInfoDO, ExamInfoVO.class);
|
||||
ExamPaperDO paperDO = examPaperDAO.selectByPrimaryKey(examInfoDO.getPaperId());
|
||||
if (paperDO != null) {
|
||||
vo.setPaperName(paperDO.getPaperName());
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExamInfoVO getExamByToken(String token) {
|
||||
ExamInfoDO examInfoDO = examInfoDAO.selectByToken(token);
|
||||
if (examInfoDO == null || CommonConstants.INDEX_ONE.equals(examInfoDO.getDeleted())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_TOKEN_INVALID);
|
||||
}
|
||||
if (!ExamInfoStatusEnum.isPublished(examInfoDO.getStatus())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_NOT_PUBLISHED);
|
||||
}
|
||||
ExamInfoVO vo = BeanUtil.toBean(examInfoDO, ExamInfoVO.class);
|
||||
ExamPaperDO paperDO = examPaperDAO.selectByPrimaryKey(examInfoDO.getPaperId());
|
||||
if (paperDO != null) {
|
||||
vo.setPaperName(paperDO.getPaperName());
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteExam(Long id) {
|
||||
ExamInfoDO existExam = examInfoDAO.selectByPrimaryKey(id);
|
||||
if (existExam == null || CommonConstants.INDEX_ONE.equals(existExam.getDeleted())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_INFO_NOT_EXIST);
|
||||
}
|
||||
// 检查是否在考试中(已发布状态)
|
||||
if (ExamInfoStatusEnum.isPublished(existExam.getStatus())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_IN_PROGRESS_CANNOT_DELETE);
|
||||
}
|
||||
examInfoDAO.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void autoEndExam(Long id) {
|
||||
log.info("考试自动结束, id:{}", id);
|
||||
ExamInfoDO existExam = examInfoDAO.selectByPrimaryKey(id);
|
||||
if (existExam == null || CommonConstants.INDEX_ONE.equals(existExam.getDeleted())) {
|
||||
log.warn("自动结束考试失败,考试不存在,examId:{}", id);
|
||||
return;
|
||||
}
|
||||
// 只有已发布状态才自动结束
|
||||
if (!ExamInfoStatusEnum.isPublished(existExam.getStatus())) {
|
||||
log.info("考试非已发布状态,跳过自动结束,examId:{}, status:{}", id, existExam.getStatus());
|
||||
return;
|
||||
}
|
||||
ExamInfoDO update = new ExamInfoDO();
|
||||
update.setId(id);
|
||||
update.setStatus(ExamInfoStatusEnum.ENDED.getCode());
|
||||
update.setUpdateTime(new Date());
|
||||
examInfoDAO.updateByPrimaryKeySelective(update);
|
||||
log.info("考试自动结束成功,examId:{}", id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
package com.cool.store.service.exam.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollStreamUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.cool.store.constants.CommonConstants;
|
||||
import com.cool.store.context.CurrentUserHolder;
|
||||
import com.cool.store.dao.exam.ExamPaperDAO;
|
||||
import com.cool.store.dao.exam.ExamPaperQuestionDAO;
|
||||
import com.cool.store.dao.exam.ExamQuestionDAO;
|
||||
import com.cool.store.dto.exam.*;
|
||||
import com.cool.store.entity.exam.ExamPaperDO;
|
||||
import com.cool.store.entity.exam.ExamPaperQuestionDO;
|
||||
import com.cool.store.entity.exam.ExamQuestionDO;
|
||||
import com.cool.store.enums.ErrorCodeEnum;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.service.exam.ExamPaperService;
|
||||
import com.cool.store.utils.BeanUtil;
|
||||
import com.cool.store.vo.exam.ExamOptionVO;
|
||||
import com.cool.store.vo.exam.ExamPaperListVO;
|
||||
import com.cool.store.vo.exam.ExamPaperVO;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 试卷服务实现
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class ExamPaperServiceImpl implements ExamPaperService {
|
||||
|
||||
private final ExamPaperDAO examPaperDAO;
|
||||
private final ExamPaperQuestionDAO examPaperQuestionDAO;
|
||||
private final ExamQuestionDAO examQuestionDAO;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addPaper(ExamPaperAddDTO dto) {
|
||||
// 创建试卷
|
||||
ExamPaperDO paperDO = BeanUtil.toBean(dto, ExamPaperDO.class);
|
||||
paperDO.setCreateUserId(CurrentUserHolder.getUserId());
|
||||
examPaperDAO.insertSelective(paperDO);
|
||||
// 保存试卷题目
|
||||
BigDecimal totalScore = insertQuestionAndComputeTotalScore(dto.getQuestions(), paperDO.getId());
|
||||
// 更新总分
|
||||
ExamPaperDO updateDO = new ExamPaperDO();
|
||||
updateDO.setId(paperDO.getId());
|
||||
updateDO.setTotalScore(totalScore);
|
||||
examPaperDAO.updateByPrimaryKeySelective(updateDO);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updatePaper(ExamPaperAddDTO dto) {
|
||||
ExamPaperDO existPaper = examPaperDAO.selectByPrimaryKey(dto.getId());
|
||||
if (existPaper == null || CommonConstants.INDEX_ONE.equals(existPaper.getDeleted())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_PAPER_NOT_EXIST);
|
||||
}
|
||||
// 检查是否已开始考试
|
||||
if (CommonConstants.INDEX_ONE.equals(existPaper.getStartExam())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_PAPER_STARTED_CANNOT_EDIT);
|
||||
}
|
||||
ExamPaperDO paperDO = BeanUtil.toBean(dto, ExamPaperDO.class);
|
||||
// 如果有题目列表,更新题目
|
||||
if (CollectionUtils.isNotEmpty(dto.getQuestions())) {
|
||||
// 删除原有题目
|
||||
examPaperQuestionDAO.deleteByPaperId(dto.getId());
|
||||
// 重新添加题目(批量插入)
|
||||
BigDecimal totalScore = insertQuestionAndComputeTotalScore(dto.getQuestions(), dto.getId());
|
||||
// 更新总分
|
||||
paperDO.setTotalScore(totalScore);
|
||||
}
|
||||
examPaperDAO.updateByPrimaryKeySelective(paperDO);
|
||||
}
|
||||
|
||||
public BigDecimal insertQuestionAndComputeTotalScore(List<ExamPaperAddDTO.PaperQuestionItemDTO> questions, Long paperId) {
|
||||
BigDecimal totalScore = BigDecimal.ZERO;
|
||||
List<Long> questionIds = CollStreamUtil.toList(questions, ExamPaperAddDTO.PaperQuestionItemDTO::getQuestionId);
|
||||
Map<Long, ExamQuestionDO> questionMap = examQuestionDAO.getMapByIds(questionIds);
|
||||
List<ExamPaperQuestionDO> pqDOs = new ArrayList<>();
|
||||
for (ExamPaperAddDTO.PaperQuestionItemDTO item : questions) {
|
||||
ExamQuestionDO questionDO = questionMap.get(item.getQuestionId());
|
||||
if (questionDO == null || CommonConstants.INDEX_ONE.equals(questionDO.getDeleted())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_QUESTION_NOT_EXIST);
|
||||
}
|
||||
ExamPaperQuestionDO pqDO = BeanUtil.toBean(questionDO, ExamPaperQuestionDO.class);
|
||||
pqDO.setPaperId(paperId);
|
||||
pqDO.setQuestionId(item.getQuestionId());
|
||||
pqDO.setScore(item.getScore() != null ? item.getScore() : questionDO.getScore());
|
||||
pqDO.setCreateUserId(CurrentUserHolder.getUserId());
|
||||
pqDOs.add(pqDO);
|
||||
totalScore = totalScore.add(pqDO.getScore());
|
||||
}
|
||||
examPaperQuestionDAO.insertBatch(pqDOs);
|
||||
return totalScore;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void deletePaper(Long id) {
|
||||
ExamPaperDO existPaper = examPaperDAO.selectByPrimaryKey(id);
|
||||
if (existPaper == null || CommonConstants.INDEX_ONE.equals(existPaper.getDeleted())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_PAPER_NOT_EXIST);
|
||||
}
|
||||
// 检查是否已开始考试
|
||||
if (CommonConstants.INDEX_ONE.equals(existPaper.getStartExam())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_PAPER_STARTED_CANNOT_EDIT);
|
||||
}
|
||||
examPaperDAO.deleteById(id);
|
||||
examPaperQuestionDAO.deleteByPaperId(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageInfo<ExamPaperListVO> getPaperList(ExamPaperListDTO dto) {
|
||||
PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
|
||||
List<ExamPaperDO> list = examPaperDAO.selectList(dto.getPaperName(), dto.getEnable(), dto.getStartExam());
|
||||
PageInfo<ExamPaperListVO> pageInfo = BeanUtil.toPage(new PageInfo<>(list), ExamPaperListVO.class);
|
||||
pageInfo.getList().forEach(vo -> vo.setQuestionCount(examPaperQuestionDAO.countByPaperId(vo.getId())));
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExamPaperVO getPaperDetail(Long id) {
|
||||
ExamPaperDO paperDO = examPaperDAO.selectByPrimaryKey(id);
|
||||
if (paperDO == null || CommonConstants.INDEX_ONE.equals(paperDO.getDeleted())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_PAPER_NOT_EXIST);
|
||||
}
|
||||
|
||||
ExamPaperVO vo = new ExamPaperVO();
|
||||
BeanUtils.copyProperties(paperDO, vo);
|
||||
|
||||
// 查询题目列表
|
||||
ExamPaperQuestionDO pqQuery = new ExamPaperQuestionDO();
|
||||
pqQuery.setPaperId(id);
|
||||
pqQuery.setDeleted(0);
|
||||
List<ExamPaperQuestionDO> questions = examPaperQuestionDAO.select(pqQuery);
|
||||
List<ExamPaperVO.PaperQuestionVO> questionVOList = new ArrayList<>();
|
||||
int sortNo = 1;
|
||||
for (ExamPaperQuestionDO pq : questions) {
|
||||
ExamPaperVO.PaperQuestionVO qvo = new ExamPaperVO.PaperQuestionVO();
|
||||
BeanUtils.copyProperties(pq, qvo);
|
||||
// 将JSON字符串转为选项对象列表
|
||||
if (pq.getOptions() != null) {
|
||||
qvo.setOptions(JSON.parseArray(pq.getOptions(), ExamOptionVO.class));
|
||||
}
|
||||
qvo.setSortNo(sortNo++);
|
||||
questionVOList.add(qvo);
|
||||
}
|
||||
vo.setQuestions(questionVOList);
|
||||
vo.setQuestionCount(questionVOList.size());
|
||||
|
||||
return vo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasStartedExam(Long paperId) {
|
||||
ExamPaperDO paperDO = examPaperDAO.selectByPrimaryKey(paperId);
|
||||
return paperDO != null && CommonConstants.INDEX_ONE.equals(paperDO.getStartExam());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.cool.store.service.exam.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.cool.store.constants.CommonConstants;
|
||||
import com.cool.store.context.CurrentUserHolder;
|
||||
import com.cool.store.dao.exam.ExamQuestionDAO;
|
||||
import com.cool.store.dto.exam.*;
|
||||
import com.cool.store.entity.exam.ExamQuestionDO;
|
||||
import com.cool.store.enums.ErrorCodeEnum;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.service.exam.ExamQuestionService;
|
||||
import com.cool.store.utils.BeanUtil;
|
||||
import com.cool.store.vo.exam.ExamAnswerVO;
|
||||
import com.cool.store.vo.exam.ExamOptionVO;
|
||||
import com.cool.store.vo.exam.ExamQuestionListVO;
|
||||
import com.cool.store.vo.exam.ExamQuestionVO;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 题目服务实现
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class ExamQuestionServiceImpl implements ExamQuestionService {
|
||||
|
||||
private final ExamQuestionDAO examQuestionDAO;
|
||||
|
||||
@Override
|
||||
public void addQuestion(ExamQuestionAddDTO dto) {
|
||||
ExamQuestionDO questionDO = dto.convert();
|
||||
questionDO.setCreateUserId(CurrentUserHolder.getUserId());
|
||||
examQuestionDAO.insertSelective(questionDO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateQuestion(ExamQuestionAddDTO dto) {
|
||||
ExamQuestionDO existQuestion = examQuestionDAO.selectByPrimaryKey(dto.getId());
|
||||
if (existQuestion == null || CommonConstants.INDEX_ONE.equals(existQuestion.getDeleted())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_QUESTION_NOT_EXIST);
|
||||
}
|
||||
ExamQuestionDO questionDO = dto.convert();
|
||||
examQuestionDAO.updateByPrimaryKeySelective(questionDO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteQuestions(List<Long> ids) {
|
||||
examQuestionDAO.batchDeleteByIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageInfo<ExamQuestionListVO> getQuestionList(ExamQuestionListDTO dto) {
|
||||
PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
|
||||
List<ExamQuestionDO> list = examQuestionDAO.selecList(dto.getType(), dto.getDifficulty(), dto.getQuestionStem(), dto.getEnable());
|
||||
PageInfo<ExamQuestionDO> page = new PageInfo<>(list);
|
||||
return BeanUtil.toPage(page, ExamQuestionListVO.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExamQuestionVO getQuestionDetail(Long id) {
|
||||
ExamQuestionDO questionDO = examQuestionDAO.selectByPrimaryKey(id);
|
||||
if (questionDO == null || CommonConstants.INDEX_ONE.equals(questionDO.getDeleted())) {
|
||||
throw new ServiceException(ErrorCodeEnum.EXAM_QUESTION_NOT_EXIST);
|
||||
}
|
||||
return convertToVO(questionDO);
|
||||
}
|
||||
|
||||
private ExamQuestionVO convertToVO(ExamQuestionDO questionDO) {
|
||||
ExamQuestionVO vo = new ExamQuestionVO();
|
||||
BeanUtils.copyProperties(questionDO, vo);
|
||||
// 将JSON字符串转为答案对象
|
||||
if (questionDO.getAnswer() != null) {
|
||||
vo.setAnswer(JSON.parseObject(questionDO.getAnswer(), ExamAnswerVO.class));
|
||||
}
|
||||
// 将JSON字符串转为选项对象列表
|
||||
if (questionDO.getOptions() != null) {
|
||||
vo.setOptions(JSON.parseArray(questionDO.getOptions(), ExamOptionVO.class));
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.cool.store.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.cool.store.context.CurrentUserHolder;
|
||||
import com.cool.store.context.LoginUserInfo;
|
||||
import com.cool.store.dao.*;
|
||||
@@ -10,6 +11,7 @@ import com.cool.store.entity.SplitOrderDO;
|
||||
import com.cool.store.entity.StoreDO;
|
||||
import com.cool.store.enums.ErrorCodeEnum;
|
||||
import com.cool.store.enums.ExpenseSheetTypeEnum;
|
||||
import com.cool.store.enums.wallet.AdjustTypeEnum;
|
||||
import com.cool.store.enums.wallet.DocStatusEnum;
|
||||
import com.cool.store.enums.wallet.SplitSourceEnum;
|
||||
import com.cool.store.enums.wallet.SplitTypeEnum;
|
||||
@@ -19,11 +21,11 @@ import com.cool.store.request.wallet.ConfirmRechargeRequest;
|
||||
import com.cool.store.request.wallet.OutStoreIdRequest;
|
||||
import com.cool.store.response.AdjustmentOrderResponse;
|
||||
import com.cool.store.service.AdjustmentOrderService;
|
||||
import com.cool.store.service.SplitOrderService;
|
||||
import com.cool.store.service.UserAuthMappingService;
|
||||
import com.cool.store.service.dict.impl.DictService;
|
||||
import com.cool.store.service.wallet.WalletApiService;
|
||||
import com.cool.store.utils.GenerateNoUtil;
|
||||
import com.cool.store.vo.login.UserLoginVO;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -39,6 +41,7 @@ import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.cool.store.enums.fees.AllocationPayStatusEnum.*;
|
||||
import static com.cool.store.enums.fees.WalletFeeItemEnum.*;
|
||||
import static com.cool.store.enums.wallet.DocStatusEnum.*;
|
||||
|
||||
/**
|
||||
@@ -69,8 +72,17 @@ public class AdjustmentOrderServiceImpl implements AdjustmentOrderService {
|
||||
@Resource
|
||||
DictService dictService;
|
||||
|
||||
private static final String ADJUSTMENT_ORDER_PREFIX = "TZ";
|
||||
private static final String EXPENSE_SHEET_PREFIX = "FY";
|
||||
@Resource
|
||||
SplitOrderService splitOrderService;
|
||||
@Resource
|
||||
UserAuthMappingService userAuthMappingService;
|
||||
@Resource
|
||||
EnterpriseUserRoleDao enterpriseUserRoleDao;
|
||||
|
||||
|
||||
|
||||
private static final String PAYEE_ACCOUNT_NAME = "上海立规装饰设计工程有限公司";
|
||||
private static final String PAYEE_ACCOUNT_NO = "422011940168069";
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@@ -82,7 +94,10 @@ public class AdjustmentOrderServiceImpl implements AdjustmentOrderService {
|
||||
if (store == null) {
|
||||
throw new ServiceException(ErrorCodeEnum.STORE_IS_EXIST);
|
||||
}
|
||||
|
||||
Integer status = DOC_STATUS_1.getStatus();
|
||||
if (request.getAdjustType()!=null && request.getAdjustType()==2){
|
||||
status = DOC_STATUS_05.getStatus();
|
||||
}
|
||||
AdjustmentOrderDO adjustmentOrder = AdjustmentOrderDO.builder()
|
||||
.adjustmentNo(GenerateNoUtil.generateAdjustmentNo(request.getExpenseSheetType()))
|
||||
.storeId(request.getStoreId())
|
||||
@@ -97,7 +112,7 @@ public class AdjustmentOrderServiceImpl implements AdjustmentOrderService {
|
||||
.expenseSheetType(request.getExpenseSheetType())
|
||||
.settledAmount(new BigDecimal("0"))
|
||||
.pendingSettlementAmount(request.getAdjustAmount())
|
||||
.status(DOC_STATUS_1.getStatus())
|
||||
.status(status)
|
||||
.createUserId(userId)
|
||||
.createTime(new Date())
|
||||
.build();
|
||||
@@ -119,7 +134,7 @@ public class AdjustmentOrderServiceImpl implements AdjustmentOrderService {
|
||||
}
|
||||
|
||||
// 只有待确认缴费状态才能编辑
|
||||
if (!DOC_STATUS_1.getStatus().equals(existing.getStatus())) {
|
||||
if (!(DOC_STATUS_1.getStatus().equals(existing.getStatus())||DOC_STATUS_05.getStatus().equals(existing.getStatus()))) {
|
||||
throw new ServiceException(ErrorCodeEnum.NOT_SUPPORT_OPERATION);
|
||||
}
|
||||
|
||||
@@ -156,7 +171,7 @@ public class AdjustmentOrderServiceImpl implements AdjustmentOrderService {
|
||||
}
|
||||
|
||||
// 只有待确认缴费状态才能删除
|
||||
if (!DOC_STATUS_1.getStatus().equals(existing.getStatus())) {
|
||||
if (!DocStatusEnum.getCanDeleteStatus().contains(existing.getStatus())) {
|
||||
throw new ServiceException(ErrorCodeEnum.NOT_SUPPORT_OPERATION);
|
||||
}
|
||||
existing.setDeleted(1);
|
||||
@@ -177,10 +192,6 @@ public class AdjustmentOrderServiceImpl implements AdjustmentOrderService {
|
||||
|
||||
return buildResponse(adjustmentOrder);
|
||||
}
|
||||
@Resource
|
||||
UserAuthMappingService userAuthMappingService;
|
||||
@Resource
|
||||
EnterpriseUserRoleDao enterpriseUserRoleDao;
|
||||
|
||||
@Override
|
||||
public PageInfo<AdjustmentOrderResponse> page(AdjustmentOrderPageRequest request, String userId) {
|
||||
@@ -371,9 +382,68 @@ public class AdjustmentOrderServiceImpl implements AdjustmentOrderService {
|
||||
|
||||
log.info("费用调整单认款成功,单号:{},交易流水号:{}",
|
||||
adjustmentOrder.getAdjustmentNo(), request.getTradeNos());
|
||||
//查看当前门店是否有账户
|
||||
OutStoreIdRequest outStoreIdRequest = new OutStoreIdRequest();
|
||||
outStoreIdRequest.setOutStoreId(adjustmentOrder.getStoreId());
|
||||
AccountInfoDTO onlineAccountInfo = walletApiService.getOnlineAccountInfo(outStoreIdRequest);
|
||||
if (onlineAccountInfo==null){
|
||||
log.info("费用调整单认款成功_当前门店无网商钱包账户");
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
//费用单:费用类型为“灯箱广告类(立规) ”、“监控设备类(立规)” ,认款完成自动分账,默认分账到“上海立规装饰设计工程有限公司”
|
||||
if (autoSplitOrder(adjustmentOrder.getExpenseSheetType(),adjustmentOrder.getExpenseTypeCode(),adjustmentOrder.getAdjustType())){
|
||||
StoreDO store = storeDao.getByStoreId(adjustmentOrder.getStoreId());
|
||||
GenerateSplitOrderRequest generateSplitOrderRequest = new GenerateSplitOrderRequest();
|
||||
generateSplitOrderRequest.setId(update.getId());
|
||||
generateSplitOrderRequest.setRemark(store.getStoreName()+adjustmentOrder.getRemark());
|
||||
//
|
||||
generateSplitOrderRequest.setSplitType(SplitTypeEnum.ADD_BY_HAND.getStatus());
|
||||
generateSplitOrderRequest.setSplitAmount(adjustmentOrder.getPendingSettlementAmount());
|
||||
//收款账户
|
||||
generateSplitOrderRequest.setPayeeAccountName(PAYEE_ACCOUNT_NAME);
|
||||
generateSplitOrderRequest.setPayeeAccountNo(PAYEE_ACCOUNT_NO);
|
||||
//付款账户
|
||||
generateSplitOrderRequest.setPayerAccountName(onlineAccountInfo.getAccountName());
|
||||
generateSplitOrderRequest.setPayerAccountNo(onlineAccountInfo.getAccountNo());
|
||||
//生成分账单
|
||||
String splitOrder = generateSplitOrder(generateSplitOrderRequest);
|
||||
|
||||
SplitOrderDO adjustDO = splitOrderDAO.getBySplitNo(splitOrder);
|
||||
//确认分账
|
||||
splitOrderService.confirmSplitOrder(adjustDO.getId(),userInfo);
|
||||
}
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否自动分账
|
||||
* 费用单 广告费或者视频设备费
|
||||
* 调整单 广告费或者视频设备费 且是调增
|
||||
* @param expenseSheetType
|
||||
* @param expenseType
|
||||
* @param adjustType
|
||||
* @return
|
||||
*/
|
||||
private Boolean autoSplitOrder(Integer expenseSheetType, String expenseType, Integer adjustType) {
|
||||
// 广告费或者视频设备费
|
||||
boolean flag = ADVERTISEMENT_FEE.getExpenseType().equals(expenseType)
|
||||
|| VIDEO_DEVICE_FEE.getExpenseType().equals(expenseType);
|
||||
|
||||
if (expenseSheetType == ExpenseSheetTypeEnum.EXPENSE_SHEET.getCode()) {
|
||||
// 广告费或者视频设备费 自动分账 返回true,其他费用类型手动分账
|
||||
return flag;
|
||||
}
|
||||
|
||||
// 调整单逻辑
|
||||
if (expenseSheetType == ExpenseSheetTypeEnum.ADJUSTMENT_SHEET.getCode()) {
|
||||
// 调整单逻辑:调增 且 广告费/视频设备费 才自动分账
|
||||
return adjustType == AdjustTypeEnum.ADJUST_TYPE_1.getCode()&& flag;
|
||||
}
|
||||
|
||||
// 其他单据类型不分账
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean calculateAmount(String no, String transferAmount) {
|
||||
AdjustmentOrderDO adjustmentOrderDO = adjustmentOrderDAO.getByAdjustmentNo(no);
|
||||
@@ -410,9 +480,57 @@ public class AdjustmentOrderServiceImpl implements AdjustmentOrderService {
|
||||
|
||||
@Override
|
||||
public Long pageCount(AdjustmentOrderPageRequest request,LoginUserInfo user) {
|
||||
List<String> regionIds = new ArrayList<>();
|
||||
Boolean isAdmin = enterpriseUserRoleDao.checkIsAdmin(user.getUserId());
|
||||
//非管理员根据管辖权限查询 管理员查所有
|
||||
if (StringUtils.isNotEmpty(user.getUserId())&&!isAdmin){
|
||||
regionIds = userAuthMappingService.getAuthRegionIdAndSubRegionIdByUserId(user.getUserId());
|
||||
request.setRegionIds(regionIds);
|
||||
}
|
||||
return adjustmentOrderDAO.pageCount(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean approval(AdjustmentApprovalRequest request) {
|
||||
if (request.getId() == null) {
|
||||
throw new ServiceException(ErrorCodeEnum.CHANGE_ID_NOT_NULL);
|
||||
}
|
||||
|
||||
AdjustmentOrderDO adjustmentOrder = adjustmentOrderDAO.getById(request.getId());
|
||||
if (adjustmentOrder == null) {
|
||||
throw new ServiceException(ErrorCodeEnum.CHANGE_NOT_NULL);
|
||||
}
|
||||
|
||||
// 只有待审批状态才能审批
|
||||
if (!DOC_STATUS_05.getStatus().equals(adjustmentOrder.getStatus())) {
|
||||
throw new ServiceException(ErrorCodeEnum.NOT_SUPPORT_OPERATION);
|
||||
}
|
||||
|
||||
// 拒绝时必须填写拒绝原因
|
||||
if (request.getApprovalResult() == 2 && StringUtils.isBlank(request.getRejectReason())) {
|
||||
throw new ServiceException(ErrorCodeEnum.ERROR_MESSAGE, "拒绝原因不能为空");
|
||||
}
|
||||
|
||||
Integer newStatus;
|
||||
if (request.getApprovalResult() == 1) {
|
||||
// 审批通过,状态变为待充值
|
||||
newStatus = DOC_STATUS_1.getStatus();
|
||||
} else {
|
||||
// 审批拒绝,状态变为审批未通过
|
||||
newStatus = DOC_STATUS_15.getStatus();
|
||||
}
|
||||
|
||||
AdjustmentOrderDO update = AdjustmentOrderDO.builder()
|
||||
.id(request.getId())
|
||||
.status(newStatus)
|
||||
.rejectReason(request.getRejectReason())
|
||||
.build();
|
||||
|
||||
int result = adjustmentOrderDAO.update(update);
|
||||
return result > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建响应对象
|
||||
*/
|
||||
@@ -437,6 +555,7 @@ public class AdjustmentOrderServiceImpl implements AdjustmentOrderService {
|
||||
response.setClaimTime(adjustmentOrder.getClaimTime());
|
||||
response.setContractAttachmentInfo(adjustmentOrder.getContractAttachmentInfo());
|
||||
response.setPayTime(adjustmentOrder.getPayTime());
|
||||
response.setRejectReason(adjustmentOrder.getRejectReason());
|
||||
|
||||
// 设置门店信息
|
||||
if (StringUtils.isNotBlank(adjustmentOrder.getStoreId())) {
|
||||
|
||||
@@ -52,14 +52,14 @@ public class AuditOpeningOperationPlanImpl implements AuditOpeningOperationPlanS
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean auditPlan(OpeningOperationPlanAuditRequest request, LoginUserInfo user) {
|
||||
log.info("auditPlan request:{}", JSONObject.toJSONString(request));
|
||||
if (Objects.isNull(request)) {
|
||||
if (Boolean.TRUE) {
|
||||
log.error("auditPlan request is null");
|
||||
throw new ServiceException("auditPlan request is null");
|
||||
throw new ServiceException("接口废弃");
|
||||
}
|
||||
ShopStageInfoDO shopStageInfo = shopStageInfoDAO.getShopSubStageInfo(request.getShopId(), ShopSubStageEnum.SHOP_STAGE_14);
|
||||
if (!shopStageInfo.getShopSubStageStatus().equals(ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_141.getShopSubStageStatus())){
|
||||
throw new ServiceException(ErrorCodeEnum.NOT_ALLOW_OPERATE);
|
||||
}
|
||||
// if (!shopStageInfo.getShopSubStageStatus().equals(ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_141.getShopSubStageStatus())){
|
||||
// throw new ServiceException(ErrorCodeEnum.NOT_ALLOW_OPERATE);
|
||||
// }
|
||||
try {
|
||||
ShopAuditInfoDO shopAuditInfoDO = request.toShopAuditInfoDO();
|
||||
shopAuditInfoDO.setSubmittedUserId(user.getUserId());
|
||||
@@ -73,12 +73,12 @@ public class AuditOpeningOperationPlanImpl implements AuditOpeningOperationPlanS
|
||||
ShopSubStageStatusEnum shopSubStageStatusEnum = null;
|
||||
Boolean flag = Boolean.FALSE;
|
||||
if(OpeningOperationPlanResultTypeEnum.PASS_AUDIT.getCode().equals(request.getResultType())){
|
||||
shopSubStageStatusEnum = ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_143;
|
||||
//shopSubStageStatusEnum = ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_143;
|
||||
flag = Boolean.TRUE;
|
||||
}else {
|
||||
ShopInfoDO shopInfo = shopInfoDAO.getShopInfo(request.getShopId());
|
||||
LineInfoDO lineInfoDO = lineInfoDAO.getLineInfo(shopInfo.getLineId());
|
||||
shopSubStageStatusEnum = ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_142;
|
||||
//shopSubStageStatusEnum = ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_142;
|
||||
HashMap<String, String> map = new HashMap<>();
|
||||
map.put("partnerUsername",lineInfoDO.getUsername());
|
||||
map.put("partnerMobile",lineInfoDO.getMobile());
|
||||
|
||||
@@ -26,7 +26,7 @@ public class BigRegionServiceImpl implements BigRegionService {
|
||||
|
||||
@Override
|
||||
public List<BigRegionDTO> queryAllBigRegion(String keyword, Integer joinBrand,Integer type) {
|
||||
return bigRegionDAO.queryAllBigRegion(keyword, joinBrand,type);
|
||||
return bigRegionDAO.queryAllBigRegion(keyword, joinBrand,type,null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -51,11 +51,11 @@ import static com.cool.store.enums.point.ShopSubStageStatusEnum.SHOP_SUB_STAGE_S
|
||||
@Service
|
||||
@Slf4j
|
||||
public class BuildInformationServiceImpl implements BuildInformationService {
|
||||
@Resource
|
||||
private PlatformBuildDAO platformBuildDAO;
|
||||
@Resource
|
||||
private EnumInfoService enumInfoService;
|
||||
@Resource
|
||||
private PlatformBuildDAO platformBuildDAO;
|
||||
@Resource
|
||||
private RedisConstantUtil redisConstantUtil;
|
||||
@Resource
|
||||
private RedisUtilPool redisUtilPool;
|
||||
|
||||
@@ -1170,7 +1170,7 @@ public class DataHandlerServerImpl implements DataHandlerServer {
|
||||
shopInfoDO.setManagerRegionId(isCreateStoreDTO.getPid());
|
||||
updateList.add(shopInfoDO);
|
||||
}
|
||||
List<BigRegionDTO> bigRegionDTOS = bigRegionDAO.queryAllBigRegion(null, null,null);
|
||||
List<BigRegionDTO> bigRegionDTOS = bigRegionDAO.queryAllBigRegion(null, null,null,null);
|
||||
Map<Long, BigRegionDTO> bigRegionDTOMap = bigRegionDTOS.stream().collect(Collectors.toMap(BigRegionDTO::getRegionId, x -> x));
|
||||
//XX大区 正烧鸡
|
||||
List<Long> storeManageIds = bigRegionDTOS.stream().filter(x -> x.getStoreManageRegionId() != null).map(BigRegionDTO::getStoreManageRegionId).collect(Collectors.toList());
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.cool.store.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.cool.store.context.LoginUserInfo;
|
||||
import com.cool.store.dao.*;
|
||||
import com.cool.store.dto.DeskStageDTO;
|
||||
@@ -30,6 +31,7 @@ import com.cool.store.vo.LabelBaseInfoVO;
|
||||
import com.cool.store.vo.desk.*;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -50,6 +52,7 @@ import static com.cool.store.utils.poi.DateUtils.YYYY_MM_DD_HH_MM_SS;
|
||||
* @Date 2024/3/26 15:15
|
||||
* @Version 1.0
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class DeskServiceImpl implements DeskService {
|
||||
|
||||
@@ -96,6 +99,8 @@ public class DeskServiceImpl implements DeskService {
|
||||
@Autowired
|
||||
private ShopStageRemarkInfoDAO shopStageRemarkInfoDAO;
|
||||
@Resource
|
||||
OpeningOperationPlanDAO openingOperationPlanDAO;
|
||||
@Resource
|
||||
ShopAccountDAO shopAccountDAO;
|
||||
@Resource
|
||||
OperationsConsultantAssignDAO operationsConsultantAssignDAO;
|
||||
@@ -999,6 +1004,9 @@ public class DeskServiceImpl implements DeskService {
|
||||
List<ShopStageRemarkInfoDO> remarkInfoDOList = shopStageRemarkInfoDAO.getByShopIdsAndStage(shopIds, subStageStatusList);
|
||||
Map<Long, List<ShopStageRemarkInfoDO>> remarkInfoMap = remarkInfoDOList.stream().collect(Collectors.groupingBy(ShopStageRemarkInfoDO::getShopId));
|
||||
|
||||
List<OpeningOperationPlanDO> openingOperationPlanDOS = openingOperationPlanDAO.selectByShopIds(shopIds);
|
||||
Map<Long, OpeningOperationPlanDO> planDOMap = openingOperationPlanDOS.stream().collect(Collectors.toMap(OpeningOperationPlanDO::getShopId, Function.identity()));
|
||||
|
||||
List<PreparationCommonPendingVO> list = new ArrayList<>();
|
||||
specialShopStageInfo.forEach(x -> {
|
||||
PreparationCommonPendingVO preparationCommonPendingVO = new PreparationCommonPendingVO();
|
||||
@@ -1022,6 +1030,9 @@ public class DeskServiceImpl implements DeskService {
|
||||
preparationCommonPendingVO.setSignType(signFranchiseDO.getSignType());
|
||||
preparationCommonPendingVO.setPartnershipSignatorySecond(signFranchiseDO.getPartnershipSignatorySecond());
|
||||
}
|
||||
OpeningOperationPlanDO doMapOrDefault = planDOMap.getOrDefault(x.getShopId(), new OpeningOperationPlanDO());
|
||||
preparationCommonPendingVO.setOpenTime(doMapOrDefault.getOpenTime());
|
||||
preparationCommonPendingVO.setActivityTheme(doMapOrDefault.getActivityTheme());
|
||||
preparationCommonPendingVO.setShopCode(shopInfoDO.getShopCode());
|
||||
preparationCommonPendingVO.setJoinMode(shopInfoDO.getJoinMode());
|
||||
preparationCommonPendingVO.setInvestmentManager(userNameMap.getOrDefault(shopInfoDO.getInvestmentManager(),""));
|
||||
|
||||
@@ -73,7 +73,7 @@ public class EnterpriseServiceImpl implements EnterpriseService {
|
||||
currentUser.setId(enterpriseUser.getId());
|
||||
currentUser.setUserId(enterpriseUser.getUserId());
|
||||
currentUser.setAccount(enterpriseUser.getUserId());
|
||||
currentUser.setDbName("coolcollege_intelligent_10027");
|
||||
currentUser.setDbName("coolcollege_intelligent_74");
|
||||
currentUser.setDepartmentIds(enterpriseUser.getDepartments());
|
||||
currentUser.setRoles(enterpriseUser.getRoles());
|
||||
currentUser.setLanguage(enterpriseUser.getLanguage());
|
||||
|
||||
@@ -25,7 +25,7 @@ import com.cool.store.service.order.MiniStoreOrderService;
|
||||
import com.cool.store.service.order.impl.MiniStoreOrderServiceImpl;
|
||||
import com.cool.store.service.tp.TpScoreJournalService;
|
||||
import com.cool.store.service.visit.VisitRecordService;
|
||||
import com.cool.store.service.visit.VisitRecordService;
|
||||
import com.cool.store.utils.BeanUtil;
|
||||
import com.cool.store.utils.BeanUtil;
|
||||
import com.cool.store.utils.JSONUtils;
|
||||
import com.cool.store.utils.RedisUtilPool;
|
||||
@@ -40,7 +40,6 @@ import com.cool.store.vo.tp.TpScoreJournalVO;
|
||||
import com.cool.store.vo.visit.VisitRecordListVO;
|
||||
import com.cool.store.vo.point.PointExportVO;
|
||||
import com.cool.store.vo.point.PointPageVO;
|
||||
import com.cool.store.vo.visit.VisitRecordListVO;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@@ -853,6 +852,8 @@ public class ExportRealizeServiceImpl implements ExportRealizeService {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private List<PointExportVO> convertAndFillPointExport(List<PointPageVO> list) {
|
||||
List<Long> pointIds = CollStreamUtil.toList(list, PointPageVO::getPointId);
|
||||
Map<Long, PointFinancialDataDO> pointMap = pointFinancialDataDAO.getMapByPointIds(pointIds);
|
||||
|
||||
@@ -311,6 +311,7 @@ public class ExportServiceImpl implements ExportService {
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Long myPointExport(PointPageRequest request, LoginUserInfo user) {
|
||||
Long count = pointService.getMyPointCount(request, user.getUserId());
|
||||
|
||||
@@ -15,6 +15,8 @@ import com.cool.store.request.HqtPartnerAcceptanceRequest;
|
||||
import com.cool.store.request.hqt.*;
|
||||
import com.cool.store.response.HqtAPIResponse;
|
||||
import com.cool.store.service.HqtAPIService;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import okhttp3.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
package com.cool.store.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.cool.store.dao.BigRegionDAO;
|
||||
import com.cool.store.dao.ReceivingBankDAO;
|
||||
import com.cool.store.dao.RegionDao;
|
||||
import com.cool.store.dto.ImportOaOldShopDataDTO;
|
||||
import com.cool.store.dto.ImportOaOldShopDataErrorDTO;
|
||||
import com.cool.store.dto.ImportReceivingBankDTO;
|
||||
import com.cool.store.dto.ImportReceivingBankErrorDTO;
|
||||
import com.cool.store.dto.region.BigRegionDTO;
|
||||
import com.cool.store.entity.ImportTaskDO;
|
||||
import com.cool.store.entity.ReceivingBankDO;
|
||||
import com.cool.store.enums.FileTypeEnum;
|
||||
import com.cool.store.enums.FranchiseBrandEnum;
|
||||
import com.cool.store.enums.ImportTaskStatusEnum;
|
||||
import com.cool.store.enums.point.PayTypeEnum;
|
||||
import com.cool.store.mapper.ImportTaskMapper;
|
||||
import com.cool.store.request.ReceivingBankRequest;
|
||||
import com.cool.store.service.ImportService;
|
||||
import com.cool.store.utils.easyExcel.EasyExcelUtil;
|
||||
import com.cool.store.utils.poi.DateUtils;
|
||||
import com.cool.store.utils.poi.StringUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.ListUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.cool.store.utils.poi.DateUtils.SPECIAL_DATE_START_1;
|
||||
|
||||
/**
|
||||
* @Author: WangShuo
|
||||
* @Date: 2025/06/19/10:29
|
||||
* @Version 1.0
|
||||
* @注释:
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ImportServiceImpl implements ImportService {
|
||||
@Value("${mybatis.configuration.variables.enterpriseId}")
|
||||
private String eid;
|
||||
@Resource
|
||||
private EasyExcelUtil easyExcelUtil;
|
||||
@Resource
|
||||
private ImportTaskMapper importTaskMapper;
|
||||
@Resource
|
||||
private RegionDao regionDao;
|
||||
@Resource
|
||||
private BigRegionDAO bigRegionDAO;
|
||||
@Resource
|
||||
private ReceivingBankDAO receivingBankDAO;
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean importReceivingBank(List<ImportReceivingBankDTO> importList, String originalFilename, String userId, ImportTaskDO task) {
|
||||
List<ReceivingBankDO> list = new ArrayList<>();
|
||||
List<ImportReceivingBankErrorDTO> errorList = new ArrayList<>();
|
||||
List<BigRegionDTO> bigRegionDTOS = bigRegionDAO.queryAllBigRegion(null, null, null, null);
|
||||
Map<String, BigRegionDTO> bigRegionMap = bigRegionDTOS.stream().collect(Collectors.toMap(BigRegionDTO::getRegionName, x -> x));
|
||||
List<ReceivingBankDO> receivingBankDOS = receivingBankDAO.queryAll();
|
||||
Set<ReceivingBankDO> receivingBankSet = receivingBankDOS.stream()
|
||||
.map(bank -> new ReceivingBankDO(bank.getRegionId(), bank.getFranchiseBrand(), bank.getPayType()))
|
||||
.collect(Collectors.toSet());
|
||||
ListUtils.emptyIfNull(importList)
|
||||
.forEach(data -> {
|
||||
try {
|
||||
buildReceivingBankColumn(data,list,errorList,bigRegionMap,receivingBankSet,userId);
|
||||
} catch (Exception e) {
|
||||
ImportReceivingBankErrorDTO errorDTO = new ImportReceivingBankErrorDTO();
|
||||
//直接复制
|
||||
BeanUtils.copyProperties(data, errorDTO);
|
||||
errorDTO.setErrorMsg("数据处理异常,请确认!");
|
||||
errorList.add(errorDTO);
|
||||
log.info("importReceivingBank 转化error:{}", JSONObject.toJSONString(data));
|
||||
}
|
||||
});
|
||||
receivingBankDAO.batchInsertOrUpdate(list);
|
||||
if (!errorList.isEmpty()) {
|
||||
task.setStatus(ImportTaskStatusEnum.ERROR.getCode());
|
||||
String url = null;
|
||||
try {
|
||||
url = easyExcelUtil.exportExcel(ImportReceivingBankErrorDTO.class, errorList, null,
|
||||
FileTypeEnum.RECEIVING_BANK_IMPORT.getDesc() + DateUtils.parseDateToStr(SPECIAL_DATE_START_1, new Date()),
|
||||
FileTypeEnum.RECEIVING_BANK_IMPORT.getDesc() + DateUtils.parseDateToStr(SPECIAL_DATE_START_1, new Date()));
|
||||
} catch (Exception e) {
|
||||
log.info("导出失败列表失败 errorList:{}", JSONObject.toJSONString(errorList));
|
||||
}
|
||||
task.setFileUrl(url);
|
||||
} else {
|
||||
task.setStatus(ImportTaskStatusEnum.SUCCESS.getCode());
|
||||
}
|
||||
task.setTotalNum(importList.size());
|
||||
task.setSuccessNum(importList.size() - errorList.size());
|
||||
importTaskMapper.update(eid, task);
|
||||
log.info("导入数据条数:{}", list.size());
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
log.info("导入数据转化为空");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param dto excel列表数据
|
||||
* @param list 正常导入的数据
|
||||
* @param errorList 错误导入的数据
|
||||
* @param bigRegionMap 区域数据
|
||||
* @param receivingBankSet 重复数据校验
|
||||
* @param userId 用户id
|
||||
* @return
|
||||
*/
|
||||
private boolean buildReceivingBankColumn(ImportReceivingBankDTO dto, List<ReceivingBankDO> list,
|
||||
List<ImportReceivingBankErrorDTO> errorList,
|
||||
Map<String, BigRegionDTO> bigRegionMap,
|
||||
Set<ReceivingBankDO> receivingBankSet, String userId) {
|
||||
// 1. 统一获取并处理字段
|
||||
String franchiseBrand = StringUtils.trimToNull(dto.getFranchiseBrand());
|
||||
String regionName = StringUtils.trimToNull(dto.getRegionName());
|
||||
String payType = StringUtils.trimToNull(dto.getPayType());
|
||||
String payee = StringUtils.trimToNull(dto.getPayee());
|
||||
String receivingAccount = StringUtils.trimToNull(dto.getReceivingAccount());
|
||||
String bankName = StringUtils.trimToNull(dto.getBankName());
|
||||
String branchBankName = StringUtils.trimToNull(dto.getBranchBankName());
|
||||
|
||||
// 2. 错误信息收集
|
||||
StringBuilder errorMsg = new StringBuilder();
|
||||
|
||||
if (FranchiseBrandEnum.getCodeByDesc(franchiseBrand) == null) {
|
||||
errorMsg.append("品牌信息错误;");
|
||||
}
|
||||
if (bigRegionMap.get(regionName) == null) {
|
||||
errorMsg.append("大区信息错误;");
|
||||
}
|
||||
if (PayTypeEnum.getCodeByDesc(payType) == null) {
|
||||
errorMsg.append("付款方式信息错误;");
|
||||
}
|
||||
if (StringUtils.isBlank(payee)) {
|
||||
errorMsg.append("收款人不能为空;");
|
||||
}
|
||||
if (StringUtils.isBlank(receivingAccount)) {
|
||||
errorMsg.append("收款账户不能为空;");
|
||||
}
|
||||
if (StringUtils.isBlank(bankName)) {
|
||||
errorMsg.append("收款银行不能为空;");
|
||||
}
|
||||
if (StringUtils.isBlank(branchBankName)) {
|
||||
errorMsg.append("收款银行开户行不能为空;");
|
||||
}
|
||||
// if (receivingBankSet.contains(new ReceivingBankDO(
|
||||
// bigRegionMap.get(regionName) != null ? bigRegionMap.get(regionName).getRegionId() : null,
|
||||
// FranchiseBrandEnum.getCodeByDesc(franchiseBrand) != null ? FranchiseBrandEnum.getCodeByDesc(franchiseBrand) : null,
|
||||
// PayTypeEnum.getCodeByDesc(payType) != null ? PayTypeEnum.getCodeByDesc(payType) : null))) {
|
||||
// errorMsg.append("收款信息已存在;");
|
||||
// }
|
||||
|
||||
// 3. 只有存在错误时才创建错误dto 没有错误不需要创建对象
|
||||
if (errorMsg.length() > 0) {
|
||||
ImportReceivingBankErrorDTO errorDTO = new ImportReceivingBankErrorDTO();
|
||||
//直接复制
|
||||
BeanUtils.copyProperties(dto, errorDTO);
|
||||
errorDTO.setErrorMsg(errorMsg.toString());
|
||||
errorList.add(errorDTO);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4. 正常数据处理
|
||||
ReceivingBankDO bankDO = new ReceivingBankDO();
|
||||
bankDO.setRegionId(bigRegionMap.get(regionName).getRegionId());
|
||||
bankDO.setFranchiseBrand(FranchiseBrandEnum.getCodeByDesc(franchiseBrand));
|
||||
bankDO.setPayType(PayTypeEnum.getCodeByDesc(payType));
|
||||
bankDO.setPayee(payee);
|
||||
bankDO.setReceivingAccount(receivingAccount);
|
||||
bankDO.setBankName(bankName);
|
||||
bankDO.setBranchBankName(branchBankName);
|
||||
bankDO.setCreateTime(new Date());
|
||||
bankDO.setCreateUser(userId);
|
||||
bankDO.setUpdateTime(new Date());
|
||||
bankDO.setUpdateUser(userId);
|
||||
list.add(bankDO);
|
||||
|
||||
// 5. 添加到已存在集合
|
||||
receivingBankSet.add(new ReceivingBankDO(
|
||||
bankDO.getRegionId(),
|
||||
bankDO.getFranchiseBrand(),
|
||||
bankDO.getPayType()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package com.cool.store.service.impl;
|
||||
|
||||
import com.cool.store.constants.RedisConstant;
|
||||
import com.cool.store.dao.StoreDao;
|
||||
import com.cool.store.dao.ThirdPartyAccountDAO;
|
||||
import com.cool.store.dao.ThirdPartyStoreDAO;
|
||||
import com.cool.store.entity.StoreDO;
|
||||
import com.cool.store.entity.ThirdPartyAccountDO;
|
||||
import com.cool.store.entity.ThirdPartyStoreDO;
|
||||
import com.cool.store.enums.ErrorCodeEnum;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.request.liepin.AddStoreEmpRequest;
|
||||
import com.cool.store.request.liepin.AddStoreRequest;
|
||||
import com.cool.store.request.liepin.GetPathRequest;
|
||||
import com.cool.store.response.liepin.PathResponse;
|
||||
import com.cool.store.service.LiePinService;
|
||||
import com.cool.store.service.ThirdLiePinService;
|
||||
import com.cool.store.utils.RedisConstantUtil;
|
||||
import com.cool.store.utils.RedisUtilPool;
|
||||
import com.cool.store.utils.StringUtil;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* @Author suzhuhong
|
||||
* @Date 2025/5/26 19:27
|
||||
* @Version 1.0
|
||||
*/
|
||||
@Service
|
||||
public class LiePinServiceImpl implements LiePinService {
|
||||
|
||||
|
||||
@Resource
|
||||
ThirdPartyStoreDAO thirdPartyStoreDAO;
|
||||
@Resource
|
||||
ThirdPartyAccountDAO thirdPartyAccountDAO;
|
||||
@Resource
|
||||
StoreDao storeDao;
|
||||
@Resource
|
||||
ThirdLiePinService thirdLiePinService;
|
||||
|
||||
@Value("${liePin.tenantId}")
|
||||
private Long tenantId;
|
||||
@Resource
|
||||
RedisUtilPool redisUtilPool;
|
||||
@Resource
|
||||
private RedisConstantUtil redisConstantUtil;
|
||||
|
||||
|
||||
@Override
|
||||
public String getJumpUrl(String shopCode,String mobile,String userName) {
|
||||
String key = redisConstantUtil.getKeyCommonMethod(RedisConstant.LIE_PIN_EMP_PATH_PREFIX, shopCode,mobile);
|
||||
String path = redisUtilPool.getString(key);
|
||||
if (StringUtil.isNotEmpty(path)){
|
||||
return path;
|
||||
}
|
||||
//查询当前门店是否推送该人员和门店到猎聘 如果没有推送 先推送
|
||||
ThirdPartyAccountDO codeAndMobile = thirdPartyAccountDAO.getByCodeAndMobile(shopCode, mobile);
|
||||
Long storeId = null;
|
||||
if (codeAndMobile!=null){
|
||||
storeId = Long.valueOf(codeAndMobile.getThirdPartyStoreId());
|
||||
}else {
|
||||
//先推送门店
|
||||
storeId = pushStoreToLiePin(shopCode);
|
||||
//推送人员
|
||||
pushStoreEmpToLiePin(shopCode, mobile,userName);
|
||||
}
|
||||
//推送门店推送人员
|
||||
GetPathRequest pathRequest = GetPathRequest.builder().mobile(mobile).store_id(String.valueOf(storeId)).tenant_id(tenantId).build();
|
||||
PathResponse pathDTO = thirdLiePinService.getPath(pathRequest);
|
||||
//存储3分钟
|
||||
redisUtilPool.setString(key,pathDTO.getPath(),3*60);
|
||||
return pathDTO.getPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long pushStoreToLiePin(String shopCode) {
|
||||
//首先校验门店是否推送过
|
||||
ThirdPartyStoreDO storeRecord = thirdPartyStoreDAO.getByLocalStoreCode(shopCode);
|
||||
if (storeRecord!=null){
|
||||
return Long.valueOf(storeRecord.getThirdPartyStoreId());
|
||||
}
|
||||
//校验推送的数据是否全 不全提示信息不足
|
||||
StoreDO store = storeDao.getByStoreNum(shopCode);
|
||||
if (StringUtil.isAnyBlank(store.getStoreAddress(),store.getLatitude(),store.getLongitude(),store.getAvatar(),store.getTelephone())){
|
||||
throw new ServiceException(ErrorCodeEnum.STORE_INFO_INSUFFICIENT);
|
||||
}
|
||||
//oss文件换猎聘文件路径
|
||||
String filePath = thirdLiePinService.getFilePath(store.getAvatar());
|
||||
AddStoreRequest addStore = AddStoreRequest.builder().store_name(store.getStoreName()).
|
||||
address(store.getStoreAddress())
|
||||
.longitude(store.getLongitude())
|
||||
.latitude(store.getLatitude())
|
||||
.contact_person_mobile(store.getTelephone())
|
||||
.exigency_mobile(store.getTelephone())
|
||||
.contact_person_name(store.getStoreName() + store.getTelephone())
|
||||
.doorplate_picture(filePath).tenant_id(tenantId).build();
|
||||
Long storeId = thirdLiePinService.addStoreToLiePin(addStore);
|
||||
//成功之后新增记录
|
||||
ThirdPartyStoreDO thirdPartyStoreDO = ThirdPartyStoreDO.builder().localStoreCode(shopCode).thirdPartyStoreId(String.valueOf(storeId)).thirdPartyStoreUrl(filePath).build();
|
||||
thirdPartyStoreDAO.addPushRecord(thirdPartyStoreDO);
|
||||
return storeId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long pushStoreEmpToLiePin(String shopCode, String mobile, String userName) {
|
||||
if (StringUtil.isAnyBlank(shopCode,mobile)){
|
||||
throw new ServiceException(ErrorCodeEnum.PARAMS_REQUIRED);
|
||||
}
|
||||
ThirdPartyAccountDO codeAndMobile = thirdPartyAccountDAO.getByCodeAndMobile(shopCode, mobile);
|
||||
if (codeAndMobile!=null){
|
||||
return Long.valueOf(codeAndMobile.getThirdPartyAccountId());
|
||||
}
|
||||
if (StringUtil.isEmpty(userName)){
|
||||
userName = "店员" + mobile;
|
||||
}
|
||||
Long storeId = pushStoreToLiePin(shopCode);
|
||||
|
||||
AddStoreEmpRequest request = AddStoreEmpRequest.builder().store_id(storeId).account_type(1).position_id(1L).tenant_id(tenantId).mobile(mobile).nick_name(userName).build();
|
||||
Long accountId = thirdLiePinService.addStoreEmp(request);
|
||||
|
||||
ThirdPartyAccountDO accountDO = ThirdPartyAccountDO.builder().accountType(request.getAccount_type()).mobile(mobile)
|
||||
.positionId(request.getPosition_id()).localStoreCode(shopCode).thirdPartyStoreId(String
|
||||
.valueOf(storeId)).thirdPartyAccountId(String.valueOf(accountId)).build();
|
||||
thirdPartyAccountDAO.addPushRecord(accountDO);
|
||||
return accountId;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -101,7 +101,6 @@ public abstract class LineFlowService {
|
||||
if (CollectionUtils.isNotEmpty(shopInfoDOS)){
|
||||
throw new ServiceException(ErrorCodeEnum.SHOP_HAVE_NOT_OVER_ACCORDING);
|
||||
}
|
||||
|
||||
LineInfoDO lineInfo = lineInfoDAO.getLineInfo(request.getLineId());
|
||||
String partnerId = lineInfo.getPartnerId();
|
||||
LineAuditInfoDO auditInfo = new LineAuditInfoDO();
|
||||
|
||||
@@ -6,10 +6,7 @@ import com.alibaba.fastjson.JSONObject;
|
||||
import com.cool.store.constants.CommonConstants;
|
||||
import com.cool.store.constants.RedisConstant;
|
||||
import com.cool.store.context.LoginUserInfo;
|
||||
import com.cool.store.dao.HyPartnerUserInfoDAO;
|
||||
import com.cool.store.dao.LineInfoDAO;
|
||||
import com.cool.store.dao.LinePayDAO;
|
||||
import com.cool.store.dao.ShopStageInfoDAO;
|
||||
import com.cool.store.dao.*;
|
||||
import com.cool.store.dto.AmountDTO;
|
||||
import com.cool.store.entity.*;
|
||||
import com.cool.store.enums.*;
|
||||
@@ -21,13 +18,16 @@ import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.mapper.FranchiseFeeMapper;
|
||||
import com.cool.store.mapper.LineInfoMapper;
|
||||
import com.cool.store.mapper.ShopInfoMapper;
|
||||
import com.cool.store.request.FranchiseFeePayOnlineRequest;
|
||||
import com.cool.store.request.LinePaySubmitRequest;
|
||||
import com.cool.store.request.xgj.ReceiptCallBackRequest;
|
||||
import com.cool.store.request.xgj.ReceiptRequest;
|
||||
import com.cool.store.request.xgj.*;
|
||||
import com.cool.store.response.FranchiseFeePayInfoResponse;
|
||||
import com.cool.store.response.FranchiseFeePayOnlineResponse;
|
||||
import com.cool.store.response.ReceivingBankResponse;
|
||||
import com.cool.store.response.bigdata.ApiResponse;
|
||||
import com.cool.store.service.LinePayService;
|
||||
import com.cool.store.service.PushService;
|
||||
import com.cool.store.service.ReceivingBankService;
|
||||
import com.cool.store.service.UserAuthMappingService;
|
||||
import com.cool.store.utils.CoolDateUtils;
|
||||
import com.cool.store.utils.RedisConstantUtil;
|
||||
@@ -39,6 +39,7 @@ import com.cool.store.vo.LinePayVO;
|
||||
import com.cool.store.vo.PartnerUserInfoVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -52,6 +53,7 @@ import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.cool.store.enums.WorkflowSubStageStatusEnum.PAY_DEPOSIT_45;
|
||||
import static com.cool.store.utils.poi.DateUtils.SPECIAL_DATE_START;
|
||||
import static com.cool.store.utils.poi.DateUtils.YYYY_MM_DD_HH_MM_SS;
|
||||
|
||||
@@ -92,6 +94,8 @@ public class LinePayServiceImpl implements LinePayService {
|
||||
RedisConstantUtil redisConstantUtil;
|
||||
@Resource
|
||||
PushService pushService;
|
||||
@Resource
|
||||
private ReceivingBankService receivingBankService;
|
||||
|
||||
@Override
|
||||
public LinePayVO getLinePayInfo(Long lineId, Integer businessType, Long shopId) {
|
||||
@@ -132,7 +136,7 @@ public class LinePayServiceImpl implements LinePayService {
|
||||
if (lineInfo == null) {
|
||||
throw new ServiceException(ErrorCodeEnum.LINE_ID_IS_NOT_EXIST);
|
||||
}
|
||||
if (!WorkflowSubStageStatusEnum.PAY_DEPOSIT_45.getCode().equals(lineInfo.getWorkflowSubStageStatus())) {
|
||||
if (!PAY_DEPOSIT_45.getCode().equals(lineInfo.getWorkflowSubStageStatus())) {
|
||||
throw new ServiceException(ErrorCodeEnum.LINE_STATUS_NOT_ALLOW_OPERATE);
|
||||
}
|
||||
lineInfo.setWorkflowSubStage(WorkflowSubStageEnum.SIGN_INTENT_AGREEMENT.getCode());
|
||||
@@ -161,7 +165,8 @@ public class LinePayServiceImpl implements LinePayService {
|
||||
if (StringUtils.isBlank(userId)) {
|
||||
throw new ServiceException(ErrorCodeEnum.ACCESS_TOKEN_INVALID);
|
||||
}
|
||||
FranchiseFeeDO franchiseFeeDO = franchiseFeeMapper.selectByShopId(request.getShopId());
|
||||
// doFilter(request.getShopId(),request.getAmount(),request.getId(),request.getPayUserName());
|
||||
// FranchiseFeeDO franchiseFeeDO = franchiseFeeMapper.selectByShopId(request.getShopId());
|
||||
//判断付款人最多2人(可重复)
|
||||
List<LinePayDO> list = linePayDAO.getFranchiseFeePayInfoByShopId(request.getShopId());
|
||||
Map<Long, LinePayDO> payIdMap = list.stream().collect(Collectors.toMap(LinePayDO::getId, Function.identity()));
|
||||
@@ -216,7 +221,7 @@ public class LinePayServiceImpl implements LinePayService {
|
||||
LinePayDO linePayById = linePayDAO.getById(linePayDO.getId());
|
||||
if (linePayById == null) {
|
||||
log.info("linePayById is null");
|
||||
throw new ServiceException(ErrorCodeEnum.UPDATE_ERROR);
|
||||
throw new ServiceException(ErrorCodeEnum.UPDATE_ERROR);
|
||||
} else {
|
||||
linePayDO.setUpdateTime(new Date());
|
||||
linePayDO.setUpdateUserId(userId);
|
||||
@@ -250,6 +255,37 @@ public class LinePayServiceImpl implements LinePayService {
|
||||
}
|
||||
}
|
||||
|
||||
private void doFilter(Long shopId,BigDecimal amount,Long payId,String payUserName) {
|
||||
FranchiseFeeDO franchiseFeeDO = franchiseFeeMapper.selectByShopId(shopId);
|
||||
//判断付款人最多2人(可重复)
|
||||
List<LinePayDO> list = linePayDAO.getFranchiseFeePayInfoByShopId(shopId);
|
||||
list=list.stream().filter(linePayDO -> !linePayDO.getPayStatus().equals(PayStatusEnum.CANCELED.getCode())
|
||||
&&!linePayDO.getPayStatus().equals(PayStatusEnum.PAY_FAIL_55.getCode())).collect(Collectors.toList());
|
||||
Map<Long, LinePayDO> payIdMap = list.stream().collect(Collectors.toMap(LinePayDO::getId, Function.identity()));
|
||||
if (payId!= null) {
|
||||
payIdMap.remove(payId);
|
||||
}
|
||||
//判断缴费金额不能大于未缴费金额
|
||||
BigDecimal total = payIdMap.values().stream()
|
||||
.map(LinePayDO::getAmount)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
//应缴金额
|
||||
BigDecimal amountDue = new BigDecimal(franchiseFeeDO.getYearFranchiseFee())
|
||||
.add(new BigDecimal(franchiseFeeDO.getLoanMargin()))
|
||||
.add(new BigDecimal(franchiseFeeDO.getFirstYearFee()))
|
||||
.add(new BigDecimal(franchiseFeeDO.getFirstYearManageFee()))
|
||||
.add(new BigDecimal(franchiseFeeDO.getPerformanceBond()));
|
||||
//未缴费金额
|
||||
BigDecimal amountUnpaid = amountDue.subtract(total);
|
||||
if (amount.compareTo(amountUnpaid) > 0) {
|
||||
throw new ServiceException(ErrorCodeEnum.PAY_AMOUNT_ERROR);
|
||||
}
|
||||
Set<String> payUserList = list.stream().map(LinePayDO::getPayUserName).collect(Collectors.toSet());
|
||||
if (!payUserList.contains(payUserName) && payUserList.size() >= 2) {
|
||||
throw new ServiceException(ErrorCodeEnum.PAY_USER_NAME_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPaymentReceiptCode() {
|
||||
//当前日期
|
||||
@@ -314,6 +350,18 @@ public class LinePayServiceImpl implements LinePayService {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean onlinePushPayInfo(Long shopId, LinePayDO linePayDO) {
|
||||
FranchiseFeeDO franchiseFeeDO = franchiseFeeMapper.selectByShopId(shopId);
|
||||
ReceivingBankResponse receivingBankResponse = receivingBankService.getByShopId(shopId);
|
||||
ReceiptOnlineRequest receiptOnlineRequest = new ReceiptOnlineRequest(shopId, franchiseFeeDO.getId().intValue(), linePayDO);
|
||||
receiptOnlineRequest.setPayee(receivingBankResponse.getPayee());
|
||||
receiptOnlineRequest.setReceivingAccount(receivingBankResponse.getReceivingAccount());
|
||||
receiptOnlineRequest.setBankName(receivingBankResponse.getBankName());
|
||||
receiptOnlineRequest.setBranchBankName(receivingBankResponse.getBranchBankName());
|
||||
return pushService.pushOnlineReceiptToXGJ(receiptOnlineRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ApiResponse<Boolean> ReceiptCallBack(ReceiptCallBackRequest request) {
|
||||
@@ -322,11 +370,139 @@ public class LinePayServiceImpl implements LinePayService {
|
||||
return ApiResponse.error(ErrorCodeEnum.RECEIPT_NOT_EXIST);
|
||||
}
|
||||
linePayDO.setXgjClaimStatus(request.getClaimStatus());
|
||||
if (StringUtils.isNotEmpty(request.getFailReason())){
|
||||
linePayDO.setXgjFailReason(request.getFailReason());
|
||||
}
|
||||
linePayDO.setUpdateTime(new Date());
|
||||
linePayDAO.updateLinePay(linePayDO);
|
||||
return ApiResponse.success(Boolean.TRUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse<Boolean> changeOnlinePayInfo(OnlinePayInfoRequest onlinePayInfoRequest) {
|
||||
if (PayStatusEnum.FEES_HAVE_BEEN_PAID_50.getCode().equals(onlinePayInfoRequest.getPaymentStatus())&&StringUtils.isEmpty(onlinePayInfoRequest.getPaySerialNumber())&&
|
||||
ObjectUtils.anyNull(onlinePayInfoRequest.getActAmount(),onlinePayInfoRequest.getPayTime())){
|
||||
return ApiResponse.error(ErrorCodeEnum.PARAMS_REQUIRED);
|
||||
}
|
||||
//根据收款单编号查询
|
||||
LinePayDO linePayDO = linePayDAO.selectByPaymentReceiptCode(onlinePayInfoRequest.getReceiptId());
|
||||
if (Objects.isNull(linePayDO)) {
|
||||
return ApiResponse.error(ErrorCodeEnum.RECEIPT_NOT_EXIST);
|
||||
}
|
||||
linePayDO.setPayStatus(onlinePayInfoRequest.getPaymentStatus());
|
||||
linePayDO.setPayTime(onlinePayInfoRequest.getPayTime());
|
||||
linePayDO.setPaySerialNumber(onlinePayInfoRequest.getPaySerialNumber());
|
||||
linePayDO.setXgjClaimStatus(onlinePayInfoRequest.getClaimStatus());
|
||||
linePayDO.setAmount(onlinePayInfoRequest.getActAmount());
|
||||
linePayDAO.updateLinePay(linePayDO);
|
||||
return ApiResponse.success(Boolean.TRUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public FranchiseFeePayOnlineResponse franchiseFeePayOnline(FranchiseFeePayOnlineRequest request, String userId) {
|
||||
if (request.getId()!=null){
|
||||
throw new ServiceException(ErrorCodeEnum.NOT_ALLOW_OPERATE);
|
||||
}
|
||||
String lockKey = "submitFranchiseFeePayInfoOnline:lineId" + request.getLineId() + "shopId" + request.getShopId();
|
||||
doFilter(request.getShopId(),request.getAmount(),request.getId(),request.getPayUserName());
|
||||
ShopStageInfoDO shopSubStageInfo = shopStageInfoDAO.getShopSubStageInfo(request.getShopId(), ShopSubStageEnum.SHOP_STAGE_7);
|
||||
if (!shopSubStageInfo.getShopSubStageStatus().equals(ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_72.getShopSubStageStatus())
|
||||
&& !shopSubStageInfo.getShopSubStageStatus().equals(ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_71.getShopSubStageStatus())) {
|
||||
throw new ServiceException(ErrorCodeEnum.NOT_ALLOW_OPERATE);
|
||||
}
|
||||
//流水
|
||||
String lockValue = UUID.randomUUID().toString();
|
||||
boolean acquired = false;
|
||||
try {
|
||||
//10s过期
|
||||
acquired = redisUtilPool.setNxExpire(lockKey, lockValue, CommonConstants.TEN_SECONDS);
|
||||
if (Boolean.TRUE.equals(acquired)) {
|
||||
LineInfoDO lineInfo = lineInfoDAO.getLineInfo(request.getLineId());
|
||||
FranchiseFeePayOnlineResponse response = new FranchiseFeePayOnlineResponse();
|
||||
response.setShopId(request.getShopId());
|
||||
//新增
|
||||
if (request.getId() == null) {
|
||||
LinePayDO linePayDO = new LinePayDO();
|
||||
linePayDO.setShopId(request.getShopId());
|
||||
linePayDO.setLineId(request.getLineId());
|
||||
linePayDO.setAmount(request.getAmount());
|
||||
linePayDO.setPayBusinessType(PayBusinessTypeEnum.FRANCHISE_FEE.getCode());
|
||||
linePayDO.setPartnerId(lineInfo.getPartnerId());
|
||||
linePayDO.setPayStatus(PayStatusEnum.WAIT_PAY_45.getCode());
|
||||
linePayDO.setPayType(PayTypeEnum.ONLINE_PAY.getCode());
|
||||
linePayDO.setPayUserName(request.getPayUserName());
|
||||
linePayDO.setCreateUserId(userId);
|
||||
linePayDO.setCreateTime(new Date());
|
||||
linePayDO.setXgjClaimStatus(ClaimStatusEnum.TO_BE_CLAIMED.getCode());
|
||||
linePayDO.setPaymentReceiptCode(this.getPaymentReceiptCode());
|
||||
linePayDO.setDeleted(false);
|
||||
linePayDAO.addLinePay(linePayDO);
|
||||
response.setPaymentReceiptCode(linePayDO.getPaymentReceiptCode());
|
||||
//推送收款单到新管家
|
||||
this.onlinePushPayInfo(request.getShopId(),linePayDO);
|
||||
}else{
|
||||
//修改
|
||||
LinePayDO linePayDO = linePayDAO.getById(request.getId());
|
||||
if (linePayDO == null){
|
||||
throw new ServiceException(ErrorCodeEnum.UPDATE_ERROR);
|
||||
}
|
||||
if (linePayDO.getXgjClaimStatus().equals(ClaimStatusEnum.CLAIMED.getCode())){
|
||||
throw new ServiceException(ErrorCodeEnum.CLAIM_STATUS_ERROR);
|
||||
}
|
||||
if (linePayDO.getPayStatus().equals(PayStatusEnum.CANCELED.getCode())
|
||||
||linePayDO.getPayStatus().equals(PayStatusEnum.FEES_HAVE_BEEN_PAID_50.getCode())){
|
||||
throw new ServiceException(ErrorCodeEnum.NOT_ALLOW_OPERATE);
|
||||
}
|
||||
linePayDO.setUpdateTime(new Date());
|
||||
linePayDO.setPayStatus(PayStatusEnum.WAIT_PAY_45.getCode());
|
||||
linePayDO.setPayUserName(request.getPayUserName());
|
||||
linePayDO.setUpdateUserId(userId);
|
||||
linePayDO.setAmount(request.getAmount());
|
||||
//如果是认领失败状态的时候 修改需要将状态置为待认领
|
||||
if (linePayDO.getXgjClaimStatus().equals(ClaimStatusEnum.CLAIMED_FAIL.getCode())){
|
||||
linePayDO.setXgjClaimStatus(ClaimStatusEnum.TO_BE_CLAIMED.getCode());
|
||||
}
|
||||
linePayDAO.updateLinePay(linePayDO);
|
||||
response.setPaymentReceiptCode(linePayDO.getPaymentReceiptCode());
|
||||
//推送数据
|
||||
this.onlinePushPayInfo(request.getShopId(),linePayDO);
|
||||
}
|
||||
if (shopSubStageInfo.getShopSubStageStatus().equals(ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_71.getShopSubStageStatus())) {
|
||||
shopStageInfoDAO.updateShopStageInfo(request.getShopId(), ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_72);
|
||||
}
|
||||
return response;
|
||||
} else {
|
||||
throw new ServiceException(ErrorCodeEnum.DUPLICATE_SUBMISSION);
|
||||
}
|
||||
} finally {
|
||||
if (Boolean.TRUE.equals(acquired)) {
|
||||
String currentValue = redisUtilPool.getString(lockKey);
|
||||
if (lockValue.equals(currentValue)) {
|
||||
redisUtilPool.delKey(lockKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean cancelFranchiseFeePayOnline(Long id, String userId) {
|
||||
LinePayDO linePay = linePayDAO.getById(id);
|
||||
if (linePay == null) {
|
||||
throw new ServiceException(ErrorCodeEnum.DELETE_ERROR);
|
||||
}
|
||||
if (linePay.getXgjClaimStatus().equals(ClaimStatusEnum.CLAIMED.getCode())){
|
||||
throw new ServiceException(ErrorCodeEnum.CLAIM_STATUS_ERROR);
|
||||
}
|
||||
linePay.setPayStatus(PayStatusEnum.CANCELED.getCode());
|
||||
linePayDAO.updateLinePay(linePay);
|
||||
|
||||
//取消支付
|
||||
this.onlinePushPayInfo(linePay.getShopId(),linePay);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public FranchiseFeePayInfoResponse getById(Long id) {
|
||||
|
||||
@@ -80,9 +80,9 @@ public class MessageTemplateServiceImpl implements MessageTemplateService {
|
||||
@Resource
|
||||
TaskExecutor noticeThreadPool;
|
||||
@Resource
|
||||
HyPartnerUserInfoDAO hyPartnerUserInfoDAO;
|
||||
@Resource
|
||||
MessageIssueService messageIssueService;
|
||||
@Resource
|
||||
HyPartnerUserInfoDAO hyPartnerUserInfoDAO;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.cool.store.enums.point.ShopSubStageStatusEnum;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.request.PostAndOrderRequest;
|
||||
import com.cool.store.request.xgj.FranchiseFeeCallBackRequest;
|
||||
import com.cool.store.request.xgj.OnlinePayInfoRequest;
|
||||
import com.cool.store.request.xgj.ReceiptCallBackRequest;
|
||||
import com.cool.store.response.bigdata.ApiResponse;
|
||||
import com.cool.store.service.FranchiseFeeService;
|
||||
@@ -139,4 +140,9 @@ public class OpenApiServiceImpl implements OpenApiService {
|
||||
public ApiResponse<Boolean> changePaymentStatus(FranchiseFeeCallBackRequest request) {
|
||||
return franchiseFeeService.changePaymentStatus(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse<Boolean> changeOnlinePayInfo(OnlinePayInfoRequest onlinePayInfoRequest) {
|
||||
return linePayService.changeOnlinePayInfo(onlinePayInfoRequest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,11 @@ import com.cool.store.enums.point.ShopSubStageStatusEnum;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.mapper.UserAuthMappingMapper;
|
||||
import com.cool.store.request.OpeningOperationPlanRequest;
|
||||
import com.cool.store.request.OrderSummaryRequest;
|
||||
import com.cool.store.request.PlanListRequest;
|
||||
import com.cool.store.response.OrderSummaryResponse;
|
||||
import com.cool.store.service.*;
|
||||
import com.cool.store.utils.poi.DateUtils;
|
||||
import com.cool.store.utils.poi.StringUtils;
|
||||
import com.cool.store.vo.OpeningOperationPlanListVO;
|
||||
import com.cool.store.vo.OpeningOperationPlanVO;
|
||||
@@ -32,6 +35,7 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -65,6 +69,8 @@ public class OpeningOperationPlanImpl implements OpeningOperationPlanService {
|
||||
private LineInfoDAO lineInfoDAO;
|
||||
@Resource
|
||||
private ShopService shopService;
|
||||
@Resource
|
||||
HuoMaService huoMaService;
|
||||
|
||||
@Resource
|
||||
UserAuthMappingService userAuthMappingService;
|
||||
@@ -79,10 +85,7 @@ public class OpeningOperationPlanImpl implements OpeningOperationPlanService {
|
||||
log.error("addNewPlan ActivityTheme length error");
|
||||
throw new ServiceException(ErrorCodeEnum.ACTIVITY_THEME_LENGTH_FALSE);
|
||||
}
|
||||
if (request.getSurveyResult().length() > CommonConstants.MAX_LENGTH_ONE_HUNDRED) {
|
||||
log.error("addNewPlan SurveyResult length error");
|
||||
throw new ServiceException(ErrorCodeEnum.SURVEYRESULT_LENGTH_FALSE);
|
||||
}
|
||||
ShopInfoDO shopInfo = shopInfoDAO.getShopInfo(request.getShopId());
|
||||
String userId = userInfo.getUserId();
|
||||
OpeningOperationPlanDO selectByShopId = openingOperationPlanDAO.selectByShopId(request.getShopId());
|
||||
Long planId;
|
||||
@@ -95,6 +98,10 @@ public class OpeningOperationPlanImpl implements OpeningOperationPlanService {
|
||||
openingOperationPlanDO.setId(selectByShopId.getId());
|
||||
openingOperationPlanDO.setUpdateTime(new Date());
|
||||
openingOperationPlanDO.setUpdateUserId(userId);
|
||||
//如果开业时间调整 需要重新获取数据 时间相同不需要拉取数据
|
||||
if (!DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD,request.getOpenTime()).equals(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD,selectByShopId.getOpenTime()))){
|
||||
getIncome(shopInfo.getShopCode(),openingOperationPlanDO);
|
||||
}
|
||||
planId = openingOperationPlanDAO.updateSelective(openingOperationPlanDO);
|
||||
} else {
|
||||
//新增
|
||||
@@ -102,32 +109,11 @@ public class OpeningOperationPlanImpl implements OpeningOperationPlanService {
|
||||
openingOperationPlanDO.setSubmittedUserId(userId);
|
||||
openingOperationPlanDO.setCreateTime(new Date());
|
||||
openingOperationPlanDO.setCreateUserId(userId);
|
||||
getIncome(shopInfo.getShopCode(),openingOperationPlanDO);
|
||||
planId = openingOperationPlanDAO.insertSelective(openingOperationPlanDO);
|
||||
}
|
||||
shopStageInfoDAO.updateShopStageInfo(request.getShopId(), ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_141);
|
||||
ShopInfoDO shopInfoDO = shopInfoDAO.getShopInfo(request.getShopId());
|
||||
LineInfoDO lineInfoDO = lineInfoDAO.getLineInfo(shopInfoDO.getLineId());
|
||||
Set<String> planAuditUser = new HashSet<>();
|
||||
List<EnterpriseUserDO> regionManagerUser = userAuthMappingService.getAllUserByRoleEnumAndRegionId(UserRoleEnum.REGION_MANAGER, shopInfoDO.getRegionId());
|
||||
if (Objects.nonNull(regionManagerUser)){
|
||||
Set<String> regionManagerUserIds = regionManagerUser.stream().map(EnterpriseUserDO::getUserId).collect(Collectors.toSet());
|
||||
planAuditUser.addAll(regionManagerUserIds);
|
||||
}
|
||||
List<EnterpriseUserDO> regionalManager = userAuthMappingService.getAllUserByRoleEnumAndRegionId(UserRoleEnum.REGIONAL_MANAGER, shopInfoDO.getRegionId());
|
||||
if (Objects.nonNull(regionalManager)){
|
||||
Set<String> regionalManagerUserIds = regionalManager.stream().map(EnterpriseUserDO::getUserId).collect(Collectors.toSet());
|
||||
planAuditUser.addAll(regionalManagerUserIds);
|
||||
}
|
||||
|
||||
HashMap<String, String> map = new HashMap<>();
|
||||
map.put("partnerUsername",lineInfoDO.getUsername());
|
||||
map.put("partnerMobile",lineInfoDO.getMobile());
|
||||
map.put("storeName",shopInfoDO.getShopName());
|
||||
commonService.sendQWMessage(new ArrayList<>(planAuditUser),
|
||||
MessageEnum.MESSAGE_42,
|
||||
map);
|
||||
shopStageInfoDAO.updateShopStageInfo(request.getShopId(), ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_143);
|
||||
return planId;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -141,21 +127,9 @@ public class OpeningOperationPlanImpl implements OpeningOperationPlanService {
|
||||
ShopInfoDO shopInfo = shopInfoDAO.getShopInfo(shopId);
|
||||
OpeningOperationPlanDO openingOperationPlanDO = openingOperationPlanDAO.selectByShopId(shopId);
|
||||
EnterpriseUserDO userInfoById = enterpriseUserDAO.getUserInfoById(shopInfo.getSupervisorUserId());
|
||||
List<EnterpriseUserDO> allUserByRoleEnumAndRegionId = userAuthMappingService.getAllUserByRoleEnumAndRegionId(UserRoleEnum.OPERATIONS_MANAGER, shopInfo.getRegionId());
|
||||
List<String> collect = new ArrayList<>();
|
||||
if (CollectionUtils.isEmpty(allUserByRoleEnumAndRegionId)){
|
||||
collect = null;
|
||||
}else {
|
||||
collect = allUserByRoleEnumAndRegionId.stream()
|
||||
.filter(user -> user.getName() != null)
|
||||
.map(user -> user.getName())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
if (Objects.nonNull(openingOperationPlanDO)) {
|
||||
openingOperationPlanVO = new OpeningOperationPlanVO(openingOperationPlanDO);
|
||||
openingOperationPlanVO.setSubmiter(Objects.isNull(userInfoById) ? null : userInfoById.getName());
|
||||
openingOperationPlanVO.setApprover(CollectionUtils.isEmpty(collect) ? null : collect.stream().collect(Collectors.joining(",")));
|
||||
String preparationUserIds = openingOperationPlanDO.getPreparationUserIds();
|
||||
if (StringUtils.isNotBlank(preparationUserIds)){
|
||||
List<String> stream = Arrays.stream(preparationUserIds.split(CommonConstants.COMMA)).collect(Collectors.toList());
|
||||
@@ -165,14 +139,71 @@ public class OpeningOperationPlanImpl implements OpeningOperationPlanService {
|
||||
String userName = enterpriseUserDAO.getUserName(openingOperationPlanDO.getSubmittedUserId());
|
||||
openingOperationPlanVO.setSubmittedUserName(userName);
|
||||
openingOperationPlanVO.setShopName(shopInfo.getShopName());
|
||||
|
||||
if (StringUtils.isAnyEmpty(openingOperationPlanDO.getFirstDayIncome(),openingOperationPlanDO.getSecondDayIncome(),openingOperationPlanDO.getThirdDayIncome())){
|
||||
getIncome(shopInfo.getShopCode(),openingOperationPlanDO);
|
||||
openingOperationPlanDAO.updateSelective(openingOperationPlanDO);
|
||||
}
|
||||
openingOperationPlanVO.setFirstDayIncome(openingOperationPlanDO.getFirstDayIncome());
|
||||
openingOperationPlanVO.setSecondDayIncome(openingOperationPlanDO.getSecondDayIncome());
|
||||
openingOperationPlanVO.setThirdDayIncome(openingOperationPlanDO.getThirdDayIncome());
|
||||
return openingOperationPlanVO;
|
||||
}
|
||||
openingOperationPlanVO.setSubmiter(Objects.isNull(userInfoById) ? null : userInfoById.getName());
|
||||
openingOperationPlanVO.setApprover(CollectionUtils.isEmpty(collect) ? null : collect.stream().collect(Collectors.joining(",")));
|
||||
return openingOperationPlanVO;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private OpeningOperationPlanDO getIncome(String code,OpeningOperationPlanDO openingOperationPlanDO){
|
||||
if (openingOperationPlanDO.getOpenTime()==null||StringUtils.isEmpty(code)){
|
||||
return openingOperationPlanDO;
|
||||
}
|
||||
OrderSummaryRequest orderSummaryRequest = new OrderSummaryRequest();
|
||||
orderSummaryRequest.setType("1");
|
||||
orderSummaryRequest.setShop_sn(code);
|
||||
//当前日期
|
||||
try {
|
||||
String dateStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, openingOperationPlanDO.getOpenTime());
|
||||
if (StringUtils.isEmpty(openingOperationPlanDO.getFirstDayIncome())||"0.00".equals(openingOperationPlanDO.getFirstDayIncome())){
|
||||
orderSummaryRequest.setStart_date(dateStr);
|
||||
orderSummaryRequest.setEnd_date(dateStr);
|
||||
OrderSummaryResponse orderSummary = huoMaService.getOrderSummary(orderSummaryRequest);
|
||||
//第一天收入
|
||||
BigDecimal firstDay = OrderSummaryResponse.calculateExpectedIncome(orderSummary);
|
||||
openingOperationPlanDO.setFirstDayIncome(firstDay.toString());
|
||||
}
|
||||
|
||||
//当前日期加1
|
||||
String dateStr1 = DateUtils.getPlusFDays(openingOperationPlanDO.getOpenTime(), 1).toString();
|
||||
if (StringUtils.isEmpty(openingOperationPlanDO.getSecondDayIncome())||"0.00".equals(openingOperationPlanDO.getSecondDayIncome())){
|
||||
orderSummaryRequest.setStart_date(dateStr1);
|
||||
orderSummaryRequest.setEnd_date(dateStr1);
|
||||
OrderSummaryResponse orderSummary = huoMaService.getOrderSummary(orderSummaryRequest);
|
||||
//第一天收入
|
||||
BigDecimal secondDay = OrderSummaryResponse.calculateExpectedIncome(orderSummary);
|
||||
openingOperationPlanDO.setSecondDayIncome(secondDay.toString());
|
||||
}
|
||||
|
||||
//当前日期加2
|
||||
String dateStr2 = DateUtils.getPlusFDays(openingOperationPlanDO.getOpenTime(), 2).toString();
|
||||
if (StringUtils.isEmpty(openingOperationPlanDO.getThirdDayIncome())||"0.00".equals(openingOperationPlanDO.getThirdDayIncome())){
|
||||
orderSummaryRequest.setStart_date(dateStr2);
|
||||
orderSummaryRequest.setEnd_date(dateStr2);
|
||||
OrderSummaryResponse orderSummary = huoMaService.getOrderSummary(orderSummaryRequest);
|
||||
//第一天收入
|
||||
BigDecimal thirdDay = OrderSummaryResponse.calculateExpectedIncome(orderSummary);
|
||||
openingOperationPlanDO.setThirdDayIncome(thirdDay.toString());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("收入查询失败:{}",e.getMessage());
|
||||
return openingOperationPlanDO;
|
||||
}
|
||||
return openingOperationPlanDO;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public PageInfo<OpeningOperationPlanListVO> getPlanListPage(PlanListRequest request) {
|
||||
log.info("getPlanListPage request:{}", JSONObject.toJSONString(request));
|
||||
if (!sysRoleService.checkIsAdmin(request.getCurUserId())) {
|
||||
|
||||
@@ -235,6 +235,30 @@ public class OperationLogServiceImpl implements OperationLogService {
|
||||
return operationLogDAO.batchUpdateByPrimaryKeySelective(operationLogList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean handleApproveTimeNoDate(Long shopId,ShopSubStageStatusEnum subStageStatusEnum, Long audit, String userId, String reason) {
|
||||
OperationLogDO operationLogDO = new OperationLogDO();
|
||||
operationLogDO.setOperator(userId);
|
||||
operationLogDO.setAuditResultId(audit);
|
||||
operationLogDO.setRemarks(reason);
|
||||
operationLogDO.setShopId(shopId);
|
||||
operationLogDO.setShopSubStage(subStageStatusEnum.getShopSubStageEnum().getShopSubStage());
|
||||
operationLogDO.setShopSubStageStatus(subStageStatusEnum.getShopSubStageStatus());
|
||||
operationLogDO.setStatus(OperationStatusEnum.PROCESSED.getCode());
|
||||
operationLogDO.setType(OperationTypeEnum.OPERATION_TYPE_1.getCode());
|
||||
String userName = enterpriseUserDAO.getUserName(userId);
|
||||
if (StringUtils.isNotBlank(userName)) {
|
||||
operationLogDO.setOperatorName(userName);
|
||||
}
|
||||
Date createTime = new Date();
|
||||
Date updateTime = new Date();
|
||||
operationLogDO.setCreateTime(createTime);
|
||||
operationLogDO.setUpdateTime(updateTime);
|
||||
operationLogDO.setCreateUserId(userId);
|
||||
operationLogDAO.addOperationLog(operationLogDO);
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -51,8 +51,7 @@ import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.cool.store.enums.point.ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_21;
|
||||
import static com.cool.store.enums.point.ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_21_5;
|
||||
import static com.cool.store.enums.point.ShopSubStageStatusEnum.*;
|
||||
|
||||
/**
|
||||
* @author zhangchenbiao
|
||||
@@ -106,6 +105,10 @@ public class PointServiceImpl implements PointService {
|
||||
private String enterpriseId;
|
||||
@Resource
|
||||
SysRoleMapper sysRoleMapper;
|
||||
@Resource
|
||||
OperationLogService operationLogService;
|
||||
@Resource
|
||||
OperationLogDAO operationLogDAO;
|
||||
|
||||
@Resource
|
||||
PointFinancialDataDAO pointFinancialDataDAO;
|
||||
@@ -1195,14 +1198,13 @@ public class PointServiceImpl implements PointService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer uploadRentContract(AddRentContractRequest request) {
|
||||
public Integer uploadRentContract(AddRentContractRequest request,String userId,String userName) {
|
||||
if (!request.check()) {
|
||||
throw new ServiceException(ErrorCodeEnum.PARAMS_VALIDATE_ERROR);
|
||||
}
|
||||
Long pointId = request.getPointId(), shopId = request.getShopId();
|
||||
ShopInfoDO shopInfo = null;
|
||||
ShopInfoDO shopInfo = shopInfo = shopInfoDAO.getShopInfo(shopId);;
|
||||
if (Objects.isNull(pointId) && Objects.nonNull(shopId)) {
|
||||
shopInfo = shopInfoDAO.getShopInfo(shopId);
|
||||
pointId = shopInfo.getPointId();
|
||||
}
|
||||
if (Objects.nonNull(pointId) && Objects.isNull(shopId)) {
|
||||
@@ -1239,6 +1241,13 @@ public class PointServiceImpl implements PointService {
|
||||
MessageEnum.MESSAGE_15,
|
||||
map);
|
||||
}
|
||||
// 审批记录
|
||||
operationLogService.addOperationLog(shopId, ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_20, userId, userName,
|
||||
OperationTypeEnum.OPERATION_TYPE_0, "加盟商上传租赁合同", OperationStatusEnum.PROCESSED);
|
||||
List<EnterpriseUserDO> userDOList = userAuthMappingService.getAllUserByRoleEnumAndRegionId(UserRoleEnum.REGION_MANAGER, shopInfo.getInvestRegionId());
|
||||
operationLogService.addOperationLog(shopId, ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_21,
|
||||
userId, userDOList,
|
||||
OperationTypeEnum.OPERATION_TYPE_1, "招商片区老总审核", OperationStatusEnum.NOT_PROCESSED);
|
||||
return shopStageInfoDAO.updateShopStageInfo(shopId, SHOP_SUB_STAGE_STATUS_21);
|
||||
}
|
||||
|
||||
@@ -1286,6 +1295,8 @@ public class PointServiceImpl implements PointService {
|
||||
Long auditId = shopAuditInfoDAO.addAuditInfo(AuditRentContractRequest.convert(request, AuditTypeEnum.UPLOAD_RENT_CONTRACT));
|
||||
|
||||
ShopSubStageStatusEnum subStageStatus = null;
|
||||
Integer current = shopStageInfo.getShopSubStageStatus();
|
||||
ShopSubStageStatusEnum currentShopSubStageStatusEnum = getShopSubStageStatusEnum(current);
|
||||
if (AuditResultTypeEnum.PASS.getCode().equals(request.getResultType())){
|
||||
if (shopStageInfo.getShopSubStageStatus().equals(SHOP_SUB_STAGE_STATUS_21.getShopSubStageStatus())){
|
||||
subStageStatus = SHOP_SUB_STAGE_STATUS_21_5;
|
||||
@@ -1296,6 +1307,16 @@ public class PointServiceImpl implements PointService {
|
||||
}else {
|
||||
subStageStatus = ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_22;
|
||||
}
|
||||
//处理审批
|
||||
handleApprove(shopId,AuditTypeEnum.UPLOAD_RENT_CONTRACT,request.getOperateUserId(),request.getOperateUserName(),
|
||||
request.getResultType(),currentShopSubStageStatusEnum,request.getReason());
|
||||
//如果有下一级
|
||||
if (SHOP_SUB_STAGE_STATUS_21.getShopSubStageStatus().equals(currentShopSubStageStatusEnum.getShopSubStageStatus())){
|
||||
List<EnterpriseUserDO> userDOList = userAuthMappingService.getAllUserByRoleEnumAndRegionId(UserRoleEnum.BRANCH_OFFICE, shopInfo.getInvestRegionId());
|
||||
operationLogService.addOperationLog(shopId, ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_21_5,
|
||||
request.getOperateUserId(), userDOList,
|
||||
OperationTypeEnum.OPERATION_TYPE_1, "分部内勤审核", OperationStatusEnum.NOT_PROCESSED);
|
||||
}
|
||||
|
||||
if (ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_23.equals(subStageStatus)) {
|
||||
//审核通过铺位变为已签约
|
||||
@@ -1324,6 +1345,41 @@ public class PointServiceImpl implements PointService {
|
||||
return CommonConstants.ONE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 处理审批
|
||||
* @param shopId
|
||||
* @param auditTypeEnum
|
||||
* @param userId
|
||||
* @param userName
|
||||
* @param resultType
|
||||
* @param currentStatusEnum
|
||||
* @param cause
|
||||
* @return
|
||||
*/
|
||||
private Boolean handleApprove(Long shopId,AuditTypeEnum auditTypeEnum,String userId,String userName,Integer resultType,ShopSubStageStatusEnum currentStatusEnum,String cause){
|
||||
ShopAuditInfoDO shopAuditInfoDO = new ShopAuditInfoDO();
|
||||
shopAuditInfoDO.setShopId(shopId);
|
||||
shopAuditInfoDO.setAuditType(auditTypeEnum.getCode());
|
||||
shopAuditInfoDO.setSubmittedUserId(userId);
|
||||
shopAuditInfoDO.setSubmittedUserName(userName);
|
||||
shopAuditInfoDO.setResultType(resultType);
|
||||
if (AuditResultTypeEnum.PASS.getCode().equals(shopAuditInfoDO.getResultType())) {
|
||||
shopAuditInfoDO.setPassReason(cause);
|
||||
} else {
|
||||
shopAuditInfoDO.setRejectReason(cause);
|
||||
}
|
||||
Long auditId = shopAuditInfoDAO.addAuditInfo(shopAuditInfoDO);
|
||||
//更新操作记录
|
||||
List<OperationLogDO> operationLogs = operationLogDAO.getBySubStageStatusEnumAndsStatus(shopId, currentStatusEnum, OperationTypeEnum.OPERATION_TYPE_1.getCode());
|
||||
if (CollectionUtils.isNotEmpty(operationLogs)){
|
||||
operationLogService.batchUpdateProcessed(operationLogs, auditId, userId, cause);
|
||||
}else {
|
||||
operationLogService.handleApproveTimeNoDate(shopId,currentStatusEnum,auditId, userId, cause);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer updateRentContract(UpdateRentContractRequest request) {
|
||||
if (!request.check()) {
|
||||
|
||||
@@ -212,6 +212,28 @@ public class PreparationServiceImpl implements PreparationService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decorationCompletion(Long shopId) {
|
||||
List<ShopStageInfoDO> shopStageInfo = shopStageInfoDAO.getShopStageInfo(shopId, null);
|
||||
if (CollectionUtils.isNotEmpty(shopStageInfo)) {
|
||||
Map<Integer, ShopStageInfoDO> shopStageInfoDOMap = shopStageInfo.stream().collect(Collectors.toMap(ShopStageInfoDO::getShopSubStage, data -> data));
|
||||
Boolean flag2 = ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_123.getShopSubStageStatus().
|
||||
equals(shopStageInfoDOMap.get(ShopSubStageEnum.SHOP_STAGE_12.getShopSubStage()).getShopSubStageStatus());
|
||||
|
||||
//如果阶段已经初始化过 直接跳过 针对老数据
|
||||
if(shopStageInfoDOMap.get(ShopSubStageEnum.SHOP_STAGE_14.getShopSubStage()).getShopSubStageStatus()
|
||||
>ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_140.getShopSubStageStatus()){
|
||||
return;
|
||||
}
|
||||
|
||||
if (flag2){
|
||||
List<ShopSubStageStatusEnum> list = new ArrayList<>();
|
||||
list.add(ShopSubStageStatusEnum.SHOP_SUB_STAGE_STATUS_140);
|
||||
shopStageInfoDAO.batchUpdateShopStageStatus(shopId, list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sysStoreCompleted(Long shopId) {
|
||||
List<ShopStageInfoDO> shopStageInfo = shopStageInfoDAO.getShopStageInfo(shopId, null);
|
||||
|
||||
@@ -16,7 +16,9 @@ import com.cool.store.enums.ErrorCodeEnum;
|
||||
import com.cool.store.enums.UserRoleEnum;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.request.ZxjpApiRequest;
|
||||
import com.cool.store.request.xgj.CancelPayRequest;
|
||||
import com.cool.store.request.xgj.PushFranchiseFeeRequest;
|
||||
import com.cool.store.request.xgj.ReceiptOnlineRequest;
|
||||
import com.cool.store.request.xgj.ReceiptRequest;
|
||||
import com.cool.store.response.XgjAccessTokenDTO;
|
||||
import com.cool.store.response.XgjBaseResponse;
|
||||
@@ -153,6 +155,12 @@ public class PushServiceImpl implements PushService {
|
||||
return executePostApiCall(apiUrl, request, Boolean.class, xgjUsername, xgjSecret,getXgjAccessToken().getAccess_token());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean pushOnlineReceiptToXGJ(ReceiptOnlineRequest receiptRequest) {
|
||||
String apiUrl = xgjUrl + "/dmp/dmp-join/open/franchiseeReceipts/online";
|
||||
return executePostApiCall(apiUrl, receiptRequest, Boolean.class, xgjUsername, xgjSecret,getXgjAccessToken().getAccess_token());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean pushDataToPOS(ZxjpApiRequest zxjpApiRequest) {
|
||||
String apiUrl = url + "/dzgV1/zxcrm/shop/upsert";
|
||||
@@ -297,7 +305,7 @@ public class PushServiceImpl implements PushService {
|
||||
}
|
||||
String responseBody = response.body().string();
|
||||
log.info("getUnReadMessageNum response num:{}", responseBody);
|
||||
return Integer.valueOf(responseBody);
|
||||
return Integer.valueOf(responseBody)+100;
|
||||
} catch (Exception e) {
|
||||
log.error("API调用异常 - URL: {}, 错误: {}", url, e.getMessage(), e);
|
||||
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, "接口调用异常: " + e.getMessage());
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
package com.cool.store.service.impl;
|
||||
|
||||
import com.cool.store.dao.*;
|
||||
import com.cool.store.entity.BigRegionDO;
|
||||
import com.cool.store.entity.FranchiseFeeDO;
|
||||
import com.cool.store.entity.ReceivingBankDO;
|
||||
import com.cool.store.entity.ShopInfoDO;
|
||||
import com.cool.store.enums.ErrorCodeEnum;
|
||||
import com.cool.store.enums.point.PayTypeEnum;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.mapper.FranchiseFeeMapper;
|
||||
import com.cool.store.request.ReceivingBankListRequest;
|
||||
import com.cool.store.request.ReceivingBankRequest;
|
||||
import com.cool.store.response.ReceivingBankResponse;
|
||||
import com.cool.store.service.ReceivingBankService;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Author: WangShuo
|
||||
* @Date: 2025/06/18/17:53
|
||||
* @Version 1.0
|
||||
* @注释:
|
||||
*/
|
||||
@Service
|
||||
public class ReceivingBankServiceImpl implements ReceivingBankService {
|
||||
@Resource
|
||||
private ReceivingBankDAO receivingBankDAO;
|
||||
@Resource
|
||||
private RegionDao regionDao;
|
||||
@Resource
|
||||
private BigRegionDAO bigRegionDAO;
|
||||
@Resource
|
||||
private EnterpriseUserDAO enterpriseUserDAO;
|
||||
@Resource
|
||||
private ShopInfoDAO shopInfoDAO;
|
||||
@Resource
|
||||
private FranchiseFeeMapper franchiseFeeMapper;
|
||||
|
||||
|
||||
@Override
|
||||
public Integer submit(ReceivingBankRequest request, String userId) {
|
||||
ReceivingBankDO receivingBankDO = new ReceivingBankDO();
|
||||
receivingBankDO.setRegionId(request.getRegionId());
|
||||
receivingBankDO.setFranchiseBrand(Integer.parseInt(request.getFranchiseBrand()));
|
||||
receivingBankDO.setPayee(request.getPayee());
|
||||
receivingBankDO.setPayType(request.getPayType());
|
||||
receivingBankDO.setReceivingAccount(request.getReceivingAccount());
|
||||
receivingBankDO.setBankName(request.getBankName());
|
||||
receivingBankDO.setBranchBankName(request.getBranchBankName());
|
||||
if (request.getId() == null) {
|
||||
receivingBankDO.setCreateTime(new Date());
|
||||
receivingBankDO.setCreateUser(userId);
|
||||
} else {
|
||||
receivingBankDO.setId(request.getId());
|
||||
receivingBankDO.setUpdateTime(new Date());
|
||||
receivingBankDO.setUpdateUser(userId);
|
||||
}
|
||||
return receivingBankDAO.batchInsertOrUpdate(Collections.singletonList(receivingBankDO));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageInfo<ReceivingBankResponse> getByFranchiseBrandAndRegionId(ReceivingBankListRequest request) {
|
||||
PageHelper.startPage(request.getPageNum(),request.getPageSize());
|
||||
List<ReceivingBankDO> list = receivingBankDAO.getByFranchiseBrandAndRegionId(request.getFranchiseBrandList(),request.getRegionIdList());
|
||||
if (CollectionUtils.isEmpty(list)){
|
||||
return new PageInfo<>();
|
||||
}
|
||||
PageInfo pageInfo = new PageInfo<>(list);
|
||||
List<ReceivingBankResponse> responses = new ArrayList<>();
|
||||
Set<Long> regionSet = list.stream().filter(Objects::nonNull).map(ReceivingBankDO::getRegionId).collect(Collectors.toSet());
|
||||
Set<String> userIds = list.stream().filter(Objects::nonNull).map(ReceivingBankDO::getCreateUser).collect(Collectors.toSet());
|
||||
userIds.addAll(list.stream().filter(Objects::nonNull).map(ReceivingBankDO::getUpdateUser).collect(Collectors.toSet()));
|
||||
Map<String, String> userNameMap = enterpriseUserDAO.getUserNameMap(new ArrayList<>(userIds));
|
||||
Map<Long, String> regionNameMap = regionDao.getRegionNameMap(new ArrayList<>(regionSet));
|
||||
Map<Long, BigRegionDO> bigRegionMap = bigRegionDAO.getMapByRegionIds(new ArrayList<>(regionSet));
|
||||
for (ReceivingBankDO x:list){
|
||||
ReceivingBankResponse response = new ReceivingBankResponse();
|
||||
response.setId(x.getId());
|
||||
response.setRegionId(x.getRegionId());
|
||||
response.setRegionName(regionNameMap.getOrDefault(x.getRegionId(),""));
|
||||
response.setGroup(bigRegionMap.getOrDefault(x.getRegionId(),new BigRegionDO()).getGroupName());
|
||||
response.setFranchiseBrand(x.getFranchiseBrand().toString());
|
||||
response.setPayType(x.getPayType());
|
||||
response.setPayee(x.getPayee());
|
||||
response.setReceivingAccount(x.getReceivingAccount());
|
||||
response.setBankName(x.getBankName());
|
||||
response.setBranchBankName(x.getBranchBankName());
|
||||
response.setCreateUserName(userNameMap.getOrDefault(x.getCreateUser(),""));
|
||||
response.setUpdateUserName(userNameMap.getOrDefault(x.getUpdateUser(),""));
|
||||
response.setCreateTime(x.getCreateTime());
|
||||
response.setUpdateTime(x.getUpdateTime());
|
||||
responses.add(response);
|
||||
}
|
||||
pageInfo.setList(responses);
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReceivingBankResponse getByShopId(Long shopId) {
|
||||
ShopInfoDO shopInfo = shopInfoDAO.getShopInfo(shopId);
|
||||
if (shopInfo.getRegionId()==null){
|
||||
throw new ServiceException(ErrorCodeEnum.SHOP_REGION_NOT_EXIST);
|
||||
}
|
||||
if (StringUtils.isBlank(shopInfo.getFranchiseBrand())){
|
||||
throw new ServiceException(ErrorCodeEnum.SHOP_FRANCHISE_BRAND_NOT_EXITS);
|
||||
}
|
||||
FranchiseFeeDO franchiseFeeDO = franchiseFeeMapper.selectByShopId(shopId);
|
||||
if (franchiseFeeDO == null){
|
||||
throw new ServiceException(ErrorCodeEnum.UNISSUED_STATEMENT);
|
||||
}
|
||||
if (franchiseFeeDO.getPayType() == null
|
||||
|| (!franchiseFeeDO.getPayType().equals(PayTypeEnum.ONLINE_PAY.getCode())
|
||||
&&!franchiseFeeDO.getPayType().equals(PayTypeEnum.OFFLINE_PAY.getCode()) )){
|
||||
throw new ServiceException(ErrorCodeEnum.PAY_TYPE_NOT_EXIST);
|
||||
}
|
||||
List<ReceivingBankDO> receivingBankDOList = receivingBankDAO.getByRegionAndFranchiseBrandAndPayType(shopInfo.getRegionId(), Integer.parseInt(shopInfo.getFranchiseBrand()), franchiseFeeDO.getPayType());
|
||||
if (CollectionUtils.isEmpty(receivingBankDOList)){
|
||||
throw new ServiceException(ErrorCodeEnum.RECEIVING_BANK_NOT_EXIST);
|
||||
}
|
||||
if (receivingBankDOList.size() > 1){
|
||||
throw new ServiceException(ErrorCodeEnum.THERE_ARE_SEVERAL_RECEIVING_BANK);
|
||||
}
|
||||
ReceivingBankResponse response= new ReceivingBankResponse();
|
||||
response.setPayType(receivingBankDOList.get(0).getPayType());
|
||||
response.setPayee(receivingBankDOList.get(0).getPayee());
|
||||
response.setReceivingAccount(receivingBankDOList.get(0).getReceivingAccount());
|
||||
response.setBankName(receivingBankDOList.get(0).getBankName());
|
||||
response.setBranchBankName(receivingBankDOList.get(0).getBranchBankName());
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@ import java.util.stream.Stream;
|
||||
import static com.cool.store.enums.ErrorCodeEnum.*;
|
||||
import static com.cool.store.enums.UserRoleEnum.*;
|
||||
import static com.cool.store.enums.WorkflowSubStageStatusEnum.*;
|
||||
import static com.cool.store.enums.point.ShopSubStageEnum.SHOP_STAGE_8;
|
||||
import static com.cool.store.enums.point.ShopSubStageEnum.SHOP_STAGE_15;
|
||||
import static com.cool.store.enums.point.ShopSubStageEnum.SHOP_STAGE_8;
|
||||
|
||||
@@ -943,8 +944,6 @@ public class ShopServiceImpl implements ShopService {
|
||||
case SHOP_SUB_STAGE_STATUS_11:
|
||||
case SHOP_SUB_STAGE_STATUS_50:
|
||||
case SHOP_SUB_STAGE_STATUS_140:
|
||||
case SHOP_SUB_STAGE_STATUS_141:
|
||||
case SHOP_SUB_STAGE_STATUS_142:
|
||||
case SHOP_SUB_STAGE_STATUS_171:
|
||||
case SHOP_SUB_STAGE_STATUS_270:
|
||||
case SHOP_SUB_STAGE_STATUS_274:
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.alibaba.fastjson.JSONObject;
|
||||
import com.cool.store.constants.CommonConstants;
|
||||
import com.cool.store.constants.RedisConstant;
|
||||
import com.cool.store.constants.DictConstants;
|
||||
import com.cool.store.constants.RedisConstant;
|
||||
import com.cool.store.context.LoginUserInfo;
|
||||
import com.cool.store.dao.*;
|
||||
import com.cool.store.dao.fees.WalletPayInfoDAO;
|
||||
@@ -483,6 +484,9 @@ public class SignFranchiseServiceImpl implements SignFranchiseService, AuditResu
|
||||
shopInfoDO.setDecorationRequirement(request.getDecorationRequirement());
|
||||
shopInfoDO.setSpecialInstruction(request.getSpecialInstruction());
|
||||
shopInfoMapper.updateByPrimaryKeySelective(shopInfoDO);
|
||||
//添加修改日志
|
||||
handleDecorartionReq(shopInfoDO.getId(),request.getDecorationLevel(),request.getDecorationRequirement(),
|
||||
request.getShopDecorationAttributes(),request.getSpecialInstruction(),user);
|
||||
if (Objects.nonNull(pointInfoById)) {
|
||||
pointInfoById.setProvince(request.getProvince());
|
||||
pointInfoById.setCity(request.getCity());
|
||||
@@ -675,6 +679,7 @@ public class SignFranchiseServiceImpl implements SignFranchiseService, AuditResu
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 分部内勤/财务审批拒绝
|
||||
*/
|
||||
@@ -937,6 +942,7 @@ public class SignFranchiseServiceImpl implements SignFranchiseService, AuditResu
|
||||
return pushService.pushContract(contractInformationDTO);
|
||||
} catch (Exception e) {
|
||||
log.error("推送合同信息失败", e);
|
||||
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR,e.getMessage());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package com.cool.store.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollStreamUtil;
|
||||
import cn.hutool.core.collection.CollStreamUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.cool.store.constants.CommonConstants;
|
||||
import com.cool.store.context.CurrentUserHolder;
|
||||
import com.cool.store.dao.store.StoreBusinessReportDAO;
|
||||
import com.cool.store.dto.StoreNameDTO;
|
||||
import com.cool.store.dao.store.StoreMasterSignerInfoDAO;
|
||||
import com.cool.store.dto.store.*;
|
||||
@@ -16,8 +17,10 @@ import com.cool.store.dao.SysRoleDao;
|
||||
import com.cool.store.dto.StoreDTO;
|
||||
import com.cool.store.dto.UserSimpleDTO;
|
||||
import com.cool.store.entity.*;
|
||||
import com.cool.store.entity.store.StoreBusinessReportDO;
|
||||
import com.cool.store.entity.store.StoreMasterSignerInfoDO;
|
||||
import com.cool.store.enums.*;
|
||||
import com.cool.store.enums.master.BrandTypeEnum;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.mapper.*;
|
||||
import com.cool.store.request.store.StoreListRequest;
|
||||
@@ -29,8 +32,6 @@ import com.cool.store.utils.GeoMapUtil;
|
||||
import com.cool.store.utils.poi.constant.Constants;
|
||||
import com.cool.store.vo.SysRoleVO;
|
||||
import com.cool.store.vo.store.StoreListVO;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.google.common.collect.Lists;
|
||||
@@ -81,6 +82,8 @@ public class StoreServiceImpl implements StoreService {
|
||||
StoreMasterSignerInfoDAO storeMasterSignerInfoDAO;
|
||||
@Resource
|
||||
EnterpriseUserRoleMapper enterpriseUserRoleMapper;
|
||||
@Resource
|
||||
StoreBusinessReportDAO storeBusinessReportDAO;
|
||||
|
||||
@Override
|
||||
public PageInfo<StoreDTO> getStoreExtendFieldInfo(Integer pageSize, Integer pageNum, Boolean queryOperations) {
|
||||
@@ -398,6 +401,44 @@ public class StoreServiceImpl implements StoreService {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveStoreReport(String date) {
|
||||
List<StoreBusinessReportDO> reportList = new ArrayList<>();
|
||||
List<Integer> joinList = Arrays.asList(BrandTypeEnum.JP.getCode(), BrandTypeEnum.ZSJ.getCode(), BrandTypeEnum.MX.getCode());
|
||||
reportList.addAll(storeReportStatistics(date, joinList, null));
|
||||
// 处理正新鸡排境内境外
|
||||
reportList.addAll(storeReportStatistics(date, Collections.singletonList(BrandTypeEnum.JP.getCode()), 1));
|
||||
reportList.addAll(storeReportStatistics(date, Collections.singletonList(BrandTypeEnum.JP.getCode()), 2));
|
||||
|
||||
if (CollectionUtils.isNotEmpty(reportList)) {
|
||||
storeBusinessReportDAO.insertOrUpdateBatch(reportList);
|
||||
}
|
||||
}
|
||||
|
||||
private List<StoreBusinessReportDO> storeReportStatistics(String date, List<Integer> joinList, Integer domestic) {
|
||||
Map<Integer, Integer> totalMap = storeDao.totalOpenStoreReport(date, domestic, joinList);
|
||||
Map<Integer, Integer> periodBeginMap = storeDao.periodBeginStoreReport(date, domestic, joinList);
|
||||
Map<Integer, Integer> newMap = storeDao.newOpenStoreReport(date, domestic, joinList);
|
||||
Map<Integer, Integer> closeMap = storeDao.closeStoreReport(date, domestic, joinList);
|
||||
List<StoreBusinessReportDO> reportList = new ArrayList<>();
|
||||
for (Integer joinBrand : joinList) {
|
||||
Integer periodBeginNum = periodBeginMap.getOrDefault(joinBrand, 0);
|
||||
Integer newOpenNum = newMap.getOrDefault(joinBrand, 0);
|
||||
Integer closeNum = closeMap.getOrDefault(joinBrand, 0);
|
||||
StoreBusinessReportDO report = new StoreBusinessReportDO();
|
||||
report.setJoinBrand(joinBrand);
|
||||
report.setDomestic(Objects.nonNull(domestic) ? domestic : 0);
|
||||
report.setDate(date);
|
||||
report.setOpenTotalNum(totalMap.getOrDefault(joinBrand, 0));
|
||||
report.setPeriodBeginNum(periodBeginNum);
|
||||
report.setNewOpenNum(newOpenNum);
|
||||
report.setCloseNum(closeNum);
|
||||
report.setPeriodEndNum(periodBeginNum + newOpenNum - closeNum);
|
||||
reportList.add(report);
|
||||
}
|
||||
return reportList;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<AuthStoreUserDTO> authStoreUser(List<String> storeIdList, String positionType) {
|
||||
|
||||
@@ -8,6 +8,10 @@ import com.cool.store.dto.recipe.RecipeSpLaunchDTO;
|
||||
import com.cool.store.dto.recipe.RevenueDataDTO;
|
||||
import com.cool.store.dto.recipe.RevenueDataQueryDTO;
|
||||
import com.cool.store.dto.recipe.SalesVolumeDayQueryDTO;
|
||||
import com.cool.store.dto.GetAccessTokenDTO;
|
||||
import com.cool.store.dto.food.DishesDTO;
|
||||
import com.cool.store.dto.store.StoreUserPositionDTO;
|
||||
import com.cool.store.dto.recipe.SalesVolumeDayQueryDTO;
|
||||
import com.cool.store.dto.store.StoreUserUpdateDTO;
|
||||
import com.cool.store.entity.StoreDO;
|
||||
import com.cool.store.enums.ErrorCodeEnum;
|
||||
@@ -28,7 +32,9 @@ import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
import org.apache.poi.ss.formula.functions.T;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@@ -64,6 +70,22 @@ public class ThirdFoodServiceImpl implements ThirdFoodService {
|
||||
return executeApiCall(url, dto, String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DishesDTO> getPurchasedDishesList(FoodTokenDTO dto) {
|
||||
String url = "/v1/recipe/getPurchasedRecipeList";
|
||||
ParameterizedTypeReference<OpportunityApiResponse<List<DishesDTO>>> responseType =
|
||||
new ParameterizedTypeReference<OpportunityApiResponse<List<DishesDTO>>>() {};
|
||||
return listByExecuteApiCall(url, dto, responseType).getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DishesDTO> getMyDesignDishesList(FoodTokenDTO dto) {
|
||||
String url = "/v1/recipe/getRecipeList";
|
||||
ParameterizedTypeReference<OpportunityApiResponse<List<DishesDTO>>> responseType =
|
||||
new ParameterizedTypeReference<OpportunityApiResponse<List<DishesDTO>>>() {};
|
||||
return listByExecuteApiCall(url, dto, responseType).getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public StoreUserResponse pushStoreUser(List<StoreUserUpdateDTO> dto) {
|
||||
String url = "/v1/store/updateStoreUser";
|
||||
@@ -105,6 +127,45 @@ public class ThirdFoodServiceImpl implements ThirdFoodService {
|
||||
return BeanUtil.toList(list, RevenueDataVO.class, CopyOptions.create().setFieldMapping(Collections.singletonMap("storeCode", "storeNum")));
|
||||
}
|
||||
|
||||
private <T> T listByExecuteApiCall(String url, Object requestBody, ParameterizedTypeReference<T> responseType) {
|
||||
// 1. 打印请求前日志
|
||||
//logRequest(url, requestBody);
|
||||
try {
|
||||
Request request = buildRequest(requestBody, url);
|
||||
|
||||
try (Response response = okHttpClient.newCall(request).execute()) {
|
||||
// 2. 获取原始响应内容
|
||||
String responseBody = response.body().string();
|
||||
|
||||
// 3. 打印响应日志
|
||||
logResponse(url, response.code(), responseBody);
|
||||
|
||||
if (!response.isSuccessful()) {
|
||||
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR,
|
||||
"HTTP请求失败,状态码: " + response.code());
|
||||
}
|
||||
// 4. 解析响应
|
||||
JavaType javaType = objectMapper.getTypeFactory().constructType(responseType.getType());
|
||||
|
||||
OpportunityApiResponse<T> apiResponse = objectMapper.readValue(responseBody, javaType);
|
||||
|
||||
if (apiResponse.getCode() != 200) {
|
||||
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, apiResponse.getMsg());
|
||||
}
|
||||
return objectMapper.readValue(responseBody, javaType);
|
||||
}
|
||||
} catch (ServiceException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
log.error("API调用异常 - URL: {}, 错误: {}", url, e.getMessage(), e);
|
||||
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, "接口调用异常: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private <T> T executeApiCall(String url, Object requestBody, Class<T> responseType) {
|
||||
// 1. 打印请求前日志
|
||||
//logRequest(url, requestBody);
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
package com.cool.store.service.impl;
|
||||
|
||||
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.cool.store.constants.RedisConstant;
|
||||
import com.cool.store.enums.ErrorCodeEnum;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.request.liepin.*;
|
||||
import com.cool.store.response.liepin.*;
|
||||
import com.cool.store.service.ThirdLiePinService;
|
||||
import com.cool.store.service.XbbApiCaller;
|
||||
import com.cool.store.utils.*;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import okhttp3.OkHttpClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* @Author suzhuhong
|
||||
* @Date 2025/5/20 15:33
|
||||
* @Version 1.0
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ThirdLiePinServiceImpl implements ThirdLiePinService {
|
||||
|
||||
private XbbApiCaller xbbApiCaller;
|
||||
|
||||
private GetAccessTokenRequest getAccessTokenRequest;
|
||||
|
||||
private final Lock lock = new ReentrantLock();
|
||||
|
||||
@Value("${liePin.appId}")
|
||||
private String appId;
|
||||
@Value("${liePin.secretKey}")
|
||||
private String secretKey;
|
||||
@Value("${liePin.aesSecretKey}")
|
||||
private String aesSecretKey;
|
||||
@Value("${liePin.baseUrl}")
|
||||
private String liePinBaseUrl;
|
||||
@Value("${liePin.tenantId}")
|
||||
private Long tenantId;
|
||||
@Value("${liePin.mobile}")
|
||||
private String mobile;
|
||||
|
||||
@Resource
|
||||
OkHttpClient okHttpClient;
|
||||
|
||||
@Resource
|
||||
ObjectMapper objectMapper;
|
||||
|
||||
@Autowired
|
||||
private RedisUtilPool redisUtilPool;
|
||||
@Resource
|
||||
private RedisConstantUtil redisConstantUtil;
|
||||
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
this.xbbApiCaller = new XbbApiCaller(liePinBaseUrl, appId, secretKey, aesSecretKey,objectMapper);
|
||||
this.getAccessTokenRequest = new GetAccessTokenRequest(tenantId,mobile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessToken(GetAccessTokenRequest request) {
|
||||
String key = redisConstantUtil.getKeyCommonMethod(RedisConstant.ACCESS_TOKEN_CACHE_PREFIX, String.valueOf(request.getTenant_id()), request.getMobile());
|
||||
String accessToken = redisUtilPool.getString(key);
|
||||
if (StringUtil.isNotEmpty(accessToken)){
|
||||
return accessToken;
|
||||
}
|
||||
String url = "/open_api/v2/super/b_applet/access_token";
|
||||
XbbPostRequest xbbPostRequest = XbbPostRequest.newBuilder().uri(url).jsonString(JSONUtil.toJsonStr(request)).build();
|
||||
XbbResponse<LiePinTokenInfo> response = xbbApiCaller.post(xbbPostRequest, LiePinTokenInfo.class,getToken());
|
||||
accessToken = response.getData().getAccess_token();
|
||||
redisUtilPool.setString(key,accessToken,RedisConstant.ONE_DAY_SECONDS*7);
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long addStoreToLiePin(AddStoreRequest addStoreRequest) {
|
||||
String accessToken = getAccessToken(getAccessTokenRequest);
|
||||
Map<String, String> queryString = new HashMap<>();
|
||||
queryString.put("access_token",accessToken);
|
||||
String url = "/open_api/v2/super/b_applet/store";
|
||||
XbbPostRequest xbbPostRequest = XbbPostRequest.newBuilder().uri(url).queryParam(queryString).jsonString(JSONUtil.toJsonStr(addStoreRequest)).build();
|
||||
XbbResponse<StoreInfoResponse> storeInfoResponse = xbbApiCaller.post(xbbPostRequest, StoreInfoResponse.class,getToken());
|
||||
return storeInfoResponse.getData().getStore_id();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long addStoreEmp(AddStoreEmpRequest addStoreEmpRequest) {
|
||||
String accessToken = getAccessToken(getAccessTokenRequest);
|
||||
Map<String, String> queryString = new HashMap<>();
|
||||
queryString.put("access_token",accessToken);
|
||||
String url = "/open_api/v2/super/b_applet/store/account";
|
||||
XbbPostRequest xbbPostRequest = XbbPostRequest.newBuilder().uri(url).queryParam(queryString).jsonString(JSONUtil.toJsonStr(addStoreEmpRequest)).build();
|
||||
XbbResponse<StoreEmpInfoResponse> empInfoResponseXbbResponse = xbbApiCaller.post(xbbPostRequest, StoreEmpInfoResponse.class,getToken());
|
||||
return empInfoResponseXbbResponse.getData().getAccount_id();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathResponse getPath(GetPathRequest getPathRequest) {
|
||||
String accessToken = getAccessToken(getAccessTokenRequest);
|
||||
Map<String, String> queryString = new HashMap<>();
|
||||
queryString.put("access_token",accessToken);
|
||||
String url = "/open_api/v2/super/b_applet/jump_url";
|
||||
XbbPostRequest xbbPostRequest = XbbPostRequest.newBuilder().uri(url).queryParam(queryString).jsonString(JSONUtil.toJsonStr(getPathRequest)).build();
|
||||
XbbResponse<PathResponse> jumpUrl = xbbApiCaller.post(xbbPostRequest, PathResponse.class,getToken());
|
||||
return jumpUrl.getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilePath(String ossUrl) {
|
||||
String accessToken = getAccessToken(getAccessTokenRequest);
|
||||
Map<String, String> queryString = new HashMap<>();
|
||||
queryString.put("access_token",accessToken);
|
||||
String url = "/open_api/v2/super/common/upload";
|
||||
UploadRequest uploadRequest = new UploadRequest(OssUtil.getUrlName(ossUrl), OssUtil.convertPublicOssUrlToBase64(ossUrl));
|
||||
XbbPostRequest xbbPostRequest = XbbPostRequest.newBuilder().uri(url).queryParam(queryString).jsonString(JSONUtil.toJsonStr(uploadRequest)).build();
|
||||
XbbResponse<FileResponse> file = xbbApiCaller.post(xbbPostRequest, FileResponse.class,getToken());
|
||||
return file.getData().getFile_id();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 接口授权token
|
||||
* @return
|
||||
*/
|
||||
public String getToken() {
|
||||
String key = redisConstantUtil.getKeyCommonMethod(RedisConstant.TOKEN_CACHE_PREFIX, appId,secretKey);
|
||||
String accessToken = redisUtilPool.getString(key);
|
||||
if (StringUtil.isNotEmpty(accessToken)){
|
||||
return accessToken;
|
||||
}
|
||||
try {
|
||||
if (!lock.tryLock(10, TimeUnit.SECONDS)) {
|
||||
throw new ServiceException("获取token失败");
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new ServiceException("获取token失败");
|
||||
}
|
||||
try {
|
||||
Exception error = null;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
try {
|
||||
String urlTemplate = "{}/open_api/access_token?app_id={}&secret_key={}";
|
||||
String url = StrUtil.format(urlTemplate, liePinBaseUrl, appId, URLUtil.encode(secretKey));
|
||||
// 创建POST请求并设置请求头
|
||||
HttpRequest request = HttpUtil.createPost(url).header("Content-Type", "application/json");
|
||||
String responseBody;
|
||||
try (HttpResponse httpResponse = request.execute()) {
|
||||
responseBody = httpResponse.body();
|
||||
}
|
||||
// 解析JSON响应
|
||||
TokenResponse tokenResponse = JSONUtil.toBean(responseBody, TokenResponse.class);
|
||||
if (!tokenResponse.isSuccess()) {
|
||||
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR,tokenResponse.getMsg());
|
||||
}
|
||||
// 获取缓存的时间 提前半小时过期 重新获取
|
||||
Long expire = ((tokenResponse.getData().getExpire() - System.currentTimeMillis())/1000)-1800;
|
||||
redisUtilPool.setString(key,tokenResponse.getData().getToken(),expire.intValue());
|
||||
return tokenResponse.getData().getToken();
|
||||
} catch (Exception e) {
|
||||
log.error("第{}次获取token error:{}",i+1,error.getMessage());
|
||||
ThreadUtil.sleep(2, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
throw new ServiceException("获取token失败");
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.request.oppty.*;
|
||||
import com.cool.store.response.oppty.*;
|
||||
import com.cool.store.service.ThirdOpportunityService;
|
||||
import com.cool.store.utils.CommonContextUtil;
|
||||
import com.cool.store.utils.JsonUtils;
|
||||
import com.cool.store.utils.SignatureUtils;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
@@ -79,8 +80,8 @@ public class ThirdOpportunityServiceImpl implements ThirdOpportunityService {
|
||||
@Override
|
||||
public String berthOperation(BerthOperationRequest requestBody) {
|
||||
String url = apiUrl+"open/oppty/v1/addBerthInfo";
|
||||
return executeApiCall(url, requestBody, String.class);
|
||||
|
||||
String profileName = CommonContextUtil.getProfileName();
|
||||
return "online".equals(profileName) ? executeApiCall(url, requestBody, String.class) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -6,7 +6,10 @@ import com.cool.store.constants.CommonConstants;
|
||||
import com.cool.store.context.CurrentUserHolder;
|
||||
import com.cool.store.context.LoginUserInfo;
|
||||
import com.cool.store.dao.*;
|
||||
import com.cool.store.dto.BigRegionUserDTO;
|
||||
import com.cool.store.dto.BigRegionUserListDTO;
|
||||
import com.cool.store.dto.UserDTO;
|
||||
import com.cool.store.dto.region.BigRegionDTO;
|
||||
import com.cool.store.entity.*;
|
||||
import com.cool.store.enums.*;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
@@ -14,6 +17,7 @@ import com.cool.store.mapper.RegionMapper;
|
||||
import com.cool.store.mapper.SysRoleMapper;
|
||||
import com.cool.store.mapper.UserAuthMappingMapper;
|
||||
import com.cool.store.request.SysRoleRequest;
|
||||
import com.cool.store.response.bigdata.ApiResponse;
|
||||
import com.cool.store.service.UserAuthMappingService;
|
||||
import com.cool.store.utils.RedisConstantUtil;
|
||||
import com.cool.store.utils.RedisUtilPool;
|
||||
@@ -78,8 +82,11 @@ public class UserAuthMappingServiceImpl implements UserAuthMappingService {
|
||||
private EnterpriseUserRoleDao enterpriseUserRoleDao;
|
||||
@Autowired
|
||||
private RegionDao regionDao;
|
||||
@Autowired
|
||||
private BigRegionDAO bigRegionDAO;
|
||||
@Resource
|
||||
BigRegionDAO bigRegionDAO;
|
||||
|
||||
@Resource
|
||||
StoreDao storeDao;
|
||||
|
||||
|
||||
@Override
|
||||
@@ -228,22 +235,22 @@ public class UserAuthMappingServiceImpl implements UserAuthMappingService {
|
||||
// 查找有区域权限的人
|
||||
List<String> authRegionUserIdList = authWarRegionUser(regionId);
|
||||
if (CollectionUtils.isEmpty(authRegionUserIdList)) {
|
||||
return null;
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
Long roleId = userRoleEnum.getCode();
|
||||
List<String> hasRoleUserIdList = sysRoleMapper.getPositionUserIds(Collections.singletonList(String.valueOf(roleId)));
|
||||
if (CollectionUtils.isEmpty(hasRoleUserIdList)) {
|
||||
return null;
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
authRegionUserIdList.retainAll(hasRoleUserIdList);
|
||||
if (CollectionUtils.isEmpty(authRegionUserIdList)) {
|
||||
return null;
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(authRegionUserIdList)) {
|
||||
List<EnterpriseUserDO> userInfoByUserIds = enterpriseUserDAO.getUserInfoByUserIds(authRegionUserIdList);
|
||||
return userInfoByUserIds;
|
||||
}
|
||||
return null;
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -266,12 +273,12 @@ public class UserAuthMappingServiceImpl implements UserAuthMappingService {
|
||||
// 查找有区域权限的人
|
||||
List<String> authRegionUserIdList = authWarRegionUser(regionId);
|
||||
if (CollectionUtils.isEmpty(authRegionUserIdList)) {
|
||||
return null;
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
Long roleId = userRoleEnum.getCode();
|
||||
List<String> hasRoleUserIdList = sysRoleMapper.getPositionUserIds(Collections.singletonList(String.valueOf(roleId)));
|
||||
if (CollectionUtils.isEmpty(hasRoleUserIdList)) {
|
||||
return null;
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
authRegionUserIdList.retainAll(hasRoleUserIdList);
|
||||
if (CollectionUtils.isEmpty(authRegionUserIdList)) {
|
||||
@@ -536,6 +543,42 @@ public class UserAuthMappingServiceImpl implements UserAuthMappingService {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse<List<BigRegionUserListDTO>> getAllBigRegionSpecialRoleUserList(String storeCode, UserRoleEnum userRoleEnum) {
|
||||
StoreDO store = storeDao.getByStoreNum(storeCode);
|
||||
if (Objects.isNull(store)){
|
||||
return ApiResponse.error(ErrorCodeEnum.STORE_NUM_NOT_FOUND);
|
||||
}
|
||||
//如果没有大区 则返回空
|
||||
if (store.getBranch()==null){
|
||||
return ApiResponse.success( null);
|
||||
}
|
||||
//查询所有启用的大区
|
||||
List<BigRegionUserDTO> bigRegionByUserId = userAuthMappingMapper.getBigRegionByUserId(Arrays.asList(store.getBranch()), userRoleEnum.getDesc());
|
||||
//根据区域ID对bigRegionByUserId人员进行分组
|
||||
Map<Long, List<BigRegionUserDTO>> bigRegionByRegionId = bigRegionByUserId.stream().collect(Collectors.groupingBy(BigRegionUserDTO::getRegionId));
|
||||
//转为对象BigRegionUserListDTO
|
||||
List<BigRegionUserListDTO> result = bigRegionByRegionId.entrySet().stream().map(entry -> {
|
||||
BigRegionUserListDTO dto = new BigRegionUserListDTO();
|
||||
dto.setRegionId(entry.getKey());
|
||||
// 获取对应区域的大区信息
|
||||
if (CollectionUtils.isNotEmpty(entry.getValue())){
|
||||
BigRegionUserDTO regionDTO = entry.getValue().get(0);
|
||||
dto.setRegionName(regionDTO.getRegionName());
|
||||
}
|
||||
// 将 BigRegionUserDTO 转换为 UserDTO
|
||||
List<UserDTO> userDTOList = entry.getValue().stream().map(bigRegionUser -> {
|
||||
UserDTO userDTO = new UserDTO();
|
||||
userDTO.setName(bigRegionUser.getName());
|
||||
userDTO.setMobile(bigRegionUser.getMobile());
|
||||
return userDTO;
|
||||
}).collect(Collectors.toList());
|
||||
dto.setSpecialRoleUserList(userDTOList);
|
||||
return dto;
|
||||
}).collect(Collectors.toList());
|
||||
return ApiResponse.success(result);
|
||||
}
|
||||
|
||||
private List<String> extractNumbers(String regionPath) {
|
||||
List<String> regionIds = new ArrayList<>();
|
||||
Pattern pattern = Pattern.compile("\\d+");
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.cool.store.enums.*;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.http.WechatRest;
|
||||
import com.cool.store.mapper.HyPartnerUserChannelMapper;
|
||||
import com.cool.store.oss.OssClientService;
|
||||
import com.cool.store.request.MobileUpdateRequest;
|
||||
import com.cool.store.service.WechatMiniAppService;
|
||||
import com.cool.store.utils.RedisUtilPool;
|
||||
@@ -24,10 +25,13 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.cool.store.utils.easyExcel.EasyExcelUtil.getUploadPath;
|
||||
|
||||
/**
|
||||
* @author zhangchenbiao
|
||||
* @FileName: WechatMiniAppServiceImpl
|
||||
@@ -52,6 +56,8 @@ public class WechatMiniAppServiceImpl implements WechatMiniAppService {
|
||||
HyOpenAreaInfoDAO hyOpenAreaInfoDAO;
|
||||
@Resource
|
||||
PartnerUserWechatBindDAO partnerUserWechatBindDAO;
|
||||
@Resource
|
||||
private OssClientService ossClientService;
|
||||
@Value("${weixin.appId}")
|
||||
private String wxAppId;
|
||||
@Value("${weixin.appSecret}")
|
||||
@@ -62,6 +68,8 @@ public class WechatMiniAppServiceImpl implements WechatMiniAppService {
|
||||
private Integer exhibition;
|
||||
@Value("${recommended.channel.id}")
|
||||
private Integer recommended;
|
||||
@Value("${mybatis.configuration.variables.enterpriseId}")
|
||||
private String eid;
|
||||
|
||||
@Override
|
||||
public PartnerUserInfoVO miniProgramLogin(MiniProgramLoginDTO param) {
|
||||
@@ -286,4 +294,42 @@ public class WechatMiniAppServiceImpl implements WechatMiniAppService {
|
||||
return null;
|
||||
}
|
||||
|
||||
private String delCacheAndGetAccessToken() {
|
||||
String cacheAccessToken = "wechat_mini_" + wxAppId;
|
||||
redisUtilPool.delKey(cacheAccessToken);
|
||||
return wechatRest.getAccessToken(wxAppId, wxAppSecret);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createQrCode(String page, String scene, String width) {
|
||||
String accessToken = wechatRest.getAccessToken(wxAppId, wxAppSecret);
|
||||
if (StringUtils.isBlank(accessToken)) {
|
||||
log.error("token获取失败");
|
||||
return null;
|
||||
}
|
||||
byte[] qrCode = null;
|
||||
try {
|
||||
qrCode = wechatRest.createQrCode(accessToken, page, scene, width);
|
||||
} catch (ServiceException e) {
|
||||
if (ErrorCodeEnum.WX_ACCESS_TOKEN_INVALID.getCode() == e.getErrorCode()) {
|
||||
accessToken = delCacheAndGetAccessToken();
|
||||
qrCode = wechatRest.createQrCode(accessToken, page, scene, width);
|
||||
}
|
||||
}
|
||||
if (qrCode == null || qrCode.length == 0) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
// 生成唯一文件名
|
||||
String fileName = getUploadPath(eid) + "qrcode" + UUIDUtils.get32UUID() + ".png";
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(qrCode);
|
||||
String url = ossClientService.putObject(fileName, inputStream, (long) qrCode.length, "image/png");
|
||||
log.info("二维码上传OSS成功,url:{}", url);
|
||||
return url;
|
||||
} catch (Exception e) {
|
||||
log.error("二维码上传OSS失败", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,11 +5,13 @@ import com.cool.store.constants.RedisConstant;
|
||||
import com.cool.store.context.CurrentUserHolder;
|
||||
import com.cool.store.context.LoginUserInfo;
|
||||
import com.cool.store.dao.EnterpriseUserDAO;
|
||||
import com.cool.store.dao.StoreDao;
|
||||
import com.cool.store.dao.WithdrawApplicationDAO;
|
||||
import com.cool.store.dao.wallet.WalletTradeDAO;
|
||||
import com.cool.store.dto.wallet.AccountWithdrawerDTO;
|
||||
import com.cool.store.dto.wallet.TradeRecordDTO;
|
||||
import com.cool.store.dto.wallet.WithdrawApplicationDTO;
|
||||
import com.cool.store.entity.StoreDO;
|
||||
import com.cool.store.entity.WithdrawApplicationDO;
|
||||
import com.cool.store.entity.wallet.WalletTradeDO;
|
||||
import com.cool.store.enums.ErrorCodeEnum;
|
||||
@@ -28,6 +30,7 @@ import com.cool.store.utils.RedisUtil;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -35,12 +38,14 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.cool.store.enums.wallet.WalletTradeModuleEnum.STANDARD_STORE;
|
||||
import static com.cool.store.enums.wallet.WalletTradeModuleEnum.TRANSFER;
|
||||
|
||||
/**
|
||||
@@ -65,6 +70,9 @@ public class WithdrawApplicationServiceImpl implements WithdrawApplicationServic
|
||||
@Resource
|
||||
EnterpriseUserDAO enterpriseUserDAO;
|
||||
|
||||
@Resource
|
||||
StoreDao storeDao;
|
||||
|
||||
private static final String WITHDRAW_ORDER_PREFIX = "TX";
|
||||
|
||||
@Override
|
||||
@@ -77,8 +85,19 @@ public class WithdrawApplicationServiceImpl implements WithdrawApplicationServic
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.collect(Collectors.toSet());
|
||||
Map<String, String> userNameMap = enterpriseUserDAO.getUserNameMap(new ArrayList<>(userIdList));
|
||||
|
||||
// 获取门店ID列表并查询门店名称
|
||||
Set<String> storeIdList = responses.stream()
|
||||
.filter(x -> StringUtils.isNotBlank(x.getRelateStoreId()))
|
||||
.map(WithdrawApplicationDTO::getRelateStoreId)
|
||||
.collect(Collectors.toSet());
|
||||
Map<String, StoreDO> storeNameMap = storeDao.getStoreMapByStoreIds(new ArrayList<>(storeIdList));
|
||||
responses.stream().forEach(x->{
|
||||
x.setCreateUserName(userNameMap.get(x.getCreateUserId()));
|
||||
StoreDO storeDO = storeNameMap.get(x.getRelateStoreId());
|
||||
if (storeDO!=null){
|
||||
x.setRelateStoreName(storeDO.getStoreName());
|
||||
}
|
||||
});
|
||||
return new PageInfo<>(responses);
|
||||
}
|
||||
@@ -96,6 +115,8 @@ public class WithdrawApplicationServiceImpl implements WithdrawApplicationServic
|
||||
.amount(request.getAmount())
|
||||
.bankCardNo(request.getBankCardNo())
|
||||
.bankName(request.getBankName())
|
||||
.relateStoreId(request.getRelateStoreId())
|
||||
.remark(request.getRemark())
|
||||
.status(AllocationPayStatusEnum.UNPAID.getStatus())
|
||||
.createUserId(userId)
|
||||
.createTime(new Date())
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.cool.store.service.renewal;
|
||||
|
||||
import com.cool.store.request.renewal.RenewalApplicationCreateRequest;
|
||||
import com.cool.store.request.renewal.RenewalApplicationQueryRequest;
|
||||
import com.cool.store.request.renewal.RenewalApprovalRequest;
|
||||
import com.cool.store.request.renewal.RenewalFranchiseeConfirmRequest;
|
||||
import com.cool.store.vo.PartnerUserInfoVO;
|
||||
import com.cool.store.vo.renewal.RenewalApplicationDetailVO;
|
||||
import com.cool.store.vo.renewal.RenewalApplicationListVO;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
public interface RenewalApplicationService {
|
||||
|
||||
PageInfo<RenewalApplicationListVO> queryRenewalApplicationList(RenewalApplicationQueryRequest request);
|
||||
|
||||
RenewalApplicationDetailVO getRenewalApplicationDetail(Long renewalId);
|
||||
|
||||
Boolean createRenewalApplication(RenewalApplicationCreateRequest request);
|
||||
|
||||
Boolean franchiseeConfirm(RenewalFranchiseeConfirmRequest request, PartnerUserInfoVO user);
|
||||
|
||||
Boolean operationsConsultantApproval(RenewalApprovalRequest request);
|
||||
|
||||
Boolean regionalConsultantApproval(RenewalApprovalRequest request);
|
||||
|
||||
Boolean groupEngineeringApproval(RenewalApprovalRequest request);
|
||||
|
||||
void autoGenerateRenewalApplications();
|
||||
}
|
||||
@@ -0,0 +1,557 @@
|
||||
package com.cool.store.service.renewal.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollStreamUtil;
|
||||
import com.cool.store.context.CurrentUserHolder;
|
||||
import com.cool.store.context.LoginUserInfo;
|
||||
import com.cool.store.dao.EnterpriseUserDAO;
|
||||
import com.cool.store.dao.RegionDao;
|
||||
import com.cool.store.dao.StoreDao;
|
||||
import com.cool.store.dao.contract.ContractMasterDAO;
|
||||
import com.cool.store.dao.renewal.RenewalApplicationDAO;
|
||||
import com.cool.store.dao.renewal.RenewalRenovateApprovalDAO;
|
||||
import com.cool.store.dao.renewal.RenewalApplicationSignerInfoDAO;
|
||||
import com.cool.store.dao.store.StoreMasterSignerInfoDAO;
|
||||
import com.cool.store.entity.EnterpriseUserDO;
|
||||
import com.cool.store.entity.RegionDO;
|
||||
import com.cool.store.entity.StoreDO;
|
||||
import com.cool.store.entity.approval.CommonApprovalLogDO;
|
||||
import com.cool.store.entity.contract.ContractMasterDO;
|
||||
import com.cool.store.entity.renewal.RenewalApplicationDO;
|
||||
import com.cool.store.entity.renewal.RenewalApplicationSignerInfoDO;
|
||||
import com.cool.store.entity.renewal.RenewalRenovateApprovalDO;
|
||||
import com.cool.store.entity.store.StoreMasterSignerInfoDO;
|
||||
import com.cool.store.enums.ErrorCodeEnum;
|
||||
import com.cool.store.enums.UserRoleEnum;
|
||||
import com.cool.store.enums.approval.ApprovalResultEnum;
|
||||
import com.cool.store.enums.master.BrandTypeEnum;
|
||||
import com.cool.store.enums.renewal.RenewalNodeEnum;
|
||||
import com.cool.store.enums.renewal.RenewalStatusEnum;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
import com.cool.store.request.renewal.RenewalApplicationCreateRequest;
|
||||
import com.cool.store.request.renewal.RenewalApplicationQueryRequest;
|
||||
import com.cool.store.request.renewal.RenewalApprovalRequest;
|
||||
import com.cool.store.request.renewal.RenewalFranchiseeConfirmRequest;
|
||||
import com.cool.store.service.UserAuthMappingService;
|
||||
import com.cool.store.service.approval.CommonApprovalLogService;
|
||||
import com.cool.store.service.renewal.RenewalApplicationService;
|
||||
import com.cool.store.utils.BeanUtil;
|
||||
import com.cool.store.utils.GenerateNoUtil;
|
||||
import com.cool.store.utils.poi.StringUtils;
|
||||
import com.cool.store.vo.PartnerUserInfoVO;
|
||||
import com.cool.store.vo.approval.ApprovalGroupedVO;
|
||||
import com.cool.store.vo.renewal.ContractRelatedInfoVO;
|
||||
import com.cool.store.vo.renewal.RenewalApplicationDetailVO;
|
||||
import com.cool.store.vo.renewal.RenewalApplicationListVO;
|
||||
import com.cool.store.vo.renewal.RenewalRenovateApprovalVO;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.ListUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static javassist.CtClass.version;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class RenewalApplicationServiceImpl implements RenewalApplicationService {
|
||||
|
||||
private final RenewalApplicationDAO renewalApplicationDAO;
|
||||
private final ContractMasterDAO contractMasterDAO;
|
||||
private final StoreDao storeDao;
|
||||
private final RegionDao regionDao;
|
||||
private final EnterpriseUserDAO enterpriseUserDAO;
|
||||
private final CommonApprovalLogService commonApprovalLogService;
|
||||
private final UserAuthMappingService userAuthMappingService;
|
||||
private final RenewalRenovateApprovalDAO renewalRenovateApprovalDAO;
|
||||
private final StoreMasterSignerInfoDAO storeMasterSignerInfoDAO;
|
||||
private final RenewalApplicationSignerInfoDAO renewalApplicationSignerInfoDAO;
|
||||
private final com.cool.store.dao.approval.CommonApprovalLogDAO commonApprovalLogDAO;
|
||||
|
||||
|
||||
@Override
|
||||
public PageInfo<RenewalApplicationListVO> queryRenewalApplicationList(RenewalApplicationQueryRequest request) {
|
||||
if (request.getKeyword() != null && !request.getKeyword().isEmpty()) {
|
||||
request.setQueryStore(true);
|
||||
}
|
||||
List<String> regionIds = null;
|
||||
if (request.getRegionId() != null) {
|
||||
regionIds = Collections.singletonList(String.valueOf(request.getRegionId()));
|
||||
}
|
||||
PageHelper.startPage(request.getPageNum(), request.getPageSize());
|
||||
List<RenewalApplicationListVO> list = renewalApplicationDAO.queryRenewalApplicationList(request, regionIds);
|
||||
PageInfo<RenewalApplicationListVO> pageInfo = new PageInfo<>(list);
|
||||
|
||||
// 填充状态名称
|
||||
list.forEach(vo -> vo.setStatusName(RenewalStatusEnum.getNameByStatus(vo.getStatus())));
|
||||
|
||||
// 批量查询签约人信息并填充
|
||||
if (CollectionUtils.isNotEmpty(list)) {
|
||||
List<String> applicationNos = list.stream().map(RenewalApplicationListVO::getApplicationNo).collect(Collectors.toList());
|
||||
Map<String, RenewalApplicationSignerInfoDO> signerMap = renewalApplicationSignerInfoDAO.getByApplicationNos(applicationNos);
|
||||
List<String> storeCodeList = list.stream().map(RenewalApplicationListVO::getStoreCode).collect(Collectors.toList());
|
||||
List<StoreDO> storeList = storeDao.getStoreNumByStoreCodes(storeCodeList);
|
||||
Map<String, StoreDO> map = CollStreamUtil.toMap(storeList, StoreDO::getStoreNum, v -> v);
|
||||
List<Long> regionIdList = storeList.stream()
|
||||
.flatMap(store -> Stream.of(store.getRegionId(), store.getBranch()))
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
Map<Long, String> regionNameMap = regionDao.getRegionNameMap(regionIdList);
|
||||
List<String> userIds = storeList.stream().map(StoreDO::getJoinSupervision).collect(Collectors.toList());
|
||||
Map<String, String> userNameMap = enterpriseUserDAO.getUserNameMap(userIds);
|
||||
list.forEach(vo -> {
|
||||
RenewalApplicationSignerInfoDO signer = signerMap.get(vo.getApplicationNo());
|
||||
if (signer != null) {
|
||||
vo.setSigner1Name(signer.getSigner1Name());
|
||||
vo.setSigner1Mobile(signer.getSigner1Mobile());
|
||||
vo.setSigner2Name(signer.getSigner2Name());
|
||||
vo.setSigner2Mobile(signer.getSigner2Mobile());
|
||||
}
|
||||
StoreDO store = map.get(vo.getStoreCode());
|
||||
if (store!=null){
|
||||
vo.setStoreName(store.getStoreName());
|
||||
vo.setStoreAddress(store.getStoreAddress());
|
||||
vo.setBrandName(BrandTypeEnum.getDescByCode(store.getJoinBrand()));
|
||||
if (StringUtils.isNotBlank(store.getJoinSupervision())){
|
||||
vo.setRecruitmentManager(userNameMap.get(store.getJoinSupervision()));
|
||||
}
|
||||
vo.setRegionName(regionNameMap.get(store.getRegionId()));
|
||||
vo.setBranchName(regionNameMap.get(store.getBranch()));
|
||||
}
|
||||
});
|
||||
}
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenewalApplicationDetailVO getRenewalApplicationDetail(Long renewalId) {
|
||||
RenewalApplicationDO renewalDO = renewalApplicationDAO.getById(renewalId);
|
||||
if (renewalDO == null) {
|
||||
throw new ServiceException(ErrorCodeEnum.RENEWAL_APPLY_NOT_EXIST);
|
||||
}
|
||||
|
||||
RenewalApplicationDetailVO detailVO = new RenewalApplicationDetailVO();
|
||||
detailVO.setRenewalId(renewalDO.getId());
|
||||
detailVO.setApplicationNo(renewalDO.getApplicationNo());
|
||||
detailVO.setStoreCode(renewalDO.getStoreCode());
|
||||
detailVO.setContractExpireDate(renewalDO.getContractExpireDate());
|
||||
detailVO.setIsRenovate(renewalDO.getIsRenovate());
|
||||
detailVO.setStatus(renewalDO.getStatus());
|
||||
detailVO.setStatusName(RenewalStatusEnum.getNameByStatus(renewalDO.getStatus()));
|
||||
detailVO.setRemark(renewalDO.getRemark());
|
||||
detailVO.setOriginalContractNo(renewalDO.getOriginalContractNo());
|
||||
detailVO.setCreateUserName(renewalDO.getCreateUserName());
|
||||
detailVO.setCreatedTime(renewalDO.getCreatedTime());
|
||||
|
||||
// 查询门店信息补充
|
||||
if (renewalDO.getStoreCode() != null) {
|
||||
StoreDO store = storeDao.getByStoreNum(renewalDO.getStoreCode());
|
||||
if (store != null) {
|
||||
detailVO.setStoreName(store.getStoreName());
|
||||
detailVO.setStoreAddress(store.getStoreAddress());
|
||||
detailVO.setBrandName(BrandTypeEnum.getDescByCode(store.getJoinBrand()));
|
||||
detailVO.setStoreStatus(store.getStoreStatus());
|
||||
if (StringUtils.isNotBlank(store.getJoinSupervision())){
|
||||
String userName = enterpriseUserDAO.getUserName(store.getJoinSupervision());
|
||||
detailVO.setRecruitmentManager(userName);
|
||||
}
|
||||
Map<Long, String> regionNameMap = regionDao.getRegionNameMap(Arrays.asList(store.getBranch(), store.getRegionId()));
|
||||
detailVO.setRegionName(regionNameMap.get(store.getRegionId()));
|
||||
detailVO.setBranchName(regionNameMap.get(store.getBranch()));
|
||||
}
|
||||
}
|
||||
|
||||
// 查询关联合同信息
|
||||
if (renewalDO.getOriginalContractNo() != null) {
|
||||
ContractMasterDO contractDO = contractMasterDAO.getByContractNo(renewalDO.getOriginalContractNo());
|
||||
if (contractDO != null) {
|
||||
ContractRelatedInfoVO contractInfo = new ContractRelatedInfoVO();
|
||||
contractInfo.setContractNo(contractDO.getContractNo());
|
||||
contractInfo.setBrandName(contractDO.getBrandName());
|
||||
contractInfo.setSignDate(contractDO.getSignDate());
|
||||
contractInfo.setContractType(contractDO.getContractType());
|
||||
contractInfo.setStartDate(contractDO.getStartDate());
|
||||
contractInfo.setEndDate(contractDO.getEndDate());
|
||||
detailVO.setContractInfo(contractInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// 查询签约人信息快照
|
||||
RenewalApplicationSignerInfoDO signerInfo = renewalApplicationSignerInfoDAO.getByApplicationNo(renewalDO.getApplicationNo());
|
||||
if (signerInfo != null) {
|
||||
detailVO.setSigner1Name(signerInfo.getSigner1Name());
|
||||
detailVO.setSigner1Mobile(signerInfo.getSigner1Mobile());
|
||||
detailVO.setSigner2Name(signerInfo.getSigner2Name());
|
||||
detailVO.setSigner2Mobile(signerInfo.getSigner2Mobile());
|
||||
}
|
||||
|
||||
// 查询审批记录
|
||||
ApprovalGroupedVO approvalBatches = commonApprovalLogService.getApprovalRecordsGroupedByVersion(renewalDO.getApplicationNo());
|
||||
detailVO.setApprovalBatches(approvalBatches);
|
||||
|
||||
if (detailVO.getIsRenovate()==1){
|
||||
RenewalRenovateApprovalDO byApplicationNo = renewalRenovateApprovalDAO.getByApplicationNo(renewalDO.getApplicationNo());
|
||||
RenewalRenovateApprovalVO renewalRenovateApprovalVO = new RenewalRenovateApprovalVO();
|
||||
BeanUtil.copyProperties(byApplicationNo,renewalRenovateApprovalVO);
|
||||
detailVO.setRenewalRenovateApprovalVO(renewalRenovateApprovalVO);
|
||||
}
|
||||
|
||||
return detailVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Boolean createRenewalApplication(RenewalApplicationCreateRequest request) {
|
||||
LoginUserInfo currentUser = CurrentUserHolder.getUser();
|
||||
|
||||
// 查询门店信息
|
||||
StoreDO store = storeDao.getByStoreId(request.getStoreId());
|
||||
if (store == null) {
|
||||
throw new ServiceException(ErrorCodeEnum.STORE_NOT_EXIST);
|
||||
}
|
||||
|
||||
// 查询当前门店最新合同
|
||||
ContractMasterDO latestContract = contractMasterDAO.getLatestContractByStoreCode(store.getStoreNum());
|
||||
if (latestContract!=null&&latestContract.getRenewalCreated() != null && latestContract.getRenewalCreated() == 1) {
|
||||
throw new ServiceException(ErrorCodeEnum.CURRENT_SHOP_EXIST_APPLY);
|
||||
}
|
||||
|
||||
// 生成申请编号
|
||||
String applicationNo = GenerateNoUtil.generateNo("XQ");
|
||||
|
||||
// 构建续签申请
|
||||
RenewalApplicationDO renewalDO = RenewalApplicationDO.builder()
|
||||
.applicationNo(applicationNo)
|
||||
.storeCode(store.getStoreNum())
|
||||
.isDeleted(0)
|
||||
.status(RenewalStatusEnum.PENDING_FRANCHISEE.getStatus())
|
||||
.isRenovate(0)
|
||||
.remark(request.getRemark())
|
||||
.createUserName(currentUser.getName())
|
||||
.createUserId(currentUser.getUserId())
|
||||
.applyTime(new Date())
|
||||
.build();
|
||||
if (latestContract!=null){
|
||||
renewalDO.setOriginalContractNo(latestContract.getContractNo());
|
||||
renewalDO.setContractExpireDate(latestContract.getEndDate());
|
||||
}
|
||||
renewalApplicationDAO.insertSelective(renewalDO);
|
||||
|
||||
// 更新合同续签标记
|
||||
if (latestContract!=null){
|
||||
contractMasterDAO.updateRenewalCreated(latestContract.getId(), 1);
|
||||
}
|
||||
|
||||
// 保存签约人信息快照
|
||||
StoreMasterSignerInfoDO signerInfo = storeMasterSignerInfoDAO.getByStoreId(store.getStoreId());
|
||||
if (signerInfo != null) {
|
||||
RenewalApplicationSignerInfoDO signerSnapshot = RenewalApplicationSignerInfoDO.builder()
|
||||
.applicationNo(applicationNo)
|
||||
.signer1Name(signerInfo.getSigner1Name())
|
||||
.signer1Mobile(signerInfo.getSigner1Mobile())
|
||||
.signer2Name(signerInfo.getSigner2Name())
|
||||
.signer2Mobile(signerInfo.getSigner2Mobile())
|
||||
.createdTime(new Date())
|
||||
.updatedTime(new Date())
|
||||
.build();
|
||||
renewalApplicationSignerInfoDAO.insertSelective(signerSnapshot);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Boolean franchiseeConfirm(RenewalFranchiseeConfirmRequest request, PartnerUserInfoVO userInfoVO) {
|
||||
RenewalApplicationDO renewalDO = renewalApplicationDAO.getById(request.getRenewalId());
|
||||
if (renewalDO == null) {
|
||||
throw new ServiceException(ErrorCodeEnum.RENEWAL_APPLY_NOT_EXIST);
|
||||
}
|
||||
if (!RenewalStatusEnum.PENDING_FRANCHISEE.getStatus().equals(renewalDO.getStatus())) {
|
||||
throw new ServiceException(ErrorCodeEnum.NOT_SUPPORT_OPERATION);
|
||||
}
|
||||
|
||||
if (request.getConfirmed()) {
|
||||
// 确认续签 -> 待运营顾问审核
|
||||
renewalDO.setStatus(RenewalStatusEnum.PENDING_OPS.getStatus());
|
||||
renewalApplicationDAO.updateByPrimaryKeySelective(renewalDO);
|
||||
|
||||
|
||||
// 写入审批记录:加盟商提交记录
|
||||
commonApprovalLogService.insertSingleRecord(
|
||||
renewalDO.getApplicationNo(), userInfoVO.getPartnerId(), userInfoVO.getUsername(),
|
||||
RenewalNodeEnum.FRANCHISEE_CONFIRM.getCode(), RenewalNodeEnum.FRANCHISEE_CONFIRM.getName()
|
||||
);
|
||||
|
||||
// 获取区域信息
|
||||
StoreDO store = storeDao.getByStoreNum(renewalDO.getStoreCode());
|
||||
RegionDO regionDO = regionDao.getRegionByStoreId(store.getStoreId());
|
||||
|
||||
// 生成运营顾问审批节点
|
||||
List<String> auditUserIds = getAuditUserIds(regionDO != null ? regionDO.getId() : null, UserRoleEnum.SUPERVISION);
|
||||
List<CommonApprovalLogDO> approveRecords = new ArrayList<>();
|
||||
for (String userId : auditUserIds) {
|
||||
EnterpriseUserDO user = enterpriseUserDAO.getUserInfoById(userId);
|
||||
String userName = user != null ? user.getName() : "";
|
||||
approveRecords.add(CommonApprovalLogDO.builder()
|
||||
.nodeCode(RenewalNodeEnum.OPS_CONSULTANT.getCode())
|
||||
.nodeName(RenewalNodeEnum.OPS_CONSULTANT.getName())
|
||||
.handleUserId(userId)
|
||||
.handleUserName(userName)
|
||||
.build());
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(approveRecords)) {
|
||||
commonApprovalLogService.batchInsertApprovalRecords(renewalDO.getApplicationNo(), approveRecords);
|
||||
}
|
||||
|
||||
} else {
|
||||
// 不续签
|
||||
renewalDO.setStatus(RenewalStatusEnum.NOT_RENEWED.getStatus());
|
||||
renewalApplicationDAO.updateByPrimaryKeySelective(renewalDO);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Boolean operationsConsultantApproval(RenewalApprovalRequest request) {
|
||||
RenewalApplicationDO renewalDO = renewalApplicationDAO.getById(request.getRenewalId());
|
||||
if (renewalDO == null) {
|
||||
throw new ServiceException(ErrorCodeEnum.RENEWAL_APPLY_NOT_EXIST);
|
||||
}
|
||||
if (!RenewalStatusEnum.PENDING_OPS.getStatus().equals(renewalDO.getStatus())) {
|
||||
throw new ServiceException(ErrorCodeEnum.NOT_SUPPORT_OPERATION);
|
||||
}
|
||||
|
||||
LoginUserInfo currentUser = CurrentUserHolder.getUser();
|
||||
|
||||
if (request.getPass()) {
|
||||
// 翻新信息处理
|
||||
if (request.getIsRenovate() != null && request.getIsRenovate() == 1) {
|
||||
renewalDO.setIsRenovate(1);
|
||||
RenewalRenovateApprovalDO renovateDO = RenewalRenovateApprovalDO.builder()
|
||||
.applicationNo(renewalDO.getApplicationNo())
|
||||
.shopAreaId(request.getShopAreaId())
|
||||
.decorationAttributes(request.getDecorationAttributes())
|
||||
.decorationLevel(request.getDecorationLevel())
|
||||
.decorationRequirement(request.getDecorationRequirement())
|
||||
.specialInstruction(request.getSpecialInstruction())
|
||||
.videoUrl(request.getVideoUrl())
|
||||
.shopFrontPhotoUrl(request.getShopFrontPhotoUrl())
|
||||
.build();
|
||||
renewalRenovateApprovalDAO.insertSelective(renovateDO);
|
||||
}
|
||||
|
||||
// 通过 -> 待片区顾问审核
|
||||
renewalDO.setStatus(RenewalStatusEnum.PENDING_REGION.getStatus());
|
||||
renewalApplicationDAO.updateByPrimaryKeySelective(renewalDO);
|
||||
|
||||
commonApprovalLogService.updateNodeApprovalStatus(
|
||||
renewalDO.getApplicationNo(),
|
||||
RenewalNodeEnum.OPS_CONSULTANT.getCode(),
|
||||
ApprovalResultEnum.PASS.getResult(),
|
||||
currentUser.getUserId(), currentUser.getName(),
|
||||
request.getRemark(), true,
|
||||
getRegionIdByStoreCode(renewalDO.getStoreCode())
|
||||
);
|
||||
} else {
|
||||
// 拒绝
|
||||
renewalDO.setStatus(RenewalStatusEnum.REJECTED.getStatus());
|
||||
renewalApplicationDAO.updateByPrimaryKeySelective(renewalDO);
|
||||
|
||||
commonApprovalLogService.updateNodeApprovalStatus(
|
||||
renewalDO.getApplicationNo(),
|
||||
RenewalNodeEnum.OPS_CONSULTANT.getCode(),
|
||||
ApprovalResultEnum.REJECT.getResult(),
|
||||
currentUser.getUserId(), currentUser.getName(),
|
||||
request.getRemark(), false, null
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Boolean regionalConsultantApproval(RenewalApprovalRequest request) {
|
||||
LoginUserInfo currentUser = CurrentUserHolder.getUser();
|
||||
RenewalApplicationDO renewalDO = renewalApplicationDAO.getById(request.getRenewalId());
|
||||
if (renewalDO == null) {
|
||||
throw new ServiceException(ErrorCodeEnum.RENEWAL_APPLY_NOT_EXIST);
|
||||
}
|
||||
if (!RenewalStatusEnum.PENDING_REGION.getStatus().equals(renewalDO.getStatus())) {
|
||||
throw new ServiceException(ErrorCodeEnum.NOT_SUPPORT_OPERATION);
|
||||
}
|
||||
|
||||
if (request.getPass()) {
|
||||
// 通过 -> 待集团工程部审核
|
||||
renewalDO.setStatus(RenewalStatusEnum.PENDING_GROUP.getStatus());
|
||||
renewalApplicationDAO.updateByPrimaryKeySelective(renewalDO);
|
||||
|
||||
commonApprovalLogService.updateNodeApprovalStatus(
|
||||
renewalDO.getApplicationNo(),
|
||||
RenewalNodeEnum.REGION_CONSULTANT.getCode(),
|
||||
ApprovalResultEnum.PASS.getResult(),
|
||||
currentUser.getUserId(), currentUser.getName(),
|
||||
request.getRemark(), true,
|
||||
getRegionIdByStoreCode(renewalDO.getStoreCode())
|
||||
);
|
||||
} else {
|
||||
// 拒绝
|
||||
renewalDO.setStatus(RenewalStatusEnum.REJECTED.getStatus());
|
||||
renewalApplicationDAO.updateByPrimaryKeySelective(renewalDO);
|
||||
|
||||
commonApprovalLogService.updateNodeApprovalStatus(
|
||||
renewalDO.getApplicationNo(),
|
||||
RenewalNodeEnum.REGION_CONSULTANT.getCode(),
|
||||
ApprovalResultEnum.REJECT.getResult(),
|
||||
currentUser.getUserId(), currentUser.getName(),
|
||||
request.getRemark(), false, null
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Boolean groupEngineeringApproval(RenewalApprovalRequest request) {
|
||||
RenewalApplicationDO renewalDO = renewalApplicationDAO.getById(request.getRenewalId());
|
||||
if (renewalDO == null) {
|
||||
throw new ServiceException(ErrorCodeEnum.RENEWAL_APPLY_NOT_EXIST);
|
||||
}
|
||||
if (!RenewalStatusEnum.PENDING_GROUP.getStatus().equals(renewalDO.getStatus())) {
|
||||
throw new ServiceException(ErrorCodeEnum.NOT_SUPPORT_OPERATION);
|
||||
}
|
||||
|
||||
LoginUserInfo currentUser = CurrentUserHolder.getUser();
|
||||
Long version = getCurrentVersion(renewalDO.getApplicationNo());
|
||||
|
||||
if (request.getPass()) {
|
||||
// 通过 -> 续签中
|
||||
renewalDO.setStatus(RenewalStatusEnum.RENEWAL_ING.getStatus());
|
||||
renewalApplicationDAO.updateByPrimaryKeySelective(renewalDO);
|
||||
|
||||
commonApprovalLogService.updateNodeApprovalStatus(
|
||||
renewalDO.getApplicationNo(),
|
||||
RenewalNodeEnum.GROUP_ENGINEERING.getCode(),
|
||||
ApprovalResultEnum.PASS.getResult(),
|
||||
currentUser.getUserId(), currentUser.getName(),
|
||||
request.getRemark(), false, null
|
||||
);
|
||||
} else {
|
||||
// 拒绝
|
||||
renewalDO.setStatus(RenewalStatusEnum.REJECTED.getStatus());
|
||||
renewalApplicationDAO.updateByPrimaryKeySelective(renewalDO);
|
||||
|
||||
commonApprovalLogService.updateNodeApprovalStatus(
|
||||
renewalDO.getApplicationNo(),
|
||||
RenewalNodeEnum.GROUP_ENGINEERING.getCode(),
|
||||
ApprovalResultEnum.REJECT.getResult(),
|
||||
currentUser.getUserId(), currentUser.getName(),
|
||||
request.getRemark(), false, null
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void autoGenerateRenewalApplications() {
|
||||
// 查询90天内到期且未生成续签的合同
|
||||
List<ContractMasterDO> contracts = contractMasterDAO.queryContractsNearExpiry(90);
|
||||
if (CollectionUtils.isEmpty(contracts)) {
|
||||
log.info("没有即将到期的合同需要生成续签申请");
|
||||
return;
|
||||
}
|
||||
|
||||
for (ContractMasterDO contract : contracts) {
|
||||
try {
|
||||
// 再次检查renewalCreated状态(防止并发)
|
||||
ContractMasterDO fresh = contractMasterDAO.getById(contract.getId());
|
||||
if (fresh == null || fresh.getRenewalCreated() == 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String applicationNo = GenerateNoUtil.generateNo("XQ");
|
||||
RenewalApplicationDO renewalDO = RenewalApplicationDO.builder()
|
||||
.applicationNo(applicationNo)
|
||||
.storeCode(contract.getStoreCode())
|
||||
.originalContractNo(contract.getContractNo())
|
||||
.contractExpireDate(contract.getEndDate())
|
||||
.isDeleted(0)
|
||||
.status(RenewalStatusEnum.PENDING_FRANCHISEE.getStatus())
|
||||
.isRenovate(0)
|
||||
.remark("系统自动生成")
|
||||
.createUserName("系统")
|
||||
.applyTime(new Date())
|
||||
.build();
|
||||
renewalApplicationDAO.insertSelective(renewalDO);
|
||||
|
||||
// 保存签约人信息快照
|
||||
StoreDO store = storeDao.getByStoreNum(contract.getStoreCode());
|
||||
if (store != null) {
|
||||
StoreMasterSignerInfoDO signerInfo = storeMasterSignerInfoDAO.getByStoreId(store.getStoreId());
|
||||
if (signerInfo != null) {
|
||||
RenewalApplicationSignerInfoDO signerSnapshot = RenewalApplicationSignerInfoDO.builder()
|
||||
.applicationNo(applicationNo)
|
||||
.signer1Name(signerInfo.getSigner1Name())
|
||||
.signer1Mobile(signerInfo.getSigner1Mobile())
|
||||
.signer2Name(signerInfo.getSigner2Name())
|
||||
.signer2Mobile(signerInfo.getSigner2Mobile())
|
||||
.createdTime(new Date())
|
||||
.updatedTime(new Date())
|
||||
.build();
|
||||
renewalApplicationSignerInfoDAO.insertSelective(signerSnapshot);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新续签标记
|
||||
contractMasterDAO.updateRenewalCreated(contract.getId(), 1);
|
||||
|
||||
log.info("自动生成续签申请: applicationNo={}, storeCode={}", applicationNo, contract.getStoreCode());
|
||||
} catch (Exception e) {
|
||||
log.error("自动生成续签申请失败: contractId={}", contract.getId(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取申请当前批次版本号
|
||||
* 同一批次提交的所有审批记录使用相同的版本号
|
||||
*/
|
||||
private Long getCurrentVersion(String applicationNo) {
|
||||
return GenerateNoUtil.generateVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据门店编码获取区域ID
|
||||
*/
|
||||
private Long getRegionIdByStoreCode(String storeCode) {
|
||||
StoreDO store = storeDao.getByStoreNum(storeCode);
|
||||
if (store != null) {
|
||||
RegionDO region = regionDao.getRegionByStoreId(store.getStoreId());
|
||||
if (region != null) {
|
||||
return region.getId();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取审批人ID列表
|
||||
*/
|
||||
private List<String> getAuditUserIds(Long regionId, UserRoleEnum userRoleEnum) {
|
||||
List<EnterpriseUserDO> users = userAuthMappingService.getAllUserByRoleEnumAndRegionId(userRoleEnum, regionId);
|
||||
return ListUtils.emptyIfNull(users).stream()
|
||||
.map(EnterpriseUserDO::getUserId)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -114,7 +114,7 @@ public class VisitRecordServiceImpl implements VisitRecordService {
|
||||
.stream()
|
||||
.map(Long::valueOf)
|
||||
.collect(Collectors.toList());
|
||||
List<BigRegionDTO> bigRegionList = bigRegionDAO.queryAllBigRegion(null, null, null);
|
||||
List<BigRegionDTO> bigRegionList = bigRegionDAO.queryAllBigRegion(null, null, null, null);
|
||||
Set<Long> bigRegionIds = CollStreamUtil.toSet(bigRegionList, BigRegionDTO::getRegionId);
|
||||
authRegionIds.retainAll(bigRegionIds);
|
||||
if (CollectionUtils.isEmpty(authRegionIds)) {
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.cool.store.mapper.ApplyLicenseMapper;
|
||||
import com.cool.store.request.wallet.*;
|
||||
import com.cool.store.service.UserAuthMappingService;
|
||||
import com.cool.store.service.dict.impl.DictService;
|
||||
import com.cool.store.service.fees.WalletPayInfoService;
|
||||
import com.cool.store.service.impl.CommonService;
|
||||
import com.cool.store.service.wallet.*;
|
||||
import com.cool.store.utils.BeanUtil;
|
||||
@@ -82,6 +83,7 @@ public class WalletServiceImpl implements WalletService {
|
||||
private final UserAuthMappingService userAuthMappingService;
|
||||
private final CommonService commonService;
|
||||
private final WalletTradeService walletTradeService;
|
||||
private final WalletPayInfoService walletPayInfoService;
|
||||
@Value("${wallet.org.id}")
|
||||
private Long orgId;
|
||||
|
||||
@@ -558,6 +560,10 @@ public class WalletServiceImpl implements WalletService {
|
||||
if (orgFlag){
|
||||
tradeRecodePageRequest.setOrgId(orgId);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(request.getExpenseTypeCode())){
|
||||
tradeRecodePageRequest.setFeeItemId(walletPayInfoService.getFeeItemId(request.getExpenseTypeCode()));
|
||||
}
|
||||
|
||||
TradeRecordListDTO tradeRecordListDTO = walletApiService.getTradeRecordList(tradeRecodePageRequest);
|
||||
return toPageInfo(tradeRecordListDTO.getPageData(), TradeRecordDTO.class, tradeRecordListDTO.getPage());
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ public class EasyExcelUtil {
|
||||
|
||||
}
|
||||
|
||||
private String getUploadPath(String eid) {
|
||||
public static String getUploadPath(String eid) {
|
||||
String time = DateUtil.format(new Date(), "yyMM");
|
||||
return "eid" + "/" + eid + "/" + time + "/";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
package com.cool.store.utils.easyExcel;
|
||||
|
||||
import com.cool.store.dto.StoreImageExportDTO;
|
||||
import com.cool.store.oss.OssClientService;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author suzhuhong
|
||||
* @Date 2025/11/20 18:53
|
||||
* @Version 1.0
|
||||
*/
|
||||
@Service
|
||||
public class StoreImageExcelExporter {
|
||||
|
||||
@Resource
|
||||
private OssClientService ossClientService;
|
||||
/**
|
||||
* 导出带图片的门店信息到Excel
|
||||
* @param dataList 门店图片数据列表
|
||||
* @param response HTTP响应对象
|
||||
* @param fileName 导出文件名
|
||||
*/
|
||||
/**
|
||||
* 导出带图片的门店信息到Excel
|
||||
* @param dataList 门店图片数据列表
|
||||
* @param response HTTP响应对象
|
||||
* @param fileName 导出文件名
|
||||
*/
|
||||
public String exportStoreImages(List<StoreImageExportDTO> dataList,
|
||||
HttpServletResponse response,
|
||||
String fileName) throws Exception {
|
||||
Workbook workbook = new XSSFWorkbook();
|
||||
Sheet sheet = workbook.createSheet("门店图片信息");
|
||||
|
||||
// 设置表头
|
||||
Row headerRow = sheet.createRow(0);
|
||||
CellStyle headerStyle = createHeaderStyle(workbook);
|
||||
|
||||
Cell storeCodeHeader = headerRow.createCell(0);
|
||||
storeCodeHeader.setCellValue("门店编码");
|
||||
storeCodeHeader.setCellStyle(headerStyle);
|
||||
|
||||
Cell storeNameHeader = headerRow.createCell(1);
|
||||
storeNameHeader.setCellValue("门店名称");
|
||||
storeNameHeader.setCellStyle(headerStyle);
|
||||
|
||||
Cell imageHeader = headerRow.createCell(2);
|
||||
imageHeader.setCellValue("图片");
|
||||
imageHeader.setCellStyle(headerStyle);
|
||||
|
||||
// 创建绘图容器
|
||||
Drawing<?> drawing = sheet.createDrawingPatriarch();
|
||||
|
||||
// 填充数据
|
||||
for (int i = 0; i < dataList.size(); i++) {
|
||||
StoreImageExportDTO item = dataList.get(i);
|
||||
Row row = sheet.createRow(i + 1);
|
||||
|
||||
// 设置行高以便显示图片
|
||||
row.setHeightInPoints(300);
|
||||
|
||||
// 门店编码
|
||||
Cell storeCodeCell = row.createCell(0);
|
||||
storeCodeCell.setCellValue(item.getStoreCode());
|
||||
|
||||
// 门店名称
|
||||
Cell storeNameCell = row.createCell(1);
|
||||
storeNameCell.setCellValue(item.getStoreName());
|
||||
|
||||
// 插入图片到第3列(索引2)
|
||||
if (item.getImageUrl() != null && !item.getImageUrl().isEmpty()) {
|
||||
insertImageToCell(workbook, drawing, row, i, item.getImageUrl());
|
||||
}
|
||||
}
|
||||
|
||||
// 设置列宽
|
||||
sheet.setColumnWidth(0, 20 * 256); // 门店编码列宽
|
||||
sheet.setColumnWidth(1, 30 * 256); // 门店名称列宽
|
||||
sheet.setColumnWidth(2, 50 * 256);
|
||||
sheet.setColumnWidth(3, 50 * 256);
|
||||
sheet.setColumnWidth(4, 50 * 256);
|
||||
sheet.setColumnWidth(5, 50 * 256);
|
||||
sheet.setColumnWidth(6, 50 * 256);
|
||||
sheet.setColumnWidth(7, 50 * 256);
|
||||
sheet.setColumnWidth(8, 50 * 256);
|
||||
|
||||
// 设置响应头
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=" + java.net.URLEncoder.encode(fileName, "UTF-8"));
|
||||
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
workbook.write(byteArrayOutputStream);
|
||||
workbook.close();
|
||||
|
||||
// 准备上传到OSS
|
||||
byte[] bytes = byteArrayOutputStream.toByteArray();
|
||||
long size = bytes.length;
|
||||
InputStream inputStream = new ByteArrayInputStream(bytes);
|
||||
|
||||
// 提取文件名(不含扩展名)
|
||||
String objectName = fileName;
|
||||
if (fileName.contains(".")) {
|
||||
objectName = fileName.substring(0, fileName.lastIndexOf("."));
|
||||
}
|
||||
|
||||
// 上传到OSS并返回访问URL
|
||||
return ossClientService.putObject(objectName + ".xlsx", inputStream, size,
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 在指定列中垂直排列显示多张图片
|
||||
*/
|
||||
private void insertImageToCell(Workbook workbook, Drawing<?> drawing, Row row, int rowIndex, String imageUrl) {
|
||||
if (imageUrl == null || imageUrl.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String[] imageUrls = imageUrl.split(";");
|
||||
int imageCount = Math.min(imageUrls.length, 10);
|
||||
|
||||
if (imageCount == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 根据图片数量调整行高
|
||||
row.setHeightInPoints(300);
|
||||
|
||||
// 计算每张图片的宽度(平均分配)
|
||||
|
||||
for (int i = 0; i < imageCount; i++) {
|
||||
String singleImageUrl = imageUrls[i].trim();
|
||||
if (singleImageUrl.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
byte[] imageBytes = downloadImage(singleImageUrl);
|
||||
if (imageBytes != null) {
|
||||
int pictureIdx = workbook.addPicture(imageBytes, getImageType(singleImageUrl));
|
||||
CreationHelper helper = workbook.getCreationHelper();
|
||||
ClientAnchor anchor = helper.createClientAnchor();
|
||||
|
||||
// 水平排列:每张图片在相同的行,但不同的列位置
|
||||
anchor.setCol1(2 + i); // 起始列递增
|
||||
anchor.setRow1(rowIndex+1); // 相同的行
|
||||
anchor.setCol2(3 + i); // 结束列递增
|
||||
anchor.setRow2(rowIndex + 2); // 相同的结束行
|
||||
|
||||
anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
|
||||
|
||||
Picture picture = drawing.createPicture(anchor, pictureIdx);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Cell errorCell = row.createCell(2);
|
||||
errorCell.setCellValue("图片加载失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 创建表头样式
|
||||
*/
|
||||
private static CellStyle createHeaderStyle(Workbook workbook) {
|
||||
CellStyle style = workbook.createCellStyle();
|
||||
Font font = workbook.createFont();
|
||||
font.setBold(true);
|
||||
style.setFont(font);
|
||||
style.setAlignment(HorizontalAlignment.CENTER);
|
||||
return style;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载网络图片
|
||||
*/
|
||||
private byte[] downloadImage(String imageUrl) throws Exception {
|
||||
URL url = new URL(imageUrl);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setConnectTimeout(5000);
|
||||
connection.setReadTimeout(5000);
|
||||
connection.setRequestMethod("GET");
|
||||
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
try (InputStream inputStream = connection.getInputStream()) {
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||
outputStream.write(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
return outputStream.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文件扩展名判断图片类型
|
||||
*/
|
||||
private int getImageType(String imageUrl) {
|
||||
if (imageUrl.toLowerCase().endsWith(".png")) {
|
||||
return Workbook.PICTURE_TYPE_PNG;
|
||||
} else if (imageUrl.toLowerCase().endsWith(".jpg") || imageUrl.toLowerCase().endsWith(".jpeg")) {
|
||||
return Workbook.PICTURE_TYPE_JPEG;
|
||||
} else if (imageUrl.toLowerCase().endsWith(".gif")) {
|
||||
return Workbook.PICTURE_TYPE_JPEG;
|
||||
} else {
|
||||
return Workbook.PICTURE_TYPE_JPEG; // 默认JPEG
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -140,8 +140,8 @@ public class ExcelUtil<T> {
|
||||
* @param is 输入流
|
||||
* @return 转换后集合
|
||||
*/
|
||||
public List<T> importExcel(InputStream is) throws Exception {
|
||||
return importExcel(StringUtils.EMPTY, is);
|
||||
public List<T> importExcel(InputStream is,Integer titleRows) throws Exception {
|
||||
return importExcel(StringUtils.EMPTY, is, titleRows);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,7 +162,7 @@ public class ExcelUtil<T> {
|
||||
* @param is 输入流
|
||||
* @return 转换后集合
|
||||
*/
|
||||
public List<T> importExcel(String sheetName, InputStream is) throws Exception {
|
||||
public List<T> importExcel(String sheetName, InputStream is,Integer titleRows) throws Exception {
|
||||
this.type = Excel.Type.IMPORT;
|
||||
this.wb = WorkbookFactory.create(is);
|
||||
List<T> list = null;
|
||||
@@ -218,7 +218,7 @@ public class ExcelUtil<T> {
|
||||
// 定义一个map用于存放excel列的序号和field.
|
||||
Map<String, Integer> cellMap = new HashMap<>(16);
|
||||
// 获取表头
|
||||
Row heard = sheet.getRow(0);
|
||||
Row heard = sheet.getRow(titleRows);
|
||||
for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) {
|
||||
Cell cell = heard.getCell(i);
|
||||
if (ObjectUtil.isNotNull(cell)) {
|
||||
@@ -245,8 +245,10 @@ public class ExcelUtil<T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
//数据读取行数 默认表头+1
|
||||
Integer startRow = heard.getRowNum()+1;
|
||||
// 将数据填入集合
|
||||
list = fillCollection(sheet, rows, fieldsMap);
|
||||
list = fillCollection(sheet, rows, fieldsMap, startRow);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@@ -1130,10 +1132,10 @@ public class ExcelUtil<T> {
|
||||
* @throws InstantiationException 实例创建异常
|
||||
* @throws IllegalAccessException 实例创建异常
|
||||
*/
|
||||
private List<T> fillCollection(Sheet sheet, int rows, Map<Integer, Field> fieldsMap) throws InstantiationException, IllegalAccessException {
|
||||
private List<T> fillCollection(Sheet sheet, int rows, Map<Integer, Field> fieldsMap,Integer startRow) throws InstantiationException, IllegalAccessException {
|
||||
List<T> list = new ArrayList<>();
|
||||
int j=1;
|
||||
for (int i = 0; i < rows-1; i++) {
|
||||
int j=startRow;
|
||||
for (int i = j; i < rows; i++) {
|
||||
// 从第2行开始取数据,默认第一行是表头.
|
||||
Row row = sheet.getRow(j);
|
||||
j++;
|
||||
|
||||
Reference in New Issue
Block a user