Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/yudao-cloud
# Conflicts: # yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/KeFuMessageController.java # yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/AppKeFuMessageController.java # yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuMessageServiceImpl.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/record/BrokerageRecordBaseVO.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/user/BrokerageUserBaseVO.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/user/BrokerageUserClearBrokerageUserReqVO.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/user/BrokerageUserUpdateBrokerageEnabledReqVO.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/user/BrokerageUserUpdateBrokerageUserReqVO.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/withdraw/BrokerageWithdrawBaseVO.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/withdraw/BrokerageWithdrawRejectReqVO.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryPickUpStoreController.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/pickup/DeliveryPickUpStoreBaseVO.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/pickup/DeliveryPickUpStoreCreateReqVO.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/pickup/DeliveryPickUpStoreUpdateReqVO.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImpl.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryPickUpStoreService.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryPickUpStoreServiceImpl.java # yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/PayTransferApi.java # yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/app/vo/PayAppBaseVO.java # yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java # yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientConfig.java # yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/order/PayOrderUnifiedReqDTO.java # yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/refund/PayRefundUnifiedReqDTO.java # yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/transfer/PayTransferUnifiedReqDTO.java # yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/NonePayClientConfig.javapull/158/MERGE
commit
2b8334018a
|
@ -51,7 +51,8 @@ public class ProductBrowseHistoryController {
|
||||||
convertSet(pageResult.getList(), ProductBrowseHistoryDO::getSpuId));
|
convertSet(pageResult.getList(), ProductBrowseHistoryDO::getSpuId));
|
||||||
return success(BeanUtils.toBean(pageResult, ProductBrowseHistoryRespVO.class,
|
return success(BeanUtils.toBean(pageResult, ProductBrowseHistoryRespVO.class,
|
||||||
vo -> Optional.ofNullable(spuMap.get(vo.getSpuId()))
|
vo -> Optional.ofNullable(spuMap.get(vo.getSpuId()))
|
||||||
.ifPresent(spu -> vo.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl()).setPrice(spu.getPrice()))));
|
.ifPresent(spu -> vo.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl()).setPrice(spu.getPrice())
|
||||||
|
.setSalesCount(spu.getSalesCount()).setStock(spu.getStock()))));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,12 +1,9 @@
|
||||||
package cn.iocoder.yudao.module.product.controller.admin.history.vo;
|
package cn.iocoder.yudao.module.product.controller.admin.history.vo;
|
||||||
|
|
||||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||||
import com.alibaba.excel.annotation.ExcelProperty;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
|
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
|
||||||
|
|
||||||
@Schema(description = "管理后台 - 商品浏览记录 Response VO")
|
@Schema(description = "管理后台 - 商品浏览记录 Response VO")
|
||||||
|
@ -31,4 +28,10 @@ public class ProductBrowseHistoryRespVO {
|
||||||
@Schema(description = "商品单价", example = "100")
|
@Schema(description = "商品单价", example = "100")
|
||||||
private Integer price;
|
private Integer price;
|
||||||
|
|
||||||
|
@Schema(description = "商品销量", example = "100")
|
||||||
|
private Integer salesCount;
|
||||||
|
|
||||||
|
@Schema(description = "库存", example = "100")
|
||||||
|
private Integer stock;
|
||||||
|
|
||||||
}
|
}
|
|
@ -67,7 +67,8 @@ public class AppProductBrowseHistoryController {
|
||||||
Map<Long, ProductSpuDO> spuMap = convertMap(productSpuService.getSpuList(spuIds), ProductSpuDO::getId);
|
Map<Long, ProductSpuDO> spuMap = convertMap(productSpuService.getSpuList(spuIds), ProductSpuDO::getId);
|
||||||
return success(BeanUtils.toBean(pageResult, AppProductBrowseHistoryRespVO.class,
|
return success(BeanUtils.toBean(pageResult, AppProductBrowseHistoryRespVO.class,
|
||||||
vo -> Optional.ofNullable(spuMap.get(vo.getSpuId()))
|
vo -> Optional.ofNullable(spuMap.get(vo.getSpuId()))
|
||||||
.ifPresent(spu -> vo.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl()).setPrice(spu.getPrice()))));
|
.ifPresent(spu -> vo.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl()).setPrice(spu.getPrice())
|
||||||
|
.setSalesCount(spu.getSalesCount()).setStock(spu.getStock()))));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,19 @@ public class AppProductBrowseHistoryRespVO {
|
||||||
|
|
||||||
// ========== 商品相关字段 ==========
|
// ========== 商品相关字段 ==========
|
||||||
|
|
||||||
@Schema(description = "商品 SPU 名称", example = "赵六")
|
@Schema(description = "商品 SPU 名称", requiredMode = REQUIRED, example = "赵六")
|
||||||
private String spuName;
|
private String spuName;
|
||||||
|
|
||||||
@Schema(description = "商品封面图", example = "https://domain/pic.png")
|
@Schema(description = "商品封面图", requiredMode = REQUIRED, example = "https://www.iocoder.cn/pic.png")
|
||||||
private String picUrl;
|
private String picUrl;
|
||||||
|
|
||||||
@Schema(description = "商品单价", example = "100")
|
@Schema(description = "商品单价", requiredMode = REQUIRED, example = "50")
|
||||||
private Integer price;
|
private Integer price;
|
||||||
|
|
||||||
|
@Schema(description = "商品销量", requiredMode = REQUIRED, example = "60")
|
||||||
|
private Integer salesCount;
|
||||||
|
|
||||||
|
@Schema(description = "库存", requiredMode = REQUIRED, example = "80")
|
||||||
|
private Integer stock;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||||
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.conversation.KeFuConversationRespVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.conversation.KeFuConversationRespVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.conversation.KeFuConversationUpdatePinnedReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.conversation.KeFuConversationUpdatePinnedReqVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuConversationDO;
|
||||||
import cn.iocoder.yudao.module.promotion.service.kefu.KeFuConversationService;
|
import cn.iocoder.yudao.module.promotion.service.kefu.KeFuConversationService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
@ -34,6 +35,25 @@ public class KeFuConversationController {
|
||||||
@Resource
|
@Resource
|
||||||
private MemberUserApi memberUserApi;
|
private MemberUserApi memberUserApi;
|
||||||
|
|
||||||
|
@GetMapping("/get")
|
||||||
|
@Operation(summary = "获得客服会话")
|
||||||
|
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||||
|
@PreAuthorize("@ss.hasPermission('promotion:kefu-conversation:query')")
|
||||||
|
public CommonResult<KeFuConversationRespVO> getConversation(@RequestParam("id") Long id) {
|
||||||
|
KeFuConversationDO conversation = conversationService.getConversation(id);
|
||||||
|
if (conversation == null) {
|
||||||
|
return success(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拼接数据
|
||||||
|
KeFuConversationRespVO result = BeanUtils.toBean(conversation, KeFuConversationRespVO.class);
|
||||||
|
MemberUserRespDTO memberUser = memberUserApi.getUser(conversation.getUserId()).getCheckedData();
|
||||||
|
if (memberUser != null) {
|
||||||
|
result.setUserAvatar(memberUser.getAvatar()).setUserNickname(memberUser.getNickname());
|
||||||
|
}
|
||||||
|
return success(result);
|
||||||
|
}
|
||||||
|
|
||||||
@PutMapping("/update-conversation-pinned")
|
@PutMapping("/update-conversation-pinned")
|
||||||
@Operation(summary = "置顶/取消置顶客服会话")
|
@Operation(summary = "置顶/取消置顶客服会话")
|
||||||
@PreAuthorize("@ss.hasPermission('promotion:kefu-conversation:update')")
|
@PreAuthorize("@ss.hasPermission('promotion:kefu-conversation:update')")
|
||||||
|
|
|
@ -2,9 +2,8 @@ package cn.iocoder.yudao.module.promotion.controller.admin.kefu;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|
||||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessagePageReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageListReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageRespVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageRespVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageSendReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageSendReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO;
|
||||||
|
@ -14,12 +13,13 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import java.util.List;
|
||||||
import javax.validation.Valid;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
@ -56,19 +56,18 @@ public class KeFuMessageController {
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/page")
|
@GetMapping("/list")
|
||||||
@Operation(summary = "获得客服消息分页")
|
@Operation(summary = "获得客服消息列表")
|
||||||
@PreAuthorize("@ss.hasPermission('promotion:kefu-message:query')")
|
@PreAuthorize("@ss.hasPermission('promotion:kefu-message:query')")
|
||||||
public CommonResult<PageResult<KeFuMessageRespVO>> getKeFuMessagePage(@Valid KeFuMessagePageReqVO pageReqVO) {
|
public CommonResult<List<KeFuMessageRespVO>> getKeFuMessageList(@Valid KeFuMessageListReqVO pageReqVO) {
|
||||||
// 获得数据
|
// 获得数据
|
||||||
PageResult<KeFuMessageDO> pageResult = messageService.getKeFuMessagePage(pageReqVO);
|
List<KeFuMessageDO> list = messageService.getKeFuMessageList(pageReqVO);
|
||||||
|
|
||||||
// 拼接数据
|
// 拼接数据
|
||||||
PageResult<KeFuMessageRespVO> result = BeanUtils.toBean(pageResult, KeFuMessageRespVO.class);
|
List<KeFuMessageRespVO> result = BeanUtils.toBean(list, KeFuMessageRespVO.class);
|
||||||
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSet(filterList(result.getList(),
|
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSet(filterList(result,
|
||||||
item -> UserTypeEnum.ADMIN.getValue().equals(item.getSenderType())), KeFuMessageRespVO::getSenderId));
|
item -> UserTypeEnum.ADMIN.getValue().equals(item.getSenderType())), KeFuMessageRespVO::getSenderId));
|
||||||
result.getList().forEach(item-> findAndThen(userMap, item.getSenderId(),
|
result.forEach(item -> findAndThen(userMap, item.getSenderId(), user -> item.setSenderAvatar(user.getAvatar())));
|
||||||
user -> item.setSenderAvatar(user.getAvatar())));
|
|
||||||
return success(result);
|
return success(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.Max;
|
||||||
|
import jakarta.validation.constraints.Min;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 客服消息列表 Request VO")
|
||||||
|
@Data
|
||||||
|
public class KeFuMessageListReqVO {
|
||||||
|
|
||||||
|
private static final Integer LIMIT = 10;
|
||||||
|
|
||||||
|
@Schema(description = "会话编号", example = "12580")
|
||||||
|
@NotNull(message = "会话编号不能为空")
|
||||||
|
private Long conversationId;
|
||||||
|
|
||||||
|
@Schema(description = "发送时间", example = "2024-03-27 12:00:00")
|
||||||
|
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
@Schema(description = "每次查询条数,最大值为 100", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||||
|
@NotNull(message = "每次查询条数不能为空")
|
||||||
|
@Min(value = 1, message = "每次查询条数最小值为 1")
|
||||||
|
@Max(value = 100, message = "每次查询最大值为 100")
|
||||||
|
private Integer limit = LIMIT;
|
||||||
|
|
||||||
|
}
|
|
@ -1,16 +0,0 @@
|
||||||
package cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
@Schema(description = "管理后台 - 客服消息分页 Request VO")
|
|
||||||
@Data
|
|
||||||
@ToString(callSuper = true)
|
|
||||||
public class KeFuMessagePageReqVO extends PageParam {
|
|
||||||
|
|
||||||
@Schema(description = "会话编号", example = "12580")
|
|
||||||
private Long conversationId;
|
|
||||||
|
|
||||||
}
|
|
|
@ -5,11 +5,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
|
||||||
|
|
||||||
@Schema(description = "管理后台 - 积分商城活动分页 Request VO")
|
@Schema(description = "管理后台 - 积分商城活动分页 Request VO")
|
||||||
@Data
|
@Data
|
||||||
|
@ -17,20 +12,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
public class PointActivityPageReqVO extends PageParam {
|
public class PointActivityPageReqVO extends PageParam {
|
||||||
|
|
||||||
@Schema(description = "积分商城活动商品", example = "19509")
|
|
||||||
private Long spuId;
|
|
||||||
|
|
||||||
@Schema(description = "活动状态", example = "2")
|
@Schema(description = "活动状态", example = "2")
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
@Schema(description = "备注", example = "你说的对")
|
|
||||||
private String remark;
|
|
||||||
|
|
||||||
@Schema(description = "排序")
|
|
||||||
private Integer sort;
|
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
|
||||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
|
||||||
private LocalDateTime[] createTime;
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -2,23 +2,29 @@ package cn.iocoder.yudao.module.promotion.controller.app.kefu;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|
||||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageRespVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageRespVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessagePageReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessagePageReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessageSendReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessageSendReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO;
|
||||||
import cn.iocoder.yudao.module.promotion.service.kefu.KeFuMessageService;
|
import cn.iocoder.yudao.module.promotion.service.kefu.KeFuMessageService;
|
||||||
|
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||||
|
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import java.util.List;
|
||||||
import javax.validation.Valid;
|
import java.util.Map;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
|
||||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||||
|
|
||||||
@Tag(name = "用户 APP - 客服消息")
|
@Tag(name = "用户 APP - 客服消息")
|
||||||
|
@ -30,6 +36,9 @@ public class AppKeFuMessageController {
|
||||||
@Resource
|
@Resource
|
||||||
private KeFuMessageService kefuMessageService;
|
private KeFuMessageService kefuMessageService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AdminUserApi adminUserApi;
|
||||||
|
|
||||||
@PostMapping("/send")
|
@PostMapping("/send")
|
||||||
@Operation(summary = "发送客服消息")
|
@Operation(summary = "发送客服消息")
|
||||||
public CommonResult<Long> sendKefuMessage(@Valid @RequestBody AppKeFuMessageSendReqVO sendReqVO) {
|
public CommonResult<Long> sendKefuMessage(@Valid @RequestBody AppKeFuMessageSendReqVO sendReqVO) {
|
||||||
|
@ -45,11 +54,17 @@ public class AppKeFuMessageController {
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/page")
|
@GetMapping("/list")
|
||||||
@Operation(summary = "获得客服消息分页")
|
@Operation(summary = "获得客服消息列表")
|
||||||
public CommonResult<PageResult<KeFuMessageRespVO>> getKefuMessagePage(@Valid AppKeFuMessagePageReqVO pageReqVO) {
|
public CommonResult<List<KeFuMessageRespVO>> getKefuMessageList(@Valid AppKeFuMessagePageReqVO pageReqVO) {
|
||||||
PageResult<KeFuMessageDO> pageResult = kefuMessageService.getKeFuMessagePage(pageReqVO, getLoginUserId());
|
List<KeFuMessageDO> list = kefuMessageService.getKeFuMessageList(pageReqVO, getLoginUserId());
|
||||||
return success(BeanUtils.toBean(pageResult, KeFuMessageRespVO.class));
|
|
||||||
|
// 拼接数据
|
||||||
|
List<KeFuMessageRespVO> result = BeanUtils.toBean(list, KeFuMessageRespVO.class);
|
||||||
|
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSet(filterList(result,
|
||||||
|
item -> UserTypeEnum.ADMIN.getValue().equals(item.getSenderType())), KeFuMessageRespVO::getSenderId));
|
||||||
|
result.forEach(item -> findAndThen(userMap, item.getSenderId(), user -> item.setSenderAvatar(user.getAvatar())));
|
||||||
|
return success(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,16 +1,33 @@
|
||||||
package cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message;
|
package cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.Max;
|
||||||
|
import jakarta.validation.constraints.Min;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.ToString;
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
@Schema(description = "用户 App - 客服消息分页 Request VO")
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||||
|
|
||||||
|
@Schema(description = "用户 App - 客服消息 Request VO")
|
||||||
@Data
|
@Data
|
||||||
@ToString(callSuper = true)
|
public class AppKeFuMessagePageReqVO {
|
||||||
public class AppKeFuMessagePageReqVO extends PageParam {
|
|
||||||
|
private static final Integer LIMIT = 10;
|
||||||
|
|
||||||
@Schema(description = "会话编号", example = "12580")
|
@Schema(description = "会话编号", example = "12580")
|
||||||
private Long conversationId;
|
private Long conversationId;
|
||||||
|
|
||||||
|
@Schema(description = "发送时间", example = "2024-03-27 12:00:00")
|
||||||
|
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
@Schema(description = "每次查询条数,最大值为 100", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||||
|
@NotNull(message = "每次查询条数不能为空")
|
||||||
|
@Min(value = 1, message = "每次查询条数最小值为 1")
|
||||||
|
@Max(value = 100, message = "每次查询最大值为 100")
|
||||||
|
private Integer limit = LIMIT;
|
||||||
|
|
||||||
}
|
}
|
|
@ -4,8 +4,6 @@ import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
@Schema(description = "用户 App - 积分商城活动 Response VO")
|
@Schema(description = "用户 App - 积分商城活动 Response VO")
|
||||||
@Data
|
@Data
|
||||||
public class AppPointActivityRespVO {
|
public class AppPointActivityRespVO {
|
||||||
|
@ -30,20 +28,6 @@ public class AppPointActivityRespVO {
|
||||||
@ExcelProperty("积分商城活动总库存")
|
@ExcelProperty("积分商城活动总库存")
|
||||||
private Integer totalStock;
|
private Integer totalStock;
|
||||||
|
|
||||||
// TODO @puhui999:只返回必要的字段,例如说 remark、sort、createTime 应该是不需要的呢。也可以看看别的也不需要哈。
|
|
||||||
|
|
||||||
@Schema(description = "备注", example = "你说的对")
|
|
||||||
@ExcelProperty("备注")
|
|
||||||
private String remark;
|
|
||||||
|
|
||||||
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
@ExcelProperty("排序")
|
|
||||||
private Integer sort;
|
|
||||||
|
|
||||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
@ExcelProperty("创建时间")
|
|
||||||
private LocalDateTime createTime;
|
|
||||||
|
|
||||||
// ========== 商品字段 ==========
|
// ========== 商品字段 ==========
|
||||||
|
|
||||||
@Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, // 从 SPU 的 name 读取
|
@Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, // 从 SPU 的 name 读取
|
||||||
|
|
|
@ -217,8 +217,7 @@ public interface CombinationActivityConvert {
|
||||||
List<CombinationRecordDO> createRecords = new ArrayList<>(count);
|
List<CombinationRecordDO> createRecords = new ArrayList<>(count);
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
// 基础信息和团长保持一致
|
// 基础信息和团长保持一致
|
||||||
CombinationRecordDO newRecord = BeanUtils.toBean(headRecord, CombinationRecordDO.class)
|
CombinationRecordDO newRecord = convert5(headRecord).setHeadId(headRecord.getId());
|
||||||
.setId(null).setHeadId(headRecord.getHeadId());
|
|
||||||
// 虚拟信息
|
// 虚拟信息
|
||||||
newRecord.setCount(0) // 会单独更新下,在后续的 Service 逻辑里
|
newRecord.setCount(0) // 会单独更新下,在后续的 Service 逻辑里
|
||||||
.setUserId(0L).setNickname("").setAvatar("").setOrderId(0L);
|
.setUserId(0L).setNickname("").setAvatar("").setOrderId(0L);
|
||||||
|
@ -226,5 +225,7 @@ public interface CombinationActivityConvert {
|
||||||
}
|
}
|
||||||
return createRecords;
|
return createRecords;
|
||||||
}
|
}
|
||||||
|
@Mapping(target = "id", ignore = true)
|
||||||
|
CombinationRecordDO convert5(CombinationRecordDO headRecord);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
package cn.iocoder.yudao.module.promotion.dal.mysql.kefu;
|
package cn.iocoder.yudao.module.promotion.dal.mysql.kefu;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessagePageReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageListReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessagePageReqVO;
|
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
|
@ -21,10 +19,20 @@ import java.util.List;
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface KeFuMessageMapper extends BaseMapperX<KeFuMessageDO> {
|
public interface KeFuMessageMapper extends BaseMapperX<KeFuMessageDO> {
|
||||||
|
|
||||||
default PageResult<KeFuMessageDO> selectPage(KeFuMessagePageReqVO reqVO) {
|
/**
|
||||||
return selectPage(reqVO, new LambdaQueryWrapperX<KeFuMessageDO>()
|
* 获得消息列表
|
||||||
.eqIfPresent(KeFuMessageDO::getConversationId, reqVO.getConversationId())
|
* 1. 第一次查询时,不带时间,默认查询最新的十条消息
|
||||||
.orderByDesc(KeFuMessageDO::getCreateTime));
|
* 2. 第二次查询时,带时间,查询历史消息
|
||||||
|
*
|
||||||
|
* @param reqVO 列表请求
|
||||||
|
* @return 消息列表
|
||||||
|
*/
|
||||||
|
default List<KeFuMessageDO> selectList(KeFuMessageListReqVO reqVO) {
|
||||||
|
return selectList(new QueryWrapperX<KeFuMessageDO>()
|
||||||
|
.eqIfPresent("conversation_id", reqVO.getConversationId())
|
||||||
|
.ltIfPresent("create_time", reqVO.getCreateTime())
|
||||||
|
.orderByDesc("create_time")
|
||||||
|
.limitN(reqVO.getLimit()));
|
||||||
}
|
}
|
||||||
|
|
||||||
default List<KeFuMessageDO> selectListByConversationIdAndUserTypeAndReadStatus(Long conversationId, Integer userType,
|
default List<KeFuMessageDO> selectListByConversationIdAndUserTypeAndReadStatus(Long conversationId, Integer userType,
|
||||||
|
@ -40,10 +48,4 @@ public interface KeFuMessageMapper extends BaseMapperX<KeFuMessageDO> {
|
||||||
.in(KeFuMessageDO::getId, ids));
|
.in(KeFuMessageDO::getId, ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
default PageResult<KeFuMessageDO> selectPage(AppKeFuMessagePageReqVO pageReqVO) {
|
|
||||||
return selectPage(pageReqVO, new LambdaQueryWrapperX<KeFuMessageDO>()
|
|
||||||
.eqIfPresent(KeFuMessageDO::getConversationId, pageReqVO.getConversationId())
|
|
||||||
.orderByDesc(KeFuMessageDO::getCreateTime));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -19,12 +19,8 @@ public interface PointActivityMapper extends BaseMapperX<PointActivityDO> {
|
||||||
|
|
||||||
default PageResult<PointActivityDO> selectPage(PointActivityPageReqVO reqVO) {
|
default PageResult<PointActivityDO> selectPage(PointActivityPageReqVO reqVO) {
|
||||||
return selectPage(reqVO, new LambdaQueryWrapperX<PointActivityDO>()
|
return selectPage(reqVO, new LambdaQueryWrapperX<PointActivityDO>()
|
||||||
.eqIfPresent(PointActivityDO::getSpuId, reqVO.getSpuId())
|
|
||||||
.eqIfPresent(PointActivityDO::getStatus, reqVO.getStatus())
|
.eqIfPresent(PointActivityDO::getStatus, reqVO.getStatus())
|
||||||
.eqIfPresent(PointActivityDO::getRemark, reqVO.getRemark())
|
.orderByDesc(PointActivityDO::getSort));
|
||||||
.eqIfPresent(PointActivityDO::getSort, reqVO.getSort())
|
|
||||||
.betweenIfPresent(PointActivityDO::getCreateTime, reqVO.getCreateTime())
|
|
||||||
.orderByDesc(PointActivityDO::getId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -375,7 +375,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
|
||||||
CombinationRecordDO updateRecord = new CombinationRecordDO().setId(item.getId())
|
CombinationRecordDO updateRecord = new CombinationRecordDO().setId(item.getId())
|
||||||
.setStatus(status.getStatus()).setEndTime(now);
|
.setStatus(status.getStatus()).setEndTime(now);
|
||||||
if (CombinationRecordStatusEnum.isSuccess(status.getStatus())) { // 虚拟成团完事更改状态成功后还需要把参与人数修改为成团需要人数
|
if (CombinationRecordStatusEnum.isSuccess(status.getStatus())) { // 虚拟成团完事更改状态成功后还需要把参与人数修改为成团需要人数
|
||||||
updateRecord.setUserCount(updateRecord.getUserSize());
|
updateRecord.setUserCount(records.size());
|
||||||
}
|
}
|
||||||
updateRecords.add(updateRecord);
|
updateRecords.add(updateRecord);
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,6 +13,14 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public interface KeFuConversationService {
|
public interface KeFuConversationService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得客服会话
|
||||||
|
*
|
||||||
|
* @param id 编号
|
||||||
|
* @return 客服会话
|
||||||
|
*/
|
||||||
|
KeFuConversationDO getConversation(Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 【管理员】删除客服会话
|
* 【管理员】删除客服会话
|
||||||
*
|
*
|
||||||
|
|
|
@ -30,6 +30,11 @@ public class KeFuConversationServiceImpl implements KeFuConversationService {
|
||||||
@Resource
|
@Resource
|
||||||
private KeFuConversationMapper conversationMapper;
|
private KeFuConversationMapper conversationMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeFuConversationDO getConversation(Long id) {
|
||||||
|
return conversationMapper.selectById(id);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteKefuConversation(Long id) {
|
public void deleteKefuConversation(Long id) {
|
||||||
// 校验存在
|
// 校验存在
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.promotion.service.kefu;
|
package cn.iocoder.yudao.module.promotion.service.kefu;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageListReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessagePageReqVO;
|
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageSendReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageSendReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessagePageReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessagePageReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessageSendReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessageSendReqVO;
|
||||||
|
@ -9,6 +8,8 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 客服消息 Service 接口
|
* 客服消息 Service 接口
|
||||||
*
|
*
|
||||||
|
@ -47,7 +48,7 @@ public interface KeFuMessageService {
|
||||||
* @param pageReqVO 分页查询
|
* @param pageReqVO 分页查询
|
||||||
* @return 客服消息分页
|
* @return 客服消息分页
|
||||||
*/
|
*/
|
||||||
PageResult<KeFuMessageDO> getKeFuMessagePage(KeFuMessagePageReqVO pageReqVO);
|
List<KeFuMessageDO> getKeFuMessageList(KeFuMessageListReqVO pageReqVO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 【会员】获得客服消息分页
|
* 【会员】获得客服消息分页
|
||||||
|
@ -56,6 +57,6 @@ public interface KeFuMessageService {
|
||||||
* @param userId 用户编号
|
* @param userId 用户编号
|
||||||
* @return 客服消息分页
|
* @return 客服消息分页
|
||||||
*/
|
*/
|
||||||
PageResult<KeFuMessageDO> getKeFuMessagePage(AppKeFuMessagePageReqVO pageReqVO, Long userId);
|
List<KeFuMessageDO> getKeFuMessageList(AppKeFuMessagePageReqVO pageReqVO, Long userId);
|
||||||
|
|
||||||
}
|
}
|
|
@ -2,14 +2,12 @@ package cn.iocoder.yudao.module.promotion.service.kefu;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.util.ObjUtil;
|
import cn.hutool.core.util.ObjUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import cn.hutool.extra.spring.SpringUtil;
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|
||||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
|
import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
|
||||||
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessagePageReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageListReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageSendReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageSendReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessagePageReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessagePageReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessageSendReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessageSendReqVO;
|
||||||
|
@ -17,12 +15,13 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuConversationDO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.mysql.kefu.KeFuMessageMapper;
|
import cn.iocoder.yudao.module.promotion.dal.mysql.kefu.KeFuMessageMapper;
|
||||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
@ -113,9 +112,9 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
|
||||||
// 2.3 发送消息通知会员,管理员已读 -> 会员更新发送的消息状态
|
// 2.3 发送消息通知会员,管理员已读 -> 会员更新发送的消息状态
|
||||||
KeFuMessageDO keFuMessage = getFirst(filterList(messageList, message -> UserTypeEnum.MEMBER.getValue().equals(message.getSenderType())));
|
KeFuMessageDO keFuMessage = getFirst(filterList(messageList, message -> UserTypeEnum.MEMBER.getValue().equals(message.getSenderType())));
|
||||||
assert keFuMessage != null; // 断言避免警告
|
assert keFuMessage != null; // 断言避免警告
|
||||||
getSelf().sendAsyncMessageToMember(keFuMessage.getSenderId(), KEFU_MESSAGE_ADMIN_READ, StrUtil.EMPTY);
|
getSelf().sendAsyncMessageToMember(keFuMessage.getSenderId(), KEFU_MESSAGE_ADMIN_READ, conversation.getId());
|
||||||
// 2.4 通知所有管理员消息已读
|
// 2.4 通知所有管理员消息已读
|
||||||
getSelf().sendAsyncMessageToAdmin(KEFU_MESSAGE_ADMIN_READ, StrUtil.EMPTY);
|
getSelf().sendAsyncMessageToAdmin(KEFU_MESSAGE_ADMIN_READ, conversation.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateReceiverExist(Long receiverId, Integer receiverType) {
|
private void validateReceiverExist(Long receiverId, Integer receiverType) {
|
||||||
|
@ -138,20 +137,20 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageResult<KeFuMessageDO> getKeFuMessagePage(KeFuMessagePageReqVO pageReqVO) {
|
public List<KeFuMessageDO> getKeFuMessageList(KeFuMessageListReqVO pageReqVO) {
|
||||||
return keFuMessageMapper.selectPage(pageReqVO);
|
return keFuMessageMapper.selectList(pageReqVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageResult<KeFuMessageDO> getKeFuMessagePage(AppKeFuMessagePageReqVO pageReqVO, Long userId) {
|
public List<KeFuMessageDO> getKeFuMessageList(AppKeFuMessagePageReqVO pageReqVO, Long userId) {
|
||||||
// 1. 获得客服会话
|
// 1. 获得客服会话
|
||||||
KeFuConversationDO conversation = conversationService.getConversationByUserId(userId);
|
KeFuConversationDO conversation = conversationService.getConversationByUserId(userId);
|
||||||
if (conversation == null) {
|
if (conversation == null) {
|
||||||
return PageResult.empty();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
// 2. 设置会话编号
|
// 2. 设置会话编号
|
||||||
pageReqVO.setConversationId(conversation.getId());
|
pageReqVO.setConversationId(conversation.getId());
|
||||||
return keFuMessageMapper.selectPage(pageReqVO);
|
return keFuMessageMapper.selectList(BeanUtils.toBean(pageReqVO, KeFuMessageListReqVO.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
private KeFuMessageServiceImpl getSelf() {
|
private KeFuMessageServiceImpl getSelf() {
|
||||||
|
|
|
@ -36,6 +36,7 @@ public interface ErrorCodeConstants {
|
||||||
ErrorCode ORDER_UPDATE_ADDRESS_FAIL_STATUS_NOT_DELIVERED = new ErrorCode(1_011_000_031, "交易订单修改收货地址失败,原因:订单不是【待发货】状态");
|
ErrorCode ORDER_UPDATE_ADDRESS_FAIL_STATUS_NOT_DELIVERED = new ErrorCode(1_011_000_031, "交易订单修改收货地址失败,原因:订单不是【待发货】状态");
|
||||||
ErrorCode ORDER_CREATE_FAIL_EXIST_UNPAID = new ErrorCode(1_011_000_032, "交易订单创建失败,原因:存在未付款订单");
|
ErrorCode ORDER_CREATE_FAIL_EXIST_UNPAID = new ErrorCode(1_011_000_032, "交易订单创建失败,原因:存在未付款订单");
|
||||||
ErrorCode ORDER_CANCEL_PAID_FAIL = new ErrorCode(1_011_000_033, "交易订单取消支付失败,原因:订单不是【{}】状态");
|
ErrorCode ORDER_CANCEL_PAID_FAIL = new ErrorCode(1_011_000_033, "交易订单取消支付失败,原因:订单不是【{}】状态");
|
||||||
|
ErrorCode ORDER_PICK_UP_FAIL_NOT_VERIFY_USER = new ErrorCode(1_011_000_034, "交易订单自提失败,原因:你没有核销该门店订单的权限");
|
||||||
|
|
||||||
// ========== After Sale 模块 1-011-000-100 ==========
|
// ========== After Sale 模块 1-011-000-100 ==========
|
||||||
ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1_011_000_100, "售后单不存在");
|
ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1_011_000_100, "售后单不存在");
|
||||||
|
@ -80,6 +81,7 @@ public interface ErrorCodeConstants {
|
||||||
|
|
||||||
// ========== 物流 PICK_UP 模块 1-011-006-000 ==========
|
// ========== 物流 PICK_UP 模块 1-011-006-000 ==========
|
||||||
ErrorCode PICK_UP_STORE_NOT_EXISTS = new ErrorCode(1_011_006_000, "自提门店不存在");
|
ErrorCode PICK_UP_STORE_NOT_EXISTS = new ErrorCode(1_011_006_000, "自提门店不存在");
|
||||||
|
ErrorCode PICK_UP_STORE_STAFF_NOT_EXISTS = new ErrorCode(1_011_006_000, "自提门店店员不存在");
|
||||||
|
|
||||||
// ========== 分销用户 模块 1-011-007-000 ==========
|
// ========== 分销用户 模块 1-011-007-000 ==========
|
||||||
ErrorCode BROKERAGE_USER_NOT_EXISTS = new ErrorCode(1_011_007_000, "分销用户不存在");
|
ErrorCode BROKERAGE_USER_NOT_EXISTS = new ErrorCode(1_011_007_000, "分销用户不存在");
|
||||||
|
|
|
@ -11,9 +11,6 @@ public interface MessageTemplateConstants {
|
||||||
|
|
||||||
String SMS_ORDER_DELIVERY = "order_delivery"; // 短信模版编号
|
String SMS_ORDER_DELIVERY = "order_delivery"; // 短信模版编号
|
||||||
|
|
||||||
String SMS_BROKERAGE_WITHDRAW_AUDIT_APPROVE = "brokerage_withdraw_audit_approve"; // 佣金提现(审核通过)
|
|
||||||
String SMS_BROKERAGE_WITHDRAW_AUDIT_REJECT = "brokerage_withdraw_audit_reject"; // 佣金提现(审核不通过)
|
|
||||||
|
|
||||||
// ======================= 小程序订阅消息模版 =======================
|
// ======================= 小程序订阅消息模版 =======================
|
||||||
|
|
||||||
String WXA_ORDER_DELIVERY = "订单发货通知";
|
String WXA_ORDER_DELIVERY = "订单发货通知";
|
||||||
|
|
|
@ -17,8 +17,9 @@ public enum BrokerageWithdrawTypeEnum implements IntArrayValuable {
|
||||||
|
|
||||||
WALLET(1, "钱包"),
|
WALLET(1, "钱包"),
|
||||||
BANK(2, "银行卡"),
|
BANK(2, "银行卡"),
|
||||||
WECHAT(3, "微信"),
|
WECHAT(3, "微信"), // 手动打款
|
||||||
ALIPAY(4, "支付宝"),
|
ALIPAY(4, "支付宝"),
|
||||||
|
WECHAT_API(5, "微信零钱"), // 自动打款,通过微信转账 API
|
||||||
;
|
;
|
||||||
|
|
||||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageWithdrawTypeEnum::getType).toArray();
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageWithdrawTypeEnum::getType).toArray();
|
||||||
|
@ -37,4 +38,14 @@ public enum BrokerageWithdrawTypeEnum implements IntArrayValuable {
|
||||||
return ARRAYS;
|
return ARRAYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否通过支付平台的 API 打款
|
||||||
|
*
|
||||||
|
* @param type 类型
|
||||||
|
* @return 是否
|
||||||
|
*/
|
||||||
|
public static boolean isApi(Integer type) {
|
||||||
|
return WECHAT_API.getType().equals(type);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
/**
|
||||||
|
* 占位符,可忽略
|
||||||
|
*/
|
||||||
|
package cn.iocoder.yudao.module.trade.controller.admin.base.system;
|
|
@ -0,0 +1,19 @@
|
||||||
|
package cn.iocoder.yudao.module.trade.controller.admin.base.system.user;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Schema(description = "用户精简信息 VO")
|
||||||
|
@Data
|
||||||
|
public class UserSimpleBaseVO {
|
||||||
|
|
||||||
|
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
|
||||||
|
private String nickname;
|
||||||
|
|
||||||
|
@Schema(description = "用户头像", example = "https://www.iocoder.cn/1.png")
|
||||||
|
private String avatar;
|
||||||
|
|
||||||
|
}
|
|
@ -44,7 +44,7 @@ public class BrokerageRecordController {
|
||||||
@Operation(summary = "获得佣金记录")
|
@Operation(summary = "获得佣金记录")
|
||||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||||
@PreAuthorize("@ss.hasPermission('trade:brokerage-record:query')")
|
@PreAuthorize("@ss.hasPermission('trade:brokerage-record:query')")
|
||||||
public CommonResult<BrokerageRecordRespVO> getBrokerageRecord(@RequestParam("id") Integer id) {
|
public CommonResult<BrokerageRecordRespVO> getBrokerageRecord(@RequestParam("id") Long id) {
|
||||||
BrokerageRecordDO brokerageRecord = brokerageRecordService.getBrokerageRecord(id);
|
BrokerageRecordDO brokerageRecord = brokerageRecordService.getBrokerageRecord(id);
|
||||||
return success(BrokerageRecordConvert.INSTANCE.convert(brokerageRecord));
|
return success(BrokerageRecordConvert.INSTANCE.convert(brokerageRecord));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||||
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
||||||
|
import cn.iocoder.yudao.module.pay.api.notify.dto.PayTransferNotifyReqDTO;
|
||||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawRejectReqVO;
|
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawRejectReqVO;
|
||||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawPageReqVO;
|
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawPageReqVO;
|
||||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawRespVO;
|
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawRespVO;
|
||||||
|
@ -14,6 +15,8 @@ import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageWithdrawService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.annotation.security.PermitAll;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
@ -24,11 +27,13 @@ import java.util.Map;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
|
||||||
|
|
||||||
@Tag(name = "管理后台 - 佣金提现")
|
@Tag(name = "管理后台 - 佣金提现")
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/trade/brokerage-withdraw")
|
@RequestMapping("/trade/brokerage-withdraw")
|
||||||
@Validated
|
@Validated
|
||||||
|
@Slf4j
|
||||||
public class BrokerageWithdrawController {
|
public class BrokerageWithdrawController {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
|
@ -40,8 +45,9 @@ public class BrokerageWithdrawController {
|
||||||
@PutMapping("/approve")
|
@PutMapping("/approve")
|
||||||
@Operation(summary = "通过申请")
|
@Operation(summary = "通过申请")
|
||||||
@PreAuthorize("@ss.hasPermission('trade:brokerage-withdraw:audit')")
|
@PreAuthorize("@ss.hasPermission('trade:brokerage-withdraw:audit')")
|
||||||
public CommonResult<Boolean> approveBrokerageWithdraw(@RequestParam("id") Integer id) {
|
public CommonResult<Boolean> approveBrokerageWithdraw(@RequestParam("id") Long id) {
|
||||||
brokerageWithdrawService.auditBrokerageWithdraw(id, BrokerageWithdrawStatusEnum.AUDIT_SUCCESS, "");
|
brokerageWithdrawService.auditBrokerageWithdraw(id,
|
||||||
|
BrokerageWithdrawStatusEnum.AUDIT_SUCCESS, "", getClientIP());
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +55,8 @@ public class BrokerageWithdrawController {
|
||||||
@Operation(summary = "驳回申请")
|
@Operation(summary = "驳回申请")
|
||||||
@PreAuthorize("@ss.hasPermission('trade:brokerage-withdraw:audit')")
|
@PreAuthorize("@ss.hasPermission('trade:brokerage-withdraw:audit')")
|
||||||
public CommonResult<Boolean> rejectBrokerageWithdraw(@Valid @RequestBody BrokerageWithdrawRejectReqVO reqVO) {
|
public CommonResult<Boolean> rejectBrokerageWithdraw(@Valid @RequestBody BrokerageWithdrawRejectReqVO reqVO) {
|
||||||
brokerageWithdrawService.auditBrokerageWithdraw(reqVO.getId(), BrokerageWithdrawStatusEnum.AUDIT_FAIL, reqVO.getAuditReason());
|
brokerageWithdrawService.auditBrokerageWithdraw(reqVO.getId(),
|
||||||
|
BrokerageWithdrawStatusEnum.AUDIT_FAIL, reqVO.getAuditReason(), getClientIP());
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +64,7 @@ public class BrokerageWithdrawController {
|
||||||
@Operation(summary = "获得佣金提现")
|
@Operation(summary = "获得佣金提现")
|
||||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||||
@PreAuthorize("@ss.hasPermission('trade:brokerage-withdraw:query')")
|
@PreAuthorize("@ss.hasPermission('trade:brokerage-withdraw:query')")
|
||||||
public CommonResult<BrokerageWithdrawRespVO> getBrokerageWithdraw(@RequestParam("id") Integer id) {
|
public CommonResult<BrokerageWithdrawRespVO> getBrokerageWithdraw(@RequestParam("id") Long id) {
|
||||||
BrokerageWithdrawDO brokerageWithdraw = brokerageWithdrawService.getBrokerageWithdraw(id);
|
BrokerageWithdrawDO brokerageWithdraw = brokerageWithdrawService.getBrokerageWithdraw(id);
|
||||||
return success(BrokerageWithdrawConvert.INSTANCE.convert(brokerageWithdraw));
|
return success(BrokerageWithdrawConvert.INSTANCE.convert(brokerageWithdraw));
|
||||||
}
|
}
|
||||||
|
@ -75,4 +82,15 @@ public class BrokerageWithdrawController {
|
||||||
return success(BrokerageWithdrawConvert.INSTANCE.convertPage(pageResult, userMap));
|
return success(BrokerageWithdrawConvert.INSTANCE.convertPage(pageResult, userMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO @luchi:update-transferred,url 改成这个。和 update-paid 、update-refunded 保持一致
|
||||||
|
@PostMapping("/update-transfer")
|
||||||
|
@Operation(summary = "更新转账订单为转账成功") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob
|
||||||
|
@PermitAll // 无需登录,安全由 PayDemoOrderService 内部校验实现
|
||||||
|
public CommonResult<Boolean> updateBrokerageWithdrawTransferred(@RequestBody PayTransferNotifyReqDTO notifyReqDTO) {
|
||||||
|
log.info("[updateAfterRefund][notifyReqDTO({})]", notifyReqDTO);
|
||||||
|
brokerageWithdrawService.updateBrokerageWithdrawTransferred(
|
||||||
|
Long.parseLong(notifyReqDTO.getMerchantTransferId()), notifyReqDTO.getPayTransferId());
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record;
|
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||||
|
|
|
@ -14,7 +14,7 @@ import java.time.LocalDateTime;
|
||||||
public class BrokerageRecordRespVO extends BrokerageRecordBaseVO {
|
public class BrokerageRecordRespVO extends BrokerageRecordBaseVO {
|
||||||
|
|
||||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28896")
|
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28896")
|
||||||
private Integer id;
|
private Long id;
|
||||||
|
|
||||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user;
|
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user;
|
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
@Schema(description = "管理后台 - 分销用户 - 清除推广员 Request VO")
|
@Schema(description = "管理后台 - 分销用户 - 清除推广员 Request VO")
|
||||||
@Data
|
@Data
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user;
|
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
@Schema(description = "管理后台 - 分销用户 - 修改推广员 Request VO")
|
@Schema(description = "管理后台 - 分销用户 - 修改推广员 Request VO")
|
||||||
@Data
|
@Data
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user;
|
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
@Schema(description = "管理后台 - 分销用户 - 修改推广员 Request VO")
|
@Schema(description = "管理后台 - 分销用户 - 修改推广员 Request VO")
|
||||||
@Data
|
@Data
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw;
|
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw;
|
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
@Schema(description = "管理后台 - 驳回申请 Request VO")
|
@Schema(description = "管理后台 - 驳回申请 Request VO")
|
||||||
@Data
|
@Data
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
|
@ -14,7 +13,7 @@ public class BrokerageWithdrawRejectReqVO {
|
||||||
|
|
||||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7161")
|
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7161")
|
||||||
@NotNull(message = "编号不能为空")
|
@NotNull(message = "编号不能为空")
|
||||||
private Integer id;
|
private Long id;
|
||||||
|
|
||||||
@Schema(description = "审核驳回原因", example = "不对")
|
@Schema(description = "审核驳回原因", example = "不对")
|
||||||
@NotEmpty(message = "审核驳回原因不能为空")
|
@NotEmpty(message = "审核驳回原因不能为空")
|
||||||
|
|
|
@ -14,7 +14,7 @@ import java.time.LocalDateTime;
|
||||||
public class BrokerageWithdrawRespVO extends BrokerageWithdrawBaseVO {
|
public class BrokerageWithdrawRespVO extends BrokerageWithdrawBaseVO {
|
||||||
|
|
||||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7161")
|
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7161")
|
||||||
private Integer id;
|
private Long id;
|
||||||
|
|
||||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
package cn.iocoder.yudao.module.trade.controller.admin.delivery;
|
package cn.iocoder.yudao.module.trade.controller.admin.delivery;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
|
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||||
|
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||||
|
import cn.iocoder.yudao.module.trade.controller.admin.base.system.user.UserSimpleBaseVO;
|
||||||
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.*;
|
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.*;
|
||||||
import cn.iocoder.yudao.module.trade.convert.delivery.DeliveryPickUpStoreConvert;
|
import cn.iocoder.yudao.module.trade.convert.delivery.DeliveryPickUpStoreConvert;
|
||||||
import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO;
|
import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO;
|
||||||
|
@ -10,12 +15,12 @@ import cn.iocoder.yudao.module.trade.service.delivery.DeliveryPickUpStoreService
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.validation.Valid;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -30,6 +35,9 @@ public class DeliveryPickUpStoreController {
|
||||||
@Resource
|
@Resource
|
||||||
private DeliveryPickUpStoreService deliveryPickUpStoreService;
|
private DeliveryPickUpStoreService deliveryPickUpStoreService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AdminUserApi adminUserApi;
|
||||||
|
|
||||||
@PostMapping("/create")
|
@PostMapping("/create")
|
||||||
@Operation(summary = "创建自提门店")
|
@Operation(summary = "创建自提门店")
|
||||||
@PreAuthorize("@ss.hasPermission('trade:delivery:pick-up-store:create')")
|
@PreAuthorize("@ss.hasPermission('trade:delivery:pick-up-store:create')")
|
||||||
|
@ -60,10 +68,16 @@ public class DeliveryPickUpStoreController {
|
||||||
@PreAuthorize("@ss.hasPermission('trade:delivery:pick-up-store:query')")
|
@PreAuthorize("@ss.hasPermission('trade:delivery:pick-up-store:query')")
|
||||||
public CommonResult<DeliveryPickUpStoreRespVO> getDeliveryPickUpStore(@RequestParam("id") Long id) {
|
public CommonResult<DeliveryPickUpStoreRespVO> getDeliveryPickUpStore(@RequestParam("id") Long id) {
|
||||||
DeliveryPickUpStoreDO deliveryPickUpStore = deliveryPickUpStoreService.getDeliveryPickUpStore(id);
|
DeliveryPickUpStoreDO deliveryPickUpStore = deliveryPickUpStoreService.getDeliveryPickUpStore(id);
|
||||||
return success(DeliveryPickUpStoreConvert.INSTANCE.convert(deliveryPickUpStore));
|
if (deliveryPickUpStore == null) {
|
||||||
|
return success(null);
|
||||||
|
}
|
||||||
|
List<AdminUserRespDTO> verifyUsers = CollUtil.isNotEmpty(deliveryPickUpStore.getVerifyUserIds()) ?
|
||||||
|
adminUserApi.getUserList(deliveryPickUpStore.getVerifyUserIds()).getCheckedData() : null;
|
||||||
|
return success(BeanUtils.toBean(deliveryPickUpStore, DeliveryPickUpStoreRespVO.class)
|
||||||
|
.setVerifyUsers(BeanUtils.toBean(verifyUsers, UserSimpleBaseVO.class)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/list-all-simple")
|
@GetMapping("/simple-list")
|
||||||
@Operation(summary = "获得自提门店精简信息列表")
|
@Operation(summary = "获得自提门店精简信息列表")
|
||||||
public CommonResult<List<DeliveryPickUpStoreSimpleRespVO>> getSimpleDeliveryPickUpStoreList() {
|
public CommonResult<List<DeliveryPickUpStoreSimpleRespVO>> getSimpleDeliveryPickUpStoreList() {
|
||||||
List<DeliveryPickUpStoreDO> list = deliveryPickUpStoreService.getDeliveryPickUpStoreListByStatus(
|
List<DeliveryPickUpStoreDO> list = deliveryPickUpStoreService.getDeliveryPickUpStoreListByStatus(
|
||||||
|
@ -88,4 +102,12 @@ public class DeliveryPickUpStoreController {
|
||||||
return success(DeliveryPickUpStoreConvert.INSTANCE.convertPage(pageResult));
|
return success(DeliveryPickUpStoreConvert.INSTANCE.convertPage(pageResult));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/bind")
|
||||||
|
@Operation(summary = "绑定自提店员")
|
||||||
|
@PreAuthorize("@ss.hasPermission('trade:delivery:pick-up-store:create')")
|
||||||
|
public CommonResult<Boolean> bindDeliveryPickUpStore(@Valid @RequestBody DeliveryPickUpBindReqVO bindReqVO) {
|
||||||
|
deliveryPickUpStoreService.bindDeliveryPickUpStore(bindReqVO);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 自提门店绑定核销人 Request VO")
|
||||||
|
@Data
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class DeliveryPickUpBindReqVO {
|
||||||
|
|
||||||
|
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23128")
|
||||||
|
@NotNull(message = "编号不能为空")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "绑定用户编号组数", requiredMode = Schema.RequiredMode.REQUIRED, example = "23128")
|
||||||
|
@NotEmpty(message = "绑定用户编号组数不能未空")
|
||||||
|
private List<Long> verifyUserIds;
|
||||||
|
|
||||||
|
}
|
|
@ -5,10 +5,10 @@ import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||||
import cn.iocoder.yudao.framework.common.validation.Mobile;
|
import cn.iocoder.yudao.framework.common.validation.Mobile;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import javax.validation.constraints.NotBlank;
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup;
|
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup;
|
||||||
|
|
||||||
import lombok.*;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
@Schema(description = "管理后台 - 自提门店创建 Request VO")
|
@Schema(description = "管理后台 - 自提门店创建 Request VO")
|
||||||
@Data
|
@Data
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup;
|
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
|
||||||
import lombok.*;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
|
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup;
|
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.trade.controller.admin.base.system.user.UserSimpleBaseVO;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Schema(description = "管理后台 - 自提门店 Response VO")
|
@Schema(description = "管理后台 - 自提门店 Response VO")
|
||||||
@Data
|
@Data
|
||||||
|
@ -19,4 +21,7 @@ public class DeliveryPickUpStoreRespVO extends DeliveryPickUpStoreBaseVO {
|
||||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
@Schema(description = "核销用户数组", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private List<UserSimpleBaseVO> verifyUsers;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Schema(description = "管理后台 - 自提门店精简信息 Response VO")
|
@Schema(description = "管理后台 - 自提门店精简信息 Response VO")
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
@ -29,4 +31,7 @@ public class DeliveryPickUpStoreSimpleRespVO {
|
||||||
@Schema(description = "门店详细地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "复旦大学路 188 号")
|
@Schema(description = "门店详细地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "复旦大学路 188 号")
|
||||||
private String detailAddress;
|
private String detailAddress;
|
||||||
|
|
||||||
|
@Schema(description = "绑定用户编号组数", requiredMode = Schema.RequiredMode.REQUIRED, example = "23128")
|
||||||
|
private List<Long> verifyUserIds;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup;
|
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
@Schema(description = "管理后台 - 自提门店更新 Request VO")
|
@Schema(description = "管理后台 - 自提门店更新 Request VO")
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
|
|
@ -10,19 +10,18 @@ import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
|
||||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
||||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
|
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
|
||||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderLogDO;
|
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderLogDO;
|
||||||
import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleService;
|
|
||||||
import cn.iocoder.yudao.module.trade.service.order.TradeOrderLogService;
|
import cn.iocoder.yudao.module.trade.service.order.TradeOrderLogService;
|
||||||
import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService;
|
import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService;
|
||||||
import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService;
|
import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
@ -31,6 +30,7 @@ import java.util.Set;
|
||||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||||
|
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
|
||||||
|
|
||||||
@Tag(name = "管理后台 - 交易订单")
|
@Tag(name = "管理后台 - 交易订单")
|
||||||
@RestController
|
@RestController
|
||||||
|
@ -144,7 +144,7 @@ public class TradeOrderController {
|
||||||
@Parameter(name = "id", description = "交易订单编号")
|
@Parameter(name = "id", description = "交易订单编号")
|
||||||
@PreAuthorize("@ss.hasPermission('trade:order:pick-up')")
|
@PreAuthorize("@ss.hasPermission('trade:order:pick-up')")
|
||||||
public CommonResult<Boolean> pickUpOrderById(@RequestParam("id") Long id) {
|
public CommonResult<Boolean> pickUpOrderById(@RequestParam("id") Long id) {
|
||||||
tradeOrderUpdateService.pickUpOrderByAdmin(id);
|
tradeOrderUpdateService.pickUpOrderByAdmin(getLoginUserId(), id);
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ public class TradeOrderController {
|
||||||
@Parameter(name = "pickUpVerifyCode", description = "自提核销码")
|
@Parameter(name = "pickUpVerifyCode", description = "自提核销码")
|
||||||
@PreAuthorize("@ss.hasPermission('trade:order:pick-up')")
|
@PreAuthorize("@ss.hasPermission('trade:order:pick-up')")
|
||||||
public CommonResult<Boolean> pickUpOrderByVerifyCode(@RequestParam("pickUpVerifyCode") String pickUpVerifyCode) {
|
public CommonResult<Boolean> pickUpOrderByVerifyCode(@RequestParam("pickUpVerifyCode") String pickUpVerifyCode) {
|
||||||
tradeOrderUpdateService.pickUpOrderByAdmin(pickUpVerifyCode);
|
tradeOrderUpdateService.pickUpOrderByAdmin(getLoginUserId(), pickUpVerifyCode);
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,6 @@ public interface DeliveryPickUpStoreConvert {
|
||||||
|
|
||||||
DeliveryPickUpStoreDO convert(DeliveryPickUpStoreUpdateReqVO bean);
|
DeliveryPickUpStoreDO convert(DeliveryPickUpStoreUpdateReqVO bean);
|
||||||
|
|
||||||
DeliveryPickUpStoreRespVO convert(DeliveryPickUpStoreDO bean);
|
|
||||||
|
|
||||||
List<DeliveryPickUpStoreRespVO> convertList(List<DeliveryPickUpStoreDO> list);
|
List<DeliveryPickUpStoreRespVO> convertList(List<DeliveryPickUpStoreDO> list);
|
||||||
|
|
||||||
PageResult<DeliveryPickUpStoreRespVO> convertPage(PageResult<DeliveryPickUpStoreDO> page);
|
PageResult<DeliveryPickUpStoreRespVO> convertPage(PageResult<DeliveryPickUpStoreDO> page);
|
||||||
|
@ -43,14 +41,13 @@ public interface DeliveryPickUpStoreConvert {
|
||||||
|
|
||||||
default List<AppDeliveryPickUpStoreRespVO> convertList(List<DeliveryPickUpStoreDO> list,
|
default List<AppDeliveryPickUpStoreRespVO> convertList(List<DeliveryPickUpStoreDO> list,
|
||||||
Double latitude, Double longitude) {
|
Double latitude, Double longitude) {
|
||||||
List<AppDeliveryPickUpStoreRespVO> voList = CollectionUtils.convertList(list, store -> {
|
return CollectionUtils.convertList(list, store -> {
|
||||||
AppDeliveryPickUpStoreRespVO storeVO = convert03(store);
|
AppDeliveryPickUpStoreRespVO storeVO = convert03(store);
|
||||||
if (latitude != null && longitude != null) {
|
if (latitude != null && longitude != null) {
|
||||||
storeVO.setDistance(NumberUtils.getDistance(latitude, longitude, storeVO.getLatitude(), storeVO.getLongitude()));
|
storeVO.setDistance(NumberUtils.getDistance(latitude, longitude, storeVO.getLatitude(), storeVO.getLongitude()));
|
||||||
}
|
}
|
||||||
return storeVO;
|
return storeVO;
|
||||||
});
|
});
|
||||||
return voList;
|
|
||||||
}
|
}
|
||||||
@Mapping(source = "areaId", target = "areaName", qualifiedByName = "convertAreaIdToAreaName")
|
@Mapping(source = "areaId", target = "areaName", qualifiedByName = "convertAreaIdToAreaName")
|
||||||
AppDeliveryPickUpStoreRespVO convert03(DeliveryPickUpStoreDO bean);
|
AppDeliveryPickUpStoreRespVO convert03(DeliveryPickUpStoreDO bean);
|
||||||
|
|
|
@ -2,19 +2,23 @@ package cn.iocoder.yudao.module.trade.dal.dataobject.delivery;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
|
||||||
|
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自提门店 DO
|
* 自提门店 DO
|
||||||
*
|
*
|
||||||
* @author jason
|
* @author jason
|
||||||
*/
|
*/
|
||||||
@TableName(value ="trade_delivery_pick_up_store")
|
@TableName(value ="trade_delivery_pick_up_store", autoResultMap = true)
|
||||||
@KeySequence("trade_delivery_pick_up_store_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
@KeySequence("trade_delivery_pick_up_store_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||||
@Data
|
@Data
|
||||||
public class DeliveryPickUpStoreDO extends BaseDO {
|
public class DeliveryPickUpStoreDO extends BaseDO {
|
||||||
|
@ -74,6 +78,16 @@ public class DeliveryPickUpStoreDO extends BaseDO {
|
||||||
*/
|
*/
|
||||||
private Double longitude;
|
private Double longitude;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 核销员工用户编号数组
|
||||||
|
*
|
||||||
|
* 订单自提核销时,只有对应门店的店员才能核销
|
||||||
|
*
|
||||||
|
* 关联 {@link AdminUserRespDTO#getId()} 管理员编号
|
||||||
|
*/
|
||||||
|
@TableField(typeHandler = LongListTypeHandler.class)
|
||||||
|
private List<Long> verifyUserIds;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 门店状态
|
* 门店状态
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
package cn.iocoder.yudao.module.trade.dal.dataobject.delivery;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
|
||||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
// TODO @芋艿:后续再详细 review 一轮
|
|
||||||
// TODO @芋艿:可能改成 DeliveryPickUpStoreUserDO
|
|
||||||
/**
|
|
||||||
* 自提门店店员 DO
|
|
||||||
*
|
|
||||||
* @author jason
|
|
||||||
*/
|
|
||||||
@TableName(value ="trade_delivery_pick_up_store_staff")
|
|
||||||
@KeySequence("trade_delivery_pick_up_store_staff_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
|
||||||
@Data
|
|
||||||
public class DeliveryPickUpStoreStaffDO extends BaseDO {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 编号,自增
|
|
||||||
*/
|
|
||||||
@TableId
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自提门店编号
|
|
||||||
*
|
|
||||||
* 关联 {@link DeliveryPickUpStoreDO#getId()}
|
|
||||||
*/
|
|
||||||
private Long storeId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 管理员用户id
|
|
||||||
*
|
|
||||||
* 关联 {AdminUserDO#getId()}
|
|
||||||
*/
|
|
||||||
private Long adminUserId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 状态
|
|
||||||
*
|
|
||||||
* 枚举 {@link CommonStatusEnum}
|
|
||||||
*/
|
|
||||||
private Integer status;
|
|
||||||
|
|
||||||
}
|
|
|
@ -35,7 +35,7 @@ public interface BrokerageWithdrawMapper extends BaseMapperX<BrokerageWithdrawDO
|
||||||
.orderByAsc(BrokerageWithdrawDO::getStatus).orderByDesc(BrokerageWithdrawDO::getId));
|
.orderByAsc(BrokerageWithdrawDO::getStatus).orderByDesc(BrokerageWithdrawDO::getId));
|
||||||
}
|
}
|
||||||
|
|
||||||
default int updateByIdAndStatus(Integer id, Integer status, BrokerageWithdrawDO updateObj) {
|
default int updateByIdAndStatus(Long id, Integer status, BrokerageWithdrawDO updateObj) {
|
||||||
return update(updateObj, new LambdaUpdateWrapper<BrokerageWithdrawDO>()
|
return update(updateObj, new LambdaUpdateWrapper<BrokerageWithdrawDO>()
|
||||||
.eq(BrokerageWithdrawDO::getId, id)
|
.eq(BrokerageWithdrawDO::getId, id)
|
||||||
.eq(BrokerageWithdrawDO::getStatus, status));
|
.eq(BrokerageWithdrawDO::getStatus, status));
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
package cn.iocoder.yudao.module.trade.dal.mysql.delivery;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
|
||||||
import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreStaffDO;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
|
|
||||||
@Mapper
|
|
||||||
public interface DeliveryPickUpStoreStaffMapper extends BaseMapperX<DeliveryPickUpStoreStaffDO> {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ public interface BrokerageRecordService {
|
||||||
* @param id 编号
|
* @param id 编号
|
||||||
* @return 佣金记录
|
* @return 佣金记录
|
||||||
*/
|
*/
|
||||||
BrokerageRecordDO getBrokerageRecord(Integer id);
|
BrokerageRecordDO getBrokerageRecord(Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得佣金记录分页
|
* 获得佣金记录分页
|
||||||
|
|
|
@ -64,7 +64,7 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
|
||||||
private ProductSkuApi productSkuApi;
|
private ProductSkuApi productSkuApi;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BrokerageRecordDO getBrokerageRecord(Integer id) {
|
public BrokerageRecordDO getBrokerageRecord(Long id) {
|
||||||
return brokerageRecordMapper.selectById(id);
|
return brokerageRecordMapper.selectById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,9 @@ public interface BrokerageWithdrawService {
|
||||||
* @param id 佣金编号
|
* @param id 佣金编号
|
||||||
* @param status 审核状态
|
* @param status 审核状态
|
||||||
* @param auditReason 驳回原因
|
* @param auditReason 驳回原因
|
||||||
|
* @param userIp 操作 IP
|
||||||
*/
|
*/
|
||||||
void auditBrokerageWithdraw(Integer id, BrokerageWithdrawStatusEnum status, String auditReason);
|
void auditBrokerageWithdraw(Long id, BrokerageWithdrawStatusEnum status, String auditReason, String userIp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得佣金提现
|
* 获得佣金提现
|
||||||
|
@ -36,7 +37,7 @@ public interface BrokerageWithdrawService {
|
||||||
* @param id 编号
|
* @param id 编号
|
||||||
* @return 佣金提现
|
* @return 佣金提现
|
||||||
*/
|
*/
|
||||||
BrokerageWithdrawDO getBrokerageWithdraw(Integer id);
|
BrokerageWithdrawDO getBrokerageWithdraw(Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得佣金提现分页
|
* 获得佣金提现分页
|
||||||
|
@ -55,6 +56,16 @@ public interface BrokerageWithdrawService {
|
||||||
*/
|
*/
|
||||||
Long createBrokerageWithdraw(Long userId, AppBrokerageWithdrawCreateReqVO createReqVO);
|
Long createBrokerageWithdraw(Long userId, AppBrokerageWithdrawCreateReqVO createReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【API】更新佣金提现的转账结果
|
||||||
|
*
|
||||||
|
* 目前用于支付回调,标记提现转账结果
|
||||||
|
*
|
||||||
|
* @param id 提现编号
|
||||||
|
* @param payTransferId 转账订单编号
|
||||||
|
*/
|
||||||
|
void updateBrokerageWithdrawTransferred(Long id, Long payTransferId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按照 userId,汇总每个用户的提现
|
* 按照 userId,汇总每个用户的提现
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,38 +1,48 @@
|
||||||
package cn.iocoder.yudao.module.trade.service.brokerage;
|
package cn.iocoder.yudao.module.trade.service.brokerage;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
|
||||||
import cn.hutool.core.map.MapUtil;
|
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
|
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
|
||||||
|
import cn.iocoder.yudao.module.pay.api.transfer.PayTransferApi;
|
||||||
|
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
|
||||||
|
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO;
|
||||||
|
import cn.iocoder.yudao.module.pay.api.wallet.PayWalletApi;
|
||||||
|
import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletAddBalanceReqDTO;
|
||||||
|
import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum;
|
||||||
|
import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferTypeEnum;
|
||||||
|
import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
|
||||||
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
|
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
|
||||||
import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;
|
import cn.iocoder.yudao.module.system.api.social.SocialUserApi;
|
||||||
|
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
|
||||||
|
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
|
||||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawPageReqVO;
|
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawPageReqVO;
|
||||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawCreateReqVO;
|
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawCreateReqVO;
|
||||||
import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageWithdrawConvert;
|
import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageWithdrawConvert;
|
||||||
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageWithdrawDO;
|
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageWithdrawDO;
|
||||||
import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
|
import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
|
||||||
import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageWithdrawMapper;
|
import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageWithdrawMapper;
|
||||||
import cn.iocoder.yudao.module.trade.enums.MessageTemplateConstants;
|
|
||||||
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
|
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
|
||||||
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum;
|
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum;
|
||||||
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawTypeEnum;
|
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawTypeEnum;
|
||||||
|
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
|
||||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageWithdrawSummaryRespBO;
|
import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageWithdrawSummaryRespBO;
|
||||||
import cn.iocoder.yudao.module.trade.service.config.TradeConfigService;
|
import cn.iocoder.yudao.module.trade.service.config.TradeConfigService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.validation.Validator;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.validation.Validator;
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
|
||||||
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
|
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,6 +52,7 @@ import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
@Validated
|
@Validated
|
||||||
|
@Slf4j
|
||||||
public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
|
@ -54,13 +65,22 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private NotifyMessageSendApi notifyMessageSendApi;
|
private NotifyMessageSendApi notifyMessageSendApi;
|
||||||
|
@Resource
|
||||||
|
private PayTransferApi payTransferApi;
|
||||||
|
@Resource
|
||||||
|
private SocialUserApi socialUserApi;
|
||||||
|
@Resource
|
||||||
|
private PayWalletApi payWalletApi;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private Validator validator;
|
private Validator validator;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TradeOrderProperties tradeOrderProperties;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void auditBrokerageWithdraw(Integer id, BrokerageWithdrawStatusEnum status, String auditReason) {
|
public void auditBrokerageWithdraw(Long id, BrokerageWithdrawStatusEnum status, String auditReason, String userIp) {
|
||||||
// 1.1 校验存在
|
// 1.1 校验存在
|
||||||
BrokerageWithdrawDO withdraw = validateBrokerageWithdrawExists(id);
|
BrokerageWithdrawDO withdraw = validateBrokerageWithdrawExists(id);
|
||||||
// 1.2 校验状态为审核中
|
// 1.2 校验状态为审核中
|
||||||
|
@ -68,41 +88,67 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
||||||
throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING);
|
throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 更新
|
// 2. 更新状态
|
||||||
int rows = brokerageWithdrawMapper.updateByIdAndStatus(id, BrokerageWithdrawStatusEnum.AUDITING.getStatus(),
|
int rows = brokerageWithdrawMapper.updateByIdAndStatus(id, BrokerageWithdrawStatusEnum.AUDITING.getStatus(),
|
||||||
new BrokerageWithdrawDO().setStatus(status.getStatus()).setAuditReason(auditReason).setAuditTime(LocalDateTime.now()));
|
new BrokerageWithdrawDO().setStatus(status.getStatus()).setAuditReason(auditReason).setAuditTime(LocalDateTime.now()));
|
||||||
if (rows == 0) {
|
if (rows == 0) {
|
||||||
throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING);
|
throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING);
|
||||||
}
|
}
|
||||||
|
|
||||||
String templateCode;
|
// 3.1 审批通过的后续处理
|
||||||
if (BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.equals(status)) {
|
if (BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.equals(status)) {
|
||||||
templateCode = MessageTemplateConstants.SMS_BROKERAGE_WITHDRAW_AUDIT_APPROVE;
|
auditBrokerageWithdrawSuccess(withdraw);
|
||||||
// 3.1 通过时佣金转余额
|
// 3.2 审批不通过的后续处理
|
||||||
if (BrokerageWithdrawTypeEnum.WALLET.getType().equals(withdraw.getType())) {
|
|
||||||
// todo 疯狂:
|
|
||||||
}
|
|
||||||
// TODO 疯狂:调用转账接口
|
|
||||||
} else if (BrokerageWithdrawStatusEnum.AUDIT_FAIL.equals(status)) {
|
} else if (BrokerageWithdrawStatusEnum.AUDIT_FAIL.equals(status)) {
|
||||||
templateCode = MessageTemplateConstants.SMS_BROKERAGE_WITHDRAW_AUDIT_REJECT;
|
|
||||||
// 3.2 驳回时需要退还用户佣金
|
|
||||||
brokerageRecordService.addBrokerage(withdraw.getUserId(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT,
|
brokerageRecordService.addBrokerage(withdraw.getUserId(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT,
|
||||||
String.valueOf(withdraw.getId()), withdraw.getPrice(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT.getTitle());
|
String.valueOf(withdraw.getId()), withdraw.getPrice(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT.getTitle());
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("不支持的提现状态:" + status);
|
throw new IllegalArgumentException("不支持的提现状态:" + status);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 通知用户
|
|
||||||
Map<String, Object> templateParams = MapUtil.<String, Object>builder()
|
|
||||||
.put("createTime", LocalDateTimeUtil.formatNormal(withdraw.getCreateTime()))
|
|
||||||
.put("price", MoneyUtils.fenToYuanStr(withdraw.getPrice()))
|
|
||||||
.put("reason", auditReason)
|
|
||||||
.build();
|
|
||||||
notifyMessageSendApi.sendSingleMessageToMember(new NotifySendSingleToUserReqDTO()
|
|
||||||
.setUserId(withdraw.getUserId()).setTemplateCode(templateCode).setTemplateParams(templateParams)).checkError();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private BrokerageWithdrawDO validateBrokerageWithdrawExists(Integer id) {
|
private void auditBrokerageWithdrawSuccess(BrokerageWithdrawDO withdraw) {
|
||||||
|
// 1.1 钱包
|
||||||
|
if (BrokerageWithdrawTypeEnum.WALLET.getType().equals(withdraw.getType())) {
|
||||||
|
payWalletApi.addWalletBalance(new PayWalletAddBalanceReqDTO()
|
||||||
|
.setUserId(withdraw.getUserId()).setUserType(UserTypeEnum.MEMBER.getValue())
|
||||||
|
.setBizType(PayWalletBizTypeEnum.BROKERAGE_WITHDRAW.getType()).setBizId(withdraw.getId().toString())
|
||||||
|
.setPrice(withdraw.getPrice())).checkError();
|
||||||
|
// 1.2 微信 API
|
||||||
|
} else if (BrokerageWithdrawTypeEnum.WECHAT_API.getType().equals(withdraw.getType())) {
|
||||||
|
// TODO @luchi:这里,要加个转账单号的记录;另外,调用 API 转账,是立马成功,还是有延迟的哈?
|
||||||
|
Long payTransferId = createPayTransfer(withdraw);
|
||||||
|
// 1.3 剩余类型,都是手动打款,所以不处理
|
||||||
|
} else {
|
||||||
|
// TODO 可优化:未来可以考虑,接入支付宝、银联等 API 转账,实现自动打款
|
||||||
|
log.info("[auditBrokerageWithdrawSuccess][withdraw({}) 类型({}) 手动打款,无需处理]", withdraw.getId(), withdraw.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 非支付 API,则直接体现成功
|
||||||
|
if (!BrokerageWithdrawTypeEnum.isApi(withdraw.getType())) {
|
||||||
|
brokerageWithdrawMapper.updateByIdAndStatus(withdraw.getId(), BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.getStatus(),
|
||||||
|
new BrokerageWithdrawDO().setStatus(BrokerageWithdrawStatusEnum.WITHDRAW_SUCCESS.getStatus()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long createPayTransfer(BrokerageWithdrawDO withdraw) {
|
||||||
|
// 1.1 获取微信 openid
|
||||||
|
SocialUserRespDTO socialUser = socialUserApi.getSocialUserByUserId(
|
||||||
|
UserTypeEnum.MEMBER.getValue(), withdraw.getUserId(), SocialTypeEnum.WECHAT_MINI_APP.getType()).getCheckedData();
|
||||||
|
// TODO @luchi:这里,需要校验非空。如果空的话,要有业务异常哈;
|
||||||
|
// 1.2 构建请求
|
||||||
|
PayTransferCreateReqDTO payTransferCreateReqDTO = new PayTransferCreateReqDTO()
|
||||||
|
.setAppKey(tradeOrderProperties.getPayAppKey())
|
||||||
|
.setChannelCode("wx_lite").setType(PayTransferTypeEnum.WX_BALANCE.getType())
|
||||||
|
.setMerchantTransferId(withdraw.getId().toString())
|
||||||
|
.setPrice(withdraw.getPrice())
|
||||||
|
.setSubject("佣金提现")
|
||||||
|
.setOpenid(socialUser.getOpenid()).setUserIp(getClientIP());
|
||||||
|
// 2. 发起请求
|
||||||
|
return payTransferApi.createTransfer(payTransferCreateReqDTO).getCheckedData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private BrokerageWithdrawDO validateBrokerageWithdrawExists(Long id) {
|
||||||
BrokerageWithdrawDO withdraw = brokerageWithdrawMapper.selectById(id);
|
BrokerageWithdrawDO withdraw = brokerageWithdrawMapper.selectById(id);
|
||||||
if (withdraw == null) {
|
if (withdraw == null) {
|
||||||
throw exception(BROKERAGE_WITHDRAW_NOT_EXISTS);
|
throw exception(BROKERAGE_WITHDRAW_NOT_EXISTS);
|
||||||
|
@ -111,7 +157,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BrokerageWithdrawDO getBrokerageWithdraw(Integer id) {
|
public BrokerageWithdrawDO getBrokerageWithdraw(Long id) {
|
||||||
return brokerageWithdrawMapper.selectById(id);
|
return brokerageWithdrawMapper.selectById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,15 +187,6 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
||||||
return withdraw.getId();
|
return withdraw.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<BrokerageWithdrawSummaryRespBO> getWithdrawSummaryListByUserId(Collection<Long> userIds,
|
|
||||||
BrokerageWithdrawStatusEnum status) {
|
|
||||||
if (CollUtil.isEmpty(userIds)) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
return brokerageWithdrawMapper.selectCountAndSumPriceByUserIdAndStatus(userIds, status.getStatus());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算提现手续费
|
* 计算提现手续费
|
||||||
*
|
*
|
||||||
|
@ -157,7 +194,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
||||||
* @param percent 手续费百分比
|
* @param percent 手续费百分比
|
||||||
* @return 提现手续费
|
* @return 提现手续费
|
||||||
*/
|
*/
|
||||||
Integer calculateFeePrice(Integer withdrawPrice, Integer percent) {
|
private Integer calculateFeePrice(Integer withdrawPrice, Integer percent) {
|
||||||
Integer feePrice = 0;
|
Integer feePrice = 0;
|
||||||
if (percent != null && percent > 0) {
|
if (percent != null && percent > 0) {
|
||||||
feePrice = MoneyUtils.calculateRatePrice(withdrawPrice, Double.valueOf(percent));
|
feePrice = MoneyUtils.calculateRatePrice(withdrawPrice, Double.valueOf(percent));
|
||||||
|
@ -171,11 +208,42 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
||||||
* @param withdrawPrice 提现金额
|
* @param withdrawPrice 提现金额
|
||||||
* @return 分销配置
|
* @return 分销配置
|
||||||
*/
|
*/
|
||||||
TradeConfigDO validateWithdrawPrice(Integer withdrawPrice) {
|
private TradeConfigDO validateWithdrawPrice(Integer withdrawPrice) {
|
||||||
TradeConfigDO tradeConfig = tradeConfigService.getTradeConfig();
|
TradeConfigDO tradeConfig = tradeConfigService.getTradeConfig();
|
||||||
if (tradeConfig.getBrokerageWithdrawMinPrice() != null && withdrawPrice < tradeConfig.getBrokerageWithdrawMinPrice()) {
|
if (tradeConfig.getBrokerageWithdrawMinPrice() != null && withdrawPrice < tradeConfig.getBrokerageWithdrawMinPrice()) {
|
||||||
throw exception(BROKERAGE_WITHDRAW_MIN_PRICE, MoneyUtils.fenToYuanStr(tradeConfig.getBrokerageWithdrawMinPrice()));
|
throw exception(BROKERAGE_WITHDRAW_MIN_PRICE, MoneyUtils.fenToYuanStr(tradeConfig.getBrokerageWithdrawMinPrice()));
|
||||||
}
|
}
|
||||||
return tradeConfig;
|
return tradeConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void updateBrokerageWithdrawTransferred(Long id, Long payTransferId) {
|
||||||
|
BrokerageWithdrawDO withdraw = validateBrokerageWithdrawExists(id);
|
||||||
|
PayTransferRespDTO transfer = payTransferApi.getTransfer(payTransferId).getCheckedData();
|
||||||
|
// TODO @luchi:建议参考支付那,即使成功的情况下,也要各种校验;金额是否匹配、转账单号是否匹配、是否重复调用;
|
||||||
|
if (PayTransferStatusEnum.isSuccess(transfer.getStatus())) {
|
||||||
|
withdraw.setStatus(BrokerageWithdrawStatusEnum.WITHDRAW_SUCCESS.getStatus());
|
||||||
|
// TODO @luchi:发送站内信
|
||||||
|
} else if (PayTransferStatusEnum.isPendingStatus(transfer.getStatus())) {
|
||||||
|
// TODO @luchi:这里,是不是不用更新哈?
|
||||||
|
withdraw.setStatus(BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.getStatus());
|
||||||
|
} else {
|
||||||
|
withdraw.setStatus(BrokerageWithdrawStatusEnum.WITHDRAW_FAIL.getStatus());
|
||||||
|
// 3.2 驳回时需要退还用户佣金
|
||||||
|
brokerageRecordService.addBrokerage(withdraw.getUserId(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT,
|
||||||
|
String.valueOf(withdraw.getId()), withdraw.getPrice(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT.getTitle());
|
||||||
|
}
|
||||||
|
brokerageWithdrawMapper.updateById(withdraw);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BrokerageWithdrawSummaryRespBO> getWithdrawSummaryListByUserId(Collection<Long> userIds,
|
||||||
|
BrokerageWithdrawStatusEnum status) {
|
||||||
|
if (CollUtil.isEmpty(userIds)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
return brokerageWithdrawMapper.selectCountAndSumPriceByUserIdAndStatus(userIds, status.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
package cn.iocoder.yudao.module.trade.service.delivery;
|
package cn.iocoder.yudao.module.trade.service.delivery;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.DeliveryPickUpBindReqVO;
|
||||||
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.DeliveryPickUpStoreCreateReqVO;
|
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.DeliveryPickUpStoreCreateReqVO;
|
||||||
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.DeliveryPickUpStorePageReqVO;
|
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.DeliveryPickUpStorePageReqVO;
|
||||||
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.DeliveryPickUpStoreUpdateReqVO;
|
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.DeliveryPickUpStoreUpdateReqVO;
|
||||||
import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO;
|
import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -55,6 +56,14 @@ public interface DeliveryPickUpStoreService {
|
||||||
*/
|
*/
|
||||||
List<DeliveryPickUpStoreDO> getDeliveryPickUpStoreList(Collection<Long> ids);
|
List<DeliveryPickUpStoreDO> getDeliveryPickUpStoreList(Collection<Long> ids);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得指定状态的自提门店列表
|
||||||
|
*
|
||||||
|
* @param status 状态
|
||||||
|
* @return 自提门店列表
|
||||||
|
*/
|
||||||
|
List<DeliveryPickUpStoreDO> getDeliveryPickUpStoreListByStatus(Integer status);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得自提门店分页
|
* 获得自提门店分页
|
||||||
*
|
*
|
||||||
|
@ -64,10 +73,10 @@ public interface DeliveryPickUpStoreService {
|
||||||
PageResult<DeliveryPickUpStoreDO> getDeliveryPickUpStorePage(DeliveryPickUpStorePageReqVO pageReqVO);
|
PageResult<DeliveryPickUpStoreDO> getDeliveryPickUpStorePage(DeliveryPickUpStorePageReqVO pageReqVO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得指定状态的自提门店列表
|
* 绑定自提店员
|
||||||
*
|
*
|
||||||
* @param status 状态
|
* @param bindReqVO 绑定数据
|
||||||
* @return 自提门店列表
|
|
||||||
*/
|
*/
|
||||||
List<DeliveryPickUpStoreDO> getDeliveryPickUpStoreListByStatus(Integer status);
|
void bindDeliveryPickUpStore(DeliveryPickUpBindReqVO bindReqVO);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
package cn.iocoder.yudao.module.trade.service.delivery;
|
package cn.iocoder.yudao.module.trade.service.delivery;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
|
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||||
|
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.DeliveryPickUpBindReqVO;
|
||||||
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.DeliveryPickUpStoreCreateReqVO;
|
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.DeliveryPickUpStoreCreateReqVO;
|
||||||
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.DeliveryPickUpStorePageReqVO;
|
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.DeliveryPickUpStorePageReqVO;
|
||||||
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.DeliveryPickUpStoreUpdateReqVO;
|
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.DeliveryPickUpStoreUpdateReqVO;
|
||||||
import cn.iocoder.yudao.module.trade.convert.delivery.DeliveryPickUpStoreConvert;
|
import cn.iocoder.yudao.module.trade.convert.delivery.DeliveryPickUpStoreConvert;
|
||||||
import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO;
|
import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO;
|
||||||
import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryPickUpStoreMapper;
|
import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryPickUpStoreMapper;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -29,6 +32,9 @@ public class DeliveryPickUpStoreServiceImpl implements DeliveryPickUpStoreServic
|
||||||
@Resource
|
@Resource
|
||||||
private DeliveryPickUpStoreMapper deliveryPickUpStoreMapper;
|
private DeliveryPickUpStoreMapper deliveryPickUpStoreMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AdminUserApi adminUserApi;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long createDeliveryPickUpStore(DeliveryPickUpStoreCreateReqVO createReqVO) {
|
public Long createDeliveryPickUpStore(DeliveryPickUpStoreCreateReqVO createReqVO) {
|
||||||
// 插入
|
// 插入
|
||||||
|
@ -56,7 +62,8 @@ public class DeliveryPickUpStoreServiceImpl implements DeliveryPickUpStoreServic
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateDeliveryPickUpStoreExists(Long id) {
|
private void validateDeliveryPickUpStoreExists(Long id) {
|
||||||
if (deliveryPickUpStoreMapper.selectById(id) == null) {
|
DeliveryPickUpStoreDO deliveryPickUpStore = deliveryPickUpStoreMapper.selectById(id);
|
||||||
|
if (deliveryPickUpStore == null) {
|
||||||
throw exception(PICK_UP_STORE_NOT_EXISTS);
|
throw exception(PICK_UP_STORE_NOT_EXISTS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,14 +78,26 @@ public class DeliveryPickUpStoreServiceImpl implements DeliveryPickUpStoreServic
|
||||||
return deliveryPickUpStoreMapper.selectBatchIds(ids);
|
return deliveryPickUpStoreMapper.selectBatchIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DeliveryPickUpStoreDO> getDeliveryPickUpStoreListByStatus(Integer status) {
|
||||||
|
return deliveryPickUpStoreMapper.selectListByStatus(status);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageResult<DeliveryPickUpStoreDO> getDeliveryPickUpStorePage(DeliveryPickUpStorePageReqVO pageReqVO) {
|
public PageResult<DeliveryPickUpStoreDO> getDeliveryPickUpStorePage(DeliveryPickUpStorePageReqVO pageReqVO) {
|
||||||
return deliveryPickUpStoreMapper.selectPage(pageReqVO);
|
return deliveryPickUpStoreMapper.selectPage(pageReqVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<DeliveryPickUpStoreDO> getDeliveryPickUpStoreListByStatus(Integer status) {
|
public void bindDeliveryPickUpStore(DeliveryPickUpBindReqVO bindReqVO) {
|
||||||
return deliveryPickUpStoreMapper.selectListByStatus(status);
|
// 1.1 校验门店存在
|
||||||
|
validateDeliveryPickUpStoreExists(bindReqVO.getId());
|
||||||
|
// 1.2 校验用户存在
|
||||||
|
adminUserApi.validateUserList(bindReqVO.getVerifyUserIds()).checkError();
|
||||||
|
|
||||||
|
// 2. 更新
|
||||||
|
DeliveryPickUpStoreDO updateObj = BeanUtils.toBean(bindReqVO, DeliveryPickUpStoreDO.class);
|
||||||
|
deliveryPickUpStoreMapper.updateById(updateObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,16 +129,18 @@ public interface TradeOrderUpdateService {
|
||||||
/**
|
/**
|
||||||
* 【管理员】核销订单
|
* 【管理员】核销订单
|
||||||
*
|
*
|
||||||
|
* @param userId 管理员编号
|
||||||
* @param id 订单编号
|
* @param id 订单编号
|
||||||
*/
|
*/
|
||||||
void pickUpOrderByAdmin(Long id);
|
void pickUpOrderByAdmin(Long userId, Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 【管理员】核销订单
|
* 【管理员】核销订单
|
||||||
*
|
*
|
||||||
|
* @param userId 管理员编号
|
||||||
* @param pickUpVerifyCode 自提核销码
|
* @param pickUpVerifyCode 自提核销码
|
||||||
*/
|
*/
|
||||||
void pickUpOrderByAdmin(String pickUpVerifyCode);
|
void pickUpOrderByAdmin(Long userId, String pickUpVerifyCode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 【管理员】根据自提核销码,查询订单
|
* 【管理员】根据自提核销码,查询订单
|
||||||
|
|
|
@ -36,6 +36,7 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderI
|
||||||
import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
|
import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
|
||||||
import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO;
|
import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO;
|
||||||
import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
|
import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
|
||||||
|
import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO;
|
||||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
||||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
|
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
|
||||||
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper;
|
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper;
|
||||||
|
@ -48,6 +49,7 @@ import cn.iocoder.yudao.module.trade.framework.order.core.annotations.TradeOrder
|
||||||
import cn.iocoder.yudao.module.trade.framework.order.core.utils.TradeOrderLogUtils;
|
import cn.iocoder.yudao.module.trade.framework.order.core.utils.TradeOrderLogUtils;
|
||||||
import cn.iocoder.yudao.module.trade.service.cart.CartService;
|
import cn.iocoder.yudao.module.trade.service.cart.CartService;
|
||||||
import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService;
|
import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService;
|
||||||
|
import cn.iocoder.yudao.module.trade.service.delivery.DeliveryPickUpStoreService;
|
||||||
import cn.iocoder.yudao.module.trade.service.message.TradeMessageService;
|
import cn.iocoder.yudao.module.trade.service.message.TradeMessageService;
|
||||||
import cn.iocoder.yudao.module.trade.service.message.bo.TradeOrderMessageWhenDeliveryOrderReqBO;
|
import cn.iocoder.yudao.module.trade.service.message.bo.TradeOrderMessageWhenDeliveryOrderReqBO;
|
||||||
import cn.iocoder.yudao.module.trade.service.order.handler.TradeOrderHandler;
|
import cn.iocoder.yudao.module.trade.service.order.handler.TradeOrderHandler;
|
||||||
|
@ -104,6 +106,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
|
||||||
private DeliveryExpressService deliveryExpressService;
|
private DeliveryExpressService deliveryExpressService;
|
||||||
@Resource
|
@Resource
|
||||||
private TradeMessageService tradeMessageService;
|
private TradeMessageService tradeMessageService;
|
||||||
|
@Resource
|
||||||
|
private DeliveryPickUpStoreService pickUpStoreService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private PayOrderApi payOrderApi;
|
private PayOrderApi payOrderApi;
|
||||||
|
@ -718,14 +722,14 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@TradeOrderLog(operateType = TradeOrderOperateTypeEnum.ADMIN_PICK_UP_RECEIVE)
|
@TradeOrderLog(operateType = TradeOrderOperateTypeEnum.ADMIN_PICK_UP_RECEIVE)
|
||||||
public void pickUpOrderByAdmin(Long id) {
|
public void pickUpOrderByAdmin(Long userId, Long id) {
|
||||||
getSelf().pickUpOrder(tradeOrderMapper.selectById(id));
|
getSelf().pickUpOrder(userId, tradeOrderMapper.selectById(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@TradeOrderLog(operateType = TradeOrderOperateTypeEnum.ADMIN_PICK_UP_RECEIVE)
|
@TradeOrderLog(operateType = TradeOrderOperateTypeEnum.ADMIN_PICK_UP_RECEIVE)
|
||||||
public void pickUpOrderByAdmin(String pickUpVerifyCode) {
|
public void pickUpOrderByAdmin(Long userId, String pickUpVerifyCode) {
|
||||||
getSelf().pickUpOrder(tradeOrderMapper.selectOneByPickUpVerifyCode(pickUpVerifyCode));
|
getSelf().pickUpOrder(userId, tradeOrderMapper.selectOneByPickUpVerifyCode(pickUpVerifyCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -734,13 +738,19 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void pickUpOrder(TradeOrderDO order) {
|
public void pickUpOrder(Long userId, TradeOrderDO order) {
|
||||||
if (order == null) {
|
if (order == null) {
|
||||||
throw exception(ORDER_NOT_FOUND);
|
throw exception(ORDER_NOT_FOUND);
|
||||||
}
|
}
|
||||||
if (ObjUtil.notEqual(DeliveryTypeEnum.PICK_UP.getType(), order.getDeliveryType())) {
|
if (ObjUtil.notEqual(DeliveryTypeEnum.PICK_UP.getType(), order.getDeliveryType())) {
|
||||||
throw exception(ORDER_RECEIVE_FAIL_DELIVERY_TYPE_NOT_PICK_UP);
|
throw exception(ORDER_RECEIVE_FAIL_DELIVERY_TYPE_NOT_PICK_UP);
|
||||||
}
|
}
|
||||||
|
DeliveryPickUpStoreDO deliveryPickUpStore = pickUpStoreService.getDeliveryPickUpStore(order.getPickUpStoreId());
|
||||||
|
if (deliveryPickUpStore == null
|
||||||
|
|| !CollUtil.contains(deliveryPickUpStore.getVerifyUserIds(), userId)) {
|
||||||
|
throw exception(ORDER_PICK_UP_FAIL_NOT_VERIFY_USER);
|
||||||
|
}
|
||||||
|
|
||||||
receiveOrder0(order);
|
receiveOrder0(order);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,18 @@ package cn.iocoder.yudao.module.pay.api.transfer;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
|
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
|
||||||
|
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO;
|
||||||
import cn.iocoder.yudao.module.pay.enums.ApiConstants;
|
import cn.iocoder.yudao.module.pay.enums.ApiConstants;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
|
||||||
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory =
|
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory =
|
||||||
@Tag(name = "RPC 服务 - 转账单")
|
@Tag(name = "RPC 服务 - 转账单")
|
||||||
|
@ -21,4 +25,9 @@ public interface PayTransferApi {
|
||||||
@Operation(summary = "创建转账单")
|
@Operation(summary = "创建转账单")
|
||||||
CommonResult<Long> createTransfer(@Valid @RequestBody PayTransferCreateReqDTO reqDTO);
|
CommonResult<Long> createTransfer(@Valid @RequestBody PayTransferCreateReqDTO reqDTO);
|
||||||
|
|
||||||
|
@GetMapping(PREFIX + "/get")
|
||||||
|
@Operation(summary = "获得转账单")
|
||||||
|
@Parameter(name = "id", description = "转账单编号", required = true, example = "1024")
|
||||||
|
CommonResult<PayTransferRespDTO> getTransfer(@RequestParam("id") Long id);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package cn.iocoder.yudao.module.pay.api.transfer.dto;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class PayTransferRespDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编号
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转账单号
|
||||||
|
*/
|
||||||
|
private String no;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转账金额,单位:分
|
||||||
|
*/
|
||||||
|
private Integer price;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转账状态
|
||||||
|
*
|
||||||
|
* 枚举 {@link PayTransferStatusEnum}
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package cn.iocoder.yudao.module.pay.api.wallet;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletAddBalanceReqDTO;
|
||||||
|
import cn.iocoder.yudao.module.pay.enums.ApiConstants;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
|
||||||
|
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory =
|
||||||
|
@Tag(name = "RPC 服务 - 钱包")
|
||||||
|
public interface PayWalletApi {
|
||||||
|
|
||||||
|
String PREFIX = ApiConstants.PREFIX + "/wallet";
|
||||||
|
|
||||||
|
@PostMapping(PREFIX + "/add-balance")
|
||||||
|
@Operation(summary = "添加钱包余额")
|
||||||
|
CommonResult<Boolean> addWalletBalance(@Valid @RequestBody PayWalletAddBalanceReqDTO reqDTO);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package cn.iocoder.yudao.module.pay.api.wallet.dto;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钱包余额增加 Request DTO
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class PayWalletAddBalanceReqDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户编号
|
||||||
|
*
|
||||||
|
* 关联 MemberUserDO 的 id 属性,或者 AdminUserDO 的 id 属性
|
||||||
|
*/
|
||||||
|
@NotNull(message = "用户编号不能为空")
|
||||||
|
private Long userId;
|
||||||
|
/**
|
||||||
|
* 用户类型
|
||||||
|
*
|
||||||
|
* 关联 {@link UserTypeEnum}
|
||||||
|
*/
|
||||||
|
@NotNull(message = "用户类型不能为空")
|
||||||
|
private Integer userType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关联业务分类
|
||||||
|
*/
|
||||||
|
@NotNull(message = "关联业务分类不能为空")
|
||||||
|
private Integer bizType;
|
||||||
|
/**
|
||||||
|
* 关联业务编号
|
||||||
|
*/
|
||||||
|
@NotNull(message = "关联业务编号不能为空")
|
||||||
|
private String bizId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 交易金额,单位分
|
||||||
|
*
|
||||||
|
* 正值表示余额增加,负值表示余额减少
|
||||||
|
*/
|
||||||
|
@NotNull(message = "交易金额不能为空")
|
||||||
|
private Integer price;
|
||||||
|
|
||||||
|
}
|
|
@ -19,7 +19,8 @@ public enum PayWalletBizTypeEnum implements IntArrayValuable {
|
||||||
RECHARGE_REFUND(2, "充值退款"),
|
RECHARGE_REFUND(2, "充值退款"),
|
||||||
PAYMENT(3, "支付"),
|
PAYMENT(3, "支付"),
|
||||||
PAYMENT_REFUND(4, "支付退款"),
|
PAYMENT_REFUND(4, "支付退款"),
|
||||||
UPDATE_BALANCE(5, "更新余额");
|
UPDATE_BALANCE(5, "更新余额"),
|
||||||
|
BROKERAGE_WITHDRAW(6, "分佣提现");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 业务分类
|
* 业务分类
|
||||||
|
@ -36,4 +37,9 @@ public enum PayWalletBizTypeEnum implements IntArrayValuable {
|
||||||
public int[] array() {
|
public int[] array() {
|
||||||
return ARRAYS;
|
return ARRAYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static PayWalletBizTypeEnum valueOf(Integer type) {
|
||||||
|
return Arrays.stream(values()).filter(item -> item.getType().equals(type)).findFirst().orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
package cn.iocoder.yudao.module.pay.api.transfer;
|
package cn.iocoder.yudao.module.pay.api.transfer;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
|
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
|
||||||
|
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO;
|
||||||
|
import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
|
||||||
import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService;
|
import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
@ -27,4 +30,10 @@ public class PayTransferApiImpl implements PayTransferApi {
|
||||||
return success(payTransferService.createTransfer(reqDTO));
|
return success(payTransferService.createTransfer(reqDTO));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<PayTransferRespDTO> getTransfer(Long id) {
|
||||||
|
PayTransferDO transfer = payTransferService.getTransfer(id);
|
||||||
|
return success(BeanUtils.toBean(transfer, PayTransferRespDTO.class));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package cn.iocoder.yudao.module.pay.api.wallet;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletAddBalanceReqDTO;
|
||||||
|
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
|
||||||
|
import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
|
||||||
|
import cn.iocoder.yudao.module.pay.service.wallet.PayWalletService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钱包 API 实现类
|
||||||
|
*
|
||||||
|
* @author jason
|
||||||
|
*/
|
||||||
|
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||||
|
@Validated
|
||||||
|
public class PayWalletApiImpl implements PayWalletApi {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PayWalletService payWalletService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Boolean> addWalletBalance(PayWalletAddBalanceReqDTO reqDTO) {
|
||||||
|
// 创建或获取钱包
|
||||||
|
PayWalletDO wallet = payWalletService.getOrCreateWallet(reqDTO.getUserId(), reqDTO.getUserType());
|
||||||
|
Assert.notNull(wallet, "钱包({}/{})不存在", reqDTO.getUserId(), reqDTO.getUserType());
|
||||||
|
|
||||||
|
// 增加余额
|
||||||
|
PayWalletBizTypeEnum bizType = PayWalletBizTypeEnum.valueOf(reqDTO.getBizType());
|
||||||
|
payWalletService.addWalletBalance(wallet.getId(), reqDTO.getBizId(), bizType, reqDTO.getPrice());
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,18 +1,16 @@
|
||||||
package cn.iocoder.yudao.module.pay.controller.admin.app.vo;
|
package cn.iocoder.yudao.module.pay.controller.admin.app.vo;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.*;
|
||||||
import org.hibernate.validator.constraints.URL;
|
import org.hibernate.validator.constraints.URL;
|
||||||
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.*;
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付应用信息 Base VO,提供给添加、修改、详细的子 VO 使用
|
* 支付应用信息 Base VO,提供给添加、修改、详细的子 VO 使用
|
||||||
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
|
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class PayAppBaseVO {
|
public class PayAppBaseVO {
|
||||||
|
|
||||||
|
@ -42,4 +40,8 @@ public class PayAppBaseVO {
|
||||||
@URL(message = "退款结果的回调地址必须为 URL 格式")
|
@URL(message = "退款结果的回调地址必须为 URL 格式")
|
||||||
private String refundNotifyUrl;
|
private String refundNotifyUrl;
|
||||||
|
|
||||||
|
@Schema(description = "转账结果的回调地址", example = "http://127.0.0.1:48080/transfer-callback")
|
||||||
|
@URL(message = "转账结果的回调地址必须为 URL 格式")
|
||||||
|
private String transferNotifyUrl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
|
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
|
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
|
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
|
||||||
|
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
|
||||||
import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskDetailRespVO;
|
import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskDetailRespVO;
|
||||||
import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO;
|
import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO;
|
||||||
import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskRespVO;
|
import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskRespVO;
|
||||||
|
@ -18,6 +19,7 @@ import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
|
||||||
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
|
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
|
||||||
import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
|
import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
|
||||||
import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
|
import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
|
||||||
|
import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
@ -26,9 +28,9 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import javax.annotation.security.PermitAll;
|
import jakarta.annotation.security.PermitAll;
|
||||||
import javax.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -49,6 +51,8 @@ public class PayNotifyController {
|
||||||
@Resource
|
@Resource
|
||||||
private PayRefundService refundService;
|
private PayRefundService refundService;
|
||||||
@Resource
|
@Resource
|
||||||
|
private PayTransferService payTransferService;
|
||||||
|
@Resource
|
||||||
private PayNotifyService notifyService;
|
private PayNotifyService notifyService;
|
||||||
@Resource
|
@Resource
|
||||||
private PayAppService appService;
|
private PayAppService appService;
|
||||||
|
@ -65,7 +69,7 @@ public class PayNotifyController {
|
||||||
// 1. 校验支付渠道是否存在
|
// 1. 校验支付渠道是否存在
|
||||||
PayClient payClient = channelService.getPayClient(channelId);
|
PayClient payClient = channelService.getPayClient(channelId);
|
||||||
if (payClient == null) {
|
if (payClient == null) {
|
||||||
log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId);
|
log.error("[notifyOrder][渠道编号({}) 找不到对应的支付客户端]", channelId);
|
||||||
throw exception(CHANNEL_NOT_FOUND);
|
throw exception(CHANNEL_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +89,7 @@ public class PayNotifyController {
|
||||||
// 1. 校验支付渠道是否存在
|
// 1. 校验支付渠道是否存在
|
||||||
PayClient payClient = channelService.getPayClient(channelId);
|
PayClient payClient = channelService.getPayClient(channelId);
|
||||||
if (payClient == null) {
|
if (payClient == null) {
|
||||||
log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId);
|
log.error("[notifyRefund][渠道编号({}) 找不到对应的支付客户端]", channelId);
|
||||||
throw exception(CHANNEL_NOT_FOUND);
|
throw exception(CHANNEL_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,6 +99,26 @@ public class PayNotifyController {
|
||||||
return "success";
|
return "success";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping(value = "/transfer/{channelId}")
|
||||||
|
@Operation(summary = "支付渠道的统一【转账】回调")
|
||||||
|
@PermitAll
|
||||||
|
public String notifyTransfer(@PathVariable("channelId") Long channelId,
|
||||||
|
@RequestParam(required = false) Map<String, String> params,
|
||||||
|
@RequestBody(required = false) String body) {
|
||||||
|
log.info("[notifyTransfer][channelId({}) 回调数据({}/{})]", channelId, params, body);
|
||||||
|
// 1. 校验支付渠道是否存在
|
||||||
|
PayClient payClient = channelService.getPayClient(channelId);
|
||||||
|
if (payClient == null) {
|
||||||
|
log.error("[notifyTransfer][渠道编号({}) 找不到对应的支付客户端]", channelId);
|
||||||
|
throw exception(CHANNEL_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 解析通知数据
|
||||||
|
PayTransferRespDTO notify = payClient.parseTransferNotify(params, body);
|
||||||
|
payTransferService.notifyTransfer(channelId, notify);
|
||||||
|
return "success";
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/get-detail")
|
@GetMapping("/get-detail")
|
||||||
@Operation(summary = "获得回调通知的明细")
|
@Operation(summary = "获得回调通知的明细")
|
||||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||||
|
|
|
@ -27,4 +27,5 @@ public interface PayTransferConvert {
|
||||||
PayTransferRespVO convert(PayTransferDO bean);
|
PayTransferRespVO convert(PayTransferDO bean);
|
||||||
|
|
||||||
PageResult<PayTransferPageItemRespVO> convertPage(PageResult<PayTransferDO> pageResult);
|
PageResult<PayTransferPageItemRespVO> convertPage(PageResult<PayTransferDO> pageResult);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,10 +23,6 @@ public interface PayTransferMapper extends BaseMapperX<PayTransferDO> {
|
||||||
PayTransferDO::getMerchantTransferId, merchantTransferId);
|
PayTransferDO::getMerchantTransferId, merchantTransferId);
|
||||||
}
|
}
|
||||||
|
|
||||||
default PayTransferDO selectByNo(String no){
|
|
||||||
return selectOne(PayTransferDO::getNo, no);
|
|
||||||
}
|
|
||||||
|
|
||||||
default PageResult<PayTransferDO> selectPage(PayTransferPageReqVO reqVO) {
|
default PageResult<PayTransferDO> selectPage(PayTransferPageReqVO reqVO) {
|
||||||
return selectPage(reqVO, new LambdaQueryWrapperX<PayTransferDO>()
|
return selectPage(reqVO, new LambdaQueryWrapperX<PayTransferDO>()
|
||||||
.eqIfPresent(PayTransferDO::getNo, reqVO.getNo())
|
.eqIfPresent(PayTransferDO::getNo, reqVO.getNo())
|
||||||
|
@ -41,9 +37,15 @@ public interface PayTransferMapper extends BaseMapperX<PayTransferDO> {
|
||||||
.orderByDesc(PayTransferDO::getId));
|
.orderByDesc(PayTransferDO::getId));
|
||||||
}
|
}
|
||||||
|
|
||||||
default List<PayTransferDO> selectListByStatus(Integer status){
|
default List<PayTransferDO> selectListByStatus(Integer status) {
|
||||||
return selectList(PayTransferDO::getStatus, status);
|
return selectList(PayTransferDO::getStatus, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default PayTransferDO selectByAppIdAndNo(Long appId, String no) {
|
||||||
|
return selectOne(PayTransferDO::getAppId, appId,
|
||||||
|
PayTransferDO::getNo, no);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,19 @@ public interface PayWalletMapper extends BaseMapperX<PayWalletDO> {
|
||||||
return update(null, lambdaUpdateWrapper);
|
return update(null, lambdaUpdateWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 增加余额的时候,更新钱包
|
||||||
|
*
|
||||||
|
* @param id 钱包 id
|
||||||
|
* @param price 钱包金额
|
||||||
|
*/
|
||||||
|
default void updateWhenAdd(Long id, Integer price) {
|
||||||
|
LambdaUpdateWrapper<PayWalletDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<PayWalletDO>()
|
||||||
|
.setSql(" balance = balance + " + price)
|
||||||
|
.eq(PayWalletDO::getId, id);
|
||||||
|
update(null, lambdaUpdateWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 冻结钱包部分余额
|
* 冻结钱包部分余额
|
||||||
*
|
*
|
||||||
|
@ -114,7 +127,6 @@ public interface PayWalletMapper extends BaseMapperX<PayWalletDO> {
|
||||||
return update(null, lambdaUpdateWrapper);
|
return update(null, lambdaUpdateWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,15 @@ public class PayProperties {
|
||||||
@URL(message = "支付回调地址的格式必须是 URL")
|
@URL(message = "支付回调地址的格式必须是 URL")
|
||||||
private String refundNotifyUrl;
|
private String refundNotifyUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转账回调地址
|
||||||
|
*
|
||||||
|
* 实际上,对应的 PayNotifyController 的 notifyTransfer 方法的 URL
|
||||||
|
*
|
||||||
|
* 回调顺序:支付渠道(支付宝支付、微信支付) => yudao-module-pay 的 transferNotifyUrl 地址 => 业务的 PayAppDO.transferNotifyUrl 地址
|
||||||
|
*/
|
||||||
|
private String transferNotifyUrl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付订单 no 的前缀
|
* 支付订单 no 的前缀
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -177,6 +177,11 @@ public class WalletPayClient extends AbstractPayClient<NonePayClientConfig> {
|
||||||
throw new IllegalStateException(String.format("支付退款单[%s] 状态不正确", outRefundNo));
|
throw new IllegalStateException(String.format("支付退款单[%s] 状态不正确", outRefundNo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body) throws Throwable {
|
||||||
|
throw new UnsupportedOperationException("未实现");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
|
public PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
|
||||||
throw new UnsupportedOperationException("待实现");
|
throw new UnsupportedOperationException("待实现");
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.pay.service.transfer;
|
package cn.iocoder.yudao.module.pay.service.transfer;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
|
||||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
|
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
|
||||||
import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateReqVO;
|
import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateReqVO;
|
||||||
import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferPageReqVO;
|
import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferPageReqVO;
|
||||||
|
@ -54,4 +55,13 @@ public interface PayTransferService {
|
||||||
* @return 同步到状态的转账数量,包括转账成功、转账失败、转账中的
|
* @return 同步到状态的转账数量,包括转账成功、转账失败、转账中的
|
||||||
*/
|
*/
|
||||||
int syncTransfer();
|
int syncTransfer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渠道的转账通知
|
||||||
|
*
|
||||||
|
* @param channelId 渠道编号
|
||||||
|
* @param notify 通知
|
||||||
|
*/
|
||||||
|
void notifyTransfer(Long channelId, PayTransferRespDTO notify);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import cn.iocoder.yudao.module.pay.dal.mysql.transfer.PayTransferMapper;
|
||||||
import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO;
|
import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO;
|
||||||
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
|
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
|
||||||
import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum;
|
import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum;
|
||||||
|
import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties;
|
||||||
import cn.iocoder.yudao.module.pay.service.app.PayAppService;
|
import cn.iocoder.yudao.module.pay.service.app.PayAppService;
|
||||||
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
|
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
|
||||||
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
|
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
|
||||||
|
@ -50,6 +51,9 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||||
|
|
||||||
private static final String TRANSFER_NO_PREFIX = "T";
|
private static final String TRANSFER_NO_PREFIX = "T";
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PayProperties payProperties;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private PayTransferMapper transferMapper;
|
private PayTransferMapper transferMapper;
|
||||||
@Resource
|
@Resource
|
||||||
|
@ -96,13 +100,15 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||||
transfer = INSTANCE.convert(reqDTO)
|
transfer = INSTANCE.convert(reqDTO)
|
||||||
.setChannelId(channel.getId())
|
.setChannelId(channel.getId())
|
||||||
.setNo(no).setStatus(WAITING.getStatus())
|
.setNo(no).setStatus(WAITING.getStatus())
|
||||||
.setNotifyUrl(payApp.getTransferNotifyUrl());
|
.setNotifyUrl(payApp.getTransferNotifyUrl())
|
||||||
|
.setAppId(channel.getAppId());
|
||||||
transferMapper.insert(transfer);
|
transferMapper.insert(transfer);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// 3. 调用三方渠道发起转账
|
// 3. 调用三方渠道发起转账
|
||||||
PayTransferUnifiedReqDTO transferUnifiedReq = INSTANCE.convert2(transfer)
|
PayTransferUnifiedReqDTO transferUnifiedReq = INSTANCE.convert2(transfer)
|
||||||
.setOutTransferNo(transfer.getNo());
|
.setOutTransferNo(transfer.getNo());
|
||||||
|
transferUnifiedReq.setNotifyUrl(genChannelTransferNotifyUrl(channel));
|
||||||
PayTransferRespDTO unifiedTransferResp = client.unifiedTransfer(transferUnifiedReq);
|
PayTransferRespDTO unifiedTransferResp = client.unifiedTransfer(transferUnifiedReq);
|
||||||
// 4. 通知转账结果
|
// 4. 通知转账结果
|
||||||
getSelf().notifyTransfer(channel, unifiedTransferResp);
|
getSelf().notifyTransfer(channel, unifiedTransferResp);
|
||||||
|
@ -116,6 +122,16 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||||
return transfer.getId();
|
return transfer.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据支付渠道的编码,生成支付渠道的回调地址
|
||||||
|
*
|
||||||
|
* @param channel 支付渠道
|
||||||
|
* @return 支付渠道的回调地址 配置地址 + "/" + channel id
|
||||||
|
*/
|
||||||
|
private String genChannelTransferNotifyUrl(PayChannelDO channel) {
|
||||||
|
return payProperties.getTransferNotifyUrl() + "/" + channel.getId();
|
||||||
|
}
|
||||||
|
|
||||||
private PayTransferDO validateTransferCanCreate(PayTransferCreateReqDTO dto, Long appId) {
|
private PayTransferDO validateTransferCanCreate(PayTransferCreateReqDTO dto, Long appId) {
|
||||||
PayTransferDO transfer = transferMapper.selectByAppIdAndMerchantTransferId(appId, dto.getMerchantTransferId());
|
PayTransferDO transfer = transferMapper.selectByAppIdAndMerchantTransferId(appId, dto.getMerchantTransferId());
|
||||||
if (transfer != null) {
|
if (transfer != null) {
|
||||||
|
@ -154,7 +170,7 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||||
|
|
||||||
private void notifyTransferInProgress(PayChannelDO channel, PayTransferRespDTO notify) {
|
private void notifyTransferInProgress(PayChannelDO channel, PayTransferRespDTO notify) {
|
||||||
// 1.校验
|
// 1.校验
|
||||||
PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo());
|
PayTransferDO transfer = transferMapper.selectByAppIdAndNo(channel.getAppId(), notify.getOutTransferNo());
|
||||||
if (transfer == null) {
|
if (transfer == null) {
|
||||||
throw exception(PAY_TRANSFER_NOT_FOUND);
|
throw exception(PAY_TRANSFER_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
@ -172,16 +188,12 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||||
throw exception(PAY_TRANSFER_STATUS_IS_NOT_WAITING);
|
throw exception(PAY_TRANSFER_STATUS_IS_NOT_WAITING);
|
||||||
}
|
}
|
||||||
log.info("[notifyTransferInProgress][transfer({}) 更新为转账进行中状态]", transfer.getId());
|
log.info("[notifyTransferInProgress][transfer({}) 更新为转账进行中状态]", transfer.getId());
|
||||||
|
|
||||||
// 3. 插入转账通知记录
|
|
||||||
notifyService.createPayNotifyTask(PayNotifyTypeEnum.TRANSFER.getType(),
|
|
||||||
transfer.getId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void notifyTransferSuccess(PayChannelDO channel, PayTransferRespDTO notify) {
|
private void notifyTransferSuccess(PayChannelDO channel, PayTransferRespDTO notify) {
|
||||||
// 1.校验
|
// 1.校验
|
||||||
PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo());
|
PayTransferDO transfer = transferMapper.selectByAppIdAndNo(channel.getAppId(), notify.getOutTransferNo());
|
||||||
if (transfer == null) {
|
if (transfer == null) {
|
||||||
throw exception(PAY_TRANSFER_NOT_FOUND);
|
throw exception(PAY_TRANSFER_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
@ -210,7 +222,7 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||||
|
|
||||||
private void notifyTransferClosed(PayChannelDO channel, PayTransferRespDTO notify) {
|
private void notifyTransferClosed(PayChannelDO channel, PayTransferRespDTO notify) {
|
||||||
// 1.校验
|
// 1.校验
|
||||||
PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo());
|
PayTransferDO transfer = transferMapper.selectByAppIdAndNo(channel.getAppId(), notify.getOutTransferNo());
|
||||||
if (transfer == null) {
|
if (transfer == null) {
|
||||||
throw exception(PAY_TRANSFER_NOT_FOUND);
|
throw exception(PAY_TRANSFER_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
@ -283,7 +295,7 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyTransfer(Long channelId, PayTransferRespDTO notify) {
|
public void notifyTransfer(Long channelId, PayTransferRespDTO notify) {
|
||||||
// 校验渠道是否有效
|
// 校验渠道是否有效
|
||||||
PayChannelDO channel = channelService.validPayChannel(channelId);
|
PayChannelDO channel = channelService.validPayChannel(channelId);
|
||||||
// 通知转账结果给对应的业务
|
// 通知转账结果给对应的业务
|
||||||
|
|
|
@ -187,7 +187,7 @@ public class PayWalletServiceImpl implements PayWalletService {
|
||||||
|
|
||||||
// 2. 加锁,更新钱包余额(目的:避免钱包流水的并发更新时,余额变化不连贯)
|
// 2. 加锁,更新钱包余额(目的:避免钱包流水的并发更新时,余额变化不连贯)
|
||||||
return lockRedisDAO.lock(walletId, UPDATE_TIMEOUT_MILLIS, () -> {
|
return lockRedisDAO.lock(walletId, UPDATE_TIMEOUT_MILLIS, () -> {
|
||||||
// 2. 更新钱包金额
|
// 3. 更新钱包金额
|
||||||
switch (bizType) {
|
switch (bizType) {
|
||||||
case PAYMENT_REFUND: { // 退款更新
|
case PAYMENT_REFUND: { // 退款更新
|
||||||
walletMapper.updateWhenConsumptionRefund(payWallet.getId(), price);
|
walletMapper.updateWhenConsumptionRefund(payWallet.getId(), price);
|
||||||
|
@ -198,15 +198,15 @@ public class PayWalletServiceImpl implements PayWalletService {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case UPDATE_BALANCE: // 更新余额
|
case UPDATE_BALANCE: // 更新余额
|
||||||
walletMapper.updateWhenRecharge(payWallet.getId(), price);
|
case BROKERAGE_WITHDRAW: // 分佣提现
|
||||||
|
walletMapper.updateWhenAdd(payWallet.getId(), price);
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
// TODO 其它类型待实现
|
throw new UnsupportedOperationException("待实现:" + bizType);
|
||||||
throw new UnsupportedOperationException("待实现");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 生成钱包流水
|
// 4. 生成钱包流水
|
||||||
WalletTransactionCreateReqBO transactionCreateReqBO = new WalletTransactionCreateReqBO()
|
WalletTransactionCreateReqBO transactionCreateReqBO = new WalletTransactionCreateReqBO()
|
||||||
.setWalletId(payWallet.getId()).setPrice(price).setBalance(payWallet.getBalance() + price)
|
.setWalletId(payWallet.getId()).setPrice(price).setBalance(payWallet.getBalance() + price)
|
||||||
.setBizId(bizId).setBizType(bizType.getType()).setTitle(bizType.getDescription());
|
.setBizId(bizId).setBizType(bizType.getType()).setTitle(bizType.getDescription());
|
||||||
|
|
|
@ -109,4 +109,5 @@ yudao:
|
||||||
pay:
|
pay:
|
||||||
order-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/order # 支付渠道的【支付】回调地址
|
order-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/order # 支付渠道的【支付】回调地址
|
||||||
refund-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/refund # 支付渠道的【退款】回调地址
|
refund-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/refund # 支付渠道的【退款】回调地址
|
||||||
|
transfer-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/transfer # 支付渠道的【转账】回调地址
|
||||||
demo: true # 关闭演示模式
|
demo: true # 关闭演示模式
|
||||||
|
|
|
@ -138,3 +138,4 @@ yudao:
|
||||||
pay:
|
pay:
|
||||||
order-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/order # 支付渠道的【支付】回调地址
|
order-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/order # 支付渠道的【支付】回调地址
|
||||||
refund-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/refund # 支付渠道的【退款】回调地址
|
refund-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/refund # 支付渠道的【退款】回调地址
|
||||||
|
transfer-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/transfer # 支付渠道的【转账】回调地址
|
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.pay.config;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
|
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.impl.PayClientFactoryImpl;
|
import cn.iocoder.yudao.framework.pay.core.client.impl.PayClientFactoryImpl;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -79,6 +79,8 @@ public interface PayClient {
|
||||||
*/
|
*/
|
||||||
PayRefundRespDTO getRefund(String outTradeNo, String outRefundNo);
|
PayRefundRespDTO getRefund(String outTradeNo, String outRefundNo);
|
||||||
|
|
||||||
|
// ============ 转账相关 ==========
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 调用渠道,进行转账
|
* 调用渠道,进行转账
|
||||||
*
|
*
|
||||||
|
@ -95,4 +97,14 @@ public interface PayClient {
|
||||||
* @return 转账信息
|
* @return 转账信息
|
||||||
*/
|
*/
|
||||||
PayTransferRespDTO getTransfer(String outTradeNo, PayTransferTypeEnum type);
|
PayTransferRespDTO getTransfer(String outTradeNo, PayTransferTypeEnum type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析 transfer 回调数据
|
||||||
|
*
|
||||||
|
* @param params HTTP 回调接口 content type 为 application/x-www-form-urlencoded 的所有参数
|
||||||
|
* @param body HTTP 回调接口的 request body
|
||||||
|
* @return 转账信息
|
||||||
|
*/
|
||||||
|
PayTransferRespDTO parseTransferNotify(Map<String, String> params, String body);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ package cn.iocoder.yudao.framework.pay.core.client;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||||
|
|
||||||
import javax.validation.Validator;
|
import jakarta.validation.Validator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付客户端的配置,本质是支付渠道的配置
|
* 支付客户端的配置,本质是支付渠道的配置
|
||||||
|
|
|
@ -5,9 +5,9 @@ import lombok.Data;
|
||||||
import org.hibernate.validator.constraints.Length;
|
import org.hibernate.validator.constraints.Length;
|
||||||
import org.hibernate.validator.constraints.URL;
|
import org.hibernate.validator.constraints.URL;
|
||||||
|
|
||||||
import javax.validation.constraints.DecimalMin;
|
import jakarta.validation.constraints.DecimalMin;
|
||||||
import javax.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import javax.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,9 @@ import lombok.NoArgsConstructor;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
import org.hibernate.validator.constraints.URL;
|
import org.hibernate.validator.constraints.URL;
|
||||||
|
|
||||||
import javax.validation.constraints.DecimalMin;
|
import jakarta.validation.constraints.DecimalMin;
|
||||||
import javax.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import javax.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 统一 退款 Request DTO
|
* 统一 退款 Request DTO
|
||||||
|
|
|
@ -5,14 +5,15 @@ import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.hibernate.validator.constraints.Length;
|
import org.hibernate.validator.constraints.Length;
|
||||||
|
|
||||||
import javax.validation.constraints.Min;
|
import jakarta.validation.constraints.Min;
|
||||||
import javax.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import javax.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import javax.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import org.hibernate.validator.constraints.URL;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum.Alipay;
|
import static cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum.*;
|
||||||
import static cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum.WxPay;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 统一转账 Request DTO
|
* 统一转账 Request DTO
|
||||||
|
@ -76,4 +77,12 @@ public class PayTransferUnifiedReqDTO {
|
||||||
* 支付渠道的额外参数
|
* 支付渠道的额外参数
|
||||||
*/
|
*/
|
||||||
private Map<String, String> channelExtras;
|
private Map<String, String> channelExtras;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转账结果的 notify 回调地址
|
||||||
|
*/
|
||||||
|
@NotEmpty(message = "转账结果的回调地址不能为空")
|
||||||
|
@URL(message = "转账结果的 notify 回调地址必须是 URL 格式")
|
||||||
|
private String notifyUrl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
package cn.iocoder.yudao.framework.pay.core.client.dto.transfer;
|
||||||
|
|
||||||
|
import com.github.binarywang.wxpay.bean.notify.OriginNotifyResponse;
|
||||||
|
import com.github.binarywang.wxpay.bean.notify.WxPayBaseNotifyV3Result;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
// TODO @luchi:这个可以复用 wxjava 里的类么?
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class WxPayTransferPartnerNotifyV3Result implements Serializable, WxPayBaseNotifyV3Result<WxPayTransferPartnerNotifyV3Result.TransferNotifyResult> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 源数据
|
||||||
|
*/
|
||||||
|
private OriginNotifyResponse rawData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解密后的数据
|
||||||
|
*/
|
||||||
|
private TransferNotifyResult result;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRawData(OriginNotifyResponse rawData) {
|
||||||
|
this.rawData = rawData;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setResult(TransferNotifyResult data) {
|
||||||
|
this.result = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TransferNotifyResult getResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OriginNotifyResponse getRawData() {
|
||||||
|
return rawData;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public static class TransferNotifyResult implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/*********************** 公共字段 ********************
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商家批次单号
|
||||||
|
*/
|
||||||
|
@SerializedName(value = "out_batch_no")
|
||||||
|
protected String outBatchNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信批次单号
|
||||||
|
*/
|
||||||
|
@SerializedName(value = "batch_id")
|
||||||
|
protected String batchId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批次状态
|
||||||
|
*/
|
||||||
|
@SerializedName(value = "batch_status")
|
||||||
|
protected String batchStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批次总笔数
|
||||||
|
*/
|
||||||
|
@SerializedName(value = "total_num")
|
||||||
|
protected Integer totalNum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批次总金额
|
||||||
|
*/
|
||||||
|
@SerializedName(value = "total_amount")
|
||||||
|
protected Integer totalAmount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批次更新时间
|
||||||
|
*/
|
||||||
|
@SerializedName(value = "update_time")
|
||||||
|
private String updateTime;
|
||||||
|
|
||||||
|
/*********************** FINISHED ********************
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转账成功金额
|
||||||
|
*/
|
||||||
|
@SerializedName(value = "success_amount")
|
||||||
|
protected Integer successAmount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转账成功笔数
|
||||||
|
*/
|
||||||
|
@SerializedName(value = "success_num")
|
||||||
|
protected Integer successNum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转账失败金额
|
||||||
|
*/
|
||||||
|
@SerializedName(value = "fail_amount")
|
||||||
|
protected Integer failAmount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转账失败笔数
|
||||||
|
*/
|
||||||
|
@SerializedName(value = "fail_num")
|
||||||
|
protected Integer failNum;
|
||||||
|
|
||||||
|
/*********************** CLOSED ********************
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商户号
|
||||||
|
*/
|
||||||
|
@SerializedName(value = "mchid")
|
||||||
|
protected String mchId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批次关闭原因
|
||||||
|
*/
|
||||||
|
@SerializedName(value = "close_reason")
|
||||||
|
protected String closeReason;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -219,6 +219,22 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final PayTransferRespDTO parseTransferNotify(Map<String, String> params, String body) {
|
||||||
|
try {
|
||||||
|
return doParseTransferNotify(params, body);
|
||||||
|
} catch (ServiceException ex) { // 业务异常,都是实现类已经翻译,所以直接抛出即可
|
||||||
|
throw ex;
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
log.error("[doParseTransferNotify][客户端({}) params({}) body({}) 解析失败]",
|
||||||
|
getId(), params, body, ex);
|
||||||
|
throw buildPayException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body)
|
||||||
|
throws Throwable;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final PayTransferRespDTO getTransfer(String outTradeNo, PayTransferTypeEnum type) {
|
public final PayTransferRespDTO getTransfer(String outTradeNo, PayTransferTypeEnum type) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -3,7 +3,7 @@ package cn.iocoder.yudao.framework.pay.core.client.impl;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
|
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import javax.validation.Validator;
|
import jakarta.validation.Validator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 无需任何配置 PayClientConfig 实现类
|
* 无需任何配置 PayClientConfig 实现类
|
||||||
|
|
|
@ -325,6 +325,12 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO @chihuo:这里是不是也要实现,支付宝的。
|
||||||
|
@Override
|
||||||
|
protected PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body) throws Throwable {
|
||||||
|
throw new UnsupportedOperationException("未实现");
|
||||||
|
}
|
||||||
|
|
||||||
// ========== 各种工具方法 ==========
|
// ========== 各种工具方法 ==========
|
||||||
|
|
||||||
protected String formatAmount(Integer amount) {
|
protected String formatAmount(Integer amount) {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
|
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
|
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
|
||||||
|
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
|
||||||
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
|
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
|
||||||
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
|
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
|
||||||
import com.alipay.api.AlipayApiException;
|
import com.alipay.api.AlipayApiException;
|
||||||
|
@ -56,4 +57,5 @@ public class AlipayAppPayClient extends AbstractAlipayPayClient {
|
||||||
return PayOrderRespDTO.waitingOf(displayMode, response.getBody(),
|
return PayOrderRespDTO.waitingOf(displayMode, response.getBody(),
|
||||||
reqDTO.getOutTradeNo(), response);
|
reqDTO.getOutTradeNo(), response);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
|
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
|
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
|
||||||
|
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
|
||||||
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
|
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
|
||||||
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
|
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
|
||||||
import com.alipay.api.AlipayApiException;
|
import com.alipay.api.AlipayApiException;
|
||||||
|
@ -82,4 +83,5 @@ public class AlipayBarPayClient extends AbstractAlipayPayClient {
|
||||||
return PayOrderRespDTO.waitingOf(displayMode, "",
|
return PayOrderRespDTO.waitingOf(displayMode, "",
|
||||||
reqDTO.getOutTradeNo(), response);
|
reqDTO.getOutTradeNo(), response);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.http.Method;
|
import cn.hutool.http.Method;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
|
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
|
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
|
||||||
|
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
|
||||||
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
|
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
|
||||||
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
|
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
|
||||||
import com.alipay.api.AlipayApiException;
|
import com.alipay.api.AlipayApiException;
|
||||||
|
@ -66,4 +67,5 @@ public class AlipayPcPayClient extends AbstractAlipayPayClient {
|
||||||
return PayOrderRespDTO.waitingOf(displayMode, response.getBody(),
|
return PayOrderRespDTO.waitingOf(displayMode, response.getBody(),
|
||||||
reqDTO.getOutTradeNo(), response);
|
reqDTO.getOutTradeNo(), response);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,11 @@ public class MockPayClient extends AbstractPayClient<NonePayClientConfig> {
|
||||||
outRefundNo, MOCK_RESP_SUCCESS_DATA);
|
outRefundNo, MOCK_RESP_SUCCESS_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body) throws Throwable {
|
||||||
|
throw new UnsupportedOperationException("未实现");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body) {
|
protected PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body) {
|
||||||
throw new UnsupportedOperationException("模拟支付无退款回调");
|
throw new UnsupportedOperationException("模拟支付无退款回调");
|
||||||
|
|
|
@ -14,6 +14,7 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
|
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
|
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
|
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
|
||||||
|
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.WxPayTransferPartnerNotifyV3Result;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
|
import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
|
||||||
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum;
|
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum;
|
||||||
import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
|
import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
|
||||||
|
@ -23,6 +24,10 @@ import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
|
||||||
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyV3Result;
|
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyV3Result;
|
||||||
import com.github.binarywang.wxpay.bean.request.*;
|
import com.github.binarywang.wxpay.bean.request.*;
|
||||||
import com.github.binarywang.wxpay.bean.result.*;
|
import com.github.binarywang.wxpay.bean.result.*;
|
||||||
|
import com.github.binarywang.wxpay.bean.transfer.QueryTransferBatchesRequest;
|
||||||
|
import com.github.binarywang.wxpay.bean.transfer.QueryTransferBatchesResult;
|
||||||
|
import com.github.binarywang.wxpay.bean.transfer.TransferBatchesRequest;
|
||||||
|
import com.github.binarywang.wxpay.bean.transfer.TransferBatchesResult;
|
||||||
import com.github.binarywang.wxpay.config.WxPayConfig;
|
import com.github.binarywang.wxpay.config.WxPayConfig;
|
||||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||||
import com.github.binarywang.wxpay.service.WxPayService;
|
import com.github.binarywang.wxpay.service.WxPayService;
|
||||||
|
@ -31,6 +36,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@ -349,6 +356,33 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
|
||||||
return PayRefundRespDTO.failureOf(result.getOutRefundNo(), response);
|
return PayRefundRespDTO.failureOf(result.getOutRefundNo(), response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body) throws WxPayException {
|
||||||
|
switch (config.getApiVersion()) {
|
||||||
|
case API_VERSION_V3:
|
||||||
|
return parseTransferNotifyV3(body);
|
||||||
|
case API_VERSION_V2:
|
||||||
|
throw new UnsupportedOperationException("V2 版本暂不支持,建议使用 V3 版本");
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PayTransferRespDTO parseTransferNotifyV3(String body) throws WxPayException {
|
||||||
|
// 1. 解析回调
|
||||||
|
// TODO @luchi:这个可以复用 wxjava 里的类么?
|
||||||
|
WxPayTransferPartnerNotifyV3Result response = client.baseParseOrderNotifyV3Result(body, null, WxPayTransferPartnerNotifyV3Result.class, WxPayTransferPartnerNotifyV3Result.TransferNotifyResult.class);
|
||||||
|
WxPayTransferPartnerNotifyV3Result.TransferNotifyResult result = response.getResult();
|
||||||
|
// 2. 构建结果
|
||||||
|
if (Objects.equals("FINISHED", result.getBatchStatus())) {
|
||||||
|
if (result.getFailNum() <= 0) {
|
||||||
|
return PayTransferRespDTO.successOf(result.getBatchId(), parseDateV3(result.getUpdateTime()),
|
||||||
|
result.getOutBatchNo(), response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PayTransferRespDTO.closedOf(result.getBatchStatus(), result.getCloseReason(), result.getOutBatchNo(), response);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) throws WxPayException {
|
protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) throws WxPayException {
|
||||||
try {
|
try {
|
||||||
|
@ -427,13 +461,54 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
|
protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) throws WxPayException {
|
||||||
throw new UnsupportedOperationException("待实现");
|
// 1. 构建 TransferBatchesRequest 请求
|
||||||
|
List<TransferBatchesRequest.TransferDetail> transferDetailList = Collections.singletonList(
|
||||||
|
TransferBatchesRequest.TransferDetail.newBuilder()
|
||||||
|
.outDetailNo(reqDTO.getOutTransferNo())
|
||||||
|
.transferAmount(reqDTO.getPrice())
|
||||||
|
.transferRemark(reqDTO.getSubject())
|
||||||
|
.openid(reqDTO.getOpenid())
|
||||||
|
.build());
|
||||||
|
// TODO @luchi:能不能我们搞个 TransferBatchesRequestX extends TransferBatchesRequest,这样更简洁一点。
|
||||||
|
TransferBatchesRequest transferBatches = TransferBatchesRequest.newBuilder()
|
||||||
|
.appid(this.config.getAppId())
|
||||||
|
.outBatchNo(reqDTO.getOutTransferNo())
|
||||||
|
.batchName(reqDTO.getSubject())
|
||||||
|
.batchRemark(reqDTO.getSubject())
|
||||||
|
.totalAmount(reqDTO.getPrice())
|
||||||
|
.totalNum(transferDetailList.size())
|
||||||
|
.transferDetailList(transferDetailList).build()
|
||||||
|
.setNotifyUrl(reqDTO.getNotifyUrl());
|
||||||
|
// 2.1 执行请求
|
||||||
|
TransferBatchesResult transferBatchesResult = client.getTransferService().transferBatches(transferBatches);
|
||||||
|
// 2.2 创建返回结果
|
||||||
|
return PayTransferRespDTO.dealingOf(transferBatchesResult.getBatchId(), reqDTO.getOutTransferNo(), transferBatchesResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PayTransferRespDTO doGetTransfer(String outTradeNo, PayTransferTypeEnum type) {
|
protected PayTransferRespDTO doGetTransfer(String outTradeNo, PayTransferTypeEnum type) throws WxPayException {
|
||||||
throw new UnsupportedOperationException("待实现");
|
QueryTransferBatchesRequest request = QueryTransferBatchesRequest.newBuilder()
|
||||||
|
.outBatchNo(outTradeNo).needQueryDetail(true).offset(0).limit(20).detailStatus("ALL")
|
||||||
|
.build();
|
||||||
|
QueryTransferBatchesResult response = client.getTransferService().transferBatchesOutBatchNo(request);
|
||||||
|
QueryTransferBatchesResult.TransferBatch transferBatch = response.getTransferBatch();
|
||||||
|
if (Objects.equals("FINISHED", transferBatch.getBatchStatus())) {
|
||||||
|
// 明细中全部成功则成功,任一失败则失败
|
||||||
|
if (response.getTransferDetailList().stream().allMatch(detail -> Objects.equals("SUCCESS", detail.getDetailStatus()))) {
|
||||||
|
return PayTransferRespDTO.successOf(transferBatch.getBatchId(), parseDateV3(transferBatch.getUpdateTime()),
|
||||||
|
transferBatch.getOutBatchNo(), response);
|
||||||
|
}
|
||||||
|
if (response.getTransferDetailList().stream().anyMatch(detail -> Objects.equals("FAIL", detail.getDetailStatus()))) {
|
||||||
|
return PayTransferRespDTO.closedOf(transferBatch.getBatchStatus(), transferBatch.getCloseReason(),
|
||||||
|
transferBatch.getOutBatchNo(), response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Objects.equals("CLOSED", transferBatch.getBatchStatus())) {
|
||||||
|
return PayTransferRespDTO.closedOf(transferBatch.getBatchStatus(), transferBatch.getCloseReason(),
|
||||||
|
transferBatch.getOutBatchNo(), response);
|
||||||
|
}
|
||||||
|
return PayTransferRespDTO.dealingOf(transferBatch.getBatchId(), transferBatch.getOutBatchNo(), response);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== 各种工具方法 ==========
|
// ========== 各种工具方法 ==========
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package cn.iocoder.yudao.framework.pay.core.enums.channel;
|
package cn.iocoder.yudao.framework.pay.core.enums.channel;
|
||||||
|
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
|
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.impl.NonePayClientConfig;
|
import cn.iocoder.yudao.framework.pay.core.client.impl.NonePayClientConfig;
|
||||||
|
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig;
|
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.impl.weixin.WxPayClientConfig;
|
import cn.iocoder.yudao.framework.pay.core.client.impl.weixin.WxPayClientConfig;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
package com.github.binarywang.wxpay.bean.transfer;
|
||||||
|
|
||||||
|
import com.github.binarywang.wxpay.v3.SpecEncrypt;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发起商家转账API参数
|
||||||
|
*
|
||||||
|
* @author zhongjun
|
||||||
|
* created on 2022/6/17
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
@Builder(builderMethodName = "newBuilder")
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class TransferBatchesRequest implements Serializable {
|
||||||
|
private static final long serialVersionUID = -2175582517588397426L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 直连商户的appid
|
||||||
|
*/
|
||||||
|
@SerializedName("appid")
|
||||||
|
private String appid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商家批次单号
|
||||||
|
*/
|
||||||
|
@SerializedName("out_batch_no")
|
||||||
|
private String outBatchNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批次名称
|
||||||
|
*/
|
||||||
|
@SerializedName("batch_name")
|
||||||
|
private String batchName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批次备注
|
||||||
|
*/
|
||||||
|
@SerializedName("batch_remark")
|
||||||
|
private String batchRemark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转账总金额
|
||||||
|
*/
|
||||||
|
@SerializedName("total_amount")
|
||||||
|
private Integer totalAmount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转账总笔数
|
||||||
|
*/
|
||||||
|
@SerializedName("total_num")
|
||||||
|
private Integer totalNum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转账明细列表
|
||||||
|
*/
|
||||||
|
@SpecEncrypt
|
||||||
|
@SerializedName("transfer_detail_list")
|
||||||
|
private List<TransferDetail> transferDetailList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转账场景ID
|
||||||
|
*/
|
||||||
|
@SerializedName("transfer_scene_id")
|
||||||
|
private String transferSceneId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通知地址 说明:异步接收微信支付结果通知的回调地址,通知url必须为公网可访问的url,必须为https,不能携带参数。
|
||||||
|
*/
|
||||||
|
@SerializedName("notify_url")
|
||||||
|
private String notifyUrl;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder(builderMethodName = "newBuilder")
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public static class TransferDetail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商家明细单号
|
||||||
|
*/
|
||||||
|
@SerializedName("out_detail_no")
|
||||||
|
private String outDetailNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转账金额
|
||||||
|
*/
|
||||||
|
@SerializedName("transfer_amount")
|
||||||
|
private Integer transferAmount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转账备注
|
||||||
|
*/
|
||||||
|
@SerializedName("transfer_remark")
|
||||||
|
private String transferRemark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户在直连商户应用下的用户标示
|
||||||
|
*/
|
||||||
|
@SerializedName("openid")
|
||||||
|
private String openid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 收款用户姓名
|
||||||
|
*/
|
||||||
|
@SpecEncrypt
|
||||||
|
@SerializedName("user_name")
|
||||||
|
private String userName;
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,4 +35,7 @@ public class UserPageReqVO extends PageParam {
|
||||||
@Schema(description = "部门编号,同时筛选子部门", example = "1024")
|
@Schema(description = "部门编号,同时筛选子部门", example = "1024")
|
||||||
private Long deptId;
|
private Long deptId;
|
||||||
|
|
||||||
|
@Schema(description = "角色编号", example = "1024")
|
||||||
|
private Long roleId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,13 +25,14 @@ public interface AdminUserMapper extends BaseMapperX<AdminUserDO> {
|
||||||
return selectOne(AdminUserDO::getMobile, mobile);
|
return selectOne(AdminUserDO::getMobile, mobile);
|
||||||
}
|
}
|
||||||
|
|
||||||
default PageResult<AdminUserDO> selectPage(UserPageReqVO reqVO, Collection<Long> deptIds) {
|
default PageResult<AdminUserDO> selectPage(UserPageReqVO reqVO, Collection<Long> deptIds, Collection<Long> userIds) {
|
||||||
return selectPage(reqVO, new LambdaQueryWrapperX<AdminUserDO>()
|
return selectPage(reqVO, new LambdaQueryWrapperX<AdminUserDO>()
|
||||||
.likeIfPresent(AdminUserDO::getUsername, reqVO.getUsername())
|
.likeIfPresent(AdminUserDO::getUsername, reqVO.getUsername())
|
||||||
.likeIfPresent(AdminUserDO::getMobile, reqVO.getMobile())
|
.likeIfPresent(AdminUserDO::getMobile, reqVO.getMobile())
|
||||||
.eqIfPresent(AdminUserDO::getStatus, reqVO.getStatus())
|
.eqIfPresent(AdminUserDO::getStatus, reqVO.getStatus())
|
||||||
.betweenIfPresent(AdminUserDO::getCreateTime, reqVO.getCreateTime())
|
.betweenIfPresent(AdminUserDO::getCreateTime, reqVO.getCreateTime())
|
||||||
.inIfPresent(AdminUserDO::getDeptId, deptIds)
|
.inIfPresent(AdminUserDO::getDeptId, deptIds)
|
||||||
|
.inIfPresent(AdminUserDO::getId, userIds)
|
||||||
.orderByDesc(AdminUserDO::getId));
|
.orderByDesc(AdminUserDO::getId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,8 +46,7 @@ import java.time.LocalDateTime;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
|
||||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
||||||
import static cn.iocoder.yudao.module.system.enums.LogRecordConstants.*;
|
import static cn.iocoder.yudao.module.system.enums.LogRecordConstants.*;
|
||||||
|
|
||||||
|
@ -272,7 +271,12 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageResult<AdminUserDO> getUserPage(UserPageReqVO reqVO) {
|
public PageResult<AdminUserDO> getUserPage(UserPageReqVO reqVO) {
|
||||||
return userMapper.selectPage(reqVO, getDeptCondition(reqVO.getDeptId()));
|
// 如果有角色编号,查询角色对应的用户编号
|
||||||
|
Set<Long> userIds = reqVO.getRoleId() != null ?
|
||||||
|
permissionService.getUserRoleIdListByRoleId(singleton(reqVO.getRoleId())) : null;
|
||||||
|
|
||||||
|
// 分页查询
|
||||||
|
return userMapper.selectPage(reqVO, getDeptCondition(reqVO.getDeptId()), userIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in New Issue