Commit 75f42651 authored by zhangfeng's avatar zhangfeng

Merge branch 'refs/heads/feature_member_score' into feature_member_score_zhangfeng

parents 9bb083b3 32b80572
......@@ -32,4 +32,5 @@ public interface DictDataFrameworkService {
*/
List<DictDataRespDTO> listDictDatasFromCache(String type);
DictDataRespDTO parseDictDataFromCacheWithMultiLang(String type, String multiLangLabel);
}
......@@ -25,4 +25,8 @@ public class DictFrameworkUtils {
return service.parseDictDataFromCache(type, label);
}
public static DictDataRespDTO parseDictDataFromCacheWithMultiLang(String type, String multiLangLabel) {
return service.parseDictDataFromCacheWithMultiLang(type, multiLangLabel);
}
}
......@@ -42,6 +42,21 @@ public class I18nMessage {
}
}
/**
* 获取一条语言配置信息
*
* @param message 配置信息属性名,eg: api.response.code.user.signUp
* @return
*/
public static String getMessage(String message, Object... arg) {
Locale locale = LocaleContextHolder.getLocale();
try {
return accessor.getMessage(message, arg, locale);
} catch (Exception e) {
return message;
}
}
/**
* 获取一条语言配置信息
* TODO 此方法暂时只支持中英文国际化,如需更多,待优化
......
package cn.iocoder.yudao.framework.apollo.core.event.export;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class RewardRedeemRecordExportEvent {
/**
* 操作用户
*/
private Long userId = 0L;
/**
* 端口
*/
private Integer userType = 2;
/**
* 请求参数
*/
private String requestParams;
/**
* 国际化语言值,默认0中文, 具体取值I18nMessage.getLang()
*/
private Integer lang = 0;
/**
* 文件名称
*/
private String fileName;
/**
* 文件路径
*/
private String path;
/**
* 下载地址
*/
private String url;
/**
* 执行结果
*/
private String result;
@ApiModelProperty(value = "文件ID")
private Long fileId;
}
......@@ -6,6 +6,7 @@ import java.math.BigDecimal;
@Data
public class CurrencyRespDTO {
private Integer id;
/**
* 中文名称
*/
......
package cn.iocoder.yudao.module.ecw.api.express;
import cn.iocoder.yudao.module.ecw.api.express.dto.ExpressRespDTO;
import java.util.List;
public interface ExpressApi {
List<ExpressRespDTO> getAllExpress();
}
package cn.iocoder.yudao.module.ecw.api.express.dto;
import lombok.Data;
@Data
public class ExpressRespDTO {
private Long id;
/**
* 快递公司名称
*/
private String companyName;
}
......@@ -208,4 +208,13 @@ public class RegionController {
return pNode;
}
@GetMapping("/getCityListByParent")
@ApiOperation("根据父节点获取城市列表")
public CommonResult<List<RegionRespVO>> getCityListByParent(@RequestParam("id") Long parentId) {
if (parentId == null) {
return CommonResult.success(Collections.emptyList());
}
List<RegionDO> cityList = regionService.getCityListByParentId(parentId);
return success(RegionConvert.INSTANCE.convertList(cityList));
}
}
......@@ -4,6 +4,7 @@ import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.ecw.api.express.dto.ExpressRespDTO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import cn.iocoder.yudao.module.ecw.controller.admin.express.vo.*;
......@@ -31,4 +32,5 @@ public interface ExpressConvert {
List<ExpressExcelVO> convertList02(List<ExpressDO> list);
List<ExpressRespDTO> convert2DTO(List<ExpressDO> list);
}
......@@ -102,4 +102,5 @@ public interface RegionMapper extends BaseMapperX<RegionDO> {
List<RegionDO> getImportExportCountryList();
List<RegionDO> getCityListByParentId(@Param("parentId") Long parentId);
}
package cn.iocoder.yudao.module.ecw.service.api;
import cn.iocoder.yudao.module.ecw.api.express.ExpressApi;
import cn.iocoder.yudao.module.ecw.api.express.dto.ExpressRespDTO;
import cn.iocoder.yudao.module.ecw.convert.express.ExpressConvert;
import cn.iocoder.yudao.module.ecw.dal.dataobject.express.ExpressDO;
import cn.iocoder.yudao.module.ecw.service.express.ExpressService;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
@Component
public class ExpressApiImpl implements ExpressApi {
@Resource
private ExpressService expressService;
@Override
public List<ExpressRespDTO> getAllExpress() {
List<ExpressDO> list = expressService.list();
return ExpressConvert.INSTANCE.convert2DTO(list);
}
}
......@@ -67,4 +67,5 @@ public interface ExpressService {
*/
List<ExpressDO> getExpressList(ExpressExportReqVO exportReqVO);
List<ExpressDO> list();
}
package cn.iocoder.yudao.module.ecw.service.express;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
......@@ -79,4 +81,11 @@ public class ExpressServiceImpl implements ExpressService {
return expressMapper.selectList(exportReqVO);
}
@Override
public List<ExpressDO> list() {
LambdaQueryWrapper<ExpressDO> wrapper = Wrappers.lambdaQuery();
wrapper.eq(ExpressDO::getDeleted, 0);
return expressMapper.selectList(wrapper);
}
}
......@@ -90,5 +90,5 @@ public interface RegionService {
List<RegionDO> getImportExportCountryList();
List<RegionDO> getCityListByParentId(Long parentId);
}
......@@ -144,4 +144,9 @@ public class RegionServiceImpl implements RegionService {
public List<RegionDO> getImportExportCountryList() {
return regionMapper.getImportExportCountryList();
}
@Override
public List<RegionDO> getCityListByParentId(Long parentId) {
return regionMapper.getCityListByParentId(parentId);
}
}
......@@ -68,4 +68,13 @@
and b.status = 0
and b.type in (1, 3)
</select>
<select id="getCityListByParentId" resultType="cn.iocoder.yudao.module.ecw.dal.dataobject.region.RegionDO">
select b.* from ecw_region a
left join ecw_region b on a.id = b.parent_id
where a.parent_id = #{parentId}
AND a.deleted = 0
and b.deleted = 0
and a.status = 0
and b.status = 0
</select>
</mapper>
......@@ -41,7 +41,7 @@
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-system-impl</artifactId>
<version>1.6.1-snapshot</version>
<version>${revision}</version>
<scope>compile</scope>
</dependency>
<dependency>
......
......@@ -15,7 +15,9 @@ public class MemberUserScoreBackVO {
@ApiModelProperty(value = "会员id")
private String id;
@ApiModelProperty(value = "会员昵称")
private String nickname;
private String memberNameZh;
@ApiModelProperty(value = "会员昵称英文")
private String memberNameEn;
@ApiModelProperty(value = "联系方式")
private String areaCode;
@ApiModelProperty(value = "手机号")
......@@ -24,6 +26,10 @@ public class MemberUserScoreBackVO {
private String countryNameZh;
@ApiModelProperty(value = "国家(英文)")
private String countryNameEn;
@ApiModelProperty(value = "城市(中文)")
private String cityNameZh;
@ApiModelProperty(value = "城市(英文)")
private String cityNameEn;
@ApiModelProperty(value = "当前积分")
private Integer holdScore;
@ApiModelProperty(value = "已兑换积分")
......
......@@ -21,8 +21,10 @@ public class MemberUserScoreLogBackVO {
private Long id;
@ApiModelProperty(value = "会员id")
private Long memberId;
@ApiModelProperty(value = "会员昵称")
private String memberName;
@ApiModelProperty(value = "会员昵称中文")
private String memberNameZh;
@ApiModelProperty(value = "会员昵称英文")
private String memberNameEn;
@ApiModelProperty(value = "积分数量")
private Integer scoreCount;
@ApiModelProperty(value = "操作类别")
......
......@@ -7,7 +7,8 @@
select
musl.id as id,
musl.member_id as memberId,
mu.nickname as memberName,
mu.nickname as memberNameZh,
mu.english_name as memberNameEn,
musl.score_count as scoreCount,
musl.operate_type as operateType,
musl.source_type as sourceType,
......
......@@ -5,7 +5,8 @@
resultType="cn.iocoder.yudao.module.member.vo.memberUserScore.MemberUserScoreBackVO">
select
mu.id,
mu.nickname,
mu.nickname as memberNameZh,
mu.english_name as memberNameEn,
mu.area_code as areaCode,
mu.mobile,
re.title_zh as countryNameZh,
......@@ -41,7 +42,7 @@
<sql id="scoreCondition">
<if test="query.key != null and query.key != ''">
and (mu.nickname like '%${query.key}%' or mu.mobile like '%${query.key}%')
and (mu.nickname like '%${query.key}%' or mu.mobile like '%${query.key}%' or mu.code like '%${query.key}%')
</if>
<if test="query.country != null">
and mu.country = #{query.country}
......
......@@ -23,5 +23,11 @@ public interface ErrorCodeConstants {
ErrorCode REWARD_REDEEM_FAIL = new ErrorCode(1001011015, "批量兑换失败");
ErrorCode REWARD_REDEEM_COUNT_NOT_ALLOW = new ErrorCode(1001011016, "批量兑换每次最多十条");
ErrorCode REWARD_REDEEM_ALLOW_COUNT_ERROR = new ErrorCode(1001011017, "超出允许兑换次数");
ErrorCode REWARD_REDEEM_NOT_EXIST = new ErrorCode(1001011018, "reward.redeem.not.exist");
ErrorCode REWARD_REDEEM_STATUS_ERROR = new ErrorCode(1001011019, "reward.redeem.status.error");
ErrorCode REWARD_REDEEM_VERIFY_NO_PARAM = new ErrorCode(1001011020, "reward.redeem.verify.no.param");
ErrorCode REWARD_REDEEM_BATCH_VERIFY_ERROR = new ErrorCode(1001011021, "reward.redeem.batch.verify.error");
ErrorCode REWARD_REDEEM_VERIFY_BACK_STATUS = new ErrorCode(1001011022, "reward.redeem.verify.back.status");
ErrorCode REDEEM_IMPORT_MAX_COUNT = new ErrorCode(1001011023, "redeem.import.max.count");
}
......@@ -39,12 +39,28 @@
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-system-api</artifactId>
<version>1.6.1-snapshot</version>
<version>${revision}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-ecw-api</artifactId>
<version>${revision}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-config</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-system-impl</artifactId>
<version>1.6.1-snapshot</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-infra-impl</artifactId>
<version>1.6.1-snapshot</version>
<scope>compile</scope>
</dependency>
......
......@@ -2,30 +2,37 @@ package cn.iocoder.yudao.module.reward.controller.admin.redeem;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.util.ExcelUtils;
import cn.iocoder.yudao.module.reward.api.reward.RedeemRewardApi;
import cn.iocoder.yudao.module.reward.api.reward.dto.RedeemRewardReqVO;
import cn.iocoder.yudao.module.reward.api.reward.dto.RedeemRewardRespDTO;
import cn.iocoder.yudao.module.reward.service.redeem.RewardRedeemService;
import cn.iocoder.yudao.module.reward.vo.reward.*;
import cn.iocoder.yudao.module.reward.vo.reward.RewardRedeemPageReqVO;
import cn.iocoder.yudao.module.reward.vo.reward.RewardRedeemPageRespVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Validated
@RestController
@Api(tags = "管理后台 - 礼品管理")
@Api(tags = "管理后台 - 兑换记录管理")
@RequestMapping("/reward/redeem")
public class RedeemRewardController {
......@@ -36,11 +43,72 @@ public class RedeemRewardController {
private RewardRedeemService rewardRedeemService;
@PostMapping("record/page")
@ApiOperation("兑换记录列表")
@ApiOperation("列表")
public CommonResult<PageResult<RewardRedeemPageRespVO>> pageInfo(@Valid @RequestBody RewardRedeemPageReqVO reqVO) {
return success(rewardRedeemService.pageInfo(reqVO));
}
@PostMapping("record/detail")
@ApiOperation("详情")
public CommonResult<RewardRedeemPageRespVO> detail(@Valid @RequestBody RewardRedeemBaseVO request) {
return success(rewardRedeemService.detail(request.getId()));
}
@PostMapping("record/update")
@ApiOperation("更新")
public CommonResult<Boolean> update(@Valid @RequestBody RewardRedeemUpdateReqVO request) {
return success(rewardRedeemService.updateRecord(request));
}
@PostMapping("record/verify")
@ApiOperation("核销")
public CommonResult<Boolean> verify(@Valid @RequestBody RewardRedeemVerifyReqVO request) {
return success(rewardRedeemService.verify(request));
}
@PostMapping("record/batch/verify")
@ApiOperation("批量核销")
public CommonResult<Boolean> batchVerify(@Valid @RequestBody RewardRedeemBatchVerifyReqVO request) {
return success(rewardRedeemService.batchVerify(request));
}
@PostMapping("record/verify-back")
@ApiOperation("核销回退")
public CommonResult<Boolean> verifyBack(@Valid @RequestBody List<Long> redeemIds) {
return success(rewardRedeemService.verifyBack(redeemIds));
}
@PostMapping("record/export")
@ApiOperation("导出")
public CommonResult<Boolean> export(@Valid @RequestBody RewardRedeemPageReqVO reqVO) {
return success(rewardRedeemService.export(reqVO));
}
@PostMapping("record/import/template")
@ApiOperation("导入模板下载")
public void importTemplate(HttpServletResponse response) throws IOException {
// 手动创建导出 demo
List<RedeemInfoImportExcelVO> list = Arrays.asList(
RedeemInfoImportExcelVO.builder().id(String.valueOf(11111)).redeemType("上门领取").courierCompany("顺丰空运").expenses(BigDecimal.valueOf(11.11))
.currency("人民币").expressDate("2024-01-01 11:22:33").expressNo("SDSD212212").remark("备注备注").expressSender("系统管理员")
.build(),
RedeemInfoImportExcelVO.builder().id(String.valueOf(11111)).redeemType("包邮到家").courierCompany("顺丰空运").expenses(BigDecimal.valueOf(11.11))
.currency("美元").expressDate("2024-01-01 11:22:33").expressNo("SDSD212212").remark("备注备注").expressSender("系统管理员")
.build());
// 输出
ExcelUtils.write(response, "兑换信息导入模板.xls", "兑换信息", RedeemInfoImportExcelVO.class, list);
}
@PostMapping(value = "record/import", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ApiOperation("兑换信息导入")
@ApiImplicitParams({
@ApiImplicitParam(name = "file", value = "Excel 文件", required = true, dataTypeClass = MultipartFile.class)
})
public CommonResult<RecordInfoImportRespVO> recordImport(@RequestParam("file") MultipartFile file) throws IOException {
List<RedeemInfoImportExcelVO> list = ExcelUtils.read(file, RedeemInfoImportExcelVO.class);
return success(rewardRedeemService.recordImport(list));
}
@PostMapping("/single")
@ApiOperation("兑换礼品")
......
......@@ -76,7 +76,7 @@ public class RewardRedeemDO extends BaseDO {
/**
* 快递公司
*/
private String courierCompany;
private Long courierCompany;
/**
* 快递单号
*/
......@@ -84,7 +84,7 @@ public class RewardRedeemDO extends BaseDO {
/**
* 快递日期
*/
private String expressDate;
private Date expressDate;
/**
* 快递寄出人
*/
......@@ -97,4 +97,8 @@ public class RewardRedeemDO extends BaseDO {
* 备注
*/
private String remark;
private String verifyUser;
private Date verifyTime;
}
......@@ -19,4 +19,8 @@ public interface RewardRedeemMapper extends AbstractMapper<RewardRedeemDO> {
List<RewardRedeemPageRespVO> pageInfo(@Param("start") int start, @Param("size") int size, @Param("req") RewardRedeemPageReqVO reqVO);
int pageCount(@Param("req") RewardRedeemPageReqVO reqVO);
RewardRedeemPageRespVO detail(@Param("id") Long id);
List<RewardRedeemPageRespVO> exportList(@Param("req") RewardRedeemPageReqVO request);
}
package cn.iocoder.yudao.module.reward.dto;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author zhaobiyan
*/
@Data
public class RedeemRecordImportDTO {
private Long id;
private Integer redeemType;
private BigDecimal expenses;
private Integer currency;
private Integer courierCompany;
private String expressNo;
private Date expressDate;
private String expressSender;
private String remark;
}
package cn.iocoder.yudao.module.reward.dto;
import lombok.Builder;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
@Builder
public class RewardRedeemVerifyDTO {
private Long id;
private Integer status;
private Integer redeemType;
private BigDecimal expense;
private Integer currency;
private Long courierCompany;
/**
* 收件人地址
*/
private String recipientAddress;
/**
* 快递单号
*/
private String expressNo;
/**
* 快递日期
*/
private Date expressDate;
/**
* 快递寄出人
*/
private String expressSender;
}
package cn.iocoder.yudao.module.reward.listener;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.apollo.core.event.export.RewardRedeemRecordExportEvent;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.util.ExcelUtils;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.infra.api.file.dto.FileRespDto;
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
import cn.iocoder.yudao.module.reward.service.redeem.RewardRedeemService;
import cn.iocoder.yudao.module.reward.vo.reward.RewardRedeemPageReqVO;
import cn.iocoder.yudao.module.reward.vo.reward.RewardRedeemPageRespVO;
import cn.iocoder.yudao.module.reward.vo.reward.RewardRedeemRecordExportVO;
import cn.iocoder.yudao.module.system.framework.ue.UeProperties;
import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.FileInputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.excel.constant.ExportConstant.DATA_FORMAT;
@Component
@AllArgsConstructor
@Slf4j
public class RewardRedeemRecordExportListener {
private RewardRedeemService rewardRedeemService;
private UeProperties ueProperties;
private FileApi fileService;
@EventListener(RewardRedeemRecordExportEvent.class)
public void listen(RewardRedeemRecordExportEvent event) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATA_FORMAT);
String nowTime = formatter.format(LocalDateTime.now());
String dir = ueProperties.getTempDir().concat("/rewardRedeemRecord/excel/");
File fileDir = new File(dir);
if (!fileDir.exists()){
// 不存在则创建一个目录
fileDir.mkdirs();
}
String fileName = event.getUserId().toString().concat(StrUtil.DASHED).concat(event.getUserType().toString()).concat(StrUtil.DASHED).concat(nowTime).concat("shipment_preload.xlsx");
RewardRedeemPageReqVO request = JSONObject.parseObject(event.getRequestParams(), RewardRedeemPageReqVO.class);
Integer totalCount = rewardRedeemService.exportCount(request);
int size = 500;
int totalPage = totalCount%size == 0 ? totalCount/size: totalCount/size + 1;
List<RewardRedeemRecordExportVO> result = new ArrayList<>();
for (int i = 1; i <= totalPage ; i++) {
request.setPageNo(i);
request.setPageSize(size);
PageResult<RewardRedeemPageRespVO> rewardRedeemPageRespVOPageResult = rewardRedeemService.pageInfo(request);
result.addAll(convert2ExcelVo(rewardRedeemPageRespVOPageResult.getList()));
}
try {
String path = ExcelUtils.write(dir, fileName, "数据", RewardRedeemRecordExportVO.class, result);
// 获取到临时文件
File file = new File(path);
// 创建FileInputStream对象
FileInputStream fileInputStream = new FileInputStream(file);
// 读取文件内容
byte[] fileBytes = new byte[(int) file.length()];
fileInputStream.read(fileBytes);
// 关闭文件流
fileInputStream.close();
// 将文件上传到资源服务器
FileRespDto fileRespDto = fileService.createFile(dir, fileName, fileBytes);
event.setPath(fileRespDto.getPath());
event.setFileName(fileRespDto.getFileName());
event.setUrl(fileRespDto.getUrl());
event.setFileId(fileRespDto.getId());
} catch (Exception e) {
log.info("reward redeem record export listener exception", e);
event.setResult(e.getMessage());
}
}
private Collection<RewardRedeemRecordExportVO> convert2ExcelVo(List<RewardRedeemPageRespVO> list) {
return list.stream().map(item -> {
RewardRedeemRecordExportVO exportVO = new RewardRedeemRecordExportVO();
exportVO.setId(String.valueOf(item.getId()));
exportVO.setStatus(item.getStatus());
exportVO.setRewardCode(item.getRewardCode());
exportVO.setRewardTitle(item.getRewardTitleZh());
exportVO.setMemberName(item.getMemberName());
exportVO.setRewardCount(item.getRewardCount());
exportVO.setRedeemType(item.getRedeemType());
exportVO.setEntrance(item.getEntrance());
exportVO.setExpenses(item.getExpenses());
exportVO.setCurrencyTitle(item.getCurrencyTitleZh());
exportVO.setRecipientName(item.getRecipientName());
exportVO.setRecipientPhoneNum(item.getRecipientPhoneNum());
exportVO.setRecipientAddress(item.getRecipientAddress());
exportVO.setRedeemer(item.getRedeemer());
exportVO.setRedemptionTime(item.getCreateTime());
exportVO.setCourierCompanyName(item.getCourierCompanyName());
exportVO.setExpressNo(item.getExpressNo());
exportVO.setExpressDate(item.getExpressDate());
exportVO.setExpressSender(item.getExpressSender());
exportVO.setRemark(item.getRemark());
exportVO.setVerifyUser(item.getVerifyUser());
exportVO.setVerifyTime(item.getVerifyTime());
exportVO.setCreatorName(item.getCreatorName());
exportVO.setCreateTime(item.getCreateTime());
exportVO.setUpdaterName(item.getUpdaterName());
exportVO.setUpdateTime(item.getUpdateTime());
return exportVO;
}).collect(Collectors.toList());
}
}
......@@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.reward.service.redeem;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.service.IService;
import cn.iocoder.yudao.module.reward.dal.dataobject.redeem.RewardRedeemDO;
import cn.iocoder.yudao.module.reward.vo.reward.RewardRedeemPageReqVO;
import cn.iocoder.yudao.module.reward.vo.reward.RewardRedeemPageRespVO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import cn.iocoder.yudao.module.reward.vo.reward.*;
import java.util.List;
/**
* 礼品兑换 Service 接口
......@@ -15,4 +15,22 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
public interface RewardRedeemService extends IService<RewardRedeemDO> {
PageResult<RewardRedeemPageRespVO> pageInfo(RewardRedeemPageReqVO reqVO);
RewardRedeemPageRespVO detail(Long id);
Boolean updateRecord(RewardRedeemUpdateReqVO request);
Boolean verify(RewardRedeemVerifyReqVO request);
Boolean batchVerify(RewardRedeemBatchVerifyReqVO request);
Boolean verifyBack(List<Long> redeemIds);
Boolean export(RewardRedeemPageReqVO reqVO);
List<RewardRedeemPageRespVO> exportList(RewardRedeemPageReqVO request);
Integer exportCount(RewardRedeemPageReqVO request);
RecordInfoImportRespVO recordImport(List<RedeemInfoImportExcelVO> dataList);
}
package cn.iocoder.yudao.module.reward.vo.reward;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
import java.util.Map;
@Data
@Builder
public class RecordInfoImportRespVO {
@ApiModelProperty(value = "导入失败的信息集合", required = true, notes = "key 为兑换id,value 为失败原因")
private Map<String, String> redeemIdFailedMap;
public RecordInfoImportRespVO() {
}
public RecordInfoImportRespVO(Map<String, String> redeemIdFailedMap) {
this.redeemIdFailedMap = redeemIdFailedMap;
}
}
package cn.iocoder.yudao.module.reward.vo.reward;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = false)
public class RedeemInfoImportExcelVO {
@ExcelProperty("兑换记录ID/Redeem ID")
private String id;
@ExcelProperty("兑换方式/Redeem Method")
private String redeemType;
@ExcelProperty("费用/fee")
private BigDecimal expenses;
@ExcelProperty("币种/Currency")
private String currency;
@ExcelProperty("快递公司/Express")
private String courierCompany;
@ExcelProperty("快递单号/Express NO")
private String expressNo;
@ExcelProperty(value = "快递日期/Delivery Date")
private String expressDate;
@ExcelProperty("快递寄出人/Sender")
private String expressSender;
@ExcelProperty("备注/Remark")
private String remark;
}
......@@ -78,7 +78,7 @@ public class RewardRedeemBaseVO {
* 快递公司
*/
@ApiModelProperty(value = "快递公司")
private String courierCompany;
private Integer courierCompany;
/**
* 快递单号
*/
......@@ -88,7 +88,7 @@ public class RewardRedeemBaseVO {
* 快递日期
*/
@ApiModelProperty(value = "快递日期")
private String expressDate;
private Date expressDate;
/**
* 快递寄出人
*/
......@@ -111,7 +111,17 @@ public class RewardRedeemBaseVO {
@ApiModelProperty(value = "更新人id")
private String updater;
@ApiModelProperty(value = "更新时间")
private String updateTime;
private Date updateTime;
@ApiModelProperty(value = "是否删除")
private Boolean deleted;
/**
* 核销人
*/
@ApiModelProperty(value = "核销人")
private String verifyUser;
/**
* 核销时间
*/
@ApiModelProperty(value = "核销时间")
private Date verifyTime;
}
package cn.iocoder.yudao.module.reward.vo.reward;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;
@Data
public class RewardRedeemBatchVerifyReqVO {
@NotNull(message = "ids is not null")
@ApiModelProperty(value = "id")
private List<Long> ids;
@ApiModelProperty(value = "核销人")
@NotNull(message = "verifyUser is not null")
private String verifyUser;
/**
* 核销时间
*/
@NotNull(message = "verify time is not null")
@ApiModelProperty(value = "核销时间")
private Date verifyTime;
}
......@@ -23,8 +23,15 @@ public class RewardRedeemPageRespVO extends RewardRedeemBaseVO {
private String nodeTitleEn;
@ApiModelProperty(value = "兑换积分")
private Integer totalCount;
@ApiModelProperty(value = "创建人时间")
@ApiModelProperty(value = "创建人")
private String creatorName;
@ApiModelProperty(value = "更新人时间")
@ApiModelProperty(value = "更新人")
private String updaterName;
@ApiModelProperty(value = "币种名称中文")
private String currencyTitleZh;
@ApiModelProperty(value = "币种名称英文")
private String currencyTitleEn;
@ApiModelProperty(value = "快递公司名称")
private String courierCompanyName;
}
package cn.iocoder.yudao.module.reward.vo.reward;
import cn.iocoder.yudao.framework.excel.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.converters.bigdecimal.BigDecimalStringConverter;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
public class RewardRedeemRecordExportVO {
@ExcelProperty("兑换记录ID")
private String id;
@ExcelProperty(value = "兑换状态", converter = DictConvert.class)
@DictFormat("reward_redeem_status")
private Integer status;
@ExcelProperty("礼品ID")
private String rewardCode;
@ExcelProperty("礼品名称")
private String rewardTitle;
@ExcelProperty("会员名称")
private String memberName;
@ExcelProperty("兑换数量")
private Integer rewardCount;
@ExcelProperty(value = "兑换方式", converter = DictConvert.class)
@DictFormat("way_of_receiving")
private Integer redeemType;
@ExcelProperty(value = "兑换入口", converter = DictConvert.class)
@DictFormat("platform_type")
private Integer entrance;
@ExcelProperty(value = "费用", converter = BigDecimalStringConverter.class)
private BigDecimal expenses;
@ExcelProperty("币种名称")
private String currencyTitle;
@ExcelProperty(value = "收件人姓名")
private String recipientName;
@ExcelProperty(value = "收件人电话")
private String recipientPhoneNum;
@ExcelProperty(value = "收件人地址")
private String recipientAddress;
@ExcelProperty(value = "兑换人")
private String redeemer;
@ExcelProperty(value = "兑换时间")
private Date redemptionTime;
@ExcelProperty(value = "快递公司名称")
private String courierCompanyName;
@ExcelProperty(value = "快递单号")
private String expressNo;
@ExcelProperty(value = "快递日期")
private Date expressDate;
@ExcelProperty(value = "快递寄出人")
private String expressSender;
@ExcelProperty(value = "备注")
private String remark;
@ExcelProperty(value = "核销人")
private String verifyUser;
@ExcelProperty(value = "核销时间")
private Date verifyTime;
@ExcelProperty(value = "创建人")
private String creatorName;
@ExcelProperty(value = "创建时间")
private Date createTime;
@ExcelProperty(value = "更新人")
private String updaterName;
@ExcelProperty(value = "更新时间")
private Date updateTime;
}
package cn.iocoder.yudao.module.reward.vo.reward;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.Date;
@Data
public class RewardRedeemUpdateReqVO {
@NotNull(message = "id is not null")
@ApiModelProperty(value = "id")
private Long id;
@NotNull(message = "redeemType is not null")
@ApiModelProperty(value = "兑换方式")
private Integer redeemType;
@ApiModelProperty(value = "费用")
private BigDecimal expenses;
@ApiModelProperty(value = "币种")
private Integer currency;
/**
* 收件人姓名
*/
@NotNull(message = "recipientName is not null")
@ApiModelProperty(value = "收件人姓名")
private String recipientName;
/**
* 收件人电话
*/
@NotNull(message = "recipientPhoneNum is not null")
@ApiModelProperty(value = "收件人电话")
private String recipientPhoneNum;
/**
* 收件人地址
*/
@ApiModelProperty(value = "收件人地址")
private String recipientAddress;
/**
* 兑换人
*/
@ApiModelProperty(value = "兑换人")
private String redeemer;
/**
* 兑换时间
*/
@ApiModelProperty(value = "兑换时间")
private Date redemptionTime;
/**
* 快递公司
*/
@ApiModelProperty(value = "快递公司")
private String courierCompany;
/**
* 快递单号
*/
@ApiModelProperty(value = "快递单号")
private String expressNo;
/**
* 快递日期
*/
@ApiModelProperty(value = "快递日期")
private String expressDate;
/**
* 快递寄出人
*/
@ApiModelProperty(value = "快递寄出人")
private String expressSender;
/**
* 上传附件
*/
@ApiModelProperty(value = "上传附件")
private String annex;
/**
* 备注
*/
@ApiModelProperty(value = "备注")
private String remark;
}
package cn.iocoder.yudao.module.reward.vo.reward;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.Date;
@Data
public class RewardRedeemVerifyReqVO {
@NotNull(message = "id is not null")
@ApiModelProperty(value = "id")
private Long id;
/**
* 收件人姓名
*/
@NotNull(message = "recipientName is not null")
@ApiModelProperty(value = "收件人姓名")
private String recipientName;
/**
* 收件人电话
*/
@NotNull(message = "recipientPhoneNum is not null")
@ApiModelProperty(value = "收件人电话")
private String recipientPhoneNum;
@ApiModelProperty(value = "快递公司")
private Long courierCompany;
/**
* 收件人地址
*/
@ApiModelProperty(value = "收件人地址")
private String recipientAddress;
/**
* 快递单号
*/
@ApiModelProperty(value = "快递单号")
private String expressNo;
/**
* 快递日期
*/
@ApiModelProperty(value = "快递日期")
private Date expressDate;
/**
* 快递寄出人
*/
@ApiModelProperty(value = "快递寄出人")
private String expressSender;
/**
* 核销人
*/
@ApiModelProperty(value = "核销人")
@NotNull(message = "verifyUser is not null")
private String verifyUser;
/**
* 核销时间
*/
@NotNull(message = "verify time is not null")
@ApiModelProperty(value = "核销时间")
private Date verifyTime;
}
......@@ -11,6 +11,62 @@
<select id="pageInfo" resultType="cn.iocoder.yudao.module.reward.vo.reward.RewardRedeemPageRespVO">
select
<include refid="columns"/>
from ecw_reward_redeem err
left join ecw_reward er on err.reward_id = er.id
left join member_user mu on mu.id = err.member_id
left join ecw_node en on er.node_id = en.id
left join system_user suc on suc.id = er.creator
left join system_user suu on suu.id = er.updater
left join ecw_currency cc on err.currency = cc.id
left join ecw_express ee on err.courier_company = ee.id
where 1=1
<include refid="pageCondition"/>
order by er.create_time desc
limit #{start}, #{size}
</select>
<select id="pageCount" resultType="java.lang.Integer">
select count(*)
from ecw_reward_redeem err
left join ecw_reward er on err.reward_id = er.id
left join member_user mu on mu.id = err.member_id
left join ecw_node en on er.node_id = en.id
left join system_user suc on suc.id = er.creator
left join system_user suu on suu.id = er.updater
left join ecw_express ee on err.courier_company = ee.id
where 1=1
<include refid="pageCondition"/>
</select>
<select id="detail" resultType="cn.iocoder.yudao.module.reward.vo.reward.RewardRedeemPageRespVO">
select
<include refid="columns"/>
from ecw_reward_redeem err
left join ecw_reward er on err.reward_id = er.id
left join member_user mu on mu.id = err.member_id
left join ecw_node en on er.node_id = en.id
left join system_user suc on suc.id = er.creator
left join system_user suu on suu.id = er.updater
left join ecw_currency cc on err.currency = cc.id
left join ecw_express ee on err.courier_company = ee.id
where err.id = #{id}
</select>
<select id="exportList" resultType="cn.iocoder.yudao.module.reward.vo.reward.RewardRedeemPageRespVO">
select
<include refid="columns"/>
from ecw_reward_redeem err
left join ecw_reward er on err.reward_id = er.id
left join member_user mu on mu.id = err.member_id
left join ecw_node en on er.node_id = en.id
left join system_user suc on suc.id = er.creator
left join system_user suu on suu.id = er.updater
left join ecw_currency cc on err.currency = cc.id
left join ecw_express ee on err.courier_company = ee.id
where 1=1
<include refid="pageCondition"/>
order by er.create_time desc
</select>
<sql id="columns">
err.id ,
err.member_id as memberId,
err.reward_id as rewardId,
......@@ -26,6 +82,7 @@
err.redeemer,
err.redemption_time as redemptionTime,
err.courier_company as courierCompany,
ee.company_name as courierCompanyName,
err.express_no as expressNo,
err.express_date as expressDate,
err.express_sender as expressSender,
......@@ -36,6 +93,8 @@
err.creator as creator,
err.updater as updater,
err.deleted as deleted,
err.verify_user as verifyUser,
err.verify_time as verifyTime,
mu.nickname as memberName,
er.code as rewardCode,
er.title_zh as rewardTitleZh,
......@@ -46,29 +105,10 @@
er.points_require*err.reward_count as totalCount,
suc.username as creatorName,
suu.username as updaterName,
cc.title_zh as currencyTitleZh,
cc.title_en as currencyTitleEn,
(select username from system_user where id = er.updater) as updaterName
from ecw_reward_redeem err
left join ecw_reward er on err.reward_id = er.id
left join member_user mu on mu.id = err.member_id
left join ecw_node en on er.node_id = en.id
left join system_user suc on suc.id = er.creator
left join system_user suu on suu.id = er.updater
where 1=1
<include refid="pageCondition"/>
order by er.create_time desc
limit #{start}, #{size}
</select>
<select id="pageCount" resultType="java.lang.Integer">
select count(*)
from ecw_reward_redeem err
left join ecw_reward er on err.reward_id = er.id
left join member_user mu on mu.id = err.member_id
left join ecw_node en on er.node_id = en.id
left join system_user suc on suc.id = er.creator
left join system_user suu on suu.id = er.updater
where 1=1
<include refid="pageCondition"/>
</select>
</sql>
<sql id="pageCondition">
<if test="req.rewardTitle != null and req.rewardTitle !=''">
......
......@@ -174,6 +174,11 @@ public enum DownloadTypeEnum implements IntArrayValuable {
*/
REPORT_SALES_ANALYSIS(32),
/**
* 礼品兑换记录
*/
REWARD_REDEEM_RECORD(33),
// ....自己补充
;
......
......@@ -70,6 +70,9 @@ public class DictDataServiceImpl implements DictDataService {
* key2:字典标签 label
*/
private ImmutableTable<String, String, DictDataDO> labelDictDataCache;
private ImmutableTable<String, String, DictDataDO> labelEnDictDataCache;
/**
* 字典数据缓存,第二个 key 使用 value
*
......@@ -93,13 +96,16 @@ public class DictDataServiceImpl implements DictDataService {
// 构建缓存
ImmutableTable.Builder<String, String, DictDataDO> labelDictDataBuilder = ImmutableTable.builder();
ImmutableTable.Builder<String, String, DictDataDO> labelEnDictDataBuilder = ImmutableTable.builder();
ImmutableTable.Builder<String, String, DictDataDO> valueDictDataBuilder = ImmutableTable.builder();
dataList.forEach(dictData -> {
labelDictDataBuilder.put(dictData.getDictType(), dictData.getLabel(), dictData);
valueDictDataBuilder.put(dictData.getDictType(), dictData.getValue(), dictData);
labelEnDictDataBuilder.put(dictData.getDictType(), dictData.getLabelEn(), dictData);
});
labelDictDataCache = labelDictDataBuilder.build();
valueDictDataCache = valueDictDataBuilder.build();
labelEnDictDataCache = labelEnDictDataBuilder.build();
maxUpdateTime = CollectionUtils.getMaxValue(dataList, DictDataDO::getUpdateTime);
log.info("[initLocalCache][缓存字典数据,数量为:{}]", dataList.size());
}
......@@ -174,6 +180,15 @@ public class DictDataServiceImpl implements DictDataService {
return DictDataConvert.INSTANCE.convertList03(labelDictDataCache.row(type).values());
}
@Override
public DictDataRespDTO parseDictDataFromCacheWithMultiLang(String type, String multiLangLabel) {
DictDataDO dictDataDO = labelDictDataCache.get(type, multiLangLabel);
if (dictDataDO == null) {
dictDataDO = labelEnDictDataCache.get(type, multiLangLabel);
}
return DictDataConvert.INSTANCE.convert02(dictDataDO);
}
@Override
public Long createDictData(DictDataCreateReqVO reqVO) {
// 校验正确性
......
......@@ -362,6 +362,9 @@ public class DownloadLogServiceImpl extends AbstractService<DownloadLogMapper, D
//销售分析报表
REPORT_SALES_ANALYSIS_Event(downloadLog);
break;
case REWARD_REDEEM_RECORD:
rewardRedeemRecordExportPushEvent(downloadLog);
break;
default:
downloadLog.setResult("unknown type");
break;
......@@ -388,6 +391,20 @@ public class DownloadLogServiceImpl extends AbstractService<DownloadLogMapper, D
}
}
private void rewardRedeemRecordExportPushEvent(DownloadLogDO downloadLog) {
RewardRedeemRecordExportEvent event = new RewardRedeemRecordExportEvent();
event.setUserId(downloadLog.getUserId());
event.setUserType(downloadLog.getUserType());
event.setLang(downloadLog.getLang());
event.setRequestParams(downloadLog.getRequestParams());
applicationContext.publishEvent(event);
downloadLog.setFileName(event.getFileName());
downloadLog.setPath(event.getPath());
downloadLog.setDownloadUrl(event.getUrl());
downloadLog.setResult(event.getResult());
downloadLog.setFileId(event.getFileId());
}
private void achievementDetailExcelExportPushEvent(DownloadLogDO downloadLog) {
AchievementDetailExcelExportPushEvent event = new AchievementDetailExcelExportPushEvent();
event.setUserId(downloadLog.getUserId());
......
......@@ -1010,4 +1010,14 @@ reward.status.change.error=The reward status change error
reward.status.not.allow.delay=Only enable status can delay
reward.status.not.allow.create=Only enabled or disabled reward status can be created
reward.time.not.allow=The reward time is not allow
get.lock.failed = The service is busy, please try again later
\ No newline at end of file
get.lock.failed = The service is busy, please try again later
reward.redeem.not.exist = reward redeem record does not exist
reward.redeem.status.error = reward redeem record that is redeeming can edit or verify
reward.redeem.verify.no.param = Fee/Currency/Express/Express NO/Delivery Date/Sender/Recipient Address must be filled in
reward.redeem.batch.verify.error = reward redeem record verify failed, please check record data : {}
reward.redeem.verify.back.status = record status must be redeemed
redeem.import.max.count = allow maximum number of imports is {}
dict.unknown.error = Not in dict {0}: {1}
express.not.exist = express not exist
currency.not.exist = currency not exist
date.format.error = date format error, for example : 2024-01-01 12:11:11
\ No newline at end of file
......@@ -1014,4 +1014,14 @@ reward.status.change.error=\u793C\u54C1\u72B6\u6001\u64CD\u4F5C\u4E0D\u7B26\u540
reward.status.not.allow.delay=\u53EA\u5141\u8BB8\u5EF6\u671F\u542F\u7528\u72B6\u6001\u793C\u54C1
reward.status.not.allow.create=\u521B\u5EFA\u7684\u793C\u54C1\u72B6\u6001\u53EA\u80FD\u662F\u542F\u7528\u6216\u672A\u542F\u7528
reward.time.not.allow=\u6D3B\u52A8\u65F6\u95F4\u4E0D\u5408\u6CD5
get.lock.failed = \u670D\u52A1\u7E41\u5FD9\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5
\ No newline at end of file
get.lock.failed = \u670D\u52A1\u7E41\u5FD9\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5
reward.redeem.not.exist = \u793C\u54C1\u5151\u6362\u8BB0\u5F55\u4E0D\u5B58\u5728
reward.redeem.status.error = \u53EA\u6709\u5151\u6362\u4E2D\u72B6\u6001\u7684\u8BB0\u5F55\u624D\u5141\u8BB8\u7F16\u8F91\u6216\u6838\u9500
reward.redeem.verify.no.param = \u8D27\u503C/\u5E01\u79CD/\u5FEB\u9012\u516C\u53F8/\u5FEB\u9012\u5355\u53F7/\u5FEB\u9012\u65F6\u95F4/\u5FEB\u9012\u53D1\u9001\u4EBA/\u6536\u4EF6\u4EBA\u5730\u5740\uFF0C\u5FC5\u987B\u586B\u5199
reward.redeem.batch.verify.error = \u793C\u54C1\u8BB0\u5F55\u6279\u91CF\u6838\u9500\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u6570\u636E\u662F\u5426\u6B63\u786E:{}
reward.redeem.verify.back.status = \u56DE\u9000\u8BB0\u5F55\u72B6\u6001\u5FC5\u987B\u4E3A\u5DF2\u5151\u6362
redeem.import.max.count = \u5141\u8BB8\u7684\u6700\u5927\u5BFC\u5165\u6761\u6570\u4E3A{}
dict.unknown.error = \u4E0D\u5728{0}\u5B57\u5178\u4E2D: {1}
express.not.exist = \u5FEB\u9012\u516C\u53F8\u4E0D\u5B58\u5728
currency.not.exist = \u5E01\u79CD\u4E0D\u5B58\u5728
date.format.error = \u65E5\u671F\u683C\u5F0F\u4E0D\u6B63\u786E, \u6B63\u786E\u683C\u5F0F\u53C2\u8003: 2024-01-01 12:11:11
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment