提交 e02dd06f authored 作者: 窦馨雨's avatar 窦馨雨

合并分支 'qa' 到 'master'

CP促销小程序改造 查看合并请求 !79
package com.wangxiaolu.promotion.controller.activity.temporary; package com.wangxiaolu.promotion.controller.activity.temporary;
import com.wangxiaolu.promotion.controller.user.tem.TemporaryInfoQueryController;
import com.wangxiaolu.promotion.domain.user.dao.TemporaryInfoDao; import com.wangxiaolu.promotion.domain.user.dao.TemporaryInfoDao;
import com.wangxiaolu.promotion.enums.activity.TemActApproveStatus; import com.wangxiaolu.promotion.enums.activity.TemActApproveStatus;
import com.wangxiaolu.promotion.exception.DataException; import com.wangxiaolu.promotion.exception.DataException;
...@@ -14,6 +15,7 @@ import com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityCloc ...@@ -14,6 +15,7 @@ import com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityCloc
import com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityClockQueryService; import com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityClockQueryService;
import com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityCoreService; import com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityCoreService;
import com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityQueryService; import com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityQueryService;
import com.wangxiaolu.promotion.service.wechat.WeChatUserQueryService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -41,6 +43,9 @@ public class TemporaryActivityCoreController { ...@@ -41,6 +43,9 @@ public class TemporaryActivityCoreController {
@Autowired @Autowired
private TemporaryActivityClockCoreService tempActivityClockCoreService; private TemporaryActivityClockCoreService tempActivityClockCoreService;
@Autowired
private WeChatUserQueryService weChatUserQueryService;
/** /**
* 促销员[今日活动]数据保存 * 促销员[今日活动]数据保存
* 返回活动生成id * 返回活动生成id
...@@ -54,6 +59,11 @@ public class TemporaryActivityCoreController { ...@@ -54,6 +59,11 @@ public class TemporaryActivityCoreController {
TemporaryActivityReportedDto temActDto = new TemporaryActivityReportedDto(); TemporaryActivityReportedDto temActDto = new TemporaryActivityReportedDto();
BeanUtils.copyProperties(activityVo, temActDto); BeanUtils.copyProperties(activityVo, temActDto);
temActDto.setId(activityVo.getActivityReportedId()); temActDto.setId(activityVo.getActivityReportedId());
//保存促销员电话号码
String temporaryPhone = weChatUserQueryService.findUserPhoneByID(activityVo.getTemporaryId());
temActDto.setTemporaryPhone(temporaryPhone);
/** /**
* 已有id,修改任务 * 已有id,修改任务
*/ */
...@@ -78,7 +88,8 @@ public class TemporaryActivityCoreController { ...@@ -78,7 +88,8 @@ public class TemporaryActivityCoreController {
.setActivityPatternId(clockDto.getActivityPatternId()) .setActivityPatternId(clockDto.getActivityPatternId())
.setActivityPattern(clockDto.getActivityPattern()) .setActivityPattern(clockDto.getActivityPattern())
.setProvince(clockDto.getClockProvince()) .setProvince(clockDto.getClockProvince())
.setCity(clockDto.getClockCity()); .setCity(clockDto.getClockCity()).setTemporaryPhone(clockDto.getPhone())
;
long reportedId = tempActivityCoreService.activityDataReportedSave(temActDto); long reportedId = tempActivityCoreService.activityDataReportedSave(temActDto);
...@@ -128,26 +139,23 @@ public class TemporaryActivityCoreController { ...@@ -128,26 +139,23 @@ public class TemporaryActivityCoreController {
@PutMapping("/reported/approve/submit/{id}") @PutMapping("/reported/approve/submit/{id}")
public R activityReportedSubmit(@PathVariable("id") Long id) { public R activityReportedSubmit(@PathVariable("id") Long id) {
TemporaryActivityReportedDto activityReportedDto = temporaryActivityQueryService.findTemporaryActivityById(id); TemporaryActivityReportedDto activityReportedDto = temporaryActivityQueryService.findTemporaryActivityById(id);
Boolean posFlag = CollectionUtils.isEmpty(activityReportedDto.getPosTaskClockPhotoUrls())|| activityReportedDto.getPosTaskClockPhotoUrls().size() < 1;
if (activityReportedDto.getApproveStatus().equals(TemActApproveStatus.APPROVED) ){ if (CollectionUtils.isEmpty(activityReportedDto.getTgscPhotoInfos()) ){
if (posFlag) {
return R.fail(RCode.NOT_POS_TASK_PHOTO_ERROR);
}
return R.success();
}else{
if (CollectionUtils.isEmpty(activityReportedDto.getTgscPhotoInfos()) || activityReportedDto.getTgscPhotoInfos().size() < 2){
throw new DataException(RCode.NOT_TGSH_PHOTO_ERROR); throw new DataException(RCode.NOT_TGSH_PHOTO_ERROR);
}else if (CollectionUtils.isEmpty(activityReportedDto.getTghdPhotoInfos()) || activityReportedDto.getTghdPhotoInfos().size() < 2){ }else if (CollectionUtils.isEmpty(activityReportedDto.getTghdPhotoInfos()) ){
throw new DataException(RCode.NOT_TGHD_PHOTO_ERROR); throw new DataException(RCode.NOT_TGHD_PHOTO_ERROR);
}else if (CollectionUtils.isEmpty(activityReportedDto.getTgcjPhotoInfos()) || activityReportedDto.getTgcjPhotoInfos().size() < 2){ }else if (CollectionUtils.isEmpty(activityReportedDto.getTgcjPhotoInfos()) ){
throw new DataException(RCode.NOT_TGCJ_PHOTO_ERROR); throw new DataException(RCode.NOT_TGCJ_PHOTO_ERROR);
}else if (CollectionUtils.isEmpty(activityReportedDto.getScpPhotoInfos()) ){
throw new DataException(RCode.NOT_SCP_PHOTO_ERROR);
} else if (CollectionUtils.isEmpty(activityReportedDto.getPfzpPhotoInfos()) ){
throw new DataException(RCode.NOT_PFZP_PHOTO_ERROR);
} else if (CollectionUtils.isEmpty(activityReportedDto.getGfqPhotoInfos()) ){
throw new DataException(RCode.NOT_GFQ_PHOTO_ERROR);
} else if (CollectionUtils.isEmpty(activityReportedDto.getScbbwlPhotoInfos()) ){
throw new DataException(RCode.NOT_SCBBWL_PHOTO_ERROR);
} }
tempActivityCoreService.activityReportedSubmit(id); tempActivityCoreService.activityReportedSubmit(id);
if (posFlag) {
return R.fail(RCode.NOT_POS_TASK_PHOTO_ERROR);
}
}
return R.success(); return R.success();
} }
......
...@@ -17,6 +17,7 @@ import lombok.extern.slf4j.Slf4j; ...@@ -17,6 +17,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.io.File;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.YearMonth; import java.time.YearMonth;
......
package com.wangxiaolu.promotion.controller.user.location;
import com.wangxiaolu.promotion.result.basedata.R;
import com.wangxiaolu.promotion.service.user.TencentLocationQueryService;
import com.wangxiaolu.promotion.utils.TencentMapUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author: DouXinYu
* @Date: 2026-01-12 11:10
* @Description:
*/
@RestController
@RequestMapping("/user/location/query")
public class TencentLocationController {
@Autowired
TencentLocationQueryService tencentLocationQueryService;
@GetMapping("/reverse")
public R getDefaultLocation(@RequestParam("lng") double lng, @RequestParam("lat") double lat){
TencentMapUtil.AddressInfo addressByLngLat = tencentLocationQueryService.getAddressByLngLat(lng, lat);
return R.success(addressByLngLat);
}
// @GetMapping("/list")
// public R getProvinceDistinctList(){
// return R.success(tencentLocationQueryService.getAddressList());
// }
}
package com.wangxiaolu.promotion.controller.user.tem; package com.wangxiaolu.promotion.controller.user.tem;
import com.wangxiaolu.promotion.common.redis.RedisKeys;
import com.wangxiaolu.promotion.common.redis.service.RedisCache; import com.wangxiaolu.promotion.common.redis.service.RedisCache;
import com.wangxiaolu.promotion.common.util.DataUtils; import com.wangxiaolu.promotion.common.util.DataUtils;
import com.wangxiaolu.promotion.common.util.EnvUtil; import com.wangxiaolu.promotion.common.util.EnvUtil;
import com.wangxiaolu.promotion.domain.user.mapper.entity.WxTemporaryInfoDelayDO;
import com.wangxiaolu.promotion.exception.ParamException; import com.wangxiaolu.promotion.exception.ParamException;
import com.wangxiaolu.promotion.pojo.activity.temporary.dto.WxTemporaryInfoDelayDtO;
import com.wangxiaolu.promotion.pojo.user.dto.WxTemporaryInfoDto; import com.wangxiaolu.promotion.pojo.user.dto.WxTemporaryInfoDto;
import com.wangxiaolu.promotion.pojo.user.vo.WxTemporaryEnrollVo; import com.wangxiaolu.promotion.pojo.user.vo.WxTemporaryEnrollVo;
import com.wangxiaolu.promotion.result.basedata.R; import com.wangxiaolu.promotion.result.basedata.R;
import com.wangxiaolu.promotion.result.basedata.RCode; import com.wangxiaolu.promotion.result.basedata.RCode;
import com.wangxiaolu.promotion.service.wechat.WeChatUserCoreService; import com.wangxiaolu.promotion.service.wechat.WeChatUserCoreService;
import com.wangxiaolu.promotion.service.wechat.WeChatUserQueryService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import java.time.LocalDate;
import org.springframework.web.bind.annotation.RestController; import java.time.LocalDateTime;
import java.util.Map;
import java.util.Objects;
/** /**
* @author : liqiulin * @author : liqiulin
...@@ -33,6 +36,8 @@ public class TemporaryInfoCoreController { ...@@ -33,6 +36,8 @@ public class TemporaryInfoCoreController {
@Autowired @Autowired
private WeChatUserCoreService weChatUserCoreService; private WeChatUserCoreService weChatUserCoreService;
@Autowired @Autowired
private WeChatUserQueryService weChatUserQueryService;
@Autowired
private RedisCache redisCache; private RedisCache redisCache;
@Autowired @Autowired
private EnvUtil envUtil; private EnvUtil envUtil;
...@@ -58,7 +63,8 @@ public class TemporaryInfoCoreController { ...@@ -58,7 +63,8 @@ public class TemporaryInfoCoreController {
// if (envUtil.isLive()) { // if (envUtil.isLive()) {
// String redisKey = RedisKeys.UserKeys.PHONE_VER_CODE.getKey() + wxTemporaryEnrollVo.getPhone(); // String redisKey = RedisKeys.UserKeys.PHONE_VER_CODE.getKey() + wxTemporaryEnrollVo.getPhone();
// String phoneCodeOld = redisCache.get(redisKey); // String phoneCodeOld = redisCache.get(redisKey);
// if (StringUtils.isBlank(phoneCodeOld) || !phoneCodeOld.equals(wxTemporaryEnrollVo.getPhoneCode())) { // if (StringUtils.isBlan
// k(phoneCodeOld) || !phoneCodeOld.equals(wxTemporaryEnrollVo.getPhoneCode())) {
// throw new ParamException(RCode.TENCENT_SMS_PHONE_CODE_ERROR, null); // throw new ParamException(RCode.TENCENT_SMS_PHONE_CODE_ERROR, null);
// } // }
// redisCache.removeKey(redisKey); // redisCache.removeKey(redisKey);
...@@ -69,4 +75,30 @@ public class TemporaryInfoCoreController { ...@@ -69,4 +75,30 @@ public class TemporaryInfoCoreController {
return R.success(weChatUserCoreService.saveWxUserInfoTemporary(temporaryDto)); return R.success(weChatUserCoreService.saveWxUserInfoTemporary(temporaryDto));
} }
@PutMapping("/temporary/changeStoreInfo")
public R changeUserInfo(@RequestBody WxTemporaryEnrollVo wxTemporaryEnrollVo) {
if (wxTemporaryEnrollVo.getOpenId() == null) {
throw new ParamException(RCode.WX_OPENID_PARAM_ERROR, null);
}
Map<String, Object> temporaryWorkStore = weChatUserQueryService.findTemporaryWorkStore(wxTemporaryEnrollVo.getOpenId(), LocalDate.now().toString());
if (Objects.isNull(temporaryWorkStore) ) {
WxTemporaryInfoDto temporaryDto = new WxTemporaryInfoDto();
BeanUtils.copyProperties(wxTemporaryEnrollVo, temporaryDto);
weChatUserCoreService.saveWxUserStoreInfoTemporary(temporaryDto);
return R.success(true);
}
// 转换为延迟表实体
WxTemporaryInfoDelayDtO delayEntity = new WxTemporaryInfoDelayDtO();
BeanUtils.copyProperties(wxTemporaryEnrollVo, delayEntity);
// 设置数据日期(当天)、创建时间、未处理状态
delayEntity.setCreateTime(LocalDateTime.now());
delayEntity.setIsProcessed(0);
// 保存到延迟表
boolean saveResult = weChatUserCoreService.saveDelayData(delayEntity);
return R.success(saveResult);
}
} }
...@@ -51,7 +51,7 @@ public class TemporaryInfoQueryController { ...@@ -51,7 +51,7 @@ public class TemporaryInfoQueryController {
if (!DataUtils.phonePattern(wxTemporaryLoginVo.getPhone())) { if (!DataUtils.phonePattern(wxTemporaryLoginVo.getPhone())) {
throw new ParamException(RCode.PHONE_PARAM_ERROR, null); throw new ParamException(RCode.PHONE_PARAM_ERROR, null);
} }
LoginVo loginVo = weChatUserQueryService.temporaryLoginByPhone(wxTemporaryLoginVo.getPhone()); LoginVo loginVo = weChatUserQueryService.loginTemporaryByOpenIdAndPhone(wxTemporaryLoginVo.getOpenId(),wxTemporaryLoginVo.getPhone());
return R.success(loginVo); return R.success(loginVo);
} }
...@@ -72,12 +72,20 @@ public class TemporaryInfoQueryController { ...@@ -72,12 +72,20 @@ public class TemporaryInfoQueryController {
/** /**
* 注册时获取门店列表 * 注册时获取门店列表
* @param temporaryRegisterVo 临时注册信息 * @param
* @return 门店列表 * @return 门店列表
*/ */
@PostMapping("/temporary/findStoreList") @GetMapping("/temporary/findStoreList")
public R findStoreList(@RequestBody TemporaryRegisterVo temporaryRegisterVo) { public R findStoreList(@RequestParam("planDay") String planDay,@RequestParam(value = "storeNameKeyword",required = false) String storeNameKeyword) {
return R.success(weChatUserQueryService.findStoreList(temporaryRegisterVo)); return R.success(weChatUserQueryService.findStoreList(planDay,storeNameKeyword));
}
@PostMapping("/temporary/findTemporaryWorkStore")
public R findTemporaryInfo(@RequestBody TemporaryRegisterVo temporaryRegisterVo) {
if (StringUtils.isBlank(temporaryRegisterVo.getOpenId())) {
throw new ParamException(RCode.LOGIN_PARAM_ERROR, null);
}
return R.success(weChatUserQueryService.findTemporaryWorkStore(temporaryRegisterVo.getOpenId(),temporaryRegisterVo.getDate()));
} }
private void phontAndOpenIdVerify(WxTemporaryLoginVo wxTemporaryLoginVo) { private void phontAndOpenIdVerify(WxTemporaryLoginVo wxTemporaryLoginVo) {
......
...@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName; ...@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
/** /**
...@@ -140,6 +141,28 @@ public class TemporaryActivityReportedDO implements Serializable { ...@@ -140,6 +141,28 @@ public class TemporaryActivityReportedDO implements Serializable {
*/ */
private Integer isDelete; private Integer isDelete;
// 促销员联系电话
private String temporaryPhone;
// 执行方式
private String executeModePlan;
// 配发试吃品是否有黑鸭口味
private String hasBlackDuckFlavor;
// 配发黑鸭试吃品(根)
private Integer blackDuckTastingNum;
// 配发卤香试吃品(根)
private Integer braisedTastingNum;
// 配发赠品个数
private Integer giftNum;
// 推广活动销额(元)
private BigDecimal promotionSales;
// 黑鸭销售(元)
private BigDecimal blackDuckSales;
// 礼盒销售(元)
private BigDecimal giftBoxSales;
// 手工POS机销额
private String posManualSalesRecord;
@TableField(exist = false) @TableField(exist = false)
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
} }
...@@ -42,9 +42,9 @@ public interface ActivityPlanInfoDao { ...@@ -42,9 +42,9 @@ public interface ActivityPlanInfoDao {
/** /**
* 根据位置信息查询当前月份的促销门店 * 根据位置信息查询当前月份的促销门店
* @param temporaryRegisterVo 查询条件参数 * @param planDay 查询条件参数
* @return 门店信息列表 * @return 门店信息列表
*/ */
List<Map<String, String>> findThisMonthStoreListByLocation(TemporaryRegisterVo temporaryRegisterVo); List<Map<String, String>> findThisMonthStoreListByLocation(String planDay,String storeNameKeyword);
} }
...@@ -129,28 +129,14 @@ public class ActivityPlanInfoDaoImpl implements ActivityPlanInfoDao { ...@@ -129,28 +129,14 @@ public class ActivityPlanInfoDaoImpl implements ActivityPlanInfoDao {
/** /**
* 根据地理位置信息查询本店本月门店列表 * 根据地理位置信息查询本店本月门店列表
* @param temporaryRegisterVo 查询条件参数 * @param planDay 查询条件参数
* @return 门店列表 * @return 门店列表
*/ */
@Override @Override
public List<Map<String, String>> findThisMonthStoreListByLocation(TemporaryRegisterVo temporaryRegisterVo) { public List<Map<String, String>> findThisMonthStoreListByLocation(String planDay,String storeNameKeyword) {
LambdaQueryWrapper<ActivityPlanInfoDo> qw = new LambdaQueryWrapper<>(); List<Map<String, String>> activityPlanInfoDoList = activityPlanInfoMapper.selectStoreInfoByCondition(planDay,storeNameKeyword);
qw.likeRight(ActivityPlanInfoDo::getDate,temporaryRegisterVo.getMonth());
if (StringUtils.isNotBlank(temporaryRegisterVo.getProvince())){ return activityPlanInfoDoList;
qw.eq(ActivityPlanInfoDo::getProvince,temporaryRegisterVo.getProvince());
}
if (StringUtils.isNotBlank(temporaryRegisterVo.getCity())){
qw.eq(ActivityPlanInfoDo::getCity,temporaryRegisterVo.getCity());
}
List<ActivityPlanInfoDo> activityPlanInfoDoList = activityPlanInfoMapper.selectList(qw);
List<Map<String, String>> resultList = activityPlanInfoDoList.stream().map(activityPlanInfoDo -> {
Map<String, String> map = new HashMap<>();
map.put("storeCode", activityPlanInfoDo.getStoreCode());
map.put("storeName", activityPlanInfoDo.getStoreName());
return map;
}).collect(Collectors.toList());
return resultList;
} }
private LambdaQueryWrapper<ActivityPlanInfoDo> buildWrapper(ActivityPlanInfoWrapper wrapper) { private LambdaQueryWrapper<ActivityPlanInfoDo> buildWrapper(ActivityPlanInfoWrapper wrapper) {
......
...@@ -7,10 +7,12 @@ import com.wangxiaolu.promotion.domain.manage.wrapperQo.ActivityPlanInfoWrapper; ...@@ -7,10 +7,12 @@ import com.wangxiaolu.promotion.domain.manage.wrapperQo.ActivityPlanInfoWrapper;
import com.wangxiaolu.promotion.pojo.activity.planv2.dto.ActivityPlanInfoDto; import com.wangxiaolu.promotion.pojo.activity.planv2.dto.ActivityPlanInfoDto;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* @author a02200059 * @author a02200059
...@@ -39,6 +41,28 @@ public interface ActivityPlanInfoMapper extends BaseMapper<ActivityPlanInfoDo> { ...@@ -39,6 +41,28 @@ public interface ActivityPlanInfoMapper extends BaseMapper<ActivityPlanInfoDo> {
List<ActivityPlanInfoDo> findClockList(ActivityPlanInfoWrapper wrapper); List<ActivityPlanInfoDo> findClockList(ActivityPlanInfoWrapper wrapper);
void updateByIds(@Param("ids") List<Long> planIds, @Param("planDto") ActivityPlanInfoDto planDto); void updateByIds(@Param("ids") List<Long> planIds, @Param("planDto") ActivityPlanInfoDto planDto);
/**
* 查询符合条件的门店编码和名称(去重)
* @param date 日期阈值(格式:yyyy-MM-dd)
* @param storeNameKeyword 门店名称关键词
* @return 包含store_code和store_name的结果列表
*/
@Select({
"<script>",
"SELECT DISTINCT api.store_code AS storeCode, api.store_name AS storeName ",
"FROM activity_plan_info api ",
"WHERE api.`date` >= #{date} ",
"<if test='storeNameKeyword != null and storeNameKeyword != \"\"'>",
"AND api.store_name LIKE CONCAT('%', #{storeNameKeyword}, '%')",
"</if>",
"AND is_delete = 1 ",
"</script>"
})
List<Map<String, String>> selectStoreInfoByCondition(
@Param("date") String date,
@Param("storeNameKeyword") String storeNameKeyword
);
} }
......
...@@ -161,14 +161,23 @@ public class ActivityPlanInfoDo implements Serializable { ...@@ -161,14 +161,23 @@ public class ActivityPlanInfoDo implements Serializable {
// private BigDecimal incidentals; // private BigDecimal incidentals;
/** /**
* 是否有试吃台 * 门店是否已配试吃台
*/ */
private String temWlSct; private String temWlSct;
/** /**
* 活动品项:老品/黑鸭/散称 * 活动品项:老品/黑鸭/散称/礼盒
*/ */
private String prdClass; private String prdClass;
/**
* 活动执行方式:经销商/第三方
*/
private String planExecuteMode;
/**
* 门店是否允许使用试吃台
*/
private String isCanUseTasteCounter;
/** /**
* 是否执行:1:执行;0:未执行; * 是否执行:1:执行;0:未执行;
*/ */
......
...@@ -4,6 +4,9 @@ import com.wangxiaolu.promotion.domain.user.wrapperQo.TemporaryWrapper; ...@@ -4,6 +4,9 @@ import com.wangxiaolu.promotion.domain.user.wrapperQo.TemporaryWrapper;
import com.wangxiaolu.promotion.pojo.PageInfo; import com.wangxiaolu.promotion.pojo.PageInfo;
import com.wangxiaolu.promotion.pojo.user.dto.WxTemporaryInfoDto; import com.wangxiaolu.promotion.pojo.user.dto.WxTemporaryInfoDto;
import java.util.List;
import java.util.Map;
/** /**
* @author : liqiulin * @author : liqiulin
* @date : 2024-04-08 16 * @date : 2024-04-08 16
...@@ -28,4 +31,11 @@ public interface TemporaryInfoDao { ...@@ -28,4 +31,11 @@ public interface TemporaryInfoDao {
void updateById(WxTemporaryInfoDto temporaryDto); void updateById(WxTemporaryInfoDto temporaryDto);
WxTemporaryInfoDto selectByPhone(String phone); WxTemporaryInfoDto selectByPhone(String phone);
int saveWxUserStoreInfoTemporary(WxTemporaryInfoDto temporaryDto);
Map<String,Object> selectStoreAndPlan(String openId, String date);
int batchInsertOrUpdate(List<WxTemporaryInfoDto> list);
} }
package com.wangxiaolu.promotion.domain.user.dao;
import com.wangxiaolu.promotion.domain.user.mapper.entity.WxTemporaryInfoDelayDO;
import com.wangxiaolu.promotion.pojo.activity.temporary.dto.WxTemporaryInfoDelayDtO;
import org.springframework.stereotype.Repository;
import java.time.LocalDateTime;
import java.util.List;
@Repository
public interface WxTemporaryInfoDelayDao {
// 查询指定时间范围未处理的数据
List<WxTemporaryInfoDelayDtO> selectUnprocessedData(LocalDateTime startTime, LocalDateTime endTime);
// 插入单条延迟数据
int insert(WxTemporaryInfoDelayDtO delayEntity);
// 批量更新处理状态
int batchUpdateProcessedStatus(List<Long> idList, Integer isProcessed);
}
\ No newline at end of file
...@@ -21,6 +21,7 @@ import org.springframework.util.CollectionUtils; ...@@ -21,6 +21,7 @@ import org.springframework.util.CollectionUtils;
import java.sql.SQLIntegrityConstraintViolationException; import java.sql.SQLIntegrityConstraintViolationException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
/** /**
...@@ -94,6 +95,53 @@ public class TemporaryInfoDaoImpl implements TemporaryInfoDao { ...@@ -94,6 +95,53 @@ public class TemporaryInfoDaoImpl implements TemporaryInfoDao {
return transitionDto(temDo); return transitionDto(temDo);
} }
@Override
public int saveWxUserStoreInfoTemporary(WxTemporaryInfoDto temporaryDto) {
TemporaryInfoDO entity = new TemporaryInfoDO();
BeanUtils.copyProperties(temporaryDto, entity);
return temporaryInfoMapper.updateById(entity);
}
@Override
public Map<String,Object> selectStoreAndPlan(String openId, String date) {
return temporaryInfoMapper.selectStoreAndPlan(openId,date);
}
@Override
public int batchInsertOrUpdate(List<WxTemporaryInfoDto> list) {
// 空列表防护:避免无效SQL执行
int affectRows;
if (CollectionUtils.isEmpty(list)) {
return 0;
}
try {
// 1. 批量转换DTO → DO
List<TemporaryInfoDO> doList = new ArrayList<>(list.size());
for (WxTemporaryInfoDto dto : list) {
TemporaryInfoDO entity = new TemporaryInfoDO();
BeanUtils.copyProperties(dto, entity);
doList.add(entity);
}
// 2. 调用Mapper层的批量插入/更新方法
affectRows = temporaryInfoMapper.batchInsertOrUpdate(doList);
// 3. 异常捕获:处理唯一键冲突(复用项目已有异常逻辑)
} catch (Exception e) {
affectRows = 0;
String eMsg = e.getCause() != null ? e.getCause().getMessage() : e.getMessage();
if (eMsg.contains("for key 'open_id_unique'")) {
throw new ParamException(RCode.USER_WXOPENID_UNIQUE_ERROR);
} else if (eMsg.contains("for key 'phone_unique'")) {
throw new ParamException(RCode.USER_PHONE_UNIQUE_ERROR);
}
}
return affectRows;
}
private LambdaQueryWrapper<TemporaryInfoDO> buildQueryList(TemporaryWrapper tw) { private LambdaQueryWrapper<TemporaryInfoDO> buildQueryList(TemporaryWrapper tw) {
LambdaQueryWrapper<TemporaryInfoDO> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<TemporaryInfoDO> queryWrapper = new LambdaQueryWrapper<>();
if (StringUtils.isNotBlank(tw.getOpenId())) { if (StringUtils.isNotBlank(tw.getOpenId())) {
......
package com.wangxiaolu.promotion.domain.user.dao.impl;
import com.wangxiaolu.promotion.common.util.BeanUtils;
import com.wangxiaolu.promotion.domain.user.dao.WxTemporaryInfoDelayDao;
import com.wangxiaolu.promotion.domain.user.mapper.WxTemporaryInfoDelayMapper;
import com.wangxiaolu.promotion.domain.user.mapper.entity.WxTemporaryInfoDelayDO;
import com.wangxiaolu.promotion.pojo.activity.temporary.dto.WxTemporaryInfoDelayDtO;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Component
public class WxTemporaryInfoDelayDaoImpl implements WxTemporaryInfoDelayDao {
@Resource
private WxTemporaryInfoDelayMapper delayMapper;
@Override
public List<WxTemporaryInfoDelayDtO> selectUnprocessedData(LocalDateTime startTime, LocalDateTime endTime) {
// 1. 查询数据库获取DO列表
List<WxTemporaryInfoDelayDO> wxTemporaryInfoDelayDOS = delayMapper.selectByTimeAndStatus(startTime, endTime, 0);
// 2. 调用类内的通用转换方法完成DO转DTO
return copyListProperties(wxTemporaryInfoDelayDOS, WxTemporaryInfoDelayDtO.class);
}
@Override
public int insert(WxTemporaryInfoDelayDtO delayEntity) {
WxTemporaryInfoDelayDO delayDO = new WxTemporaryInfoDelayDO();
BeanUtils.copyProperties(delayEntity, delayDO);
return delayMapper.insert(delayDO);
}
@Override
public int batchUpdateProcessedStatus(List<Long> idList, Integer isProcessed) {
if (idList == null || idList.isEmpty()) {
return 0;
}
return delayMapper.batchUpdateStatus(idList, isProcessed);
}
private <S, T> List<T> copyListProperties(List<S> sourceList, Class<T> targetClass) {
// 空值判断,避免空指针
if (sourceList == null || sourceList.isEmpty()) {
return new ArrayList<>();
}
// 批量转换源列表为目标列表
return sourceList.stream()
.map(source -> {
try {
// 反射创建目标对象实例
T target = targetClass.getDeclaredConstructor().newInstance();
// 拷贝属性
BeanUtils.copyProperties(source, target);
return target;
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException |
InvocationTargetException e) {
// 转换失败抛出运行时异常,便于排查问题
throw new RuntimeException("对象列表转换失败,目标类:" + targetClass.getName(), e);
}
})
.collect(Collectors.toList());
}
}
\ No newline at end of file
...@@ -4,8 +4,12 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; ...@@ -4,8 +4,12 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.wangxiaolu.promotion.domain.user.mapper.entity.TemporaryInfoDO; import com.wangxiaolu.promotion.domain.user.mapper.entity.TemporaryInfoDO;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
/** /**
* @author a02200059 * @author a02200059
* @description 针对表【temporary_info】的数据库操作Mapper * @description 针对表【temporary_info】的数据库操作Mapper
...@@ -19,6 +23,22 @@ public interface TemporaryInfoMapper extends BaseMapper<TemporaryInfoDO> { ...@@ -19,6 +23,22 @@ public interface TemporaryInfoMapper extends BaseMapper<TemporaryInfoDO> {
// 根据openId查询非保密数据,保密数据不返回:身份证号、身份证照片等信息 // 根据openId查询非保密数据,保密数据不返回:身份证号、身份证照片等信息
TemporaryInfoDO getUnimportantData(@Param("openId") String openId); TemporaryInfoDO getUnimportantData(@Param("openId") String openId);
@Select({
"SELECT ti.store_code AS storeCode, ",
" ti.store_name AS storeName, ",
" api.id AS planId ",
"FROM temporary_info ti ",
"LEFT JOIN activity_plan_info api ON ti.store_name = api.store_name ",
" AND api.is_delete = 1 ",
" AND api.`date` = #{date} ",
"WHERE ti.open_id = #{openId}"
})
Map<String, Object> selectStoreAndPlan(
@Param("openId") String openId,
@Param("date") String date
);
int batchInsertOrUpdate(@Param("list") List<TemporaryInfoDO> doList);
} }
......
package com.wangxiaolu.promotion.domain.user.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.wangxiaolu.promotion.domain.user.mapper.entity.WxTemporaryInfoDelayDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.time.LocalDateTime;
import java.util.List;
/**
* 延迟临时表Mapper
*/
@Repository
@Mapper
public interface WxTemporaryInfoDelayMapper extends BaseMapper<WxTemporaryInfoDelayDO> {
/**
* 查询指定时间范围内未处理的数据
*/
List<WxTemporaryInfoDelayDO> selectByTimeAndStatus(
@Param("startTime") LocalDateTime startTime,
@Param("endTime") LocalDateTime endTime,
@Param("isProcessed") Integer isProcessed
);
/**
* 批量更新处理状态
*/
int batchUpdateStatus(
@Param("idList") List<Long> idList,
@Param("isProcessed") Integer isProcessed
);
}
\ No newline at end of file
package com.wangxiaolu.promotion.domain.user.mapper.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 微信门店数据延迟保存临时表实体
*/
@Data
@TableName("wx_temporary_info_delay")
public class WxTemporaryInfoDelayDO {
/**
* 主键ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 微信OpenId
*/
private String openId;
/**
* 门店名称
*/
private String storeName;
/**
* 门店编码
*/
private String storeCode;
/**
* 联系电话
*/
private String contactPhone;
/**
* 数据暂存时间
*/
private LocalDateTime createTime;
/**
* 是否已处理:0-未处理 1-已处理
*/
private Integer isProcessed;
/**
* 更新时间
*/
private LocalDateTime updateTime;
}
\ No newline at end of file
...@@ -39,20 +39,29 @@ public enum ActivityPhotoType { ...@@ -39,20 +39,29 @@ public enum ActivityPhotoType {
* 下班打卡图片 * 下班打卡图片
*/ */
CLOCK_OUT(7), CLOCK_OUT(7),
/**
* 试吃照片
*/
TASTY_PHOTO(8),
/** /**
* 当日销量POS机页面凭证 * 当日销量POS机页面凭证
*/ */
POS_SELL_VOUCHER(8), POS_SELL_VOUCHER(9),
/** /**
* POS照片 * 高峰期在岗
* 更改固定任务:下午18点15任务
*/ */
POS_PHOTO(9), RANDOM_TASK(10),
/** /**
* 随机任务照片 * 配发赠品照片
* 更改固定任务:下午18点15任务 */
SEND_GIFT_PHOTO(11),
/**
* 试吃素材
*/ */
RANDOM_TASK(10) TASTY_MATERIALS(12)
; ;
private int type; private int type;
......
...@@ -77,4 +77,5 @@ public class ActivityPlanInfoVo { ...@@ -77,4 +77,5 @@ public class ActivityPlanInfoVo {
private String lineName; private String lineName;
} }
...@@ -158,14 +158,24 @@ public class ActivityPlanInfoDto implements Serializable { ...@@ -158,14 +158,24 @@ public class ActivityPlanInfoDto implements Serializable {
*/ */
// private BigDecimal incidentals; // private BigDecimal incidentals;
/** /**
* 是否有试吃台 * 门店是否已配试吃台
*/ */
private String temWlSct; private String temWlSct;
/** /**
* 活动品项:老品/黑鸭/散称 * 活动品项:老品/黑鸭/散称/礼盒
*/ */
private String prdClass; private String prdClass;
/**
* 活动执行方式:经销商/第三方
*/
private String planExecuteMode;
/**
* 门店是否允许使用试吃台
*/
private String isCanUseTasteCounter;
/** /**
* 是否执行:1:执行;0:未执行; * 是否执行:1:执行;0:未执行;
*/ */
......
...@@ -80,12 +80,21 @@ public class ActivityPlanOperVo { ...@@ -80,12 +80,21 @@ public class ActivityPlanOperVo {
private LocalDateTime noonClockInTime; private LocalDateTime noonClockInTime;
/** /**
* 是否有试吃台 * 门店是否可用试吃台
*/
private String isCanUseTasteCounter;
/**
* 门店是否配有试吃台
*/ */
private String temWlSct; private String temWlSct;
/** /**
* 活动品项:老品/黑鸭/散称 * 活动品项:老品/黑鸭/散称/礼盒
*/ */
private String prdClass; private String prdClass;
/**
* 执行方式
*/
private String planExecuteMode;
private List<Long> planIds; private List<Long> planIds;
} }
...@@ -156,6 +156,31 @@ public class TemporaryActivityReportedDto { ...@@ -156,6 +156,31 @@ public class TemporaryActivityReportedDto {
private List<TemporaryActivityPhotoDto> randTaskClockPhotoUrls; private List<TemporaryActivityPhotoDto> randTaskClockPhotoUrls;
private List<TemporaryActivityPhotoDto> posTaskClockPhotoUrls; private List<TemporaryActivityPhotoDto> posTaskClockPhotoUrls;
/**
* 试吃品照片
*/
private List<String> scpPhotoUrls;
private List<TemporaryActivityPhotoDto>scpPhotoInfos;
private List<String> scpChangePhotoUrls;
/**
* 配发赠品照片
*/
private List<String> pfzpPhotoUrls;
private List<TemporaryActivityPhotoDto>pfzpPhotoInfos;
private List<String> pfzpChangePhotoUrls;
/**
* 高峰期在岗
*/
private List<String> gfqPhotoUrls;
private List<TemporaryActivityPhotoDto> gfqPhotoInfos;
private List<String> gfqChangePhotoUrls;
/**
* 试吃必备物料照片
*/
private List<String> scbbwlPhotoUrls;
private List<TemporaryActivityPhotoDto> scbbwlPhotoInfos;
private List<String> scbbwlChangePhotoUrls;
/** /**
* 创建时间 * 创建时间
...@@ -203,6 +228,8 @@ public class TemporaryActivityReportedDto { ...@@ -203,6 +228,8 @@ public class TemporaryActivityReportedDto {
// 礼盒销售(元) // 礼盒销售(元)
private BigDecimal giftBoxSales; private BigDecimal giftBoxSales;
// 手工POS机销额
private String posManualSalesRecord;
public void approvedDataVerify(){ public void approvedDataVerify(){
} }
......
package com.wangxiaolu.promotion.pojo.activity.temporary.dto;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 微信门店数据延迟保存临时表实体
*/
@Data
public class WxTemporaryInfoDelayDtO {
/**
* 主键ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 微信OpenId
*/
private String openId;
/**
* 门店名称
*/
private String storeName;
/**
* 门店地址
*/
private String storeCode;
/**
* 联系电话
*/
private String contactPhone;
/**
* 数据暂存时间
*/
private LocalDateTime createTime;
/**
* 是否已处理:0-未处理 1-已处理
*/
private Integer isProcessed;
/**
* 更新时间
*/
private LocalDateTime updateTime;
}
\ No newline at end of file
...@@ -67,6 +67,24 @@ public class TemporaryActivityDataVo { ...@@ -67,6 +67,24 @@ public class TemporaryActivityDataVo {
*/ */
private List<String> psvPhotoUrls; private List<String> psvPhotoUrls;
private List<String> psvChangePhotoUrls; private List<String> psvChangePhotoUrls;
/**
* 试吃品照片
*/
private List<String> scpPhotoUrls;
/**
* 配发赠品照片
*/
private List<String> pfzpPhotoUrls;
/**
* 高峰期在岗
*/
private List<String> gfqPhotoUrls;
/**
* 试吃必备物料照片
*/
private List<String> scbbwlPhotoUrls;
// 促销员联系电话 // 促销员联系电话
private String temporaryPhone; private String temporaryPhone;
// 执行方式 // 执行方式
...@@ -85,5 +103,7 @@ public class TemporaryActivityDataVo { ...@@ -85,5 +103,7 @@ public class TemporaryActivityDataVo {
private BigDecimal blackDuckSales; private BigDecimal blackDuckSales;
// 礼盒销售(元) // 礼盒销售(元)
private BigDecimal giftBoxSales; private BigDecimal giftBoxSales;
// POS销额手工统计记录
private String posManualSalesRecord;
} }
...@@ -13,23 +13,9 @@ import java.util.Date; ...@@ -13,23 +13,9 @@ import java.util.Date;
@Data @Data
public class TemporaryRegisterVo { public class TemporaryRegisterVo {
/** private String openId;
* 当前月份 YYYY-MM private String phone;
*/ private Long id;
private YearMonth month; private String date;
/**
* 省份
*/
private String province;
/**
* 城市
*/
private String city;
/**
* 区
*/
private String area;
} }
...@@ -18,6 +18,7 @@ import com.wangxiaolu.promotion.pojo.activity.planv2.dto.ActivityPlanInfoDto; ...@@ -18,6 +18,7 @@ import com.wangxiaolu.promotion.pojo.activity.planv2.dto.ActivityPlanInfoDto;
import com.wangxiaolu.promotion.pojo.activity.temporary.dto.TemporaryActivityMarketCellDto; import com.wangxiaolu.promotion.pojo.activity.temporary.dto.TemporaryActivityMarketCellDto;
import com.wangxiaolu.promotion.pojo.activity.temporary.dto.TemporaryActivityReportedDto; import com.wangxiaolu.promotion.pojo.activity.temporary.dto.TemporaryActivityReportedDto;
import com.wangxiaolu.promotion.pojo.activity.temporary.vo.TemporaryActivityMarketCellVo; import com.wangxiaolu.promotion.pojo.activity.temporary.vo.TemporaryActivityMarketCellVo;
import com.wangxiaolu.promotion.pojo.user.dto.WxTemporaryInfoDto;
import com.wangxiaolu.promotion.result.basedata.RCode; import com.wangxiaolu.promotion.result.basedata.RCode;
import com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityClockQueryService; import com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityClockQueryService;
import com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityCoreService; import com.wangxiaolu.promotion.service.activity.temporary.TemporaryActivityCoreService;
...@@ -88,6 +89,7 @@ public class TemporaryActivityCoreServiceImpl implements TemporaryActivityCoreSe ...@@ -88,6 +89,7 @@ public class TemporaryActivityCoreServiceImpl implements TemporaryActivityCoreSe
// 保存图片 // 保存图片
saveActivityPhotoV2(temActDto); saveActivityPhotoV2(temActDto);
// 售卖单元新增保存 // 售卖单元新增保存
// String key = temMarketCellRedisKey(temActDto.getTemporaryId()); // String key = temMarketCellRedisKey(temActDto.getTemporaryId());
// temporaryActivityMarketCellDao.saveList(reportedId,redisCache.getToJsonArray(key)); // temporaryActivityMarketCellDao.saveList(reportedId,redisCache.getToJsonArray(key));
...@@ -107,12 +109,11 @@ public class TemporaryActivityCoreServiceImpl implements TemporaryActivityCoreSe ...@@ -107,12 +109,11 @@ public class TemporaryActivityCoreServiceImpl implements TemporaryActivityCoreSe
// 图片增量保存 // 图片增量保存
saveActivityPhotoV2(temActDto); saveActivityPhotoV2(temActDto);
// 如果数量小于2 修改状态为 SUBMITTED 已保存 // 如果数量小于2 修改状态为 SUBMITTED 已保存
if(ObjectUtil.isAllNotEmpty(temActDto.getTgscPhotoUrls(),temActDto.getTghdPhotoUrls(),temActDto.getTgcjPhotoUrls()) if(ObjectUtil.isAllNotEmpty(temActDto.getTgscPhotoUrls(),temActDto.getTghdPhotoUrls(),temActDto.getTgcjPhotoUrls())){
&& temActDto.getTgscPhotoUrls().size()>=2 && temActDto.getTghdPhotoUrls().size()>=2 && temActDto.getTgcjPhotoUrls().size()>=2 ){
temActDto.setApproveStatus(TemActApproveStatus.APPROVED); temActDto.setApproveStatus(TemActApproveStatus.APPROVED);
}else {
temActDto.setApproveStatus(TemActApproveStatus.SUBMITTED);
} }
WxTemporaryInfoDto wxTemporaryInfoDto = temporaryInfoDao.selectOneById(temActDto.getTemporaryId());
temActDto.setTemporaryPhone(wxTemporaryInfoDto.getPhone());
temporaryActivityReportedDao.updateById(temActDto); temporaryActivityReportedDao.updateById(temActDto);
// 售卖单元新增保存 // 售卖单元新增保存
...@@ -283,10 +284,38 @@ public class TemporaryActivityCoreServiceImpl implements TemporaryActivityCoreSe ...@@ -283,10 +284,38 @@ public class TemporaryActivityCoreServiceImpl implements TemporaryActivityCoreSe
tempActivityPhotoDao.saveReportedList(null, temporaryId, reportedId, ActivityPhotoType.TGCJ.getType(), temActDto.getTgcjPhotoUrls()); tempActivityPhotoDao.saveReportedList(null, temporaryId, reportedId, ActivityPhotoType.TGCJ.getType(), temActDto.getTgcjPhotoUrls());
} }
// POS机页面凭证 // 试吃品
// if (!CollectionUtils.isEmpty(temActDto.getPsvPhotoUrls())) { if (CollectionUtils.isEmpty(temActDto.getScpPhotoUrls())) {
// tempActivityPhotoDao.saveReportedList(temporaryId, reportedId, ActivityPhotoType.POS_SELL_VOUCHER.getType(), temActDto.getPsvPhotoUrls()); tempActivityPhotoDao.deleteList(reportedId, ActivityPhotoType.TASTY_PHOTO.getType());
// } }else {
tempActivityPhotoDao.saveReportedList(null,temporaryId, reportedId, ActivityPhotoType.TASTY_PHOTO.getType(), temActDto.getScpPhotoUrls());
}
// 配发赠品照片
if (CollectionUtils.isEmpty(temActDto.getPfzpPhotoUrls())) {
tempActivityPhotoDao.deleteList(reportedId, ActivityPhotoType.SEND_GIFT_PHOTO.getType());
} else {
tempActivityPhotoDao.saveReportedList(null,temporaryId, reportedId, ActivityPhotoType.SEND_GIFT_PHOTO.getType(), temActDto.getPfzpPhotoUrls());
}
//POS机页面凭证
if (CollectionUtils.isEmpty(temActDto.getPsvPhotoUrls())) {
tempActivityPhotoDao.deleteList(reportedId, ActivityPhotoType.POS_SELL_VOUCHER.getType());
} else {
tempActivityPhotoDao.saveReportedList(null,temporaryId, reportedId, ActivityPhotoType.POS_SELL_VOUCHER.getType(), temActDto.getPsvPhotoUrls());
}
//高峰期在岗
if (CollectionUtils.isEmpty(temActDto.getGfqPhotoUrls())) {
tempActivityPhotoDao.deleteList(reportedId, ActivityPhotoType.RANDOM_TASK.getType());
} else {
tempActivityPhotoDao.saveReportedList(null,temporaryId, reportedId, ActivityPhotoType.RANDOM_TASK.getType(), temActDto.getGfqPhotoUrls());
}
// 试吃必备物料照片
if (CollectionUtils.isEmpty(temActDto.getScbbwlPhotoUrls())) {
tempActivityPhotoDao.deleteList(reportedId, ActivityPhotoType.TASTY_MATERIALS.getType());
} else {
tempActivityPhotoDao.saveReportedList(null,temporaryId, reportedId, ActivityPhotoType.TASTY_MATERIALS.getType(), temActDto.getScbbwlPhotoUrls());
}
} }
// private void saveActivityPhoto(TemporaryActivityReportedDto temActDto) { // private void saveActivityPhoto(TemporaryActivityReportedDto temActDto) {
......
...@@ -80,20 +80,13 @@ public class TemporaryActivityQueryServiceImpl implements TemporaryActivityQuery ...@@ -80,20 +80,13 @@ public class TemporaryActivityQueryServiceImpl implements TemporaryActivityQuery
wer.setTemporaryId(dto.getTemporaryId()) wer.setTemporaryId(dto.getTemporaryId())
.setReportedId(activityId); .setReportedId(activityId);
TemporaryClockDto clockInfo = temporaryActivityClockQueryService.findClockInfo(wer); TemporaryClockDto clockInfo = temporaryActivityClockQueryService.findClockInfo(wer);
// 设置 随机任务照片 // 设置 高峰期在岗
TemporaryPhotoWrapper wrapper = new TemporaryPhotoWrapper(); TemporaryPhotoWrapper wrapper = new TemporaryPhotoWrapper();
wrapper.setTemporaryId(dto.getTemporaryId()) wrapper.setTemporaryId(dto.getTemporaryId())
.setClockId(clockInfo.getId()) .setClockId(clockInfo.getId())
.setType(ActivityPhotoType.RANDOM_TASK.getType() ); .setType(ActivityPhotoType.RANDOM_TASK.getType() );
List<TemporaryActivityPhotoDto> temporaryActivityPhotoDtos = temporaryActivityPhotoDao.selectPhotos(wrapper); List<TemporaryActivityPhotoDto> temporaryActivityPhotoDtos = temporaryActivityPhotoDao.selectPhotos(wrapper);
dto.setRandTaskClockPhotoUrls(temporaryActivityPhotoDtos); dto.setRandTaskClockPhotoUrls(temporaryActivityPhotoDtos);
TemporaryPhotoWrapper posWrapper = new TemporaryPhotoWrapper();
posWrapper.setTemporaryId(dto.getTemporaryId())
.setClockId(clockInfo.getId())
.setType(ActivityPhotoType.POS_PHOTO.getType() );
List<TemporaryActivityPhotoDto> posTaskClockPhotoUrls = temporaryActivityPhotoDao.selectPhotos(posWrapper);
dto.setPosTaskClockPhotoUrls(posTaskClockPhotoUrls);
return dto; return dto;
} }
...@@ -132,7 +125,11 @@ public class TemporaryActivityQueryServiceImpl implements TemporaryActivityQuery ...@@ -132,7 +125,11 @@ public class TemporaryActivityQueryServiceImpl implements TemporaryActivityQuery
dto.setTgscPhotoUrls(reportedGroup.get(ActivityPhotoType.TGSC.getType())); dto.setTgscPhotoUrls(reportedGroup.get(ActivityPhotoType.TGSC.getType()));
dto.setTghdPhotoUrls(reportedGroup.get(ActivityPhotoType.TGHD.getType())); dto.setTghdPhotoUrls(reportedGroup.get(ActivityPhotoType.TGHD.getType()));
dto.setTgcjPhotoUrls(reportedGroup.get(ActivityPhotoType.TGCJ.getType())); dto.setTgcjPhotoUrls(reportedGroup.get(ActivityPhotoType.TGCJ.getType()));
dto.setScpPhotoUrls(reportedGroup.get(ActivityPhotoType.TASTY_PHOTO.getType()));
dto.setPsvPhotoUrls(reportedGroup.get(ActivityPhotoType.POS_SELL_VOUCHER.getType())); dto.setPsvPhotoUrls(reportedGroup.get(ActivityPhotoType.POS_SELL_VOUCHER.getType()));
dto.setPfzpPhotoUrls(reportedGroup.get(ActivityPhotoType.SEND_GIFT_PHOTO.getType()));
dto.setGfqPhotoUrls(reportedGroup.get(ActivityPhotoType.RANDOM_TASK.getType()));
dto.setScbbwlPhotoUrls(reportedGroup.get(ActivityPhotoType.TASTY_MATERIALS.getType()));
} }
} }
...@@ -145,7 +142,11 @@ public class TemporaryActivityQueryServiceImpl implements TemporaryActivityQuery ...@@ -145,7 +142,11 @@ public class TemporaryActivityQueryServiceImpl implements TemporaryActivityQuery
dto.setTgscPhotoInfos(reportedGroup.get(ActivityPhotoType.TGSC.getType())); dto.setTgscPhotoInfos(reportedGroup.get(ActivityPhotoType.TGSC.getType()));
dto.setTghdPhotoInfos(reportedGroup.get(ActivityPhotoType.TGHD.getType())); dto.setTghdPhotoInfos(reportedGroup.get(ActivityPhotoType.TGHD.getType()));
dto.setTgcjPhotoInfos(reportedGroup.get(ActivityPhotoType.TGCJ.getType())); dto.setTgcjPhotoInfos(reportedGroup.get(ActivityPhotoType.TGCJ.getType()));
dto.setScpPhotoInfos(reportedGroup.get(ActivityPhotoType.TASTY_PHOTO.getType()));
dto.setPsvPhotoInfos(reportedGroup.get(ActivityPhotoType.POS_SELL_VOUCHER.getType())); dto.setPsvPhotoInfos(reportedGroup.get(ActivityPhotoType.POS_SELL_VOUCHER.getType()));
dto.setPfzpPhotoInfos(reportedGroup.get(ActivityPhotoType.SEND_GIFT_PHOTO.getType()));
dto.setGfqPhotoInfos(reportedGroup.get(ActivityPhotoType.RANDOM_TASK.getType()));
dto.setScbbwlPhotoInfos(reportedGroup.get(ActivityPhotoType.TASTY_MATERIALS.getType()));
} }
} }
} }
...@@ -73,7 +73,7 @@ public class TemporaryActivityTaskClockServiceImpl extends ServiceImpl<Temporary ...@@ -73,7 +73,7 @@ public class TemporaryActivityTaskClockServiceImpl extends ServiceImpl<Temporary
// 随机生成 下午5:30~7:30 之间的Date // 随机生成 下午5:30~7:30 之间的Date
// LocalTime randomTime = LocalTime.of(17, 30, 0).plusMinutes(ThreadLocalRandom.current().nextInt(0, 120)); // LocalTime randomTime = LocalTime.of(17, 30, 0).plusMinutes(ThreadLocalRandom.current().nextInt(0, 120));
// 随机生成改成下午6点15生成 // 随机生成改成下午6点15生成
LocalTime randomTime = LocalTime.of(18, 15, 0); LocalTime randomTime = LocalTime.of(18, 0, 0);
Date randomDate = DateUtils.parseDateByLocalTime(randomTime); Date randomDate = DateUtils.parseDateByLocalTime(randomTime);
// 生成 // 生成
...@@ -109,7 +109,7 @@ public class TemporaryActivityTaskClockServiceImpl extends ServiceImpl<Temporary ...@@ -109,7 +109,7 @@ public class TemporaryActivityTaskClockServiceImpl extends ServiceImpl<Temporary
.setClockId(dto.getId()) .setClockId(dto.getId())
.setReportId(dto.getReportedId()) .setReportId(dto.getReportedId())
.setCreateDate(DateUtil.today()) .setCreateDate(DateUtil.today())
.setTaskType(ActivityPhotoType.POS_PHOTO.getType()) .setTaskType(ActivityPhotoType.POS_SELL_VOUCHER.getType())
.setIsDelete(FlagType.NO.getType()); .setIsDelete(FlagType.NO.getType());
TemporaryActivityTaskClockDO taskClockDO1 = temporaryActivityTaskClockDao.selectOne(wrapper); TemporaryActivityTaskClockDO taskClockDO1 = temporaryActivityTaskClockDao.selectOne(wrapper);
if (ObjectUtil.isNotEmpty(taskClockDO1)) { if (ObjectUtil.isNotEmpty(taskClockDO1)) {
...@@ -124,7 +124,7 @@ public class TemporaryActivityTaskClockServiceImpl extends ServiceImpl<Temporary ...@@ -124,7 +124,7 @@ public class TemporaryActivityTaskClockServiceImpl extends ServiceImpl<Temporary
.setReportedId(null) .setReportedId(null)
.setPlanId(dto.getPlanId()) .setPlanId(dto.getPlanId())
.setClockTime(null) .setClockTime(null)
.setTaskType(ActivityPhotoType.POS_PHOTO.getType()) .setTaskType(ActivityPhotoType.POS_SELL_VOUCHER.getType())
.setTaskStatus(ActivityClockTaskStatus.STARTING.getType()) .setTaskStatus(ActivityClockTaskStatus.STARTING.getType())
.setRequiredlockTime(null) .setRequiredlockTime(null)
.setActivityPatternId(dto.getActivityPatternId()) .setActivityPatternId(dto.getActivityPatternId())
...@@ -240,11 +240,11 @@ public class TemporaryActivityTaskClockServiceImpl extends ServiceImpl<Temporary ...@@ -240,11 +240,11 @@ public class TemporaryActivityTaskClockServiceImpl extends ServiceImpl<Temporary
if (taskClockDO.getTaskType() == ActivityPhotoType.RANDOM_TASK.getType() && requiredLockTime != null) { if (taskClockDO.getTaskType() == ActivityPhotoType.RANDOM_TASK.getType() && requiredLockTime != null) {
Date now = new Date(); Date now = new Date();
if (now.compareTo(requiredLockTime) > 0 if (now.compareTo(requiredLockTime) > 0
&& now.compareTo(DateUtil.offsetMinute(requiredLockTime,15)) < 0) { && now.compareTo(DateUtil.offsetMinute(requiredLockTime,30)) < 0) {
res.setEditableFlag(true); res.setEditableFlag(true);
} }
} }
if (taskClockDO.getTaskType() == ActivityPhotoType.POS_PHOTO.getType()){ if (taskClockDO.getTaskType() == ActivityPhotoType.POS_SELL_VOUCHER.getType()){
res.setEditableFlag(true); res.setEditableFlag(true);
} }
} }
......
package com.wangxiaolu.promotion.service.user;
import com.wangxiaolu.promotion.utils.TencentMapUtil;
import java.util.List;
/**
* @Author: DouXinYu
* @Date: 2026-01-12 11:17
* @Description:
*/
public interface TencentLocationQueryService {
TencentMapUtil.AddressInfo getAddressByLngLat(double lng, double lat);
List<TencentMapUtil.RegionNode> getAddressList();
}
package com.wangxiaolu.promotion.service.user;
import com.wangxiaolu.promotion.domain.user.mapper.entity.WxTemporaryInfoDelayDO;
import com.wangxiaolu.promotion.pojo.activity.temporary.dto.WxTemporaryInfoDelayDtO;
import java.time.LocalDateTime;
import java.util.List;
/**
* 延迟临时表Service(适配前端入参字段)
*/
public interface WxTemporaryInfoDelayService {
/**
* 保存延迟数据到临时表(含storeCode/dataDate)
*/
boolean saveDelayData(WxTemporaryInfoDelayDtO delayEntity);
/**
* 查询指定时间范围未处理的数据
*/
List<WxTemporaryInfoDelayDtO> listUnprocessedData(LocalDateTime startTime, LocalDateTime endTime);
/**
* 批量更新处理状态
*/
boolean batchUpdateProcessedStatus(List<Long> idList, Integer isProcessed);
}
\ No newline at end of file
package com.wangxiaolu.promotion.service.user.impl;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.wangxiaolu.promotion.service.user.TencentLocationQueryService;
import com.wangxiaolu.promotion.utils.TencentMapUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.lang.reflect.Type;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* @Author: DouXinYu
* @Date: 2026-01-12 11:16
* @Description: 腾讯位置查询服务实现类
*/
@Service
public class TencentLocationQueryServiceImpl implements TencentLocationQueryService {
private static final String TRIPLE_REGION_CACHE_KEY = "promotion:district:triple_level";
private static final long CACHE_EXPIRE = 86400L;
private static final Type REGION_NODE_TYPE = new TypeToken<List<TencentMapUtil.RegionNode>>() {}.getType();
private static final Gson GSON = new Gson();
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
TencentMapUtil tencentMapUtil;
@Override
public TencentMapUtil.AddressInfo getAddressByLngLat(double lng, double lat) {
return tencentMapUtil.getAddressByLngLat(lng, lat);
}
@Override
public List<TencentMapUtil.RegionNode> getAddressList() {
String cacheJson = stringRedisTemplate.opsForValue().get(TRIPLE_REGION_CACHE_KEY);
if (cacheJson != null && !cacheJson.isEmpty()) {
return GSON.fromJson(cacheJson, REGION_NODE_TYPE);
}
List<TencentMapUtil.RegionNode> regionList = tencentMapUtil.getTripleLevelRegion();
if (!regionList.isEmpty()) {
stringRedisTemplate.opsForValue().set(TRIPLE_REGION_CACHE_KEY, GSON.toJson(regionList), CACHE_EXPIRE, TimeUnit.SECONDS);
}
return regionList;
}
}
package com.wangxiaolu.promotion.service.user.impl;
import com.wangxiaolu.promotion.domain.user.dao.WxTemporaryInfoDelayDao;
import com.wangxiaolu.promotion.domain.user.mapper.entity.WxTemporaryInfoDelayDO;
import com.wangxiaolu.promotion.pojo.activity.temporary.dto.WxTemporaryInfoDelayDtO;
import com.wangxiaolu.promotion.service.user.WxTemporaryInfoDelayService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
@Service
public class WxTemporaryInfoDelayServiceImpl implements WxTemporaryInfoDelayService {
@Resource
private WxTemporaryInfoDelayDao delayDao;
@Override
public boolean saveDelayData(WxTemporaryInfoDelayDtO delayEntity) {
// 调用DAO插入数据(含storeCode/dataDate)
return delayDao.insert(delayEntity) > 0;
}
@Override
public List<WxTemporaryInfoDelayDtO> listUnprocessedData(LocalDateTime startTime, LocalDateTime endTime) {
return delayDao.selectUnprocessedData(startTime, endTime);
}
@Override
public boolean batchUpdateProcessedStatus(List<Long> idList, Integer isProcessed) {
return delayDao.batchUpdateProcessedStatus(idList, isProcessed) > 0;
}
}
\ No newline at end of file
package com.wangxiaolu.promotion.service.wechat; package com.wangxiaolu.promotion.service.wechat;
import com.wangxiaolu.promotion.domain.user.mapper.entity.WxTemporaryInfoDelayDO;
import com.wangxiaolu.promotion.pojo.activity.temporary.dto.WxTemporaryInfoDelayDtO;
import com.wangxiaolu.promotion.pojo.user.dto.WxTemporaryInfoDto; import com.wangxiaolu.promotion.pojo.user.dto.WxTemporaryInfoDto;
import java.util.List;
/** /**
* @author : liqiulin * @author : liqiulin
* @date : 2024-04-08 16 * @date : 2024-04-08 16
...@@ -13,4 +17,18 @@ public interface WeChatUserCoreService { ...@@ -13,4 +17,18 @@ public interface WeChatUserCoreService {
* 保存促销员用户信息 * 保存促销员用户信息
*/ */
boolean saveWxUserInfoTemporary(WxTemporaryInfoDto temporaryDto); boolean saveWxUserInfoTemporary(WxTemporaryInfoDto temporaryDto);
/**
* 修改促销员的门店信息
* @param temporaryDto
* @return
*/
boolean saveWxUserStoreInfoTemporary(WxTemporaryInfoDto temporaryDto);
boolean batchSaveWxUserStoreInfo(List<WxTemporaryInfoDto> list);
/**
* 保存延迟数据
*/
boolean saveDelayData(WxTemporaryInfoDelayDtO delayEntity);
} }
...@@ -17,5 +17,15 @@ public interface WeChatUserQueryService { ...@@ -17,5 +17,15 @@ public interface WeChatUserQueryService {
LoginVo temporaryLoginByPhone(String phone); LoginVo temporaryLoginByPhone(String phone);
List<Map<String, String>> findStoreList(TemporaryRegisterVo temporaryRegisterVo); List<Map<String, String>> findStoreList(String planDay,String storeNameKeyword);
/**
* 根据临时ID查询手机号
* @param temporaryId 临时ID
* @return 手机号
*/
String findUserPhoneByID(Long temporaryId);
Map<String,Object> findTemporaryWorkStore(String openId,String date);
} }
...@@ -5,13 +5,16 @@ import com.wangxiaolu.promotion.domain.user.dao.QinCeEmployeeDao; ...@@ -5,13 +5,16 @@ import com.wangxiaolu.promotion.domain.user.dao.QinCeEmployeeDao;
import com.wangxiaolu.promotion.domain.user.dao.TemporaryInfoDao; import com.wangxiaolu.promotion.domain.user.dao.TemporaryInfoDao;
import com.wangxiaolu.promotion.exception.ParamException; import com.wangxiaolu.promotion.exception.ParamException;
import com.wangxiaolu.promotion.pojo.activity.temporary.dto.QinCeEmployeeDto; import com.wangxiaolu.promotion.pojo.activity.temporary.dto.QinCeEmployeeDto;
import com.wangxiaolu.promotion.pojo.activity.temporary.dto.WxTemporaryInfoDelayDtO;
import com.wangxiaolu.promotion.pojo.user.dto.WxTemporaryInfoDto; import com.wangxiaolu.promotion.pojo.user.dto.WxTemporaryInfoDto;
import com.wangxiaolu.promotion.result.basedata.RCode; import com.wangxiaolu.promotion.result.basedata.RCode;
import com.wangxiaolu.promotion.service.user.WxTemporaryInfoDelayService;
import com.wangxiaolu.promotion.service.wechat.WeChatUserCoreService; import com.wangxiaolu.promotion.service.wechat.WeChatUserCoreService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Objects; import java.util.Objects;
/** /**
...@@ -29,6 +32,9 @@ public class WeChatUserCoreServiceImpl implements WeChatUserCoreService { ...@@ -29,6 +32,9 @@ public class WeChatUserCoreServiceImpl implements WeChatUserCoreService {
@Autowired @Autowired
QinCeEmployeeDao qinCeEmployeeDao; QinCeEmployeeDao qinCeEmployeeDao;
@Autowired
private WxTemporaryInfoDelayService wxTemporaryInfoDelayService;
/** /**
* 保存促销员用户信息 * 保存促销员用户信息
*/ */
...@@ -38,4 +44,29 @@ public class WeChatUserCoreServiceImpl implements WeChatUserCoreService { ...@@ -38,4 +44,29 @@ public class WeChatUserCoreServiceImpl implements WeChatUserCoreService {
log.info("微信-促销员[{}]:[{}]注册成功:{}", saveId, temporaryDto.getName(), JSONObject.toJSONString(temporaryDto)); log.info("微信-促销员[{}]:[{}]注册成功:{}", saveId, temporaryDto.getName(), JSONObject.toJSONString(temporaryDto));
return saveId > 0; return saveId > 0;
} }
/**
* 保存用户门店信息
* @param temporaryDto
* @return
*/
@Override
public boolean saveWxUserStoreInfoTemporary(WxTemporaryInfoDto temporaryDto) {
WxTemporaryInfoDto wxTemporaryInfoDto = temporaryInfoDao.selectOneByOpenId(temporaryDto.getOpenId());
wxTemporaryInfoDto.setStoreCode(temporaryDto.getStoreCode());
wxTemporaryInfoDto.setStoreName(temporaryDto.getStoreName());
int saveId = temporaryInfoDao.saveWxUserStoreInfoTemporary(wxTemporaryInfoDto);
return saveId > 0;
}
@Override
public boolean batchSaveWxUserStoreInfo(List<WxTemporaryInfoDto> list) {
// 调用DAO批量插入/更新(含storeCode/dataDate)
return temporaryInfoDao.batchInsertOrUpdate(list) > 0;
}
@Override
public boolean saveDelayData(WxTemporaryInfoDelayDtO delayEntity) {
return wxTemporaryInfoDelayService.saveDelayData(delayEntity);
}
} }
...@@ -71,7 +71,7 @@ public class WeChatUserQueryServiceImpl implements WeChatUserQueryService { ...@@ -71,7 +71,7 @@ public class WeChatUserQueryServiceImpl implements WeChatUserQueryService {
@Override @Override
public LoginVo temporaryLoginByPhone(String phone) { public LoginVo temporaryLoginByPhone(String phone) {
WxTemporaryInfoDto temDto = temporaryInfoDao.selectByPhone(phone); WxTemporaryInfoDto temDto = temporaryInfoDao.selectOneByOpenId(phone);
if (Objects.isNull(temDto)) { if (Objects.isNull(temDto)) {
throw new DataException(RCode.LOGIN_USER_IS_NULL_ERROR); throw new DataException(RCode.LOGIN_USER_IS_NULL_ERROR);
} }
...@@ -91,7 +91,17 @@ public class WeChatUserQueryServiceImpl implements WeChatUserQueryService { ...@@ -91,7 +91,17 @@ public class WeChatUserQueryServiceImpl implements WeChatUserQueryService {
} }
@Override @Override
public List<Map<String, String>> findStoreList(TemporaryRegisterVo temporaryRegisterVo) { public List<Map<String, String>> findStoreList(String planDay,String storeNameKeyword) {
return activityPlanInfoDao.findThisMonthStoreListByLocation(temporaryRegisterVo); return activityPlanInfoDao.findThisMonthStoreListByLocation(planDay, storeNameKeyword);
}
@Override
public String findUserPhoneByID(Long temporaryId) {
return temporaryInfoDao.selectOneById(temporaryId).getPhone();
}
@Override
public Map<String,Object> findTemporaryWorkStore(String openId,String date) {
return temporaryInfoDao.selectStoreAndPlan(openId,date);
} }
} }
...@@ -162,7 +162,7 @@ public class ActivityStautsHandler { ...@@ -162,7 +162,7 @@ public class ActivityStautsHandler {
// 模板中的字段3 任务名称 // 模板中的字段3 任务名称
data.put("thing1", "请拍摄清晰的工作场景照片"); data.put("thing1", "请拍摄清晰的工作场景照片");
// 模板中的字段4 温馨提示 // 模板中的字段4 温馨提示
data.put("thing4", "请在15分钟内完成任务"); data.put("thing4", "请在30分钟内完成任务");
// 3. 发送通知 // 3. 发送通知
// 获取openid // 获取openid
......
package com.wangxiaolu.promotion.xxljobtask;
import com.wangxiaolu.promotion.pojo.activity.temporary.dto.WxTemporaryInfoDelayDtO;
import com.wangxiaolu.promotion.pojo.user.dto.WxTemporaryInfoDto;
import com.wangxiaolu.promotion.service.wechat.WeChatUserCoreService;
import com.wangxiaolu.promotion.service.user.WxTemporaryInfoDelayService;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* XXL-Job定时任务:每天00:01处理微信用户延迟更新的门店信息
* @author: 自定义
* @date: 2026-01-14
*/
@Slf4j
@Component
public class WxTemporaryInfoDelayHandler{
@Resource
private WxTemporaryInfoDelayService wxTemporaryInfoDelayService;
@Resource
private WeChatUserCoreService weChatUserCoreService;
/**
* 定时任务执行方法
* 任务描述:每天00:01处理前一天未处理的用户门店信息更新
* XXL-Job配置:cron表达式 0 1 0 * * ? (每天00:01执行)
*/
@XxlJob("wxTemporaryInfoDelayHandler")
public void execute() {
// 1. 任务日志记录(XXL-Job控制台可见)
XxlJobHelper.log("开始执行微信用户延迟信息更新任务,执行时间:{}", LocalDateTime.now());
try {
// 2. 构建时间范围:查询前一天00:00到当天00:00的未处理数据
LocalDate yesterday = LocalDate.now().minusDays(1);
LocalDateTime startTime = LocalDateTime.of(yesterday, LocalTime.MIN);
LocalDateTime endTime = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
// 3. 查询未处理的延迟数据
List<WxTemporaryInfoDelayDtO> unprocessedList = wxTemporaryInfoDelayService.listUnprocessedData(startTime, endTime);
if (unprocessedList == null || unprocessedList.isEmpty()) {
XxlJobHelper.log("未查询到需要处理的延迟数据,任务结束");
return;
}
XxlJobHelper.log("查询到待处理延迟数据共{}条", unprocessedList.size());
// 4. 转换DTO并批量更新门店信息
List<WxTemporaryInfoDto> updateList = new ArrayList<>();
List<Long> idList = new ArrayList<>();
for (WxTemporaryInfoDelayDtO delayDto : unprocessedList) {
// 4.1 收集需要标记为已处理的ID
idList.add(delayDto.getId());
// 4.2 转换为业务层需要的DTO
WxTemporaryInfoDto tempDto = new WxTemporaryInfoDto();
BeanUtils.copyProperties(delayDto, tempDto);
updateList.add(tempDto);
}
// 5. 批量更新用户门店信息
boolean updateResult = weChatUserCoreService.batchSaveWxUserStoreInfo(updateList);
if (!updateResult) {
XxlJobHelper.log("批量更新用户门店信息失败,数据量:{}", updateList.size());
XxlJobHelper.handleFail("批量更新用户门店信息失败");
return;
}
XxlJobHelper.log("批量更新用户门店信息成功,数据量:{}", updateList.size());
// 6. 标记延迟表数据为已处理(1=已处理)
boolean markResult = wxTemporaryInfoDelayService.batchUpdateProcessedStatus(idList, 1);
if (!markResult) {
XxlJobHelper.log("标记延迟数据为已处理失败,ID列表:{}", idList);
XxlJobHelper.handleFail("标记延迟数据为已处理失败");
return;
}
XxlJobHelper.log("标记{}条延迟数据为已处理成功", idList.size());
// 7. 任务执行成功
XxlJobHelper.handleSuccess("微信用户延迟信息更新任务执行成功,共处理" + unprocessedList.size() + "条数据");
} catch (Exception e) {
// 8. 异常处理
log.error("微信用户延迟信息更新任务执行异常", e);
XxlJobHelper.log("任务执行异常:{}", e.getMessage());
XxlJobHelper.handleFail("任务执行异常:" + e.getMessage());
}
}
}
\ No newline at end of file
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
<result property="idenReversePhotoFieldId" column="iden_reverse_photo_field_id" jdbcType="VARCHAR"/> <result property="idenReversePhotoFieldId" column="iden_reverse_photo_field_id" jdbcType="VARCHAR"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/> <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
<result property="modifyTime" column="modify_time" jdbcType="TIMESTAMP"/> <result property="modifyTime" column="modify_time" jdbcType="TIMESTAMP"/>
<result property="storeName" column="store_name" jdbcType="VARCHAR"/>
<result property="storeCode" column="store_code" jdbcType="VARCHAR"/>
</resultMap> </resultMap>
<sql id="Base_Column_List"> <sql id="Base_Column_List">
...@@ -37,4 +39,20 @@ ...@@ -37,4 +39,20 @@
select <include refid="Base_Column_Unimportant"/> from temporary_info where open_id = #{openId} select <include refid="Base_Column_Unimportant"/> from temporary_info where open_id = #{openId}
</select> </select>
<insert id="batchInsertOrUpdate">
INSERT INTO temporary_info (
open_id, store_name, store_code, modify_time
) VALUES
<foreach collection="list" item="item" separator=",">
(
#{item.openId}, #{item.storeName}, #{item.storeCode}, NOW()
)
</foreach>
ON DUPLICATE KEY UPDATE
store_name = VALUES(store_name), <!-- 仅更新门店名称 -->
store_code = VALUES(store_code), <!-- 仅更新门店编码 -->
modify_time = NOW() <!-- 仅更新修改时间 -->
</insert>
</mapper> </mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wangxiaolu.promotion.domain.user.mapper.WxTemporaryInfoDelayMapper">
<!-- 核心:resultMap映射(适配已有实体类WxTemporaryInfoDelay) -->
<resultMap id="WxTemporaryInfoDelayResultMap" type="com.wangxiaolu.promotion.domain.user.mapper.entity.WxTemporaryInfoDelayDO">
<id column="id" property="id"/> <!-- 主键映射 -->
<result column="open_id" property="openId"/> <!-- 数据库下划线 → Java驼峰 -->
<result column="store_name" property="storeName"/>
<result column="store_code" property="storeCode"/>
<result column="contact_phone" property="contactPhone"/>
<result column="create_time" property="createTime"/>
<result column="is_processed" property="isProcessed"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<!-- 查询指定时间范围未处理的数据(使用resultMap) -->
<select id="selectByTimeAndStatus" resultMap="WxTemporaryInfoDelayResultMap">
SELECT
id, open_id, store_name, store_code, contact_phone,
create_time, is_processed, update_time
FROM wx_temporary_info_delay
WHERE create_time BETWEEN #{startTime} AND #{endTime}
AND is_processed = #{isProcessed}
</select>
<!-- 批量更新处理状态 -->
<update id="batchUpdateStatus">
UPDATE wx_temporary_info_delay
SET is_processed = #{isProcessed}, update_time = NOW()
WHERE id IN
<foreach collection="idList" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</update>
<!-- 单条插入(适配已有实体,可选:MyBatis-Plus也可自动生成) -->
<insert id="insert" parameterType="com.wangxiaolu.promotion.domain.user.mapper.entity.WxTemporaryInfoDelayDO">
INSERT INTO wx_temporary_info_delay (
open_id, store_name, store_code, contact_phone,
create_time, is_processed, update_time
) VALUES (
#{openId}, #{storeName}, #{storeCode}, #{contactPhone},
NOW(), 0, NOW()
)
</insert>
</mapper>
\ No newline at end of file
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
<insert id="saveList"> <insert id="saveList">
INSERT INTO activity_plan_info INSERT INTO activity_plan_info
(plan_file_id,employee_id,employee_name,employee_no,year,month,date,line_name,store_name,store_code,org_qc_id,org_name,pattern_id,pattern,dealer_id,dealer_name,both_t,province,city,area,addr,clock_in_time,clock_out_time,noon_clock_out_time,noon_clock_in_time,tem_wl_sct,prd_class,create_by) (plan_file_id,employee_id,employee_name,employee_no,year,month,date,line_name,store_name,store_code,org_qc_id,org_name,pattern_id,pattern,dealer_id,dealer_name,both_t,province,city,area,addr,clock_in_time,clock_out_time,noon_clock_out_time,noon_clock_in_time,tem_wl_sct,prd_class,create_by,plan_execute_mode,is_can_use_taste_counter)
VALUES VALUES
<foreach collection="table" item="item" index="index" separator=","> <foreach collection="table" item="item" index="index" separator=",">
(#{recordId}, #{item.employeeId}, #{item.employeeName}, #{item.employeeNo}, #{item.year}, (#{recordId}, #{item.employeeId}, #{item.employeeName}, #{item.employeeNo}, #{item.year},
...@@ -76,7 +76,7 @@ ...@@ -76,7 +76,7 @@
#{item.orgQcId},#{item.orgName}, 0, #{item.pattern}, #{item.dealerId}, #{item.dealerName}, '未确定', #{item.orgQcId},#{item.orgName}, 0, #{item.pattern}, #{item.dealerId}, #{item.dealerName}, '未确定',
#{item.province}, #{item.city}, #{item.area}, #{item.addr}, #{item.province}, #{item.city}, #{item.area}, #{item.addr},
FROM_UNIXTIME(#{item.clockInTime} / 1000), FROM_UNIXTIME(#{item.clockOutTime} / 1000), FROM_UNIXTIME(#{item.noonClockOutTime} / 1000), FROM_UNIXTIME(#{item.clockInTime} / 1000), FROM_UNIXTIME(#{item.clockOutTime} / 1000), FROM_UNIXTIME(#{item.noonClockOutTime} / 1000),
FROM_UNIXTIME(#{item.noonClockInTime} / 1000),#{item.temWlSct},#{item.prdClass},#{item.createBy}) FROM_UNIXTIME(#{item.noonClockInTime} / 1000),#{item.temWlSct},#{item.prdClass},#{item.createBy}, #{item.planExecuteMode}, #{item.isCanUseTasteCounter})
</foreach> </foreach>
</insert> </insert>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论