diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsLogController.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsLogController.java new file mode 100644 index 000000000..1d0a2fed0 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsLogController.java @@ -0,0 +1,60 @@ +package cn.iocoder.dashboard.modules.system.controller.sms; + +import cn.iocoder.dashboard.common.pojo.CommonResult; +import cn.iocoder.dashboard.common.pojo.PageResult; +import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; +import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; +import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogExcelVO; +import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogExportReqVO; +import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogPageReqVO; +import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogRespVO; +import cn.iocoder.dashboard.modules.system.convert.sms.SysSmsLogConvert; +import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsLogDO; +import cn.iocoder.dashboard.modules.system.service.sms.SysSmsLogService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.dashboard.common.pojo.CommonResult.success; +import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Api(tags = "短信日志") +@RestController +@RequestMapping("/system/sms-log") +@Validated +public class SysSmsLogController { + + @Resource + private SysSmsLogService smsLogService; + + @GetMapping("/page") + @ApiOperation("获得短信日志分页") + @PreAuthorize("@ss.hasPermission('system:sms-log:query')") + public CommonResult> getSmsLogPage(@Valid SysSmsLogPageReqVO pageVO) { + PageResult pageResult = smsLogService.getSmsLogPage(pageVO); + return success(SysSmsLogConvert.INSTANCE.convertPage(pageResult)); + } + + @GetMapping("/export-excel") + @ApiOperation("导出短信日志 Excel") + @PreAuthorize("@ss.hasPermission('system:sms-log:export')") + @OperateLog(type = EXPORT) + public void exportSmsLogExcel(@Valid SysSmsLogExportReqVO exportReqVO, + HttpServletResponse response) throws IOException { + List list = smsLogService.getSmsLogList(exportReqVO); + // 导出 Excel + List datas = SysSmsLogConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "短信日志.xls", "数据", SysSmsLogExcelVO.class, datas); + } + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsTemplateVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsTemplateVO.java deleted file mode 100644 index d9daf7578..000000000 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsTemplateVO.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.iocoder.dashboard.modules.system.controller.sms.vo; - -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 渠道模板VO类 - * - * @author zzf - * @date 2021/1/25 17:03 - */ -@Data -@EqualsAndHashCode -public class SmsTemplateVO { - - /** - * 业务编码(来自数据字典, 用户自定义业务场景 一个场景可以有多个模板) - */ - private String bizCode; - - /** - * 编码 - */ - private String code; - - /** - * 实际渠道模板唯一标识 - */ - private String apiTemplateId; - - /** - * 内容 - */ - private String content; - - - -} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogExcelVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogExcelVO.java new file mode 100644 index 000000000..60cd85db1 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogExcelVO.java @@ -0,0 +1,96 @@ +package cn.iocoder.dashboard.modules.system.controller.sms.vo.log; + +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.util.Date; +import java.util.Map; + +/** + * 短信日志 Excel VO + * + * @author 芋道源码 + */ +@Data +public class SysSmsLogExcelVO { + + @ExcelProperty("编号") + private Long id; + + @ExcelProperty("短信渠道编号") + private Long channelId; + + @ExcelProperty("短信渠道编码") + // TODO 导出枚举 + private String channelCode; + + @ExcelProperty("模板编号") + private Long templateId; + + @ExcelProperty("模板编码") + private String templateCode; + + @ExcelProperty("短信类型") + private Integer templateType; + + @ExcelProperty("短信内容") + private String templateContent; + + @ExcelProperty("短信参数") + private Map templateParams; + + @ExcelProperty("短信 API 的模板编号") + private String apiTemplateId; + + @ExcelProperty("手机号") + private String mobile; + + @ExcelProperty("用户编号") + private Long userId; + + @ExcelProperty("用户类型") + // TODO 导出枚举 + private Integer userType; + + @ExcelProperty("发送状态") + // TODO 导出枚举 + private Integer sendStatus; + + @ExcelProperty("发送时间") + private Date sendTime; + + @ExcelProperty("发送结果的编码") + private Integer sendCode; + + @ExcelProperty("发送结果的提示") + private String sendMsg; + + @ExcelProperty("短信 API 发送结果的编码") + private String apiSendCode; + + @ExcelProperty("短信 API 发送失败的提示") + private String apiSendMsg; + + @ExcelProperty("短信 API 发送返回的唯一请求 ID") + private String apiRequestId; + + @ExcelProperty("短信 API 发送返回的序号") + private String apiSerialNo; + + @ExcelProperty("接收状态") + // TODO 导出枚举 + private Integer receiveStatus; + + @ExcelProperty("接收时间") + private Date receiveTime; + + @ExcelProperty("API 接收结果的编码") + private String apiReceiveCode; + + @ExcelProperty("API 接收结果的说明") + private String apiReceiveMsg; + + @ExcelProperty("创建时间") + private Date createTime; + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogExportReqVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogExportReqVO.java new file mode 100644 index 000000000..89add180a --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogExportReqVO.java @@ -0,0 +1,47 @@ +package cn.iocoder.dashboard.modules.system.controller.sms.vo.log; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@ApiModel(value = "短信日志 Excel 导出 Request VO", description = "参数和 SysSmsLogPageReqVO 是一致的") +@Data +public class SysSmsLogExportReqVO { + + @ApiModelProperty(value = "短信渠道编号", example = "10") + private Long channelId; + + @ApiModelProperty(value = "模板编号", example = "20") + private Long templateId; + + @ApiModelProperty(value = "手机号", example = "15601691300") + private String mobile; + + @ApiModelProperty(value = "发送状态", example = "1") + private Integer sendStatus; + + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @ApiModelProperty(value = "开始发送时间") + private Date beginSendTime; + + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @ApiModelProperty(value = "结束发送时间") + private Date endSendTime; + + @ApiModelProperty(value = "接收状态", example = "0") + private Integer receiveStatus; + + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @ApiModelProperty(value = "开始接收时间") + private Date beginReceiveTime; + + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @ApiModelProperty(value = "结束接收时间") + private Date endReceiveTime; + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogPageReqVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogPageReqVO.java new file mode 100644 index 000000000..6573e15a7 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogPageReqVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.dashboard.modules.system.controller.sms.vo.log; + +import cn.iocoder.dashboard.common.pojo.PageParam; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@ApiModel("短信日志分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class SysSmsLogPageReqVO extends PageParam { + + @ApiModelProperty(value = "短信渠道编号", example = "10") + private Long channelId; + + @ApiModelProperty(value = "模板编号", example = "20") + private Long templateId; + + @ApiModelProperty(value = "手机号", example = "15601691300") + private String mobile; + + @ApiModelProperty(value = "发送状态", example = "1", notes = "参见 SysSmsSendStatusEnum 枚举类") + private Integer sendStatus; + + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @ApiModelProperty(value = "开始发送时间") + private Date beginSendTime; + + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @ApiModelProperty(value = "结束发送时间") + private Date endSendTime; + + @ApiModelProperty(value = "接收状态", example = "0", notes = "参见 SysSmsReceiveStatusEnum 枚举类") + private Integer receiveStatus; + + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @ApiModelProperty(value = "开始接收时间") + private Date beginReceiveTime; + + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @ApiModelProperty(value = "结束接收时间") + private Date endReceiveTime; + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogRespVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogRespVO.java new file mode 100644 index 000000000..423a57919 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/log/SysSmsLogRespVO.java @@ -0,0 +1,89 @@ +package cn.iocoder.dashboard.modules.system.controller.sms.vo.log; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.Date; +import java.util.Map; + +@ApiModel("短信日志 Response VO") +@Data +public class SysSmsLogRespVO { + + @ApiModelProperty(value = "编号", required = true, example = "1024") + private Long id; + + @ApiModelProperty(value = "短信渠道编号", required = true, example = "10") + private Long channelId; + + @ApiModelProperty(value = "短信渠道编码", required = true, example = "ALIYUN") + private String channelCode; + + @ApiModelProperty(value = "模板编号", required = true, example = "20") + private Long templateId; + + @ApiModelProperty(value = "模板编码", required = true, example = "test-01") + private String templateCode; + + @ApiModelProperty(value = "短信类型", required = true, example = "1") + private Integer templateType; + + @ApiModelProperty(value = "短信内容", required = true, example = "你好,你的验证码是 1024") + private String templateContent; + + @ApiModelProperty(value = "短信参数", required = true, example = "name,code") + private Map templateParams; + + @ApiModelProperty(value = "短信 API 的模板编号", required = true, example = "SMS_207945135") + private String apiTemplateId; + + @ApiModelProperty(value = "手机号", required = true, example = "15601691300") + private String mobile; + + @ApiModelProperty(value = "用户编号", example = "10") + private Long userId; + + @ApiModelProperty(value = "用户类型", example = "1") + private Integer userType; + + @ApiModelProperty(value = "发送状态", required = true, example = "1") + private Integer sendStatus; + + @ApiModelProperty(value = "发送时间") + private Date sendTime; + + @ApiModelProperty(value = "发送结果的编码", example = "0") + private Integer sendCode; + + @ApiModelProperty(value = "发送结果的提示", example = "成功") + private String sendMsg; + + @ApiModelProperty(value = "短信 API 发送结果的编码", example = "SUCCESS") + private String apiSendCode; + + @ApiModelProperty(value = "短信 API 发送失败的提示", example = "成功") + private String apiSendMsg; + + @ApiModelProperty(value = "短信 API 发送返回的唯一请求 ID", example = "3837C6D3-B96F-428C-BBB2-86135D4B5B99") + private String apiRequestId; + + @ApiModelProperty(value = "短信 API 发送返回的序号", example = "62923244790") + private String apiSerialNo; + + @ApiModelProperty(value = "接收状态", required = true, example = "0") + private Integer receiveStatus; + + @ApiModelProperty(value = "接收时间") + private Date receiveTime; + + @ApiModelProperty(value = "API 接收结果的编码", example = "DELIVRD") + private String apiReceiveCode; + + @ApiModelProperty(value = "API 接收结果的说明", example = "用户接收成功") + private String apiReceiveMsg; + + @ApiModelProperty(value = "创建时间", required = true) + private Date createTime; + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SysSmsLogConvert.java b/src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SysSmsLogConvert.java new file mode 100644 index 000000000..6cb1f650a --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SysSmsLogConvert.java @@ -0,0 +1,30 @@ +package cn.iocoder.dashboard.modules.system.convert.sms; + +import cn.iocoder.dashboard.common.pojo.PageResult; +import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogExcelVO; +import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogRespVO; +import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsLogDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 短信日志 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface SysSmsLogConvert { + + SysSmsLogConvert INSTANCE = Mappers.getMapper(SysSmsLogConvert.class); + + SysSmsLogRespVO convert(SysSmsLogDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/sms/SysSmsLogDO.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/sms/SysSmsLogDO.java index 78e04e117..076e18f39 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/sms/SysSmsLogDO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/sms/SysSmsLogDO.java @@ -23,9 +23,9 @@ import java.util.Map; @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) +@Builder @AllArgsConstructor @NoArgsConstructor -@Builder public class SysSmsLogDO extends BaseDO { /** diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/sms/SysSmsLogMapper.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/sms/SysSmsLogMapper.java index 2255c444e..e3345c835 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/sms/SysSmsLogMapper.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/sms/SysSmsLogMapper.java @@ -1,9 +1,40 @@ package cn.iocoder.dashboard.modules.system.dal.mysql.sms; +import cn.iocoder.dashboard.common.pojo.PageResult; import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.dashboard.framework.mybatis.core.query.QueryWrapperX; +import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogExportReqVO; +import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogPageReqVO; import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsLogDO; import org.apache.ibatis.annotations.Mapper; +import java.util.List; + @Mapper public interface SysSmsLogMapper extends BaseMapperX { + + default PageResult selectPage(SysSmsLogPageReqVO reqVO) { + return selectPage(reqVO, new QueryWrapperX() + .eqIfPresent("channel_id", reqVO.getChannelId()) + .eqIfPresent("template_id", reqVO.getTemplateId()) + .likeIfPresent("mobile", reqVO.getMobile()) + .eqIfPresent("send_status", reqVO.getSendStatus()) + .betweenIfPresent("send_time", reqVO.getBeginSendTime(), reqVO.getEndSendTime()) + .eqIfPresent("receive_status", reqVO.getReceiveStatus()) + .betweenIfPresent("receive_time", reqVO.getBeginReceiveTime(), reqVO.getEndReceiveTime()) + .orderByDesc("id")); + } + + default List selectList(SysSmsLogExportReqVO reqVO) { + return selectList(new QueryWrapperX() + .eqIfPresent("channel_id", reqVO.getChannelId()) + .eqIfPresent("template_id", reqVO.getTemplateId()) + .likeIfPresent("mobile", reqVO.getMobile()) + .eqIfPresent("send_status", reqVO.getSendStatus()) + .betweenIfPresent("send_time", reqVO.getBeginSendTime(), reqVO.getEndSendTime()) + .eqIfPresent("receive_status", reqVO.getReceiveStatus()) + .betweenIfPresent("receive_time", reqVO.getBeginReceiveTime(), reqVO.getEndReceiveTime()) + .orderByDesc("id")); + } + } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsLogService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsLogService.java index 33fb86a36..52bb4a624 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsLogService.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsLogService.java @@ -1,8 +1,13 @@ package cn.iocoder.dashboard.modules.system.service.sms; +import cn.iocoder.dashboard.common.pojo.PageResult; +import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogExportReqVO; +import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogPageReqVO; +import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsLogDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsTemplateDO; import java.util.Date; +import java.util.List; import java.util.Map; /** @@ -53,4 +58,20 @@ public interface SysSmsLogService { */ void updateSmsReceiveResult(Long id, Boolean success, Date receiveTime, String apiReceiveCode, String apiReceiveMsg); + /** + * 获得短信日志分页 + * + * @param pageReqVO 分页查询 + * @return 短信日志分页 + */ + PageResult getSmsLogPage(SysSmsLogPageReqVO pageReqVO); + + /** + * 获得短信日志列表, 用于 Excel 导出 + * + * @param exportReqVO 查询条件 + * @return 短信日志列表 + */ + List getSmsLogList(SysSmsLogExportReqVO exportReqVO); + } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsService.java index 1346552fc..f568b11a8 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsService.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsService.java @@ -14,6 +14,34 @@ import java.util.Map; */ public interface SysSmsService { + /** + * 发送单条短信给用户(管理员) + * + * 在 mobile 为空时,使用 userId 加载对应管理员的手机号 + * + * @param mobile 手机号 + * @param userId 用户编号 + * @param templateCode 短信模板编号 + * @param templateParams 短信模板参数 + * @return 发送日志编号 + */ + Long sendSingleSmsToAdmin(String mobile, Long userId, + String templateCode, Map templateParams); + + /** + * 发送单条短信给用户(会员) + * + * 在 mobile 为空时,使用 userId 加载对应会员的手机号 + * + * @param mobile 手机号 + * @param userId 用户编号 + * @param templateCode 短信模板编号 + * @param templateParams 短信模板参数 + * @return 发送日志编号 + */ + Long sendSingleSmsToMember(String mobile, Long userId, + String templateCode, Map templateParams); + Long sendSingleSms(String mobile, Long userId, Integer userType, String templateCode, Map templateParams); diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsLogServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsLogServiceImpl.java index 6dcd9de7c..3145163c0 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsLogServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsLogServiceImpl.java @@ -1,6 +1,9 @@ package cn.iocoder.dashboard.modules.system.service.sms.impl; import cn.iocoder.dashboard.common.pojo.CommonResult; +import cn.iocoder.dashboard.common.pojo.PageResult; +import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogExportReqVO; +import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogPageReqVO; import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsLogDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsTemplateDO; import cn.iocoder.dashboard.modules.system.dal.mysql.sms.SysSmsLogMapper; @@ -12,6 +15,7 @@ import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.Date; +import java.util.List; import java.util.Map; import java.util.Objects; @@ -69,4 +73,14 @@ public class SysSmsLogServiceImpl implements SysSmsLogService { .apiReceiveCode(apiReceiveCode).apiReceiveMsg(apiReceiveMsg).build()); } + @Override + public PageResult getSmsLogPage(SysSmsLogPageReqVO pageReqVO) { + return smsLogMapper.selectPage(pageReqVO); + } + + @Override + public List getSmsLogList(SysSmsLogExportReqVO exportReqVO) { + return smsLogMapper.selectList(exportReqVO); + } + } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsServiceImpl.java index ba6b81d38..5332c813c 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsServiceImpl.java @@ -25,7 +25,6 @@ import org.springframework.util.Assert; import javax.annotation.Resource; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.stream.Collectors; import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception; @@ -53,13 +52,31 @@ public class SysSmsServiceImpl implements SysSmsService { @Resource private SysUserService userService; + @Override + public Long sendSingleSmsToAdmin(String mobile, Long userId, String templateCode, Map templateParams) { + // 如果 mobile 为空,则加载用户编号对应的手机号 + if (StrUtil.isEmpty(mobile)) { + SysUserDO user = userService.getUser(userId); + if (user != null) { + mobile = user.getMobile(); + } + } + // 执行发送 + return this.sendSingleSms(mobile, userId, UserTypeEnum.ADMIN.getValue(), templateCode, templateParams); + } + + @Override + public Long sendSingleSmsToMember(String mobile, Long userId, String templateCode, Map templateParams) { + throw new UnsupportedOperationException("暂时不支持该操作,感兴趣可以实现该功能哟!"); + } + @Override public Long sendSingleSms(String mobile, Long userId, Integer userType, String templateCode, Map templateParams) { // 校验短信模板是否合法 SysSmsTemplateDO template = this.checkSmsTemplateValid(templateCode); // 校验手机号码是否存在 - mobile = this.checkMobile(mobile, userId, userType); + mobile = this.checkMobile(mobile); // 创建发送日志 Boolean isSend = CommonStatusEnum.ENABLE.getStatus().equals(template.getStatus()); // 如果模板被禁用,则不发送短信,只记录日志 @@ -77,7 +94,7 @@ public class SysSmsServiceImpl implements SysSmsService { @Override public void sendBatchSms(List mobiles, List userIds, Integer userType, String templateCode, Map templateParams) { - throw new IllegalArgumentException("暂时不支持该操作,感兴趣可以实现该功能哟!"); + throw new UnsupportedOperationException("暂时不支持该操作,感兴趣可以实现该功能哟!"); } private SysSmsTemplateDO checkSmsTemplateValid(String templateCode) { @@ -108,31 +125,13 @@ public class SysSmsServiceImpl implements SysSmsService { }).collect(Collectors.toList()); } - private String checkMobile(String mobile, Long userId, Integer userType) { - mobile = getMobile(mobile, userId, userType); + private String checkMobile(String mobile) { if (StrUtil.isEmpty(mobile)) { throw exception(SMS_SEND_MOBILE_NOT_EXISTS); } return mobile; } - private String getMobile(String mobile, Long userId, Integer userType) { - // 如果已经有手机号,则直接返回 - if (StrUtil.isNotEmpty(mobile)) { - return mobile; - } - // 没有手机号,则基于 userId 检索 - if (userId == null || userType == null) { - return null; - } - if (Objects.equals(userType, UserTypeEnum.ADMIN.getValue())) { - SysUserDO user = userService.getUser(userId); - return user != null ? user.getMobile() : null; - } - // TODO 芋艿:支持 C 端用户 - return null; - } - @Override public void doSendSms(SysSmsSendMessage message) { // 获得渠道对应的 SmsClient 客户端 diff --git a/src/main/resources/codegen/java/service/service.vm b/src/main/resources/codegen/java/service/service.vm index 04499314e..17a9b3953 100644 --- a/src/main/resources/codegen/java/service/service.vm +++ b/src/main/resources/codegen/java/service/service.vm @@ -63,7 +63,7 @@ public interface ${table.className}Service { * 获得${table.classComment}列表, 用于 Excel 导出 * * @param exportReqVO 查询条件 - * @return ${table.classComment}分页 + * @return ${table.classComment}列表 */ List<${table.className}DO> get${simpleClassName}List(${table.className}ExportReqVO exportReqVO); diff --git a/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsChannelServiceTest.java b/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsChannelServiceTest.java index 60eae778b..630adf50a 100644 --- a/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsChannelServiceTest.java +++ b/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsChannelServiceTest.java @@ -138,6 +138,8 @@ public class SysSmsChannelServiceTest extends BaseDbUnitTest { assertPojoEquals(dbSmsChannel, pageResult.getList().get(0)); } + // ========== 随机对象 ========== + @SafeVarargs private static SysSmsChannelDO randomSmsChannelDO(Consumer... consumers) { Consumer consumer = (o) -> { diff --git a/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsLogServiceTest.java b/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsLogServiceTest.java new file mode 100644 index 000000000..8b337b013 --- /dev/null +++ b/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsLogServiceTest.java @@ -0,0 +1,151 @@ +package cn.iocoder.dashboard.modules.system.service.sms; + +import cn.iocoder.dashboard.BaseDbUnitTest; +import cn.iocoder.dashboard.common.enums.UserTypeEnum; +import cn.iocoder.dashboard.common.pojo.PageResult; +import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogExportReqVO; +import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogPageReqVO; +import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsLogDO; +import cn.iocoder.dashboard.modules.system.dal.mysql.sms.SysSmsLogMapper; +import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsReceiveStatusEnum; +import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum; +import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsTemplateTypeEnum; +import cn.iocoder.dashboard.modules.system.service.sms.impl.SysSmsLogServiceImpl; +import cn.iocoder.dashboard.util.collection.ArrayUtils; +import cn.iocoder.dashboard.util.object.ObjectUtils; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.function.Consumer; + +import static cn.hutool.core.util.RandomUtil.randomEle; +import static cn.iocoder.dashboard.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.dashboard.util.RandomUtils.randomPojo; +import static cn.iocoder.dashboard.util.RandomUtils.randomString; +import static cn.iocoder.dashboard.util.date.DateUtils.buildTime; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** +* {@link SysSmsLogServiceImpl} 的单元测试类 +* +* @author 芋道源码 +*/ +@Import(SysSmsLogServiceImpl.class) +public class SysSmsLogServiceTest extends BaseDbUnitTest { + + @Resource + private SysSmsLogServiceImpl smsLogService; + + @Resource + private SysSmsLogMapper smsLogMapper; + + @Test // TODO 请修改 null 为需要的值 + public void testGetSmsLogPage() { + // mock 数据 + SysSmsLogDO dbSmsLog = randomSmsLogDO(o -> { // 等会查询到 + o.setChannelId(1L); + o.setTemplateId(10L); + o.setMobile("15601691300"); + o.setSendStatus(SysSmsSendStatusEnum.INIT.getStatus()); + o.setSendTime(buildTime(2020, 11, 11)); + o.setReceiveStatus(SysSmsReceiveStatusEnum.INIT.getStatus()); + o.setReceiveTime(buildTime(2021, 11, 11)); + }); + smsLogMapper.insert(dbSmsLog); + // 测试 channelId 不匹配 + smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setChannelId(2L))); + // 测试 templateId 不匹配 + smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setTemplateId(20L))); + // 测试 mobile 不匹配 + smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setMobile("18818260999"))); + // 测试 sendStatus 不匹配 + smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setSendStatus(SysSmsSendStatusEnum.IGNORE.getStatus()))); + // 测试 sendTime 不匹配 + smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setSendTime(buildTime(2020, 12, 12)))); + // 测试 receiveStatus 不匹配 + smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setReceiveStatus(SysSmsReceiveStatusEnum.SUCCESS.getStatus()))); + // 测试 receiveTime 不匹配 + smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setReceiveTime(buildTime(2021, 12, 12)))); + // 准备参数 + SysSmsLogPageReqVO reqVO = new SysSmsLogPageReqVO(); + reqVO.setChannelId(1L); + reqVO.setTemplateId(10L); + reqVO.setMobile("156"); + reqVO.setSendStatus(SysSmsSendStatusEnum.INIT.getStatus()); + reqVO.setBeginSendTime(buildTime(2020, 11, 1)); + reqVO.setEndSendTime(buildTime(2020, 11, 30)); + reqVO.setReceiveStatus(SysSmsReceiveStatusEnum.INIT.getStatus()); + reqVO.setBeginReceiveTime(buildTime(2021, 11, 1)); + reqVO.setEndReceiveTime(buildTime(2021, 11, 30)); + + // 调用 + PageResult pageResult = smsLogService.getSmsLogPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbSmsLog, pageResult.getList().get(0)); + } + + @Test + public void testGetSmsLogList() { + // mock 数据 + SysSmsLogDO dbSmsLog = randomSmsLogDO(o -> { // 等会查询到 + o.setChannelId(1L); + o.setTemplateId(10L); + o.setMobile("15601691300"); + o.setSendStatus(SysSmsSendStatusEnum.INIT.getStatus()); + o.setSendTime(buildTime(2020, 11, 11)); + o.setReceiveStatus(SysSmsReceiveStatusEnum.INIT.getStatus()); + o.setReceiveTime(buildTime(2021, 11, 11)); + }); + smsLogMapper.insert(dbSmsLog); + // 测试 channelId 不匹配 + smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setChannelId(2L))); + // 测试 templateId 不匹配 + smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setTemplateId(20L))); + // 测试 mobile 不匹配 + smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setMobile("18818260999"))); + // 测试 sendStatus 不匹配 + smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setSendStatus(SysSmsSendStatusEnum.IGNORE.getStatus()))); + // 测试 sendTime 不匹配 + smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setSendTime(buildTime(2020, 12, 12)))); + // 测试 receiveStatus 不匹配 + smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setReceiveStatus(SysSmsReceiveStatusEnum.SUCCESS.getStatus()))); + // 测试 receiveTime 不匹配 + smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setReceiveTime(buildTime(2021, 12, 12)))); + // 准备参数 + SysSmsLogExportReqVO reqVO = new SysSmsLogExportReqVO(); + reqVO.setChannelId(1L); + reqVO.setTemplateId(10L); + reqVO.setMobile("156"); + reqVO.setSendStatus(SysSmsSendStatusEnum.INIT.getStatus()); + reqVO.setBeginSendTime(buildTime(2020, 11, 1)); + reqVO.setEndSendTime(buildTime(2020, 11, 30)); + reqVO.setReceiveStatus(SysSmsReceiveStatusEnum.INIT.getStatus()); + reqVO.setBeginReceiveTime(buildTime(2021, 11, 1)); + reqVO.setEndReceiveTime(buildTime(2021, 11, 30)); + + // 调用 + List list = smsLogService.getSmsLogList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbSmsLog, list.get(0)); + } + + // ========== 随机对象 ========== + + @SafeVarargs + private static SysSmsLogDO randomSmsLogDO(Consumer... consumers) { + Consumer consumer = (o) -> { + o.setTemplateParams(new HashMap<>()); + o.getTemplateParams().put(randomString(), randomString()); + o.getTemplateParams().put(randomString(), randomString()); + o.setTemplateType(randomEle(SysSmsTemplateTypeEnum.values()).getType()); // 保证 templateType 的范围 + o.setUserType(randomEle(UserTypeEnum.values()).getValue()); // 保证 userType 的范围 + }; + return randomPojo(SysSmsLogDO.class, ArrayUtils.append(consumer, consumers)); + } +} diff --git a/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsTemplateServiceTest.java b/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsTemplateServiceTest.java index 51db4bed0..6ae212d7d 100644 --- a/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsTemplateServiceTest.java +++ b/src/test/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsTemplateServiceTest.java @@ -79,7 +79,7 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest { SysSmsTemplateCreateReqVO reqVO = randomPojo(SysSmsTemplateCreateReqVO.class, o -> { o.setContent("正在进行登录操作{operation},您的验证码是{code}"); o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 - o.setType(randomEle(SysSmsTemplateTypeEnum.values()).getType()); // 保证 type 的泛微 + o.setType(randomEle(SysSmsTemplateTypeEnum.values()).getType()); // 保证 type 的 范围 }); // mock Channel 的方法 SysSmsChannelDO channelDO = randomPojo(SysSmsChannelDO.class, o -> { @@ -114,7 +114,7 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest { o.setId(dbSmsTemplate.getId()); // 设置更新的 ID o.setContent("正在进行登录操作{operation},您的验证码是{code}"); o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 - o.setType(randomEle(SysSmsTemplateTypeEnum.values()).getType()); // 保证 type 的泛微 + o.setType(randomEle(SysSmsTemplateTypeEnum.values()).getType()); // 保证 type 的 范围 }); // mock 方法 SysSmsChannelDO channelDO = randomPojo(SysSmsChannelDO.class, o -> { @@ -339,7 +339,7 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest { private static SysSmsTemplateDO randomSmsTemplateDO(Consumer... consumers) { Consumer consumer = (o) -> { o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 - o.setType(randomEle(SysSmsTemplateTypeEnum.values()).getType()); // 保证 type 的泛微 + o.setType(randomEle(SysSmsTemplateTypeEnum.values()).getType()); // 保证 type 的 范围 }; return randomPojo(SysSmsTemplateDO.class, ArrayUtils.append(consumer, consumers)); } diff --git a/src/test/resources/sql/clean.sql b/src/test/resources/sql/clean.sql index c1965cbda..2eedb0ed7 100644 --- a/src/test/resources/sql/clean.sql +++ b/src/test/resources/sql/clean.sql @@ -21,3 +21,4 @@ DELETE FROM "sys_operate_log"; DELETE FROM "sys_user"; DELETE FROM "sys_sms_channel"; DELETE FROM "sys_sms_template"; +DELETE FROM "sys_sms_log"; diff --git a/src/test/resources/sql/create_tables.sql b/src/test/resources/sql/create_tables.sql index 2d758f7a5..963d18fa5 100644 --- a/src/test/resources/sql/create_tables.sql +++ b/src/test/resources/sql/create_tables.sql @@ -378,3 +378,36 @@ CREATE TABLE "sys_sms_template" ( "deleted" bit NOT NULL DEFAULT FALSE, PRIMARY KEY ("id") ) COMMENT '短信模板'; + +CREATE TABLE "sys_sms_log" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "channel_id" bigint NOT NULL, + "channel_code" varchar(63) NOT NULL, + "template_id" bigint NOT NULL, + "template_code" varchar(63) NOT NULL, + "template_type" tinyint NOT NULL, + "template_content" varchar(255) NOT NULL, + "template_params" varchar(255) NOT NULL, + "api_template_id" varchar(63) NOT NULL, + "mobile" varchar(11) NOT NULL, + "user_id" bigint DEFAULT '0', + "user_type" tinyint DEFAULT '0', + "send_status" tinyint NOT NULL DEFAULT '0', + "send_time" timestamp DEFAULT NULL, + "send_code" int DEFAULT NULL, + "send_msg" varchar(255) DEFAULT NULL, + "api_send_code" varchar(63) DEFAULT NULL, + "api_send_msg" varchar(255) DEFAULT NULL, + "api_request_id" varchar(255) DEFAULT NULL, + "api_serial_no" varchar(255) DEFAULT NULL, + "receive_status" tinyint NOT NULL DEFAULT '0', + "receive_time" timestamp DEFAULT NULL, + "api_receive_code" varchar(63) DEFAULT NULL, + "api_receive_msg" varchar(255) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") +) COMMENT '短信日志';