Commit e7a8ebd2fe06e6023ca2e54bcbb8345d28bfaa59

Authored by yeqianyong
2 parents d0bd5ee0 71b7b8f4

Merge remote-tracking branch 'origin/master_0929' into master_0929

@@ -328,7 +328,7 @@ public class ContractDistributorStandardController extends DefaultBaseController @@ -328,7 +328,7 @@ public class ContractDistributorStandardController extends DefaultBaseController
328 String materialProductRatioName = rawToProdRatioCodeAndNameMap.get(contractStdProcessingLineBo.getMaterialProductRatio()); 328 String materialProductRatioName = rawToProdRatioCodeAndNameMap.get(contractStdProcessingLineBo.getMaterialProductRatio());
329 contractStdProcessingLineBo.setRawProductName(rawProductName); 329 contractStdProcessingLineBo.setRawProductName(rawProductName);
330 contractStdProcessingLineBo.setProductName(productName); 330 contractStdProcessingLineBo.setProductName(productName);
331 - contractStdProcessingLine.setMaterialProductRatio(materialProductRatioName); 331 + contractStdProcessingLineBo.setMaterialProductRatioName(materialProductRatioName);
332 lineBoList.add(contractStdProcessingLineBo); 332 lineBoList.add(contractStdProcessingLineBo);
333 }); 333 });
334 334
@@ -751,6 +751,55 @@ public class ContractDistributorStandardController extends DefaultBaseController @@ -751,6 +751,55 @@ public class ContractDistributorStandardController extends DefaultBaseController
751 } 751 }
752 } 752 }
753 753
  754 + if (CollectionUtils.isNotEmpty(data.getContractStdProcessingLineList())) {
  755 + startRow++;
  756 + for (GetContractStdProcessingLineBo contractStdProcessingLineBo : data.getContractStdProcessingLineList()) {
  757 + setCellValue(sheet, startRow, 1, contractStdProcessingLineBo.getRawProductName() + "、" + contractStdProcessingLineBo.getRawProductGrade()); // B列
  758 + setCellValue(sheet, startRow, 4, contractStdProcessingLineBo.getSupplyTime()); // D列
  759 + setCellValue(sheet, startRow, 5, contractStdProcessingLineBo.getMaterialProductRatioName()); // D列
  760 + setCellValue(sheet, startRow, 6, contractStdProcessingLineBo.getProductName()); // D列
  761 + setCellValue(sheet, startRow, 7, contractStdProcessingLineBo.getProductGrade()); // D列
  762 + setCellValue(sheet, startRow, 8, contractStdProcessingLineBo.getProductQuantity()); // D列
  763 +
  764 + List<LatexFormulaExcelExporterUtil.FormulaComponent> formulaComponentList = new ArrayList<>(3);
  765 + if (contractStdProcessingLineBo.getThickness() != null) {
  766 + LatexFormulaExcelExporterUtil.FormulaComponent formulaComponent = new LatexFormulaExcelExporterUtil.FormulaComponent();
  767 + formulaComponent.setBase(contractStdProcessingLineBo.getThickness());
  768 + formulaComponent.setSup(contractStdProcessingLineBo.getThicknessTolPos());
  769 + formulaComponent.setSub(contractStdProcessingLineBo.getThicknessTolNeg());
  770 + formulaComponentList.add(formulaComponent);
  771 + }
  772 +
  773 + if (contractStdProcessingLineBo.getWidth() != null) {
  774 + LatexFormulaExcelExporterUtil.FormulaComponent formulaComponent = new LatexFormulaExcelExporterUtil.FormulaComponent();
  775 + formulaComponent.setBase(contractStdProcessingLineBo.getWidth());
  776 + formulaComponent.setSup(contractStdProcessingLineBo.getWidthTolPos());
  777 + formulaComponent.setSub(contractStdProcessingLineBo.getWidthTolNeg());
  778 + formulaComponentList.add(formulaComponent);
  779 + }
  780 +
  781 + if (contractStdProcessingLineBo.getLength() != null) {
  782 + LatexFormulaExcelExporterUtil.FormulaComponent formulaComponent = new LatexFormulaExcelExporterUtil.FormulaComponent();
  783 + formulaComponent.setBase(contractStdProcessingLineBo.getLength());
  784 + formulaComponent.setSup(contractStdProcessingLineBo.getLengthTolPos());
  785 + formulaComponent.setSub(contractStdProcessingLineBo.getLengthTolNeg());
  786 + formulaComponentList.add(formulaComponent);
  787 + }
  788 +
  789 + String latex = LatexFormulaExcelExporterUtil.convertToLatex(formulaComponentList);
  790 + if (StringUtils.isNotBlank(latex)) {
  791 + LatexFormulaExcelExporterUtil.insertLatexImageToCell(workbook, sheet, latex, startRow, 9);// E列
  792 + }
  793 +
  794 + setCellValue(sheet, startRow, 10, contractStdProcessingLineBo.getProductStatus()); // D列
  795 + setCellValue(sheet, startRow, 11, contractStdProcessingLineBo.getUnitPrice()); // D列
  796 + setCellValue(sheet, startRow, 12, contractStdProcessingLineBo.getAmountExcludingTax()); // D列
  797 + setCellValue(sheet, startRow, 13, contractStdProcessingLineBo.getTotalAmount()); // D列
  798 + setCellValue(sheet, startRow, 14, contractStdProcessingLineBo.getDeliveryDate() != null ?
  799 + contractStdProcessingLineBo.getDeliveryDate().format(dateFormatter) : ""); // D列
  800 + }
  801 + }
  802 +
754 Map<String, Object> dataMap = new HashMap<>(); 803 Map<String, Object> dataMap = new HashMap<>();
755 dataMap.put("title", contractTitle); 804 dataMap.put("title", contractTitle);
756 dataMap.put("code", data.getCode()); 805 dataMap.put("code", data.getCode());
@@ -33,6 +33,7 @@ import io.swagger.annotations.ApiOperation; @@ -33,6 +33,7 @@ import io.swagger.annotations.ApiOperation;
33 import org.apache.commons.collections4.CollectionUtils; 33 import org.apache.commons.collections4.CollectionUtils;
34 import org.apache.commons.lang3.StringUtils; 34 import org.apache.commons.lang3.StringUtils;
35 import org.springframework.beans.factory.annotation.Autowired; 35 import org.springframework.beans.factory.annotation.Autowired;
  36 +import org.springframework.scheduling.annotation.Scheduled;
36 import org.springframework.validation.annotation.Validated; 37 import org.springframework.validation.annotation.Validated;
37 import org.springframework.web.bind.annotation.*; 38 import org.springframework.web.bind.annotation.*;
38 39
@@ -263,4 +264,12 @@ public class SpecLockDelayApplicationController extends DefaultBaseController { @@ -263,4 +264,12 @@ public class SpecLockDelayApplicationController extends DefaultBaseController {
263 264
264 return InvokeResultBuilder.success(); 265 return InvokeResultBuilder.success();
265 } 266 }
  267 +
  268 + @ApiOperation("发送锁规延期消息")
  269 + @GetMapping("/sendSpecLockDelayMsg")
  270 + @Scheduled(cron = "0 30 0 * * ?")
  271 + public InvokeResult<Void> sendSpecLockDelayMsg() {
  272 + specLockDelayApplicationService.sendDelaySpecLockMessage();
  273 + return InvokeResultBuilder.success();
  274 + }
266 } 275 }
@@ -80,7 +80,7 @@ public class HolidaysServiceImpl extends BaseMpServiceImpl<HolidaysMapper, Holid @@ -80,7 +80,7 @@ public class HolidaysServiceImpl extends BaseMpServiceImpl<HolidaysMapper, Holid
80 .collect(Collectors.toList()); 80 .collect(Collectors.toList());
81 81
82 int workingDays = 0; 82 int workingDays = 0;
83 - LocalDate currentDate = startDate.plusDays(1); // 从签订日第二天开始计算 83 + LocalDate currentDate = startDate; // 从签订日当天开始计算
84 84
85 while (!currentDate.isAfter(endDate)) { 85 while (!currentDate.isAfter(endDate)) {
86 if (restHolidaysList.contains(currentDate)) { 86 if (restHolidaysList.contains(currentDate)) {
@@ -99,6 +99,19 @@ public class HolidaysServiceImpl extends BaseMpServiceImpl<HolidaysMapper, Holid @@ -99,6 +99,19 @@ public class HolidaysServiceImpl extends BaseMpServiceImpl<HolidaysMapper, Holid
99 return workingDays <= maxWorkdays; 99 return workingDays <= maxWorkdays;
100 } 100 }
101 101
  102 + @Override
  103 + public boolean checkWorkdayToday() {
  104 + LocalDate today = LocalDate.now();
  105 + Holidays query = new Holidays();
  106 + query.setHolidayDate(today);
  107 + List<Holidays> holidays = query(query);
  108 + if (CollectionUtils.isNotEmpty(holidays)) {
  109 + return BooleanUtils.isFalse(holidays.get(0).getRest());
  110 + }
  111 +
  112 + return today.getDayOfWeek().getValue() <= 5;
  113 + }
  114 +
102 private List<Holidays> getHolidaysForYear(int year) throws Exception { 115 private List<Holidays> getHolidaysForYear(int year) throws Exception {
103 Holidays query = new Holidays(); 116 Holidays query = new Holidays();
104 query.setYear(year); 117 query.setYear(year);
@@ -11,6 +11,7 @@ import com.lframework.starter.bpm.vo.flow.task.QueryTodoTaskListVo; @@ -11,6 +11,7 @@ import com.lframework.starter.bpm.vo.flow.task.QueryTodoTaskListVo;
11 import com.lframework.starter.common.exceptions.impl.DefaultClientException; 11 import com.lframework.starter.common.exceptions.impl.DefaultClientException;
12 import com.lframework.starter.common.utils.Assert; 12 import com.lframework.starter.common.utils.Assert;
13 import com.lframework.starter.common.utils.ObjectUtil; 13 import com.lframework.starter.common.utils.ObjectUtil;
  14 +import com.lframework.starter.mq.core.service.MqProducerService;
14 import com.lframework.starter.web.core.annotations.oplog.OpLog; 15 import com.lframework.starter.web.core.annotations.oplog.OpLog;
15 import com.lframework.starter.web.core.components.resp.PageResult; 16 import com.lframework.starter.web.core.components.resp.PageResult;
16 import com.lframework.starter.web.core.components.security.SecurityUtil; 17 import com.lframework.starter.web.core.components.security.SecurityUtil;
@@ -20,6 +21,8 @@ import com.lframework.starter.web.core.utils.OpLogUtil; @@ -20,6 +21,8 @@ import com.lframework.starter.web.core.utils.OpLogUtil;
20 import com.lframework.starter.web.core.utils.PageHelperUtil; 21 import com.lframework.starter.web.core.utils.PageHelperUtil;
21 import com.lframework.starter.web.core.utils.PageResultUtil; 22 import com.lframework.starter.web.core.utils.PageResultUtil;
22 import com.lframework.starter.web.inner.components.oplog.OtherOpLogType; 23 import com.lframework.starter.web.inner.components.oplog.OtherOpLogType;
  24 +import com.lframework.starter.web.inner.dto.message.SysSiteMessageDto;
  25 +import com.lframework.starter.web.inner.service.system.SysUserRoleService;
23 import com.lframework.xingyun.sc.entity.ContractDistributorStandard; 26 import com.lframework.xingyun.sc.entity.ContractDistributorStandard;
24 import com.lframework.xingyun.sc.entity.SpecLockDelayApplication; 27 import com.lframework.xingyun.sc.entity.SpecLockDelayApplication;
25 import com.lframework.xingyun.sc.enums.CustomerDevelopStatus; 28 import com.lframework.xingyun.sc.enums.CustomerDevelopStatus;
@@ -30,6 +33,7 @@ import com.lframework.xingyun.sc.service.contract.SpecLockDelayApplicationServic @@ -30,6 +33,7 @@ import com.lframework.xingyun.sc.service.contract.SpecLockDelayApplicationServic
30 import com.lframework.xingyun.sc.vo.contract.createVo.CreateSpecLockDelayApplicationVo; 33 import com.lframework.xingyun.sc.vo.contract.createVo.CreateSpecLockDelayApplicationVo;
31 import com.lframework.xingyun.sc.vo.contract.queryVo.QuerySpecLockDelayApplicationVo; 34 import com.lframework.xingyun.sc.vo.contract.queryVo.QuerySpecLockDelayApplicationVo;
32 import com.lframework.xingyun.sc.vo.contract.updateVo.UpdateSpecLockDelayApplicationVo; 35 import com.lframework.xingyun.sc.vo.contract.updateVo.UpdateSpecLockDelayApplicationVo;
  36 +import lombok.extern.slf4j.Slf4j;
33 import org.apache.commons.collections.CollectionUtils; 37 import org.apache.commons.collections.CollectionUtils;
34 import org.apache.commons.lang3.StringUtils; 38 import org.apache.commons.lang3.StringUtils;
35 import org.springframework.beans.factory.annotation.Autowired; 39 import org.springframework.beans.factory.annotation.Autowired;
@@ -38,13 +42,16 @@ import org.springframework.cache.annotation.Cacheable; @@ -38,13 +42,16 @@ import org.springframework.cache.annotation.Cacheable;
38 import org.springframework.stereotype.Service; 42 import org.springframework.stereotype.Service;
39 import org.springframework.transaction.annotation.Transactional; 43 import org.springframework.transaction.annotation.Transactional;
40 44
  45 +import javax.annotation.Resource;
41 import java.io.Serializable; 46 import java.io.Serializable;
42 import java.time.LocalDate; 47 import java.time.LocalDate;
43 import java.time.LocalDateTime; 48 import java.time.LocalDateTime;
44 -import java.util.List; 49 +import java.util.*;
  50 +import java.util.function.Function;
45 import java.util.stream.Collectors; 51 import java.util.stream.Collectors;
46 52
47 @Service 53 @Service
  54 +@Slf4j
48 public class SpecLockDelayApplicationServiceImpl extends BaseMpServiceImpl<SpecLockDelayApplicationMapper, SpecLockDelayApplication> implements SpecLockDelayApplicationService { 55 public class SpecLockDelayApplicationServiceImpl extends BaseMpServiceImpl<SpecLockDelayApplicationMapper, SpecLockDelayApplication> implements SpecLockDelayApplicationService {
49 56
50 private static final String SPEC_LOCK_DELAY_FLAY = "SPEC_LOCK_DELAY"; // 未锁规格申请单审批 57 private static final String SPEC_LOCK_DELAY_FLAY = "SPEC_LOCK_DELAY"; // 未锁规格申请单审批
@@ -57,6 +64,10 @@ public class SpecLockDelayApplicationServiceImpl extends BaseMpServiceImpl<SpecL @@ -57,6 +64,10 @@ public class SpecLockDelayApplicationServiceImpl extends BaseMpServiceImpl<SpecL
57 private ContractDistributorStandardService contractDistributorStandardService; 64 private ContractDistributorStandardService contractDistributorStandardService;
58 @Autowired 65 @Autowired
59 private HolidaysService holidaysService; 66 private HolidaysService holidaysService;
  67 + @Autowired
  68 + private MqProducerService mqProducerService;
  69 + @Resource
  70 + private SysUserRoleService sysUserRoleService;
60 71
61 @Override 72 @Override
62 public PageResult<SpecLockDelayApplication> query(Integer pageIndex, Integer pageSize, QuerySpecLockDelayApplicationVo vo) { 73 public PageResult<SpecLockDelayApplication> query(Integer pageIndex, Integer pageSize, QuerySpecLockDelayApplicationVo vo) {
@@ -238,4 +249,141 @@ public class SpecLockDelayApplicationServiceImpl extends BaseMpServiceImpl<SpecL @@ -238,4 +249,141 @@ public class SpecLockDelayApplicationServiceImpl extends BaseMpServiceImpl<SpecL
238 public void cleanCacheByKey(Serializable key) { 249 public void cleanCacheByKey(Serializable key) {
239 250
240 } 251 }
  252 +
  253 + public void sendDelaySpecLockMessage() {
  254 + log.info("开始执行延迟锁规消息发送任务");
  255 +
  256 + // 检查工作日
  257 + if (!holidaysService.checkWorkdayToday()) {
  258 + log.info("今日非工作日,跳过执行");
  259 + return;
  260 + }
  261 +
  262 + log.info("今日为工作日,继续执行");
  263 +
  264 + // 构建查询条件
  265 + Wrapper<ContractDistributorStandard> wrapper = Wrappers.lambdaUpdate(ContractDistributorStandard.class)
  266 + .in(ContractDistributorStandard::getType, Arrays.asList("INTL_OPEN_SPEC_AGMT", "DRAFT_DIST_AGMT"))
  267 + .eq(ContractDistributorStandard::getStatus, "FORMAL")
  268 + .and(w -> w.isNull(ContractDistributorStandard::getPriceSpecLocked)
  269 + .or()
  270 + .eq(ContractDistributorStandard::getPriceSpecLocked, false));
  271 +
  272 + log.info("查询条件构建完成:类型为INTL_OPEN_SPEC_AGMT或DRAFT_DIST_AGMT,状态为FORMAL,价格规格锁定为空或false");
  273 +
  274 + List<ContractDistributorStandard> contractDistributorStandardList = contractDistributorStandardService.list(wrapper);
  275 +
  276 + if (org.apache.commons.collections4.CollectionUtils.isEmpty(contractDistributorStandardList)) {
  277 + log.info("未查询到符合条件的合同,任务结束");
  278 + return;
  279 + }
  280 +
  281 + log.info("查询到符合条件的合同数量:{}", contractDistributorStandardList.size());
  282 +
  283 + // 提取合同ID列表
  284 + List<String> contractIdList = contractDistributorStandardList.stream()
  285 + .map(ContractDistributorStandard::getId)
  286 + .collect(Collectors.toList());
  287 + log.info("提取合同ID列表完成,共{}个合同ID", contractIdList.size());
  288 +
  289 + // 查询最新的锁规延迟申请
  290 + log.info("开始查询最新的锁规延迟申请记录");
  291 + List<SpecLockDelayApplication> latestPassedByContractIds = this.getBaseMapper().selectLatestPassedByContractIds(contractIdList);
  292 +
  293 + if (org.apache.commons.collections4.CollectionUtils.isEmpty(latestPassedByContractIds)) {
  294 + log.info("未查询到任何锁规延迟申请记录");
  295 + } else {
  296 + log.info("查询到{}条锁规延迟申请记录", latestPassedByContractIds.size());
  297 + }
  298 +
  299 + Map<String, SpecLockDelayApplication> latestPassedMap = org.apache.commons.collections4.CollectionUtils.emptyIfNull(latestPassedByContractIds)
  300 + .stream().collect(Collectors.toMap(SpecLockDelayApplication::getContractId, Function.identity()));
  301 + log.info("锁规延迟申请记录映射表构建完成");
  302 +
  303 + // 处理每个合同
  304 + log.info("开始逐个处理合同消息发送");
  305 + int totalCount = contractDistributorStandardList.size();
  306 + int processedCount = 0;
  307 + int sentCount = 0;
  308 + int errorCount = 0;
  309 +
  310 + for (ContractDistributorStandard contractDistributorStandard : contractDistributorStandardList) {
  311 + processedCount++;
  312 + String contractId = contractDistributorStandard.getId();
  313 + String contractCode = contractDistributorStandard.getCode();
  314 +
  315 + log.info("正在处理合同[{}/{}],合同ID:{},合同号:{}", processedCount, totalCount, contractId, contractCode);
  316 +
  317 + try {
  318 + SpecLockDelayApplication latestPassed = latestPassedMap.get(contractId);
  319 + boolean needSendMsg;
  320 +
  321 + if (latestPassed != null) {
  322 + log.info("合同{}存在锁规延迟申请,锁规日期:{}", contractCode, latestPassed.getSpecLockDate());
  323 + if (latestPassed.getSpecLockDate().isBefore(LocalDate.now())) {
  324 + needSendMsg = true;
  325 + log.info("合同{}锁规日期已过,需要发送消息", contractCode);
  326 + } else {
  327 + needSendMsg = false;
  328 + log.info("合同{}锁规日期未到,不需要发送消息", contractCode);
  329 + }
  330 + } else {
  331 + log.info("合同{}无锁规延迟申请记录,检查工作日限制", contractCode);
  332 + boolean withinWorkdayLimit = holidaysService.isWithinWorkdayLimit(
  333 + contractDistributorStandard.getOrderDate(), LocalDate.now(), 5);
  334 + needSendMsg = !withinWorkdayLimit;
  335 + log.info("合同{}工作日检查结果:withinWorkdayLimit={}, needSendMsg={}",
  336 + contractCode, withinWorkdayLimit, needSendMsg);
  337 + }
  338 +
  339 + if (!needSendMsg) {
  340 + log.info("合同{}不需要发送消息,跳过", contractCode);
  341 + continue;
  342 + }
  343 +
  344 + // 获取用户列表
  345 + log.info("开始获取需要通知的用户列表");
  346 + List<String> userIdList = sysUserRoleService.listUserIdByRoleCodes(Arrays.asList("bsczg", "jybzg"));
  347 + userIdList.add(contractDistributorStandard.getCreateById());
  348 + log.info("合同{}需要通知的用户数量:{}", contractCode, userIdList.size());
  349 +
  350 + // 构建消息内容
  351 + StringBuilder sb = new StringBuilder();
  352 + sb.append("您的");
  353 + if ("DRAFT_DIST_AGMT".equals(contractDistributorStandard.getType())) {
  354 + sb.append("经销未锁规合同,");
  355 + log.info("合同{}类型为经销合同", contractCode);
  356 + } else {
  357 + sb.append("外贸未锁规格合同,");
  358 + log.info("合同{}类型为外贸合同", contractCode);
  359 + }
  360 + sb.append("合同号:").append(contractDistributorStandard.getCode());
  361 + sb.append("。锁规已经延期,请及时进行规格锁定!");
  362 +
  363 + String messageContent = sb.toString();
  364 + log.info("合同{}消息内容构建完成:{}", contractCode, messageContent);
  365 +
  366 + // 发送消息
  367 + SysSiteMessageDto messageDto = new SysSiteMessageDto();
  368 + messageDto.setUserIdList(userIdList);
  369 + messageDto.setTitle("合同锁规延期通知");
  370 + messageDto.setContent(messageContent);
  371 + messageDto.setBizKey(IdUtil.getId());
  372 + messageDto.setCreateUserId(null);
  373 +
  374 + log.info("准备发送站内信给合同{},用户数量:{}", contractCode, userIdList.size());
  375 + mqProducerService.createSysSiteMessage(messageDto);
  376 + sentCount++;
  377 + log.info("合同{}站内信发送成功", contractCode);
  378 +
  379 + } catch (Exception e) {
  380 + errorCount++;
  381 + log.error("处理合同{}时发生异常,合同号:{}", contractId, contractCode, e);
  382 + // 根据业务需求决定是否继续处理其他合同
  383 + }
  384 + }
  385 +
  386 + log.info("延迟锁规消息发送任务执行完成:总共处理{}个合同,成功发送{}条消息,失败{}个",
  387 + totalCount, sentCount, errorCount);
  388 + }
241 } 389 }
@@ -21,4 +21,6 @@ public interface SpecLockDelayApplicationMapper extends BaseMapper<SpecLockDelay @@ -21,4 +21,6 @@ public interface SpecLockDelayApplicationMapper extends BaseMapper<SpecLockDelay
21 * @return 21 * @return
22 */ 22 */
23 List<SpecLockDelayApplication> query(@Param("vo") QuerySpecLockDelayApplicationVo vo); 23 List<SpecLockDelayApplication> query(@Param("vo") QuerySpecLockDelayApplicationVo vo);
  24 +
  25 + List<SpecLockDelayApplication> selectLatestPassedByContractIds(@Param("contractIds") List<String> contractIds);
24 } 26 }
@@ -44,4 +44,11 @@ public interface HolidaysService extends BaseMpService<Holidays> { @@ -44,4 +44,11 @@ public interface HolidaysService extends BaseMpService<Holidays> {
44 * @return true表示没有超过,false表示超过了 44 * @return true表示没有超过,false表示超过了
45 */ 45 */
46 boolean isWithinWorkdayLimit(LocalDate startDate, LocalDate endDate, int maxWorkdays) throws Exception; 46 boolean isWithinWorkdayLimit(LocalDate startDate, LocalDate endDate, int maxWorkdays) throws Exception;
  47 +
  48 + /**
  49 + * 判断今天是否为工作日
  50 + *
  51 + * @return true 工作日,false 休息日
  52 + */
  53 + boolean checkWorkdayToday();
47 } 54 }
@@ -67,5 +67,9 @@ public interface SpecLockDelayApplicationService extends BaseMpService<SpecLockD @@ -67,5 +67,9 @@ public interface SpecLockDelayApplicationService extends BaseMpService<SpecLockD
67 */ 67 */
68 void cancelApplication(String id); 68 void cancelApplication(String id);
69 69
  70 + /**
  71 + * 锁规合同发送延期消息
  72 + */
  73 + void sendDelaySpecLockMessage();
70 } 74 }
71 75
@@ -54,4 +54,21 @@ @@ -54,4 +54,21 @@
54 </if> 54 </if>
55 </where> 55 </where>
56 </select> 56 </select>
  57 +
  58 + <select id="selectLatestPassedByContractIds" resultMap="SpecLockDelayApplication">
  59 + SELECT t1.*
  60 + FROM `tbl_spec_lock_delay_application` t1
  61 + INNER JOIN (
  62 + SELECT `contract_id`, MAX(`spec_lock_date`) as max_date
  63 + FROM `tbl_spec_lock_delay_application`
  64 + WHERE `contract_id` IN
  65 + <foreach collection="contractIds" item="contractId" open="(" close=")" separator=",">
  66 + #{contractId}
  67 + </foreach>
  68 + AND `approval_status` = 'PASS'
  69 + GROUP BY `contract_id`
  70 + ) t2 ON t1.`contract_id` = t2.`contract_id`
  71 + AND t1.`spec_lock_date` = t2.max_date
  72 + AND t1.`approval_status` = 'PASS'
  73 + </select>
57 </mapper> 74 </mapper>