提交 4dd9e647 authored 作者: hzh's avatar hzh

商城模块集成

上级 dfc345a1
package org.dromara.mall.controller.trade.admin.aftersale;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.collection.CollUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.mybatis.core.page.PageResult;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.mall.api.dto.member.MemberUserRespDTO;
import org.dromara.mall.api.dto.pay.PayRefundNotifyReqDTO;
import org.dromara.mall.api.service.member.MemberUserApi;
import org.dromara.mall.controller.trade.admin.aftersale.vo.*;
import org.dromara.mall.convert.trade.aftersale.AfterSaleConvert;
import org.dromara.mall.domain.trade.AfterSaleDO;
import org.dromara.mall.domain.trade.AfterSaleLogDO;
import org.dromara.mall.domain.trade.TradeOrderDO;
import org.dromara.mall.domain.trade.TradeOrderItemDO;
import org.dromara.mall.service.trade.aftersale.AfterSaleLogService;
import org.dromara.mall.service.trade.aftersale.AfterSaleService;
import org.dromara.mall.service.trade.order.TradeOrderQueryService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
import static org.dromara.common.core.utils.ServletUtils.getClientIP;
import static org.dromara.common.mall.util.collection.CollectionUtils.convertSet;
@Tag(name = "管理后台 - 售后订单")
@RestController
@RequestMapping("/admin/trade/after-sale")
@Validated
@Slf4j
public class AfterSaleController {
@Resource
private AfterSaleService afterSaleService;
@Resource
private TradeOrderQueryService tradeOrderQueryService;
@Resource
private AfterSaleLogService afterSaleLogService;
@Resource
private MemberUserApi memberUserApi;
@GetMapping("/page")
@Operation(summary = "获得售后订单分页")
@SaCheckPermission("trade:after-sale:query")
public R<PageResult<AfterSaleRespPageItemVO>> getAfterSalePage(@Valid AfterSalePageReqVO pageVO) {
// 查询售后
PageResult<AfterSaleDO> pageResult = afterSaleService.getAfterSalePage(pageVO);
if (CollUtil.isEmpty(pageResult.getList())) {
return R.ok(PageResult.empty());
}
// 查询会员
Map<Long, MemberUserRespDTO> memberUsers = memberUserApi.getUserMap(
convertSet(pageResult.getList(), AfterSaleDO::getUserId));
return R.ok(AfterSaleConvert.INSTANCE.convertPage(pageResult, memberUsers));
}
@GetMapping("/get-detail")
@Operation(summary = "获得售后订单详情")
@Parameter(name = "id", description = "售后编号", required = true, example = "1")
@SaCheckPermission("trade:after-sale:query")
public R<AfterSaleDetailRespVO> getOrderDetail(@RequestParam("id") Long id) {
// 查询订单
AfterSaleDO afterSale = afterSaleService.getAfterSale(id);
if (afterSale == null) {
return R.ok(null);
}
// 查询订单
TradeOrderDO order = tradeOrderQueryService.getOrder(afterSale.getOrderId());
// 查询订单项
TradeOrderItemDO orderItem = tradeOrderQueryService.getOrderItem(afterSale.getOrderItemId());
// 拼接数据
MemberUserRespDTO user = memberUserApi.getUser(afterSale.getUserId());
List<AfterSaleLogDO> logs = afterSaleLogService.getAfterSaleLogList(afterSale.getId());
return R.ok(AfterSaleConvert.INSTANCE.convert(afterSale, order, orderItem, user, logs));
}
@PutMapping("/agree")
@Operation(summary = "同意售后")
@Parameter(name = "id", description = "售后编号", required = true, example = "1")
@SaCheckPermission("trade:after-sale:agree")
public R<Boolean> agreeAfterSale(@RequestParam("id") Long id) {
afterSaleService.agreeAfterSale(LoginHelper.getUserId(), id);
return R.ok(true);
}
@PutMapping("/disagree")
@Operation(summary = "拒绝售后")
@SaCheckPermission("trade:after-sale:disagree")
public R<Boolean> disagreeAfterSale(@RequestBody AfterSaleDisagreeReqVO confirmReqVO) {
afterSaleService.disagreeAfterSale(LoginHelper.getUserId(), confirmReqVO);
return R.ok(true);
}
@PutMapping("/receive")
@Operation(summary = "确认收货")
@Parameter(name = "id", description = "售后编号", required = true, example = "1")
@SaCheckPermission("trade:after-sale:receive")
public R<Boolean> receiveAfterSale(@RequestParam("id") Long id) {
afterSaleService.receiveAfterSale(LoginHelper.getUserId(), id);
return R.ok(true);
}
@PutMapping("/refuse")
@Operation(summary = "拒绝收货")
@Parameter(name = "id", description = "售后编号", required = true, example = "1")
@SaCheckPermission("trade:after-sale:receive")
public R<Boolean> refuseAfterSale(AfterSaleRefuseReqVO refuseReqVO) {
afterSaleService.refuseAfterSale(LoginHelper.getUserId(), refuseReqVO);
return R.ok(true);
}
@PutMapping("/refund")
@Operation(summary = "确认退款")
@Parameter(name = "id", description = "售后编号", required = true, example = "1")
@SaCheckPermission("trade:after-sale:refund")
public R<Boolean> refundAfterSale(@RequestParam("id") Long id) {
afterSaleService.refundAfterSale(LoginHelper.getUserId(), getClientIP(), id);
return R.ok(true);
}
@PostMapping("/update-refunded")
@Operation(summary = "更新售后订单为已退款") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob
@PermitAll // 无需登录,安全由 PayDemoOrderService 内部校验实现
public R<Boolean> updateAfterRefund(@RequestBody PayRefundNotifyReqDTO notifyReqDTO) {
// 目前业务逻辑,不需要做任何事情
// 当然,退款会有小概率会失败的情况,可以监控失败状态,进行告警
log.info("[updateAfterRefund][notifyReqDTO({})]", notifyReqDTO);
return R.ok(true);
}
}
### 获得交易售后分页 => 成功
GET {{baseUrl}}/trade/after-sale/page?pageNo=1&pageSize=10
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
### 同意售后 => 成功
PUT {{baseUrl}}/trade/after-sale/agree?id=7
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
Content-Type: application/json
### 拒绝售后 => 成功
PUT {{baseUrl}}/trade/after-sale/disagree
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
Content-Type: application/json
{
"id": 6,
"auditReason": "阿巴巴"
}
### 确认退款 => 成功
PUT {{baseUrl}}/trade/after-sale/refund?id=6
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
Content-Type: application/json
### 确认收货 => 成功
PUT {{baseUrl}}/trade/after-sale/receive?id=7
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
Content-Type: application/json
package org.dromara.mall.controller.trade.admin.aftersale.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import java.util.List;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 交易售后 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class AfterSaleBaseVO {
@Schema(description = "售后流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "202211190847450020500077")
@NotNull(message = "售后流水号不能为空")
private String no;
@Schema(description = "售后状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
@NotNull(message = "售后状态不能为空")
private Integer status;
@Schema(description = "售后类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
@NotNull(message = "售后类型不能为空")
private Integer type;
@Schema(description = "售后方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
@NotNull(message = "售后方式不能为空")
private Integer way;
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30337")
@NotNull(message = "用户编号不能为空")
private Long userId;
@Schema(description = "申请原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "不喜欢")
@NotNull(message = "申请原因不能为空")
private String applyReason;
@Schema(description = "补充描述", example = "你说的对")
private String applyDescription;
@Schema(description = "补充凭证图片", example = "https://www.iocoder.cn/1.png")
private List<String> applyPicUrls;
@Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18078")
@NotNull(message = "订单编号不能为空")
private Long orderId;
@Schema(description = "订单流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2022111917190001")
@NotNull(message = "订单流水号不能为空")
private String orderNo;
@Schema(description = "订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "572")
@NotNull(message = "订单项编号不能为空")
private Long orderItemId;
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2888")
@NotNull(message = "商品 SPU 编号不能为空")
private Long spuId;
@Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
@NotNull(message = "商品 SPU 名称不能为空")
private String spuName;
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15657")
@NotNull(message = "商品 SKU 编号不能为空")
private Long skuId;
@Schema(description = "商品图片", example = "https://www.iocoder.cn/2.png")
private String picUrl;
@Schema(description = "购买数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20012")
@NotNull(message = "购买数量不能为空")
private Integer count;
@Schema(description = "审批时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime auditTime;
@Schema(description = "审批人", example = "30835")
private Long auditUserId;
@Schema(description = "审批备注", example = "不香")
private String auditReason;
@Schema(description = "退款金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "18077")
@NotNull(message = "退款金额,单位:分不能为空")
private Integer refundPrice;
@Schema(description = "支付退款编号", example = "10271")
private Long payRefundId;
@Schema(description = "退款时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime refundTime;
@Schema(description = "退货物流公司编号", example = "10")
private Long logisticsId;
@Schema(description = "退货物流单号", example = "610003952009")
private String logisticsNo;
@Schema(description = "退货时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime deliveryTime;
@Schema(description = "收货时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime receiveTime;
@Schema(description = "收货备注", example = "不喜欢")
private String receiveReason;
}
package org.dromara.mall.controller.trade.admin.aftersale.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.dromara.mall.controller.trade.admin.aftersale.vo.log.AfterSaleLogRespVO;
import org.dromara.mall.controller.trade.admin.base.member.user.MemberUserRespVO;
import org.dromara.mall.controller.trade.admin.base.product.property.ProductPropertyValueDetailRespVO;
import org.dromara.mall.controller.trade.admin.order.vo.TradeOrderBaseVO;
import org.dromara.mall.controller.trade.admin.order.vo.TradeOrderItemBaseVO;
import java.util.List;
@Schema(description = "管理后台 - 售后订单的详情 Response VO")
@Data
public class AfterSaleDetailRespVO extends AfterSaleBaseVO {
@Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
/**
* 订单基本信息
*/
private TradeOrderBaseVO order;
/**
* 订单项列表
*/
private OrderItem orderItem;
/**
* 用户信息
*/
private MemberUserRespVO user;
/**
* 售后日志
*/
private List<AfterSaleLogRespVO> logs;
@Schema(description = "管理后台 - 交易订单的详情的订单项目")
@Data
public static class OrderItem extends TradeOrderItemBaseVO {
/**
* 属性数组
*/
private List<ProductPropertyValueDetailRespVO> properties;
}
}
package org.dromara.mall.controller.trade.admin.aftersale.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "管理后台 - 交易售后拒绝 Request VO")
@Data
public class AfterSaleDisagreeReqVO {
@Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "售后编号不能为空")
private Long id;
@Schema(description = "审批备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "你猜")
@NotEmpty(message = "审批备注不能为空")
private String auditReason;
}
package org.dromara.mall.controller.trade.admin.aftersale.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.dromara.common.mall.validation.InEnum;
import org.dromara.common.mybatis.core.page.PageParam;
import org.dromara.mall.enums.trade.aftersale.AfterSaleStatusEnum;
import org.dromara.mall.enums.trade.aftersale.AfterSaleTypeEnum;
import org.dromara.mall.enums.trade.aftersale.AfterSaleWayEnum;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 交易售后分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class AfterSalePageReqVO extends PageParam {
@Schema(description = "用户编号", example = "1024")
private Long userId;
@Schema(description = "售后流水号", example = "202211190847450020500077")
private String no;
@Schema(description = "售后状态", example = "10")
@InEnum(value = AfterSaleStatusEnum.class, message = "售后状态必须是 {value}")
private Integer status;
@Schema(description = "售后类型", example = "20")
@InEnum(value = AfterSaleTypeEnum.class, message = "售后类型必须是 {value}")
private Integer type;
@Schema(description = "售后方式", example = "10")
@InEnum(value = AfterSaleWayEnum.class, message = "售后方式必须是 {value}")
private Integer way;
@Schema(description = "订单编号", example = "18078")
private String orderNo;
@Schema(description = "商品 SPU 名称", example = "李四")
private String spuName;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}
package org.dromara.mall.controller.trade.admin.aftersale.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "管理后台 - 交易售后拒绝收货 Request VO")
@Data
public class AfterSaleRefuseReqVO {
@Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "售后编号不能为空")
private Long id;
@Schema(description = "收货备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "你猜")
@NotNull(message = "收货备注不能为空")
private String refuseMemo;
}
package org.dromara.mall.controller.trade.admin.aftersale.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.dromara.mall.controller.trade.admin.base.member.user.MemberUserRespVO;
import org.dromara.mall.controller.trade.admin.base.product.property.ProductPropertyValueDetailRespVO;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 交易售后分页的每一条记录 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class AfterSaleRespPageItemVO extends AfterSaleBaseVO {
@Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "27630")
private Long id;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
/**
* 商品属性数组
*/
private List<ProductPropertyValueDetailRespVO> properties;
/**
* 用户信息
*/
private MemberUserRespVO user;
}
package org.dromara.mall.controller.trade.admin.aftersale.vo.log;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 交易售后日志 Response VO")
@Data
public class AfterSaleLogRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20669")
private Long id;
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22634")
private Long userId;
@Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
private Integer userType;
@Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3023")
private Long afterSaleId;
@Schema(description = "售后状态(之前)", example = "2")
private Integer beforeStatus;
@Schema(description = "售后状态(之后)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer afterStatus;
@Schema(description = "操作明细", requiredMode = Schema.RequiredMode.REQUIRED, example = "维权完成,退款金额:¥37776.00")
private String content;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}
/**
* 占位符,可忽略
*/
package org.dromara.mall.controller.trade.admin.base.member;
package org.dromara.mall.controller.trade.admin.base.member.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 会员用户 Response VO")
@Data
public class MemberUserRespVO {
@Schema(description = "用户 ID", 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/xxx.png")
private String avatar;
}
/**
* 放置该模块通用的 VO 类
*/
package org.dromara.mall.controller.trade.admin.base;
package org.dromara.mall.controller.trade.admin.base.product.property;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 商品属性值的明细 Response VO")
@Data
public class ProductPropertyValueDetailRespVO {
@Schema(description = "属性的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long propertyId;
@Schema(description = "属性的名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "颜色")
private String propertyName;
@Schema(description = "属性值的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long valueId;
@Schema(description = "属性值的名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "红色")
private String valueName;
}
/**
* 占位符,可忽略
*/
package org.dromara.mall.controller.trade.admin.base.system;
package org.dromara.mall.controller.trade.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;
}
package org.dromara.mall.controller.trade.admin.brokerage;
import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.dromara.common.core.domain.R;
import org.dromara.common.mybatis.core.page.PageResult;
import org.dromara.mall.api.dto.member.MemberUserRespDTO;
import org.dromara.mall.api.service.member.MemberUserApi;
import org.dromara.mall.controller.trade.admin.brokerage.vo.record.BrokerageRecordPageReqVO;
import org.dromara.mall.controller.trade.admin.brokerage.vo.record.BrokerageRecordRespVO;
import org.dromara.mall.convert.trade.brokerage.BrokerageRecordConvert;
import org.dromara.mall.domain.trade.BrokerageRecordDO;
import org.dromara.mall.service.trade.brokerage.BrokerageRecordService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
import java.util.Set;
import static org.dromara.common.mall.util.collection.CollectionUtils.convertList;
import static org.dromara.common.mall.util.collection.CollectionUtils.convertSet;
@Tag(name = "管理后台 - 佣金记录")
@RestController
@RequestMapping("/admin/trade/brokerage-record")
@Validated
public class BrokerageRecordController {
@Resource
private BrokerageRecordService brokerageRecordService;
@Resource
private MemberUserApi memberUserApi;
@GetMapping("/get")
@Operation(summary = "获得佣金记录")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@SaCheckPermission("trade:brokerage-record:query")
public R<BrokerageRecordRespVO> getBrokerageRecord(@RequestParam("id") Long id) {
BrokerageRecordDO brokerageRecord = brokerageRecordService.getBrokerageRecord(id);
return R.ok(BrokerageRecordConvert.INSTANCE.convert(brokerageRecord));
}
@GetMapping("/page")
@Operation(summary = "获得佣金记录分页")
@SaCheckPermission("trade:brokerage-record:query")
public R<PageResult<BrokerageRecordRespVO>> getBrokerageRecordPage(@Valid BrokerageRecordPageReqVO pageVO) {
PageResult<BrokerageRecordDO> pageResult = brokerageRecordService.getBrokerageRecordPage(pageVO);
// 查询用户信息
Set<Long> userIds = convertSet(pageResult.getList(), BrokerageRecordDO::getUserId);
userIds.addAll(convertList(pageResult.getList(), BrokerageRecordDO::getSourceUserId));
Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds);
// 拼接数据
return R.ok(BrokerageRecordConvert.INSTANCE.convertPage(pageResult, userMap));
}
}
package org.dromara.mall.controller.trade.admin.brokerage;
import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.dromara.common.core.domain.R;
import org.dromara.common.mybatis.core.page.PageResult;
import org.dromara.mall.api.dto.member.MemberUserRespDTO;
import org.dromara.mall.api.service.member.MemberUserApi;
import org.dromara.mall.controller.trade.admin.brokerage.vo.user.*;
import org.dromara.mall.convert.trade.brokerage.BrokerageUserConvert;
import org.dromara.mall.domain.trade.BrokerageUserDO;
import org.dromara.mall.enums.trade.brokerage.BrokerageRecordBizTypeEnum;
import org.dromara.mall.enums.trade.brokerage.BrokerageRecordStatusEnum;
import org.dromara.mall.enums.trade.brokerage.BrokerageWithdrawStatusEnum;
import org.dromara.mall.service.trade.brokerage.BrokerageRecordService;
import org.dromara.mall.service.trade.brokerage.BrokerageUserService;
import org.dromara.mall.service.trade.brokerage.BrokerageWithdrawService;
import org.dromara.mall.service.trade.brokerage.bo.BrokerageWithdrawSummaryRespBO;
import org.dromara.mall.service.trade.brokerage.bo.UserBrokerageSummaryRespBO;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
import java.util.Set;
import static org.dromara.common.mall.util.collection.CollectionUtils.convertMap;
import static org.dromara.common.mall.util.collection.CollectionUtils.convertSet;
@Tag(name = "管理后台 - 分销用户")
@RestController
@RequestMapping("/admin/trade/brokerage-user")
@Validated
public class BrokerageUserController {
@Resource
private BrokerageUserService brokerageUserService;
@Resource
private BrokerageRecordService brokerageRecordService;
@Resource
private BrokerageWithdrawService brokerageWithdrawService;
@Resource
private MemberUserApi memberUserApi;
@PostMapping("/create")
@Operation(summary = "创建分销用户")
@SaCheckPermission("trade:brokerage-user:create")
public R<Long> createBrokerageUser(@Valid @RequestBody BrokerageUserCreateReqVO createReqVO) {
return R.ok(brokerageUserService.createBrokerageUser(createReqVO));
}
@PutMapping("/update-bind-user")
@Operation(summary = "修改推广员")
@SaCheckPermission("trade:brokerage-user:update-bind-user")
public R<Boolean> updateBindUser(@Valid @RequestBody BrokerageUserUpdateBrokerageUserReqVO updateReqVO) {
brokerageUserService.updateBrokerageUserId(updateReqVO.getId(), updateReqVO.getBindUserId());
return R.ok(true);
}
@PutMapping("/clear-bind-user")
@Operation(summary = "清除推广员")
@SaCheckPermission("trade:brokerage-user:clear-bind-user")
public R<Boolean> clearBindUser(@Valid @RequestBody BrokerageUserClearBrokerageUserReqVO updateReqVO) {
brokerageUserService.updateBrokerageUserId(updateReqVO.getId(), null);
return R.ok(true);
}
@PutMapping("/update-brokerage-enable")
@Operation(summary = "修改推广资格")
@SaCheckPermission("trade:brokerage-user:update-brokerage-enable")
public R<Boolean> updateBrokerageEnabled(@Valid @RequestBody BrokerageUserUpdateBrokerageEnabledReqVO updateReqVO) {
brokerageUserService.updateBrokerageUserEnabled(updateReqVO.getId(), updateReqVO.getEnabled());
return R.ok(true);
}
@GetMapping("/get")
@Operation(summary = "获得分销用户")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@SaCheckPermission("trade:brokerage-user:query")
public R<BrokerageUserRespVO> getBrokerageUser(@RequestParam("id") Long id) {
BrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(id);
// TODO @疯狂:是不是搞成一个统一的 convert?
BrokerageUserRespVO respVO = BrokerageUserConvert.INSTANCE.convert(brokerageUser);
return R.ok(BrokerageUserConvert.INSTANCE.copyTo(memberUserApi.getUser(id), respVO));
}
@GetMapping("/page")
@Operation(summary = "获得分销用户分页")
@SaCheckPermission("trade:brokerage-user:query")
public R<PageResult<BrokerageUserRespVO>> getBrokerageUserPage(@Valid BrokerageUserPageReqVO pageVO) {
// 分页查询
PageResult<BrokerageUserDO> pageResult = brokerageUserService.getBrokerageUserPage(pageVO);
// 查询用户信息
Set<Long> userIds = convertSet(pageResult.getList(), BrokerageUserDO::getId);
Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds);
// 合计分佣的推广订单
Map<Long, UserBrokerageSummaryRespBO> brokerageOrderSummaryMap = brokerageRecordService.getUserBrokerageSummaryMapByUserId(
userIds, BrokerageRecordBizTypeEnum.ORDER.getType(), BrokerageRecordStatusEnum.SETTLEMENT.getStatus());
// 合计分佣的推广用户
// TODO @疯狂:转成 map 批量读取
Map<Long, Long> brokerageUserCountMap = convertMap(userIds,
userId -> userId,
userId -> brokerageUserService.getBrokerageUserCountByBindUserId(userId, null));
// 合计分佣的提现
// TODO @疯狂:如果未来支持了打款这个动作,可能 status 会不对;
Map<Long, BrokerageWithdrawSummaryRespBO> withdrawMap = brokerageWithdrawService.getWithdrawSummaryMapByUserId(
userIds, BrokerageWithdrawStatusEnum.AUDIT_SUCCESS);
// 拼接返回
return R.ok(BrokerageUserConvert.INSTANCE.convertPage(pageResult, userMap, brokerageUserCountMap,
brokerageOrderSummaryMap, withdrawMap));
}
}
package org.dromara.mall.controller.trade.admin.brokerage;
import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.mybatis.core.page.PageResult;
import org.dromara.mall.api.dto.member.MemberUserRespDTO;
import org.dromara.mall.api.dto.pay.PayTransferNotifyReqDTO;
import org.dromara.mall.api.service.member.MemberUserApi;
import org.dromara.mall.controller.trade.admin.brokerage.vo.withdraw.BrokerageWithdrawPageReqVO;
import org.dromara.mall.controller.trade.admin.brokerage.vo.withdraw.BrokerageWithdrawRejectReqVO;
import org.dromara.mall.controller.trade.admin.brokerage.vo.withdraw.BrokerageWithdrawRespVO;
import org.dromara.mall.convert.trade.brokerage.BrokerageWithdrawConvert;
import org.dromara.mall.domain.trade.BrokerageWithdrawDO;
import org.dromara.mall.enums.trade.brokerage.BrokerageWithdrawStatusEnum;
import org.dromara.mall.service.trade.brokerage.BrokerageWithdrawService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
import static org.dromara.common.core.utils.ServletUtils.getClientIP;
import static org.dromara.common.mall.util.collection.CollectionUtils.convertSet;
@Tag(name = "管理后台 - 佣金提现")
@RestController
@RequestMapping("/admin/trade/brokerage-withdraw")
@Validated
@Slf4j
public class BrokerageWithdrawController {
@Resource
private BrokerageWithdrawService brokerageWithdrawService;
@Resource
private MemberUserApi memberUserApi;
@PutMapping("/approve")
@Operation(summary = "通过申请")
@SaCheckPermission("trade:brokerage-withdraw:audit")
public R<Boolean> approveBrokerageWithdraw(@RequestParam("id") Long id) {
brokerageWithdrawService.auditBrokerageWithdraw(id,
BrokerageWithdrawStatusEnum.AUDIT_SUCCESS, "", getClientIP());
return R.ok(true);
}
@PutMapping("/reject")
@Operation(summary = "驳回申请")
@SaCheckPermission("trade:brokerage-withdraw:audit")
public R<Boolean> rejectBrokerageWithdraw(@Valid @RequestBody BrokerageWithdrawRejectReqVO reqVO) {
brokerageWithdrawService.auditBrokerageWithdraw(reqVO.getId(),
BrokerageWithdrawStatusEnum.AUDIT_FAIL, reqVO.getAuditReason(), getClientIP());
return R.ok(true);
}
@GetMapping("/get")
@Operation(summary = "获得佣金提现")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@SaCheckPermission("trade:brokerage-withdraw:query")
public R<BrokerageWithdrawRespVO> getBrokerageWithdraw(@RequestParam("id") Long id) {
BrokerageWithdrawDO brokerageWithdraw = brokerageWithdrawService.getBrokerageWithdraw(id);
return R.ok(BrokerageWithdrawConvert.INSTANCE.convert(brokerageWithdraw));
}
@GetMapping("/page")
@Operation(summary = "获得佣金提现分页")
@SaCheckPermission("trade:brokerage-withdraw:query")
public R<PageResult<BrokerageWithdrawRespVO>> getBrokerageWithdrawPage(@Valid BrokerageWithdrawPageReqVO pageVO) {
// 分页查询
PageResult<BrokerageWithdrawDO> pageResult = brokerageWithdrawService.getBrokerageWithdrawPage(pageVO);
// 拼接信息
Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(
convertSet(pageResult.getList(), BrokerageWithdrawDO::getUserId));
return R.ok(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 R<Boolean> updateBrokerageWithdrawTransferred(@RequestBody PayTransferNotifyReqDTO notifyReqDTO) {
log.info("[updateAfterRefund][notifyReqDTO({})]", notifyReqDTO);
brokerageWithdrawService.updateBrokerageWithdrawTransferred(
Long.parseLong(notifyReqDTO.getMerchantTransferId()), notifyReqDTO.getPayTransferId());
return R.ok(true);
}
}
package org.dromara.mall.controller.trade.admin.brokerage.vo.record;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 佣金记录 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class BrokerageRecordBaseVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25973")
@NotNull(message = "用户编号不能为空")
private Long userId;
@Schema(description = "业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23353")
@NotEmpty(message = "业务编号不能为空")
private String bizId;
@Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "业务类型不能为空")
private Integer bizType;
@Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "标题不能为空")
private String title;
@Schema(description = "金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "28731")
@NotNull(message = "金额不能为空")
private Integer price;
@Schema(description = "当前总佣金", requiredMode = Schema.RequiredMode.REQUIRED, example = "13226")
@NotNull(message = "当前总佣金不能为空")
private Integer totalPrice;
@Schema(description = "说明", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对")
@NotNull(message = "说明不能为空")
private String description;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "状态不能为空")
private Integer status;
@Schema(description = "冻结时间(天)", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "冻结时间(天)不能为空")
private Integer frozenDays;
@Schema(description = "解冻时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime unfreezeTime;
@Schema(description = "来源用户等级")
private Integer sourceUserLevel;
@Schema(description = "来源用户编号")
private Long sourceUserId;
}
package org.dromara.mall.controller.trade.admin.brokerage.vo.record;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.dromara.common.mybatis.core.page.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 佣金记录分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BrokerageRecordPageReqVO extends PageParam {
@Schema(description = "用户编号", example = "25973")
private Long userId;
@Schema(description = "业务类型", example = "1")
private Integer bizType;
@Schema(description = "状态", example = "1")
private Integer status;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
@Schema(description = "用户类型", example = "1")
private Integer sourceUserLevel;
}
package org.dromara.mall.controller.trade.admin.brokerage.vo.record;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 佣金记录 Response VO")
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BrokerageRecordRespVO extends BrokerageRecordBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28896")
private Long id;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
// ========== 用户信息 ==========
@Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png")
private String userAvatar;
@Schema(description = "用户昵称", example = "李四")
private String userNickname;
// ========== 来源用户信息 ==========
@Schema(description = "来源用户头像", example = "https://www.iocoder.cn/xxx.png")
private String sourceUserAvatar;
@Schema(description = "来源用户昵称", example = "李四")
private String sourceUserNickname;
}
package org.dromara.mall.controller.trade.admin.brokerage.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 分销用户 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class BrokerageUserBaseVO {
@Schema(description = "推广员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4587")
@NotNull(message = "推广员编号不能为空")
private Long bindUserId;
@Schema(description = "推广员绑定时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime bindUserTime;
@Schema(description = "推广资格", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "推广资格不能为空")
private Boolean brokerageEnabled;
@Schema(description = "成为分销员时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime brokerageTime;
@Schema(description = "可用佣金", requiredMode = Schema.RequiredMode.REQUIRED, example = "11089")
@NotNull(message = "可用佣金不能为空")
private Integer price;
@Schema(description = "冻结佣金", requiredMode = Schema.RequiredMode.REQUIRED, example = "30916")
@NotNull(message = "冻结佣金不能为空")
private Integer frozenPrice;
}
package org.dromara.mall.controller.trade.admin.brokerage.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.ToString;
@Schema(description = "管理后台 - 分销用户 - 清除推广员 Request VO")
@Data
@ToString(callSuper = true)
public class BrokerageUserClearBrokerageUserReqVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
@NotNull(message = "用户编号不能为空")
private Long id;
}
package org.dromara.mall.controller.trade.admin.brokerage.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "管理后台 - 分销用户创建 Request VO")
@Data
public class BrokerageUserCreateReqVO {
@Schema(description = "分销用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "分销用户编号不能为空")
private Long userId;
@Schema(description = "推广员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4587")
private Long bindUserId;
}
package org.dromara.mall.controller.trade.admin.brokerage.vo.user;
import org.dromara.common.mybatis.core.page.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 分销用户分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BrokerageUserPageReqVO extends PageParam {
@Schema(description = "推广员编号", example = "4587")
private Long bindUserId;
@Schema(description = "推广资格", example = "true")
private Boolean brokerageEnabled;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
@Schema(description = "用户等级", example = "1") // 注意,这了不是用户的会员等级,而是过滤推广的层级
private Integer level;
@Schema(description = "绑定时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] bindUserTime;
}
package org.dromara.mall.controller.trade.admin.brokerage.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 分销用户 Response VO")
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BrokerageUserRespVO extends BrokerageUserBaseVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
private Long id;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
// ========== 用户信息 ==========
@Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xxx.png")
private String avatar;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
private String nickname;
// ========== 推广信息 ========== 注意:是包括 1 + 2 级的数据
@Schema(description = "推广用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
private Integer brokerageUserCount;
@Schema(description = "推广订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
private Integer brokerageOrderCount;
@Schema(description = "推广订单金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
private Integer brokerageOrderPrice;
// ========== 提现信息 ==========
@Schema(description = "已提现金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
private Integer withdrawPrice;
@Schema(description = "已提现次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
private Integer withdrawCount;
}
package org.dromara.mall.controller.trade.admin.brokerage.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.ToString;
@Schema(description = "管理后台 - 分销用户 - 修改推广员 Request VO")
@Data
@ToString(callSuper = true)
public class BrokerageUserUpdateBrokerageEnabledReqVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
@NotNull(message = "用户编号不能为空")
private Long id;
@Schema(description = "推广资格", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "推广资格不能为空")
private Boolean enabled;
}
package org.dromara.mall.controller.trade.admin.brokerage.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.ToString;
@Schema(description = "管理后台 - 分销用户 - 修改推广员 Request VO")
@Data
@ToString(callSuper = true)
public class BrokerageUserUpdateBrokerageUserReqVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
@NotNull(message = "用户编号不能为空")
private Long id;
@Schema(description = "推广员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4587")
@NotNull(message = "推广员编号不能为空")
private Long bindUserId;
}
package org.dromara.mall.controller.trade.admin.brokerage.vo.withdraw;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 佣金提现 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class BrokerageWithdrawBaseVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11436")
@NotNull(message = "用户编号不能为空")
private Long userId;
@Schema(description = "提现金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "18781")
@NotNull(message = "提现金额不能为空")
private Integer price;
@Schema(description = "提现手续费", requiredMode = Schema.RequiredMode.REQUIRED, example = "11417")
@NotNull(message = "提现手续费不能为空")
private Integer feePrice;
@Schema(description = "当前总佣金", requiredMode = Schema.RequiredMode.REQUIRED, example = "18576")
@NotNull(message = "当前总佣金不能为空")
private Integer totalPrice;
@Schema(description = "提现类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "提现类型不能为空")
private Integer type;
@Schema(description = "真实姓名", example = "赵六")
private String name;
@Schema(description = "账号", example = "88677912132")
private String accountNo;
@Schema(description = "银行名称", example = "1")
private String bankName;
@Schema(description = "开户地址", example = "海淀支行")
private String bankAddress;
@Schema(description = "收款码", example = "https://www.iocoder.cn")
private String accountQrCodeUrl;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "状态不能为空")
private Integer status;
@Schema(description = "审核驳回原因", example = "不对")
private String auditReason;
@Schema(description = "审核时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime auditTime;
@Schema(description = "备注", example = "随便")
private String remark;
}
package org.dromara.mall.controller.trade.admin.brokerage.vo.withdraw;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.dromara.common.mall.validation.InEnum;
import org.dromara.common.mybatis.core.page.PageParam;
import org.dromara.mall.enums.trade.brokerage.BrokerageWithdrawStatusEnum;
import org.dromara.mall.enums.trade.brokerage.BrokerageWithdrawTypeEnum;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 佣金提现分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BrokerageWithdrawPageReqVO extends PageParam {
@Schema(description = "用户编号", example = "11436")
private Long userId;
@Schema(description = "提现类型", example = "1")
@InEnum(value = BrokerageWithdrawTypeEnum.class, message = "提现类型必须是 {value}")
private Integer type;
@Schema(description = "真实姓名", example = "赵六")
private String name;
@Schema(description = "账号", example = "886779132")
private String accountNo;
@Schema(description = "银行名称", example = "1")
private String bankName;
@Schema(description = "状态", example = "1")
@InEnum(value = BrokerageWithdrawStatusEnum.class, message = "状态必须是 {value}")
private Integer status;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}
package org.dromara.mall.controller.trade.admin.brokerage.vo.withdraw;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.ToString;
@Schema(description = "管理后台 - 驳回申请 Request VO")
@Data
@ToString(callSuper = true)
public class BrokerageWithdrawRejectReqVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7161")
@NotNull(message = "编号不能为空")
private Long id;
@Schema(description = "审核驳回原因", example = "不对")
@NotEmpty(message = "审核驳回原因不能为空")
private String auditReason;
}
package org.dromara.mall.controller.trade.admin.brokerage.vo.withdraw;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 佣金提现 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BrokerageWithdrawRespVO extends BrokerageWithdrawBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7161")
private Long id;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
private String userNickname;
}
package org.dromara.mall.controller.trade.admin.config;
import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.dromara.common.core.domain.R;
import org.dromara.mall.controller.trade.admin.config.vo.TradeConfigRespVO;
import org.dromara.mall.controller.trade.admin.config.vo.TradeConfigSaveReqVO;
import org.dromara.mall.convert.trade.config.TradeConfigConvert;
import org.dromara.mall.domain.trade.TradeConfigDO;
import org.dromara.mall.service.trade.config.TradeConfigService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@Tag(name = "管理后台 - 交易中心配置")
@RestController
@RequestMapping("/admin/trade/config")
@Validated
public class TradeConfigController {
@Resource
private TradeConfigService tradeConfigService;
@Value("${yudao.tencent-lbs-key}")
private String tencentLbsKey;
@PutMapping("/save")
@Operation(summary = "更新交易中心配置")
@SaCheckPermission("trade:config:save")
public R<Boolean> updateConfig(@Valid @RequestBody TradeConfigSaveReqVO updateReqVO) {
tradeConfigService.saveTradeConfig(updateReqVO);
return R.ok(true);
}
@GetMapping("/get")
@Operation(summary = "获得交易中心配置")
@SaCheckPermission("trade:config:query")
public R<TradeConfigRespVO> getConfig() {
TradeConfigDO config = tradeConfigService.getTradeConfig();
TradeConfigRespVO configVO = TradeConfigConvert.INSTANCE.convert(config);
if (configVO != null) {
configVO.setTencentLbsKey(tencentLbsKey);
}
return R.ok(configVO);
}
}
package org.dromara.mall.controller.trade.admin.config.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.PositiveOrZero;
import lombok.Data;
import org.dromara.common.mall.validation.InEnum;
import org.dromara.mall.enums.trade.brokerage.BrokerageBindModeEnum;
import org.dromara.mall.enums.trade.brokerage.BrokerageEnabledConditionEnum;
import org.dromara.mall.enums.trade.brokerage.BrokerageWithdrawTypeEnum;
import org.hibernate.validator.constraints.Range;
import java.util.List;
/**
* 交易中心配置 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class TradeConfigBaseVO {
// ========== 售后相关 ==========
@Schema(description = "售后的退款理由", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "售后的退款理由不能为空")
private List<String> afterSaleRefundReasons;
@Schema(description = "售后的退货理由", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "售后的退货理由不能为空")
private List<String> afterSaleReturnReasons;
// ========== 配送相关 ==========
/**
* 是否启用全场包邮
*/
@Schema(description = "是否启用全场包邮", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否启用全场包邮不能为空")
private Boolean deliveryExpressFreeEnabled;
@Schema(description = "全场包邮的最小金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
@NotNull(message = "全场包邮的最小金额不能为空")
@PositiveOrZero(message = "全场包邮的最小金额不能是负数")
private Integer deliveryExpressFreePrice;
@Schema(description = "是否开启自提", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否开启自提不能为空")
private Boolean deliveryPickUpEnabled;
// ========== 分销相关 ==========
@Schema(description = "是否启用分佣", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否启用分佣不能为空")
private Boolean brokerageEnabled;
@Schema(description = "分佣模式", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@NotNull(message = "分佣模式不能为空")
@InEnum(value = BrokerageEnabledConditionEnum.class, message = "分佣模式必须是 {value}")
private Integer brokerageEnabledCondition;
@Schema(description = "分销关系绑定模式", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@NotNull(message = "分销关系绑定模式不能为空")
@InEnum(value = BrokerageBindModeEnum.class, message = "分销关系绑定模式必须是 {value}")
private Integer brokerageBindMode;
@Schema(description = "分销海报图地址数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/yudao.jpg]")
private List<String> brokeragePosterUrls;
@Schema(description = "一级返佣比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
@NotNull(message = "一级返佣比例不能为空")
@Range(min = 0, max = 100, message = "一级返佣比例必须在 0 - 100 之间")
private Integer brokerageFirstPercent;
@Schema(description = "二级返佣比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
@NotNull(message = "二级返佣比例不能为空")
@Range(min = 0, max = 100, message = "二级返佣比例必须在 0 - 100 之间")
private Integer brokerageSecondPercent;
@Schema(description = "用户提现最低金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
@NotNull(message = "用户提现最低金额不能为空")
@PositiveOrZero(message = "用户提现最低金额不能是负数")
private Integer brokerageWithdrawMinPrice;
@Schema(description = "用户提现手续费百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
@NotNull(message = "用户提现手续费百分比不能为空")
@PositiveOrZero(message = "用户提现手续费百分比不能是负数")
private Integer brokerageWithdrawFeePercent;
@Schema(description = "佣金冻结时间(天)", requiredMode = Schema.RequiredMode.REQUIRED, example = "7")
@NotNull(message = "佣金冻结时间(天)不能为空")
@PositiveOrZero(message = "佣金冻结时间不能是负数")
private Integer brokerageFrozenDays;
@Schema(description = "提现方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "[0, 1]")
@NotEmpty(message = "提现方式不能为空")
@InEnum(value = BrokerageWithdrawTypeEnum.class, message = "提现方式必须是 {value}")
private List<Integer> brokerageWithdrawTypes;
}
package org.dromara.mall.controller.trade.admin.config.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - 交易中心配置 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class TradeConfigRespVO extends TradeConfigBaseVO {
@Schema(description = "自增主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "腾讯地图 KEY", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
private String tencentLbsKey;
}
package org.dromara.mall.controller.trade.admin.config.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - 交易中心配置更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class TradeConfigSaveReqVO extends TradeConfigBaseVO {
}
package org.dromara.mall.controller.trade.admin.delivery;
import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.dromara.common.core.domain.R;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mall.enums.CommonStatusEnum;
import org.dromara.common.mybatis.core.page.PageResult;
import org.dromara.mall.controller.trade.admin.delivery.vo.express.*;
import org.dromara.mall.convert.trade.delivery.DeliveryExpressConvert;
import org.dromara.mall.domain.trade.DeliveryExpressDO;
import org.dromara.mall.service.trade.delivery.DeliveryExpressService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
@Tag(name = "管理后台 - 快递公司")
@RestController
@RequestMapping("/admin/trade/delivery/express")
@Validated
public class DeliveryExpressController {
@Resource
private DeliveryExpressService deliveryExpressService;
@PostMapping("/create")
@Operation(summary = "创建快递公司")
@SaCheckPermission("trade:delivery:express:create")
public R<Long> createDeliveryExpress(@Valid @RequestBody DeliveryExpressCreateReqVO createReqVO) {
return R.ok(deliveryExpressService.createDeliveryExpress(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新快递公司")
@SaCheckPermission("trade:delivery:express:update")
public R<Boolean> updateDeliveryExpress(@Valid @RequestBody DeliveryExpressUpdateReqVO updateReqVO) {
deliveryExpressService.updateDeliveryExpress(updateReqVO);
return R.ok(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除快递公司")
@Parameter(name = "id", description = "编号", required = true)
@SaCheckPermission("trade:delivery:express:delete")
public R<Boolean> deleteDeliveryExpress(@RequestParam("id") Long id) {
deliveryExpressService.deleteDeliveryExpress(id);
return R.ok(true);
}
@GetMapping("/get")
@Operation(summary = "获得快递公司")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@SaCheckPermission("trade:delivery:express:query")
public R<DeliveryExpressRespVO> getDeliveryExpress(@RequestParam("id") Long id) {
DeliveryExpressDO deliveryExpress = deliveryExpressService.getDeliveryExpress(id);
return R.ok(DeliveryExpressConvert.INSTANCE.convert(deliveryExpress));
}
@GetMapping("/list-all-simple")
@Operation(summary = "获取快递公司精简信息列表", description = "主要用于前端的下拉选项")
public R<List<DeliveryExpressSimpleRespVO>> getSimpleDeliveryExpressList() {
List<DeliveryExpressDO> list = deliveryExpressService.getDeliveryExpressListByStatus(CommonStatusEnum.ENABLE.getStatus());
return R.ok(DeliveryExpressConvert.INSTANCE.convertList1(list));
}
@GetMapping("/page")
@Operation(summary = "获得快递公司分页")
@SaCheckPermission("trade:delivery:express:query")
public R<PageResult<DeliveryExpressRespVO>> getDeliveryExpressPage(@Valid DeliveryExpressPageReqVO pageVO) {
PageResult<DeliveryExpressDO> pageResult = deliveryExpressService.getDeliveryExpressPage(pageVO);
return R.ok(DeliveryExpressConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/export-excel")
@Operation(summary = "导出快递公司 Excel")
@Log(title = "用户管理", businessType = BusinessType.EXPORT)
@SaCheckPermission("trade:delivery:express:export")
public void exportDeliveryExpressExcel(@Valid DeliveryExpressExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<DeliveryExpressDO> list = deliveryExpressService.getDeliveryExpressList(exportReqVO);
// 导出 Excel
List<DeliveryExpressExcelVO> dataList = DeliveryExpressConvert.INSTANCE.convertList02(list);
ExcelUtil.exportExcel(dataList, "用户数据", DeliveryExpressExcelVO.class, response);
}
}
package org.dromara.mall.controller.trade.admin.delivery;
import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.dromara.common.core.domain.R;
import org.dromara.common.mybatis.core.page.PageResult;
import org.dromara.mall.controller.trade.admin.delivery.vo.expresstemplate.*;
import org.dromara.mall.convert.trade.delivery.DeliveryExpressTemplateConvert;
import org.dromara.mall.domain.trade.DeliveryExpressTemplateDO;
import org.dromara.mall.service.trade.delivery.DeliveryExpressTemplateService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Collection;
import java.util.List;
@Tag(name = "管理后台 - 快递运费模板")
@RestController
@RequestMapping("/admin/trade/delivery/express-template")
@Validated
public class DeliveryExpressTemplateController {
@Resource
private DeliveryExpressTemplateService deliveryExpressTemplateService;
@PostMapping("/create")
@Operation(summary = "创建快递运费模板")
@SaCheckPermission("trade:delivery:express-template:create")
public R<Long> createDeliveryExpressTemplate(@Valid @RequestBody DeliveryExpressTemplateCreateReqVO createReqVO) {
return R.ok(deliveryExpressTemplateService.createDeliveryExpressTemplate(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新快递运费模板")
@SaCheckPermission("trade:delivery:express-template:update")
public R<Boolean> updateDeliveryExpressTemplate(@Valid @RequestBody DeliveryExpressTemplateUpdateReqVO updateReqVO) {
deliveryExpressTemplateService.updateDeliveryExpressTemplate(updateReqVO);
return R.ok(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除快递运费模板")
@Parameter(name = "id", description = "编号", required = true)
@SaCheckPermission("trade:delivery:express-template:delete")
public R<Boolean> deleteDeliveryExpressTemplate(@RequestParam("id") Long id) {
deliveryExpressTemplateService.deleteDeliveryExpressTemplate(id);
return R.ok(true);
}
@GetMapping("/get")
@Operation(summary = "获得快递运费模板")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@SaCheckPermission("trade:delivery:express-template:query")
public R<DeliveryExpressTemplateDetailRespVO> getDeliveryExpressTemplate(@RequestParam("id") Long id) {
return R.ok(deliveryExpressTemplateService.getDeliveryExpressTemplate(id));
}
@GetMapping("/list")
@Operation(summary = "获得快递运费模板列表")
@Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
@SaCheckPermission("trade:delivery:express-template:query")
public R<List<DeliveryExpressTemplateRespVO>> getDeliveryExpressTemplateList(@RequestParam("ids") Collection<Long> ids) {
List<DeliveryExpressTemplateDO> list = deliveryExpressTemplateService.getDeliveryExpressTemplateList(ids);
return R.ok(DeliveryExpressTemplateConvert.INSTANCE.convertList(list));
}
@GetMapping("/list-all-simple")
@Operation(summary = "获取快递模版精简信息列表", description = "主要用于前端的下拉选项")
public R<List<DeliveryExpressTemplateSimpleRespVO>> getSimpleTemplateList() {
// 获取运费模版列表,只要开启状态的
List<DeliveryExpressTemplateDO> list = deliveryExpressTemplateService.getDeliveryExpressTemplateList();
// 排序后,返回给前端
return R.ok(DeliveryExpressTemplateConvert.INSTANCE.convertList1(list));
}
@GetMapping("/page")
@Operation(summary = "获得快递运费模板分页")
@SaCheckPermission("trade:delivery:express-template:query")
public R<PageResult<DeliveryExpressTemplateRespVO>> getDeliveryExpressTemplatePage(@Valid DeliveryExpressTemplatePageReqVO pageVO) {
PageResult<DeliveryExpressTemplateDO> pageResult = deliveryExpressTemplateService.getDeliveryExpressTemplatePage(pageVO);
return R.ok(DeliveryExpressTemplateConvert.INSTANCE.convertPage(pageResult));
}
}
package org.dromara.mall.controller.trade.admin.delivery;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.collection.CollUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.dromara.common.core.domain.R;
import org.dromara.common.mall.enums.CommonStatusEnum;
import org.dromara.common.mall.util.object.BeanUtils;
import org.dromara.common.mybatis.core.page.PageResult;
import org.dromara.mall.api.dto.system.AdminUserRespDTO;
import org.dromara.mall.api.service.system.AdminUserApi;
import org.dromara.mall.controller.trade.admin.base.system.user.UserSimpleBaseVO;
import org.dromara.mall.controller.trade.admin.delivery.vo.pickup.*;
import org.dromara.mall.convert.trade.delivery.DeliveryPickUpStoreConvert;
import org.dromara.mall.domain.trade.DeliveryPickUpStoreDO;
import org.dromara.mall.service.trade.delivery.DeliveryPickUpStoreService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Collection;
import java.util.List;
@Tag(name = "管理后台 - 自提门店")
@RestController
@RequestMapping("/admin/trade/delivery/pick-up-store")
@Validated
public class DeliveryPickUpStoreController {
@Resource
private DeliveryPickUpStoreService deliveryPickUpStoreService;
@Resource
private AdminUserApi adminUserApi;
@PostMapping("/create")
@Operation(summary = "创建自提门店")
@SaCheckPermission("trade:delivery:pick-up-store:create")
public R<Long> createDeliveryPickUpStore(@Valid @RequestBody DeliveryPickUpStoreCreateReqVO createReqVO) {
return R.ok(deliveryPickUpStoreService.createDeliveryPickUpStore(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新自提门店")
@SaCheckPermission("trade:delivery:pick-up-store:update")
public R<Boolean> updateDeliveryPickUpStore(@Valid @RequestBody DeliveryPickUpStoreUpdateReqVO updateReqVO) {
deliveryPickUpStoreService.updateDeliveryPickUpStore(updateReqVO);
return R.ok(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除自提门店")
@Parameter(name = "id", description = "编号", required = true)
@SaCheckPermission("trade:delivery:pick-up-store:delete")
public R<Boolean> deleteDeliveryPickUpStore(@RequestParam("id") Long id) {
deliveryPickUpStoreService.deleteDeliveryPickUpStore(id);
return R.ok(true);
}
@GetMapping("/get")
@Operation(summary = "获得自提门店")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@SaCheckPermission("trade:delivery:pick-up-store:query")
public R<DeliveryPickUpStoreRespVO> getDeliveryPickUpStore(@RequestParam("id") Long id) {
DeliveryPickUpStoreDO deliveryPickUpStore = deliveryPickUpStoreService.getDeliveryPickUpStore(id);
if (deliveryPickUpStore == null) {
return R.ok(null);
}
List<AdminUserRespDTO> verifyUsers = CollUtil.isNotEmpty(deliveryPickUpStore.getVerifyUserIds()) ?
adminUserApi.getUserList(deliveryPickUpStore.getVerifyUserIds()) : null;
return R.ok(BeanUtils.toBean(deliveryPickUpStore, DeliveryPickUpStoreRespVO.class)
.setVerifyUsers(BeanUtils.toBean(verifyUsers, UserSimpleBaseVO.class)));
}
@GetMapping("/simple-list")
@Operation(summary = "获得自提门店精简信息列表")
public R<List<DeliveryPickUpStoreSimpleRespVO>> getSimpleDeliveryPickUpStoreList() {
List<DeliveryPickUpStoreDO> list = deliveryPickUpStoreService.getDeliveryPickUpStoreListByStatus(
CommonStatusEnum.ENABLE.getStatus());
return R.ok(DeliveryPickUpStoreConvert.INSTANCE.convertList1(list));
}
@GetMapping("/list")
@Operation(summary = "获得自提门店列表")
@Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
@SaCheckPermission("trade:delivery:pick-up-store:query")
public R<List<DeliveryPickUpStoreRespVO>> getDeliveryPickUpStoreList(@RequestParam("ids") Collection<Long> ids) {
List<DeliveryPickUpStoreDO> list = deliveryPickUpStoreService.getDeliveryPickUpStoreList(ids);
return R.ok(DeliveryPickUpStoreConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@Operation(summary = "获得自提门店分页")
@SaCheckPermission("trade:delivery:pick-up-store:query")
public R<PageResult<DeliveryPickUpStoreRespVO>> getDeliveryPickUpStorePage(@Valid DeliveryPickUpStorePageReqVO pageVO) {
PageResult<DeliveryPickUpStoreDO> pageResult = deliveryPickUpStoreService.getDeliveryPickUpStorePage(pageVO);
return R.ok(DeliveryPickUpStoreConvert.INSTANCE.convertPage(pageResult));
}
@PostMapping("/bind")
@Operation(summary = "绑定自提店员")
@SaCheckPermission("trade:delivery:pick-up-store:create")
public R<Boolean> bindDeliveryPickUpStore(@Valid @RequestBody DeliveryPickUpBindReqVO bindReqVO) {
deliveryPickUpStoreService.bindDeliveryPickUpStore(bindReqVO);
return R.ok(true);
}
}
package org.dromara.mall.controller.trade.admin.delivery.vo.express;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* 快递公司 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class DeliveryExpressBaseVO {
@Schema(description = "快递公司编码", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "快递公司编码不能为空")
private String code;
@Schema(description = "快递公司名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
@NotNull(message = "快递公司名称不能为空")
private String name;
@Schema(description = "快递公司logo")
private String logo;
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "排序不能为空")
private Integer sort;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "状态不能为空")
private Integer status;
}
package org.dromara.mall.controller.trade.admin.delivery.vo.express;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - 快递公司创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryExpressCreateReqVO extends DeliveryExpressBaseVO {
}
package org.dromara.mall.controller.trade.admin.delivery.vo.express;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.mall.enums.system.DictTypeConstants;
import java.time.LocalDateTime;
/**
* 快递公司 Excel VO
*/
@Data
public class DeliveryExpressExcelVO {
@ExcelProperty("编号")
private Long id;
@ExcelProperty("快递公司编码")
private String code;
@ExcelProperty("快递公司名称")
private String name;
@ExcelProperty("快递公司 logo")
private String logo;
@ExcelProperty("排序")
private Integer sort;
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = DictTypeConstants.COMMON_STATUS)
private Integer status;
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}
package org.dromara.mall.controller.trade.admin.delivery.vo.express;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 快递公司 Excel 导出 Request VO")
@Data
public class DeliveryExpressExportReqVO {
@Schema(description = "快递公司编码")
private String code;
@Schema(description = "快递公司名称", example = "李四")
private String name;
@Schema(description = "状态(0正常 1停用)", example = "1")
private Integer status;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}
package org.dromara.mall.controller.trade.admin.delivery.vo.express;
import org.dromara.common.mybatis.core.page.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 快递公司分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryExpressPageReqVO extends PageParam {
@Schema(description = "快递公司编码")
private String code;
@Schema(description = "快递公司名称", example = "李四")
private String name;
@Schema(description = "状态(0正常 1停用)", example = "1")
private Integer status;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}
package org.dromara.mall.controller.trade.admin.delivery.vo.express;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 快递公司 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryExpressRespVO extends DeliveryExpressBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6592")
private Long id;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}
package org.dromara.mall.controller.trade.admin.delivery.vo.express;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Schema(description = "管理后台 - 快递公司精简信息 Response VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DeliveryExpressSimpleRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6592")
@NotNull(message = "编号不能为空")
private Long id;
@Schema(description = "快递公司名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "顺丰速运")
@NotNull(message = "快递公司名称不能为空")
private String name;
}
package org.dromara.mall.controller.trade.admin.delivery.vo.express;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - 快递公司更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryExpressUpdateReqVO extends DeliveryExpressBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6592")
@NotNull(message = "编号不能为空")
private Long id;
}
package org.dromara.mall.controller.trade.admin.delivery.vo.expresstemplate;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* 快递运费模板 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class DeliveryExpressTemplateBaseVO {
@Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
@NotNull(message = "模板名称不能为空")
private String name;
@Schema(description = "配送计费方式 1:按件 2:按重量 3:按体积", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "配送计费方式 1:按件 2:按重量 3:按体积不能为空")
private Integer chargeMode;
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "排序不能为空")
private Integer sort;
}
package org.dromara.mall.controller.trade.admin.delivery.vo.expresstemplate;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.util.List;
/**
* 快递运费模板运费设置 Base VO,提供给添加运费模板使用
*/
@Data
public class DeliveryExpressTemplateChargeBaseVO {
@Schema(description = "编号", example = "6592", hidden = true) // 由于想简单一点,复用这个 VO 在更新操作,所以 hidden 为 false
private Long id;
@Schema(description = "区域编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1,120000]")
@NotEmpty(message = "区域编号列表不能为空")
private List<Integer> areaIds;
@Schema(description = "首件数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
@NotNull(message = "首件数量不能为空")
private Double startCount;
@Schema(description = "起步价", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
@NotNull(message = "起步价不能为空")
private Integer startPrice;
@Schema(description = "续件数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
@NotNull(message = "续件数量不能为空")
private Double extraCount;
@Schema(description = "额外价", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000")
@NotNull(message = "额外价不能为空")
private Integer extraPrice;
}
package org.dromara.mall.controller.trade.admin.delivery.vo.expresstemplate;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.List;
@Schema(description = "管理后台 - 快递运费模板创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryExpressTemplateCreateReqVO extends DeliveryExpressTemplateBaseVO {
@Schema(description = "区域运费列表")
@Valid
private List<DeliveryExpressTemplateChargeBaseVO> charges;
@Schema(description = "包邮区域列表")
@Valid
private List<DeliveryExpressTemplateFreeBaseVO> frees;
}
package org.dromara.mall.controller.trade.admin.delivery.vo.expresstemplate;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.List;
@Schema(description = "管理后台 - 快递运费模板的详细 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryExpressTemplateDetailRespVO extends DeliveryExpressTemplateBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "371")
private Long id;
@Schema(description = "运费模板运费设置", requiredMode = Schema.RequiredMode.REQUIRED)
private List<DeliveryExpressTemplateChargeBaseVO> charges;
@Schema(description = "运费模板包邮区域", requiredMode = Schema.RequiredMode.REQUIRED)
private List<DeliveryExpressTemplateFreeBaseVO> frees;
}
package org.dromara.mall.controller.trade.admin.delivery.vo.expresstemplate;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.util.List;
/**
* 快递运费模板包邮 Base VO,提供给添加运费模板使用
*/
@Data
public class DeliveryExpressTemplateFreeBaseVO {
@Schema(description = "区域编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1,120000]")
@NotEmpty(message = "区域编号列表不能为空")
private List<Integer> areaIds;
@Schema(description = "包邮金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "5000")
@NotNull(message = "包邮金额不能为空")
private Integer freePrice;
@Schema(description = "包邮件数", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
@NotNull(message = "包邮件数不能为空")
private Integer freeCount;
}
package org.dromara.mall.controller.trade.admin.delivery.vo.expresstemplate;
import org.dromara.common.mybatis.core.page.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 快递运费模板分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryExpressTemplatePageReqVO extends PageParam {
@Schema(description = "模板名称", example = "王五")
private String name;
@Schema(description = "配送计费方式 1:按件 2:按重量 3:按体积")
private Integer chargeMode;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}
package org.dromara.mall.controller.trade.admin.delivery.vo.expresstemplate;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 快递运费模板 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryExpressTemplateRespVO extends DeliveryExpressTemplateBaseVO {
@Schema(description = "编号,自增", requiredMode = Schema.RequiredMode.REQUIRED, example = "371")
private Long id;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}
package org.dromara.mall.controller.trade.admin.delivery.vo.expresstemplate;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Schema(description = "管理后台 - 模版精简信息 Response VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DeliveryExpressTemplateSimpleRespVO {
@Schema(description = "模版编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试模版")
private String name;
}
package org.dromara.mall.controller.trade.admin.delivery.vo.expresstemplate;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.List;
@Schema(description = "管理后台 - 快递运费模板更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryExpressTemplateUpdateReqVO extends DeliveryExpressTemplateBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "371")
@NotNull(message = "编号不能为空")
private Long id;
@Schema(description = "区域运费列表")
@Valid
private List<DeliveryExpressTemplateChargeBaseVO> charges;
@Schema(description = "包邮区域列表")
@Valid
private List<DeliveryExpressTemplateFreeBaseVO> frees;
}
package org.dromara.mall.controller.trade.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;
}
package org.dromara.mall.controller.trade.admin.delivery.vo.pickup;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.dromara.common.mall.enums.CommonStatusEnum;
import org.dromara.common.mall.validation.InEnum;
import org.dromara.common.mall.validation.Mobile;
import java.time.LocalTime;
/**
* 自提门店 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class DeliveryPickUpStoreBaseVO {
@Schema(description = "门店名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
@NotBlank(message = "门店名称不能为空")
private String name;
@Schema(description = "门店简介", example = "我是门店简介")
private String introduction;
@Schema(description = "门店手机", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601892312")
@NotBlank(message = "门店手机不能为空")
@Mobile
private String phone;
@Schema(description = "区域编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18733")
@NotNull(message = "区域编号不能为空")
private Integer areaId;
@Schema(description = "门店详细地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "复旦大学路 188 号")
@NotBlank(message = "门店详细地址不能为空")
private String detailAddress;
@Schema(description = "门店 logo", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
@NotBlank(message = "门店 logo 不能为空")
private String logo;
@Schema(description = "营业开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "营业开始时间不能为空")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm")
private LocalTime openingTime;
@Schema(description = "营业结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "营业结束时间不能为空")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm")
private LocalTime closingTime;
@Schema(description = "纬度", requiredMode = Schema.RequiredMode.REQUIRED, example = "5.88")
@NotNull(message = "纬度不能为空")
private Double latitude;
@Schema(description = "经度", requiredMode = Schema.RequiredMode.REQUIRED, example = "6.99")
@NotNull(message = "经度不能为空")
private Double longitude;
@Schema(description = "门店状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "门店状态不能为空")
@InEnum(CommonStatusEnum.class)
private Integer status;
}
package org.dromara.mall.controller.trade.admin.delivery.vo.pickup;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - 自提门店创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryPickUpStoreCreateReqVO extends DeliveryPickUpStoreBaseVO {
}
package org.dromara.mall.controller.trade.admin.delivery.vo.pickup;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.dromara.common.mall.enums.CommonStatusEnum;
import org.dromara.common.mall.validation.InEnum;
import org.dromara.common.mybatis.core.page.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 自提门店分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryPickUpStorePageReqVO extends PageParam {
@Schema(description = "门店名称", example = "李四")
private String name;
@Schema(description = "门店手机")
private String phone;
@Schema(description = "区域编号", example = "18733")
private Integer areaId;
@Schema(description = "门店状态", example = "1")
@InEnum(CommonStatusEnum.class)
private Integer status;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}
package org.dromara.mall.controller.trade.admin.delivery.vo.pickup;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.Accessors;
import org.dromara.mall.controller.trade.admin.base.system.user.UserSimpleBaseVO;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 自提门店 Response VO")
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryPickUpStoreRespVO extends DeliveryPickUpStoreBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23128")
private Long id;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
@Schema(description = "核销用户数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<UserSimpleBaseVO> verifyUsers;
}
package org.dromara.mall.controller.trade.admin.delivery.vo.pickup;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Schema(description = "管理后台 - 自提门店精简信息 Response VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DeliveryPickUpStoreSimpleRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23128")
private Long id;
@Schema(description = "门店名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
private String name;
@Schema(description = "门店手机", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601892312")
private String phone;
@Schema(description = "区域编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18733")
private Integer areaId;
@Schema(description = "区域名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "xx市")
private String areaName;
@Schema(description = "门店详细地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "复旦大学路 188 号")
private String detailAddress;
@Schema(description = "绑定用户编号组数", requiredMode = Schema.RequiredMode.REQUIRED, example = "23128")
private List<Long> verifyUserIds;
}
package org.dromara.mall.controller.trade.admin.delivery.vo.pickup;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - 自提门店更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryPickUpStoreUpdateReqVO extends DeliveryPickUpStoreBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23128")
@NotNull(message = "编号不能为空")
private Long id;
}
### 获得交易订单分页 => 成功
GET {{baseUrl}}/trade/order/page?pageNo=1&pageSize=10
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
### 获得交易订单分页 => 成功
GET {{baseUrl}}/trade/order/get-detail?id=21
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
### 获得交易订单的物流轨迹 => 成功
GET {{baseUrl}}/trade/order/get-express-track-list?id=21
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
\ No newline at end of file
package org.dromara.mall.controller.trade.admin.order;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.collection.CollUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.mybatis.core.page.PageResult;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.mall.api.dto.member.MemberUserRespDTO;
import org.dromara.mall.api.service.member.MemberUserApi;
import org.dromara.mall.controller.trade.admin.order.vo.*;
import org.dromara.mall.convert.trade.order.TradeOrderConvert;
import org.dromara.mall.domain.trade.TradeOrderDO;
import org.dromara.mall.domain.trade.TradeOrderItemDO;
import org.dromara.mall.domain.trade.TradeOrderLogDO;
import org.dromara.mall.service.trade.order.TradeOrderLogService;
import org.dromara.mall.service.trade.order.TradeOrderQueryService;
import org.dromara.mall.service.trade.order.TradeOrderUpdateService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import static org.dromara.common.mall.util.collection.CollectionUtils.convertList;
import static org.dromara.common.mall.util.collection.CollectionUtils.convertSet;
@Tag(name = "管理后台 - 交易订单")
@RestController
@RequestMapping("/admin/trade/order")
@Validated
@Slf4j
public class TradeOrderController {
@Resource
private TradeOrderUpdateService tradeOrderUpdateService;
@Resource
private TradeOrderQueryService tradeOrderQueryService;
@Resource
private TradeOrderLogService tradeOrderLogService;
@Resource
private MemberUserApi memberUserApi;
@GetMapping("/page")
@Operation(summary = "获得交易订单分页")
@SaCheckPermission("trade:order:query")
public R<PageResult<TradeOrderPageItemRespVO>> getOrderPage(TradeOrderPageReqVO reqVO) {
// 查询订单
PageResult<TradeOrderDO> pageResult = tradeOrderQueryService.getOrderPage(reqVO);
if (CollUtil.isEmpty(pageResult.getList())) {
return R.ok(PageResult.empty());
}
// 查询用户信息
Set<Long> userIds = CollUtil.unionDistinct(convertList(pageResult.getList(), TradeOrderDO::getUserId),
convertList(pageResult.getList(), TradeOrderDO::getBrokerageUserId, Objects::nonNull));
Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds);
// 查询订单项
List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(
convertSet(pageResult.getList(), TradeOrderDO::getId));
// 最终组合
return R.ok(TradeOrderConvert.INSTANCE.convertPage(pageResult, orderItems, userMap));
}
@GetMapping("/summary")
@Operation(summary = "获得交易订单统计")
@SaCheckPermission("trade:order:query")
public R<TradeOrderSummaryRespVO> getOrderSummary(TradeOrderPageReqVO reqVO) {
return R.ok(tradeOrderQueryService.getOrderSummary(reqVO));
}
@GetMapping("/get-detail")
@Operation(summary = "获得交易订单详情")
@Parameter(name = "id", description = "订单编号", required = true, example = "1")
@SaCheckPermission("trade:order:query")
public R<TradeOrderDetailRespVO> getOrderDetail(@RequestParam("id") Long id) {
// 查询订单
TradeOrderDO order = tradeOrderQueryService.getOrder(id);
if (order == null) {
return R.ok(null);
}
// 查询订单项
List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(id);
// 拼接数据
MemberUserRespDTO user = memberUserApi.getUser(order.getUserId());
MemberUserRespDTO brokerageUser = order.getBrokerageUserId() != null ?
memberUserApi.getUser(order.getBrokerageUserId()) : null;
List<TradeOrderLogDO> orderLogs = tradeOrderLogService.getOrderLogListByOrderId(id);
return R.ok(TradeOrderConvert.INSTANCE.convert(order, orderItems, orderLogs, user, brokerageUser));
}
@GetMapping("/get-express-track-list")
@Operation(summary = "获得交易订单的物流轨迹")
@Parameter(name = "id", description = "交易订单编号")
@SaCheckPermission("trade:order:query")
public R<List<?>> getOrderExpressTrackList(@RequestParam("id") Long id) {
return R.ok(TradeOrderConvert.INSTANCE.convertList02(
tradeOrderQueryService.getExpressTrackList(id)));
}
@PutMapping("/delivery")
@Operation(summary = "订单发货")
@SaCheckPermission("trade:order:update")
public R<Boolean> deliveryOrder(@RequestBody TradeOrderDeliveryReqVO deliveryReqVO) {
tradeOrderUpdateService.deliveryOrder(deliveryReqVO);
return R.ok(true);
}
@PutMapping("/update-remark")
@Operation(summary = "订单备注")
@SaCheckPermission("trade:order:update")
public R<Boolean> updateOrderRemark(@RequestBody TradeOrderRemarkReqVO reqVO) {
tradeOrderUpdateService.updateOrderRemark(reqVO);
return R.ok(true);
}
@PutMapping("/update-price")
@Operation(summary = "订单调价")
@SaCheckPermission("trade:order:update")
public R<Boolean> updateOrderPrice(@RequestBody TradeOrderUpdatePriceReqVO reqVO) {
tradeOrderUpdateService.updateOrderPrice(reqVO);
return R.ok(true);
}
@PutMapping("/update-address")
@Operation(summary = "修改订单收货地址")
@SaCheckPermission("trade:order:update")
public R<Boolean> updateOrderAddress(@RequestBody TradeOrderUpdateAddressReqVO reqVO) {
tradeOrderUpdateService.updateOrderAddress(reqVO);
return R.ok(true);
}
@PutMapping("/pick-up-by-id")
@Operation(summary = "订单核销")
@Parameter(name = "id", description = "交易订单编号")
@SaCheckPermission("trade:order:pick-up")
public R<Boolean> pickUpOrderById(@RequestParam("id") Long id) {
tradeOrderUpdateService.pickUpOrderByAdmin(LoginHelper.getUserId(), id);
return R.ok(true);
}
@PutMapping("/pick-up-by-verify-code")
@Operation(summary = "订单核销")
@Parameter(name = "pickUpVerifyCode", description = "自提核销码")
@SaCheckPermission("trade:order:pick-up")
public R<Boolean> pickUpOrderByVerifyCode(@RequestParam("pickUpVerifyCode") String pickUpVerifyCode) {
tradeOrderUpdateService.pickUpOrderByAdmin(LoginHelper.getUserId(), pickUpVerifyCode);
return R.ok(true);
}
@GetMapping("/get-by-pick-up-verify-code")
@Operation(summary = "查询核销码对应的订单")
@Parameter(name = "pickUpVerifyCode", description = "自提核销码")
@SaCheckPermission("trade:order:query")
public R<TradeOrderDetailRespVO> getByPickUpVerifyCode(@RequestParam("pickUpVerifyCode") String pickUpVerifyCode) {
TradeOrderDO tradeOrder = tradeOrderUpdateService.getByPickUpVerifyCode(pickUpVerifyCode);
return R.ok(TradeOrderConvert.INSTANCE.convert2(tradeOrder, null));
}
}
package org.dromara.mall.controller.trade.admin.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 交易订单 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class TradeOrderBaseVO {
// ========== 订单基本信息 ==========
@Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "订单流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1146347329394184195")
private String no;
@Schema(description = "下单时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
@Schema(description = "订单类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer type;
@Schema(description = "订单来源", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer terminal;
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
private Long userId;
@Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1")
private String userIp;
@Schema(description = "用户备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "你猜")
private String userRemark;
@Schema(description = "订单状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
@Schema(description = "购买的商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer productCount;
@Schema(description = "订单完成时间")
private LocalDateTime finishTime;
@Schema(description = "订单取消时间")
private LocalDateTime cancelTime;
@Schema(description = "取消类型", example = "10")
private Integer cancelType;
@Schema(description = "商家备注", example = "你猜一下")
private String remark;
// ========== 价格 + 支付基本信息 ==========
@Schema(description = "支付订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long payOrderId;
@Schema(description = "是否已支付", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean payStatus;
@Schema(description = "付款时间")
private LocalDateTime payTime;
@Schema(description = "支付渠道", requiredMode = Schema.RequiredMode.REQUIRED, example = "wx_lite")
private String payChannelCode;
@Schema(description = "商品原价(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
private Integer totalPrice;
@Schema(description = "订单优惠(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer discountPrice;
@Schema(description = "运费金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer deliveryPrice;
@Schema(description = "订单调价(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer adjustPrice;
@Schema(description = "应付金额(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
private Integer payPrice;
// ========== 收件 + 物流基本信息 ==========
@Schema(description = "配送方式", example = "10")
private Integer deliveryType;
@Schema(description = "自提门店", example = "10")
private Long pickUpStoreId;
@Schema(description = "自提核销码", example = "10")
private Long pickUpVerifyCode;
@Schema(description = "配送模板编号", example = "1024")
private Long deliveryTemplateId;
@Schema(description = "发货物流公司编号", example = "1024")
private Long logisticsId;
@Schema(description = "发货物流单号", example = "1024")
private String logisticsNo;
@Schema(description = "发货时间")
private LocalDateTime deliveryTime;
@Schema(description = "收货时间")
private LocalDateTime receiveTime;
@Schema(description = "收件人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
private String receiverName;
@Schema(description = "收件人手机", requiredMode = Schema.RequiredMode.REQUIRED, example = "13800138000")
private String receiverMobile;
@Schema(description = "收件人地区编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "110000")
private Integer receiverAreaId;
@Schema(description = "收件人详细地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "中关村大街 1 号")
private String receiverDetailAddress;
// ========== 售后基本信息 ==========
@Schema(description = "售后状态", example = "1")
private Integer afterSaleStatus;
@Schema(description = "退款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer refundPrice;
// ========== 营销基本信息 ==========
@Schema(description = "优惠劵编号", example = "1024")
private Long couponId;
@Schema(description = "优惠劵减免金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer couponPrice;
@Schema(description = "积分抵扣的金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer pointPrice;
@Schema(description = "VIP 减免金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "888")
private Integer vipPrice;
@Schema(description = "推广人编号", example = "1")
private Long brokerageUserId;
}
package org.dromara.mall.controller.trade.admin.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "管理后台 - 订单发货 Request VO")
@Data
public class TradeOrderDeliveryReqVO {
@Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "订单编号不能为空")
private Long id;
@Schema(description = "发货物流公司编号", example = "1")
@NotNull(message = "发货物流公司不能为空")
private Long logisticsId;
@Schema(description = "发货物流单号", example = "SF123456789")
private String logisticsNo;
}
package org.dromara.mall.controller.trade.admin.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.dromara.mall.controller.trade.admin.base.member.user.MemberUserRespVO;
import org.dromara.mall.controller.trade.admin.base.product.property.ProductPropertyValueDetailRespVO;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 交易订单的详情 Response VO")
@Data
public class TradeOrderDetailRespVO extends TradeOrderBaseVO {
/**
* 订单项列表
*/
private List<Item> items;
/**
* 下单用户信息
*/
private MemberUserRespVO user;
/**
* 推广用户信息
*/
private MemberUserRespVO brokerageUser;
/**
* 操作日志列表
*/
private List<OrderLog> logs;
@Schema(description = "收件人地区名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "上海 上海市 普陀区")
private String receiverAreaName;
@Schema(description = "管理后台 - 交易订单的操作日志")
@Data
public static class OrderLog {
@Schema(description = "操作详情", requiredMode = Schema.RequiredMode.REQUIRED, example = "订单发货")
private String content;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-06-01 10:50:20")
private LocalDateTime createTime;
@Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer userType;
}
@Schema(description = "管理后台 - 交易订单的详情的订单项目")
@Data
public static class Item extends TradeOrderItemBaseVO {
/**
* 属性数组
*/
private List<ProductPropertyValueDetailRespVO> properties;
}
}
package org.dromara.mall.controller.trade.admin.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 交易订单项 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class TradeOrderItemBaseVO {
// ========== 订单项基本信息 ==========
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long userId;
@Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long orderId;
// ========== 商品基本信息 ==========
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long spuId;
@Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
private String spuName;
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long skuId;
@Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
private String picUrl;
@Schema(description = "购买数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer count;
// ========== 价格 + 支付基本信息 ==========
@Schema(description = "商品原价(单)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer price;
@Schema(description = "商品优惠(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer discountPrice;
@Schema(description = "商品实付金额(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer payPrice;
@Schema(description = "子订单分摊金额(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer orderPartPrice;
@Schema(description = "分摊后子订单实付金额(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer orderDividePrice;
// ========== 营销基本信息 ==========
// TODO 芋艿:在捉摸一下
// ========== 售后基本信息 ==========
@Schema(description = "售后状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer afterSaleStatus;
}
package org.dromara.mall.controller.trade.admin.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.dromara.mall.controller.trade.admin.base.member.user.MemberUserRespVO;
import org.dromara.mall.controller.trade.admin.base.product.property.ProductPropertyValueDetailRespVO;
import java.util.List;
@Schema(description = "管理后台 - 交易订单的分页项 Response VO")
@Data
public class TradeOrderPageItemRespVO extends TradeOrderBaseVO {
@Schema(description = "收件人地区名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "上海 上海市 普陀区")
private String receiverAreaName;
@Schema(description = "订单项列表", requiredMode = Schema.RequiredMode.REQUIRED)
private List<Item> items;
@Schema(description = "用户信息", requiredMode = Schema.RequiredMode.REQUIRED)
private MemberUserRespVO user;
@Schema(description = "推广人信息")
private MemberUserRespVO brokerageUser;
@Schema(description = "管理后台 - 交易订单的分页项的订单项目")
@Data
public static class Item extends TradeOrderItemBaseVO {
@Schema(description = "属性列表", requiredMode = Schema.RequiredMode.REQUIRED)
private List<ProductPropertyValueDetailRespVO> properties;
}
}
package org.dromara.mall.controller.trade.admin.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.dromara.common.mall.enums.TerminalEnum;
import org.dromara.common.mall.validation.InEnum;
import org.dromara.common.mall.validation.Mobile;
import org.dromara.common.mybatis.core.page.PageParam;
import org.dromara.mall.enums.trade.order.TradeOrderStatusEnum;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import java.util.List;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 交易订单的分页 Request VO")
@Data
public class TradeOrderPageReqVO extends PageParam {
@Schema(description = "订单号", example = "88888888")
private String no;
@Schema(description = "用户编号", example = "1024")
private Long userId;
@Schema(description = "用户昵称", example = "小王")
private String userNickname;
@Schema(description = "用户手机号", example = "小王")
@Mobile
private String userMobile;
@Schema(description = "配送方式", example = "1")
private Integer deliveryType;
@Schema(description = "发货物流公司编号", example = "1")
private Long logisticsId;
@Schema(description = "自提门店编号", example = "[1,2]")
private List<Long> pickUpStoreIds;
@Schema(description = "自提核销码", example = "12345678")
private String pickUpVerifyCode;
@Schema(description = "订单类型", example = "1")
private Integer type;
@Schema(description = "订单状态", example = "1")
@InEnum(value = TradeOrderStatusEnum.class, message = "订单状态必须是 {value}")
private Integer status;
@Schema(description = "支付渠道", example = "wx_lite")
private String payChannelCode;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
@Schema(description = "订单来源", example = "10")
@InEnum(value = TerminalEnum.class, message = "订单来源 {value}")
private Integer terminal;
}
package org.dromara.mall.controller.trade.admin.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "管理后台 - 订单备注 Request VO")
@Data
public class TradeOrderRemarkReqVO {
@Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "订单编号不能为空")
private Long id;
@Schema(description = "商家备注", example = "你猜一下")
@NotEmpty(message = "订单备注不能为空")
private String remark;
}
package org.dromara.mall.controller.trade.admin.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
@Schema(description = "管理后台 - 交易订单统计 Response VO")
@Data
@Accessors(chain = true)
public class TradeOrderSummaryRespVO {
@Schema(description = "订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long orderCount;
@Schema(description = "订单金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long orderPayPrice;
@Schema(description = "退款单数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long afterSaleCount;
@Schema(description = "退款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long afterSalePrice;
}
package org.dromara.mall.controller.trade.admin.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "管理后台 - 订单修改地址 Request VO")
@Data
public class TradeOrderUpdateAddressReqVO {
@Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "订单编号不能为空")
private Long id;
@Schema(description = "收件人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "z张三")
@NotEmpty(message = "收件人名称不能为空")
private String receiverName;
@Schema(description = "收件人手机", requiredMode = Schema.RequiredMode.REQUIRED, example = "19988188888")
@NotEmpty(message = "收件人手机不能为空")
private String receiverMobile;
@Schema(description = "收件人地区编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7310")
@NotNull(message = "收件人地区编号不能为空")
private Integer receiverAreaId;
@Schema(description = "收件人详细地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "昆明市五华区xxx小区xxx")
@NotEmpty(message = "收件人详细地址不能为空")
private String receiverDetailAddress;
}
package org.dromara.mall.controller.trade.admin.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "管理后台 - 订单改价 Request VO")
@Data
public class TradeOrderUpdatePriceReqVO {
@Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "订单编号不能为空")
private Long id;
@Schema(description = "订单调价,单位:分。正数,加价;负数,减价", requiredMode = Schema.RequiredMode.REQUIRED, example = "-100")
@NotNull(message = "订单调价价格不能为空")
private Integer adjustPrice;
}
package org.dromara.mall.controller.trade.app.aftersale;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.mybatis.core.page.PageParam;
import org.dromara.common.mybatis.core.page.PageResult;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.mall.controller.trade.app.aftersale.vo.AppAfterSaleCreateReqVO;
import org.dromara.mall.controller.trade.app.aftersale.vo.AppAfterSaleDeliveryReqVO;
import org.dromara.mall.controller.trade.app.aftersale.vo.AppAfterSaleRespVO;
import org.dromara.mall.convert.trade.aftersale.AfterSaleConvert;
import org.dromara.mall.service.trade.aftersale.AfterSaleService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@Tag(name = "用户 App - 交易售后")
@RestController
@RequestMapping("/app/trade/after-sale")
@Validated
@Slf4j
public class AppAfterSaleController {
@Resource
private AfterSaleService afterSaleService;
@GetMapping(value = "/page")
@Operation(summary = "获得售后分页")
public R<PageResult<AppAfterSaleRespVO>> getAfterSalePage(PageParam pageParam) {
return R.ok(AfterSaleConvert.INSTANCE.convertPage02(
afterSaleService.getAfterSalePage(LoginHelper.getMemberId(), pageParam)));
}
@GetMapping(value = "/get")
@Operation(summary = "获得售后订单")
@Parameter(name = "id", description = "售后编号", required = true, example = "1")
public R<AppAfterSaleRespVO> getAfterSale(@RequestParam("id") Long id) {
return R.ok(AfterSaleConvert.INSTANCE.convert(afterSaleService.getAfterSale(LoginHelper.getMemberId(), id)));
}
@PostMapping(value = "/create")
@Operation(summary = "申请售后")
public R<Long> createAfterSale(@RequestBody AppAfterSaleCreateReqVO createReqVO) {
return R.ok(afterSaleService.createAfterSale(LoginHelper.getMemberId(), createReqVO));
}
@PutMapping(value = "/delivery")
@Operation(summary = "退回货物")
public R<Boolean> deliveryAfterSale(@RequestBody AppAfterSaleDeliveryReqVO deliveryReqVO) {
afterSaleService.deliveryAfterSale(LoginHelper.getMemberId(), deliveryReqVO);
return R.ok(true);
}
@DeleteMapping(value = "/cancel")
@Operation(summary = "取消售后")
@Parameter(name = "id", description = "售后编号", required = true, example = "1")
public R<Boolean> cancelAfterSale(@RequestParam("id") Long id) {
afterSaleService.cancelAfterSale(LoginHelper.getMemberId(), id);
return R.ok(true);
}
}
package org.dromara.mall.controller.trade.app.aftersale;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.mall.util.object.BeanUtils;
import org.dromara.mall.controller.trade.app.aftersale.vo.log.AppAfterSaleLogRespVO;
import org.dromara.mall.domain.trade.AfterSaleLogDO;
import org.dromara.mall.service.trade.aftersale.AfterSaleLogService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Tag(name = "用户 App - 售后日志")
@RestController
@RequestMapping("/app/trade/after-sale-log")
@Validated
@Slf4j
public class AppAfterSaleLogController {
@Resource
private AfterSaleLogService afterSaleLogService;
@GetMapping("/list")
@Operation(summary = "获得售后日志列表")
@Parameter(name = "afterSaleId", description = "售后编号", required = true, example = "1")
public R<List<AppAfterSaleLogRespVO>> getAfterSaleLogList(
@RequestParam("afterSaleId") Long afterSaleId) {
List<AfterSaleLogDO> logs = afterSaleLogService.getAfterSaleLogList(afterSaleId);
return R.ok(BeanUtils.toBean(logs, AppAfterSaleLogRespVO.class));
}
}
package org.dromara.mall.controller.trade.app.aftersale.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.dromara.common.mall.validation.InEnum;
import org.dromara.mall.enums.trade.aftersale.AfterSaleWayEnum;
import java.util.List;
@Schema(description = "用户 App - 交易售后创建 Request VO")
@Data
public class AppAfterSaleCreateReqVO {
@Schema(description = "订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "订单项编号不能为空")
private Long orderItemId;
@Schema(description = "售后方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "售后方式不能为空")
@InEnum(value = AfterSaleWayEnum.class, message = "售后方式必须是 {value}")
private Integer way;
@Schema(description = "退款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
@NotNull(message = "退款金额不能为空")
@Min(value = 1, message = "退款金额必须大于 0")
private Integer refundPrice;
@Schema(description = "申请原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "申请原因不能为空")
private String applyReason;
@Schema(description = "补充描述", example = "商品质量不好")
private String applyDescription;
@Schema(description = "补充凭证图片", example = "https://www.iocoder.cn/1.png, https://www.iocoder.cn/2.png")
private List<String> applyPicUrls;
}
package org.dromara.mall.controller.trade.app.aftersale.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "用户 App - 交易售后退回货物 Request VO")
@Data
public class AppAfterSaleDeliveryReqVO {
@Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "售后编号不能为空")
private Long id;
@Schema(description = "退货物流公司编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "退货物流公司编号不能为空")
private Long logisticsId;
@Schema(description = "退货物流单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "SF123456789")
@NotNull(message = "退货物流单号不能为空")
private String logisticsNo;
}
package org.dromara.mall.controller.trade.app.aftersale.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.dromara.mall.controller.trade.app.base.property.AppProductPropertyValueDetailRespVO;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "用户 App - 交易售后 Response VO")
@Data
public class AppAfterSaleRespVO {
@Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "售后流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1146347329394184195")
private String no;
@Schema(description = "售后状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
@Schema(description = "售后方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer way;
@Schema(description = "售后类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer type;
@Schema(description = "申请原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private String applyReason;
@Schema(description = "补充描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private String applyDescription;
@Schema(description = "补充凭证图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private List<String> applyPicUrls;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime updateTime;
// ========== 交易订单相关 ==========
@Schema(description = "交易订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long orderId;
@Schema(description = "交易订单流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private String orderNo;
@Schema(description = "交易订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long orderItemId;
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long spuId;
@Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private String spuName;
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long skuId;
/**
* 属性数组
*/
private List<AppProductPropertyValueDetailRespVO> properties;
@Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/01.jpg")
private String picUrl;
@Schema(description = "退货商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer count;
// ========== 审批相关 ==========
/**
* 审批备注
*
* 注意,只有审批不通过才会填写
*/
private String auditReason;
// ========== 退款相关 ==========
@Schema(description = "退款金额,单位:分", example = "100")
private Integer refundPrice;
@Schema(description = "退款时间")
private LocalDateTime refundTime;
// ========== 退货相关 ==========
@Schema(description = "退货物流公司编号", example = "1")
private Long logisticsId;
@Schema(description = "退货物流单号", example = "SF123456789")
private String logisticsNo;
@Schema(description = "退货时间")
private LocalDateTime deliveryTime;
@Schema(description = "收货时间")
private LocalDateTime receiveTime;
@Schema(description = "收货备注")
private String receiveReason;
}
package org.dromara.mall.controller.trade.app.aftersale.vo.log;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - App 交易售后日志 Response VO")
@Data
public class AppAfterSaleLogRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20669")
private Long id;
@Schema(description = "操作明细", requiredMode = Schema.RequiredMode.REQUIRED, example = "维权完成,退款金额:¥37776.00")
private String content;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}
/**
* 基础包,放一些通用的 VO 类
*/
package org.dromara.mall.controller.trade.app.base;
package org.dromara.mall.controller.trade.app.base.property;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "用户 App - 商品属性值的明细 Response VO")
@Data
public class AppProductPropertyValueDetailRespVO {
@Schema(description = "属性的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long propertyId;
@Schema(description = "属性的名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "颜色")
private String propertyName;
@Schema(description = "属性值的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long valueId;
@Schema(description = "属性值的名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "红色")
private String valueName;
}
package org.dromara.mall.controller.trade.app.base.sku;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.dromara.mall.controller.trade.app.base.property.AppProductPropertyValueDetailRespVO;
import java.util.List;
/**
* 商品 SKU 基础 Response VO
*
* @author 芋道源码
*/
@Data
public class AppProductSkuBaseRespVO {
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "图片地址", example = "https://www.iocoder.cn/xx.png")
private String picUrl;
@Schema(description = "销售价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer price;
@Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer stock;
/**
* 属性数组
*/
private List<AppProductPropertyValueDetailRespVO> properties;
}
package org.dromara.mall.controller.trade.app.base.spu;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 商品 SPU 基础 Response VO
*
* @author 芋道源码
*/
@Data
public class AppProductSpuBaseRespVO {
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "商品 SPU 名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
private String name;
@Schema(description = "商品主图地址", example = "https://www.iocoder.cn/xx.png")
private String picUrl;
@Schema(description = "商品分类编号", example = "1")
private Long categoryId;
}
package org.dromara.mall.controller.trade.app.brokerage;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.mybatis.core.page.PageResult;
import org.dromara.common.mybatis.util.BeanUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.mall.controller.trade.app.brokerage.vo.record.AppBrokerageProductPriceRespVO;
import org.dromara.mall.controller.trade.app.brokerage.vo.record.AppBrokerageRecordPageReqVO;
import org.dromara.mall.controller.trade.app.brokerage.vo.record.AppBrokerageRecordRespVO;
import org.dromara.mall.convert.trade.brokerage.BrokerageRecordConvert;
import org.dromara.mall.domain.trade.BrokerageRecordDO;
import org.dromara.mall.service.trade.brokerage.BrokerageRecordService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@Tag(name = "用户 APP - 分销用户")
@RestController
@RequestMapping("/app/trade/brokerage-record")
@Validated
@Slf4j
public class AppBrokerageRecordController {
@Resource
private BrokerageRecordService brokerageRecordService;
@GetMapping("/page")
@Operation(summary = "获得分销记录分页")
public R<PageResult<AppBrokerageRecordRespVO>> getBrokerageRecordPage(@Valid AppBrokerageRecordPageReqVO pageReqVO) {
PageResult<BrokerageRecordDO> pageResult = brokerageRecordService.getBrokerageRecordPage(
BrokerageRecordConvert.INSTANCE.convert(pageReqVO, LoginHelper.getUserId()));
return R.ok(BeanUtils.toBean(pageResult, AppBrokerageRecordRespVO.class));
}
@GetMapping("/get-product-brokerage-price")
@Operation(summary = "获得商品的分销金额")
public R<AppBrokerageProductPriceRespVO> getProductBrokeragePrice(@RequestParam("spuId") Long spuId) {
return R.ok(brokerageRecordService.calculateProductBrokeragePrice(LoginHelper.getUserId(), spuId));
}
}
package org.dromara.mall.controller.trade.app.brokerage;
import cn.hutool.core.date.LocalDateTimeUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.mybatis.core.page.PageResult;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.mall.api.dto.member.MemberUserRespDTO;
import org.dromara.mall.api.service.member.MemberUserApi;
import org.dromara.mall.controller.trade.app.brokerage.vo.user.*;
import org.dromara.mall.convert.trade.brokerage.BrokerageRecordConvert;
import org.dromara.mall.convert.trade.brokerage.BrokerageUserConvert;
import org.dromara.mall.domain.trade.BrokerageUserDO;
import org.dromara.mall.enums.trade.brokerage.BrokerageRecordBizTypeEnum;
import org.dromara.mall.enums.trade.brokerage.BrokerageRecordStatusEnum;
import org.dromara.mall.enums.trade.brokerage.BrokerageWithdrawStatusEnum;
import org.dromara.mall.service.trade.brokerage.BrokerageRecordService;
import org.dromara.mall.service.trade.brokerage.BrokerageUserService;
import org.dromara.mall.service.trade.brokerage.BrokerageWithdrawService;
import org.dromara.mall.service.trade.brokerage.bo.BrokerageWithdrawSummaryRespBO;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import static org.dromara.common.mall.util.collection.CollectionUtils.convertSet;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Tag(name = "用户 APP - 分销用户")
@RestController
@RequestMapping("/app/trade/brokerage-user")
@Validated
@Slf4j
public class AppBrokerageUserController {
@Resource
private BrokerageUserService brokerageUserService;
@Resource
private BrokerageRecordService brokerageRecordService;
@Resource
private BrokerageWithdrawService brokerageWithdrawService;
@Resource
private MemberUserApi memberUserApi;
@GetMapping("/get")
@Operation(summary = "获得个人分销信息")
public R<AppBrokerageUserRespVO> getBrokerageUser() {
Optional<BrokerageUserDO> user = Optional.ofNullable(brokerageUserService.getOrCreateBrokerageUser(LoginHelper.getUserId()));
// 返回数据
AppBrokerageUserRespVO respVO = new AppBrokerageUserRespVO()
.setBrokerageEnabled(user.map(BrokerageUserDO::getBrokerageEnabled).orElse(false))
.setBrokeragePrice(user.map(BrokerageUserDO::getBrokeragePrice).orElse(0))
.setFrozenPrice(user.map(BrokerageUserDO::getFrozenPrice).orElse(0));
return R.ok(respVO);
}
@PutMapping("/bind")
@Operation(summary = "绑定推广员")
public R<Boolean> bindBrokerageUser(@Valid @RequestBody AppBrokerageUserBindReqVO reqVO) {
return R.ok(brokerageUserService.bindBrokerageUser(LoginHelper.getUserId(), reqVO.getBindUserId()));
}
@GetMapping("/get-summary")
@Operation(summary = "获得个人分销统计")
public R<AppBrokerageUserMySummaryRespVO> getBrokerageUserSummary() {
// 查询当前登录用户信息
Long userId = LoginHelper.getUserId();
BrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(userId);
// 统计用户昨日的佣金
LocalDateTime yesterday = LocalDateTime.now().minusDays(1);
LocalDateTime beginTime = LocalDateTimeUtil.beginOfDay(yesterday);
LocalDateTime endTime = LocalDateTimeUtil.endOfDay(yesterday);
Integer yesterdayPrice = brokerageRecordService.getSummaryPriceByUserId(userId,
BrokerageRecordBizTypeEnum.ORDER, BrokerageRecordStatusEnum.SETTLEMENT, beginTime, endTime);
// 统计用户提现的佣金
Integer withdrawPrice = brokerageWithdrawService.getWithdrawSummaryListByUserId(Collections.singleton(userId),
BrokerageWithdrawStatusEnum.AUDIT_SUCCESS).stream()
.findFirst().map(BrokerageWithdrawSummaryRespBO::getPrice).orElse(0);
// 统计分销用户数量(一级)
Long firstBrokerageUserCount = brokerageUserService.getBrokerageUserCountByBindUserId(userId, 1);
// 统计分销用户数量(二级)
Long secondBrokerageUserCount = brokerageUserService.getBrokerageUserCountByBindUserId(userId, 2);
// 拼接返回
return R.ok(BrokerageUserConvert.INSTANCE.convert(yesterdayPrice, withdrawPrice, firstBrokerageUserCount, secondBrokerageUserCount, brokerageUser));
}
@GetMapping("/rank-page-by-user-count")
@Operation(summary = "获得分销用户排行分页(基于用户量)")
public R<PageResult<AppBrokerageUserRankByUserCountRespVO>> getBrokerageUserRankPageByUserCount(AppBrokerageUserRankPageReqVO pageReqVO) {
// 分页查询
PageResult<AppBrokerageUserRankByUserCountRespVO> pageResult = brokerageUserService.getBrokerageUserRankPageByUserCount(pageReqVO);
// 拼接数据
Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(convertSet(pageResult.getList(), AppBrokerageUserRankByUserCountRespVO::getId));
return R.ok(BrokerageUserConvert.INSTANCE.convertPage03(pageResult, userMap));
}
@GetMapping("/rank-page-by-price")
@Operation(summary = "获得分销用户排行分页(基于佣金)")
public R<PageResult<AppBrokerageUserRankByPriceRespVO>> getBrokerageUserChildSummaryPageByPrice(AppBrokerageUserRankPageReqVO pageReqVO) {
// 分页查询
PageResult<AppBrokerageUserRankByPriceRespVO> pageResult = brokerageRecordService.getBrokerageUserChildSummaryPageByPrice(pageReqVO);
// 拼接数据
Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(convertSet(pageResult.getList(), AppBrokerageUserRankByPriceRespVO::getId));
return R.ok(BrokerageRecordConvert.INSTANCE.convertPage03(pageResult, userMap));
}
@GetMapping("/child-summary-page")
@Operation(summary = "获得下级分销统计分页")
public R<PageResult<AppBrokerageUserChildSummaryRespVO>> getBrokerageUserChildSummaryPage(
AppBrokerageUserChildSummaryPageReqVO pageReqVO) {
PageResult<AppBrokerageUserChildSummaryRespVO> pageResult = brokerageUserService.getBrokerageUserChildSummaryPage(pageReqVO, LoginHelper.getUserId());
return R.ok(pageResult);
}
@GetMapping("/get-rank-by-price")
@Operation(summary = "获得分销用户排行(基于佣金)")
@Parameter(name = "times", description = "时间段", required = true)
public R<Integer> getRankByPrice(
@RequestParam("times") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) LocalDateTime[] times) {
return R.ok(brokerageRecordService.getUserRankByPrice(LoginHelper.getUserId(), times));
}
}
package org.dromara.mall.controller.trade.app.brokerage;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.mybatis.core.page.PageResult;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.mall.controller.trade.app.brokerage.vo.withdraw.AppBrokerageWithdrawCreateReqVO;
import org.dromara.mall.controller.trade.app.brokerage.vo.withdraw.AppBrokerageWithdrawPageReqVO;
import org.dromara.mall.controller.trade.app.brokerage.vo.withdraw.AppBrokerageWithdrawRespVO;
import org.dromara.mall.convert.trade.brokerage.BrokerageWithdrawConvert;
import org.dromara.mall.domain.trade.BrokerageWithdrawDO;
import org.dromara.mall.service.trade.brokerage.BrokerageWithdrawService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@Tag(name = "用户 APP - 分销提现")
@RestController
@RequestMapping("/app/trade/brokerage-withdraw")
@Validated
@Slf4j
public class AppBrokerageWithdrawController {
@Resource
private BrokerageWithdrawService brokerageWithdrawService;
@GetMapping("/page")
@Operation(summary = "获得分销提现分页")
public R<PageResult<AppBrokerageWithdrawRespVO>> getBrokerageWithdrawPage(AppBrokerageWithdrawPageReqVO pageReqVO) {
PageResult<BrokerageWithdrawDO> pageResult = brokerageWithdrawService.getBrokerageWithdrawPage(
BrokerageWithdrawConvert.INSTANCE.convert(pageReqVO, LoginHelper.getUserId()));
return R.ok(BrokerageWithdrawConvert.INSTANCE.convertPage03(pageResult));
}
@PostMapping("/create")
@Operation(summary = "创建分销提现")
public R<Long> createBrokerageWithdraw(@RequestBody @Valid AppBrokerageWithdrawCreateReqVO createReqVO) {
return R.ok(brokerageWithdrawService.createBrokerageWithdraw(LoginHelper.getUserId(), createReqVO));
}
}
package org.dromara.mall.controller.trade.app.brokerage.vo.record;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
@Schema(description = "用户 App - 商品的分销金额 Response VO")
@Data
@Accessors(chain = true)
public class AppBrokerageProductPriceRespVO {
@Schema(description = "是否开启", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Boolean enabled;
@Schema(description = "分销最小金额,单位:分", example = "100")
private Integer brokerageMinPrice;
@Schema(description = "分销最大金额,单位:分", example = "100")
private Integer brokerageMaxPrice;
}
package org.dromara.mall.controller.trade.app.brokerage.vo.record;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.dromara.common.mall.validation.InEnum;
import org.dromara.common.mybatis.core.page.PageParam;
import org.dromara.mall.enums.trade.brokerage.BrokerageRecordBizTypeEnum;
import org.dromara.mall.enums.trade.brokerage.BrokerageRecordStatusEnum;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "应用 App - 分销记录分页 Request VO")
@Data
public class AppBrokerageRecordPageReqVO extends PageParam {
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
@Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@InEnum(value = BrokerageRecordBizTypeEnum.class, message = "业务类型必须是 {value}")
private Integer bizType;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@InEnum(value = BrokerageRecordStatusEnum.class, message = "状态必须是 {value}")
private Integer status;
}
package org.dromara.mall.controller.trade.app.brokerage.vo.record;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "用户 App - 分销记录 Response VO")
@Data
public class AppBrokerageRecordRespVO {
@Schema(description = "记录编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Long id;
@Schema(description = "业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private String bizId;
@Schema(description = "分销标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "用户下单")
private String title;
@Schema(description = "分销金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
private Integer price;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
@Schema(description = "完成时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime finishTime;
}
package org.dromara.mall.controller.trade.app.brokerage.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "应用 App - 绑定推广员 Request VO")
@Data
public class AppBrokerageUserBindReqVO {
@Schema(description = "推广员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "推广员编号不能为空")
private Long bindUserId;
}
package org.dromara.mall.controller.trade.app.brokerage.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.dromara.common.mybatis.core.page.PageParam;
import org.dromara.common.mybatis.core.page.SortingField;
import org.hibernate.validator.constraints.Range;
@Schema(description = "用户 App - 下级分销统计分页 Request VO")
@Data
public class AppBrokerageUserChildSummaryPageReqVO extends PageParam {
public static final String SORT_FIELD_USER_COUNT = "userCount";
public static final String SORT_FIELD_ORDER_COUNT = "orderCount";
public static final String SORT_FIELD_PRICE = "price";
@Schema(description = "用户昵称", example = "李") // 模糊匹配
private String nickname;
@Schema(description = "排序字段", example = "userCount")
private SortingField sortingField;
@Schema(description = "下级的级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") // 1 - 直接下级;2 - 间接下级
@NotNull(message = "下级的级别不能为空")
@Range(min = 1, max = 2, message = "下级的级别只能是 {min} 或者 {max}")
private Integer level;
}
package org.dromara.mall.controller.trade.app.brokerage.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
@Schema(description = "用户 App - 下级分销统计 Response VO")
@Data
@Accessors(chain = true)
public class AppBrokerageUserChildSummaryRespVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Long id;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小王")
private String nickname;
@Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xxx.jpg")
private String avatar;
@Schema(description = "佣金金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer brokeragePrice;
@Schema(description = "分销订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
private Integer brokerageOrderCount;
@Schema(description = "分销用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "30")
private Integer brokerageUserCount;
@Schema(description = "绑定推广员的时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime brokerageTime;
}
package org.dromara.mall.controller.trade.app.brokerage.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
@Schema(description = "用户 App - 个人分销统计 Response VO")
@Data
@Accessors(chain = true)
public class AppBrokerageUserMySummaryRespVO {
@Schema(description = "昨天的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer yesterdayPrice;
@Schema(description = "提现的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer withdrawPrice;
@Schema(description = "可用的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2408")
private Integer brokeragePrice;
@Schema(description = "冻结的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "234")
private Integer frozenPrice;
@Schema(description = "分销用户数量(一级)", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Long firstBrokerageUserCount;
@Schema(description = "分销用户数量(二级)", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Long secondBrokerageUserCount;
}
package org.dromara.mall.controller.trade.app.brokerage.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "用户 App - 分销排行用户(基于用户量) Response VO")
@Data
public class AppBrokerageUserRankByPriceRespVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Long id;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小王")
private String nickname;
@Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xxx.jpg")
private String avatar;
@Schema(description = "佣金金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer brokeragePrice;
}
package org.dromara.mall.controller.trade.app.brokerage.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "用户 App - 分销排行用户(基于用户量) Response VO")
@Data
public class AppBrokerageUserRankByUserCountRespVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Long id;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小王")
private String nickname;
@Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xxx.jpg")
private String avatar;
@Schema(description = "邀请用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer brokerageUserCount;
}
package org.dromara.mall.controller.trade.app.brokerage.vo.user;
import org.dromara.common.mybatis.core.page.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static org.dromara.common.mall.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "应用 App - 分销用户排行 Request VO")
@Data
public class AppBrokerageUserRankPageReqVO extends PageParam {
@Schema(description = "开始 + 结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@NotEmpty(message = "时间不能为空")
private LocalDateTime[] times;
}
package org.dromara.mall.controller.trade.app.brokerage.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
@Schema(description = "用户 App - 分销用户信息 Response VO")
@Data
@Accessors(chain = true)
public class AppBrokerageUserRespVO {
@Schema(description = "是否有分销资格", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean brokerageEnabled;
@Schema(description = "可用的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2408")
private Integer brokeragePrice;
@Schema(description = "冻结的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "234")
private Integer frozenPrice;
}
package org.dromara.mall.controller.trade.app.brokerage.vo.withdraw;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Validator;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.PositiveOrZero;
import lombok.Data;
import org.dromara.common.mall.util.validation.ValidationUtils;
import org.dromara.common.mall.validation.InEnum;
import org.dromara.mall.enums.trade.brokerage.BrokerageWithdrawTypeEnum;
import org.hibernate.validator.constraints.URL;
@Schema(description = "用户 App - 分销提现创建 Request VO")
@Data
public class AppBrokerageWithdrawCreateReqVO {
@Schema(description = "提现方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@InEnum(value = BrokerageWithdrawTypeEnum.class, message = "提现方式必须是 {value}")
private Integer type;
@Schema(description = "提现金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
@PositiveOrZero(message = "提现金额不能小于 0")
@NotNull(message = "提现金额不能为空")
private Integer price;
// ========== 银行卡、微信、支付宝 提现相关字段 ==========
@Schema(description = "提现账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456789")
@NotBlank(message = "提现账号不能为空", groups = {Bank.class, Wechat.class, Alipay.class})
private String accountNo;
// ========== 微信、支付宝 提现相关字段 ==========
@Schema(description = "收款码的图片", example = "https://www.iocoder.cn/1.png")
@URL(message = "收款码的图片,必须是一个 URL")
private String accountQrCodeUrl;
// ========== 银行卡 提现相关字段 ==========
@Schema(description = "持卡人姓名", example = "张三")
@NotBlank(message = "持卡人姓名不能为空", groups = {Bank.class})
private String name;
@Schema(description = "提现银行", example = "1")
@NotNull(message = "提现银行不能为空", groups = {Bank.class})
private String bankName;
@Schema(description = "开户地址", example = "海淀支行")
private String bankAddress;
public interface Wallet {
}
public interface Bank {
}
public interface Wechat {
}
public interface Alipay {
}
public void validate(Validator validator) {
if (BrokerageWithdrawTypeEnum.WALLET.getType().equals(type)) {
ValidationUtils.validate(validator, this, Wallet.class);
} else if (BrokerageWithdrawTypeEnum.BANK.getType().equals(type)) {
ValidationUtils.validate(validator, this, Bank.class);
} else if (BrokerageWithdrawTypeEnum.WECHAT.getType().equals(type)) {
ValidationUtils.validate(validator, this, Wechat.class);
} else if (BrokerageWithdrawTypeEnum.ALIPAY.getType().equals(type)) {
ValidationUtils.validate(validator, this, Alipay.class);
}
}
}
package org.dromara.mall.controller.trade.app.brokerage.vo.withdraw;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.dromara.common.mall.validation.InEnum;
import org.dromara.common.mybatis.core.page.PageParam;
import org.dromara.mall.enums.trade.brokerage.BrokerageWithdrawStatusEnum;
import org.dromara.mall.enums.trade.brokerage.BrokerageWithdrawTypeEnum;
@Schema(description = "应用 App - 分销提现分页 Request VO")
@Data
public class AppBrokerageWithdrawPageReqVO extends PageParam {
@Schema(description = "类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@InEnum(value = BrokerageWithdrawTypeEnum.class, message = "类型必须是 {value}")
private Integer type;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@InEnum(value = BrokerageWithdrawStatusEnum.class, message = "状态必须是 {value}")
private Integer status;
}
package org.dromara.mall.controller.trade.app.brokerage.vo.withdraw;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "用户 App - 分销提现 Response VO")
@Data
public class AppBrokerageWithdrawRespVO {
@Schema(description = "提现编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Long id;
@Schema(description = "提现状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer status;
@Schema(description = "提现状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "审核中")
private String statusName;
@Schema(description = "提现金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
private Integer price;
@Schema(description = "提现时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}
### 请求 /trade/cart/add 接口 => 成功
POST {{appApi}}/trade/cart/add
tenant-id: {{appTenentId}}
Authorization: Bearer {{appToken}}
Content-Type: application/json
{
"skuId": 1,
"count": 10,
"addStatus": true
}
### 请求 /trade/cart/update 接口 => 成功
PUT {{appApi}}/trade/cart/update
tenant-id: {{appTenentId}}
Authorization: Bearer {{appToken}}
Content-Type: application/json
{
"id": 35,
"count": 5
}
### 请求 /trade/cart/delete 接口 => 成功
DELETE {{appApi}}/trade/cart/delete?ids=1
tenant-id: {{appTenentId}}
Authorization: Bearer {{appToken}}
### 请求 /trade/cart/get-count 接口 => 成功
GET {{appApi}}/trade/cart/get-count
tenant-id: {{appTenentId}}
Authorization: Bearer {{appToken}}
### 请求 /trade/cart/get-count-map 接口 => 成功
GET {{appApi}}/trade/cart/get-count-map
tenant-id: {{appTenentId}}
Authorization: Bearer {{appToken}}
### 请求 /trade/cart/list 接口 => 成功
GET {{appApi}}/trade/cart/list
tenant-id: {{appTenentId}}
Authorization: Bearer {{appToken}}
package org.dromara.mall.controller.trade.app.cart;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.mall.controller.trade.app.cart.vo.*;
import org.dromara.mall.service.trade.cart.CartService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Tag(name = "用户 App - 购物车")
@RestController
@RequestMapping("/app/trade/cart")
@RequiredArgsConstructor
@Validated
@Slf4j
public class AppCartController {
@Resource
private CartService cartService;
@PostMapping("/add")
@Operation(summary = "添加购物车商品")
public R<Long> addCart(@Valid @RequestBody AppCartAddReqVO addCountReqVO) {
return R.ok(cartService.addCart(LoginHelper.getUserId(), addCountReqVO));
}
@PutMapping("/update-count")
@Operation(summary = "更新购物车商品数量")
public R<Boolean> updateCartCount(@Valid @RequestBody AppCartUpdateCountReqVO updateReqVO) {
cartService.updateCartCount(LoginHelper.getUserId(), updateReqVO);
return R.ok(true);
}
@PutMapping("/update-selected")
@Operation(summary = "更新购物车商品选中")
public R<Boolean> updateCartSelected(@Valid @RequestBody AppCartUpdateSelectedReqVO updateReqVO) {
cartService.updateCartSelected(LoginHelper.getUserId(), updateReqVO);
return R.ok(true);
}
@PutMapping("/reset")
@Operation(summary = "重置购物车商品")
public R<Boolean> resetCart(@Valid @RequestBody AppCartResetReqVO updateReqVO) {
cartService.resetCart(LoginHelper.getUserId(), updateReqVO);
return R.ok(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除购物车商品")
@Parameter(name = "ids", description = "购物车商品编号", required = true, example = "1024,2048")
public R<Boolean> deleteCart(@RequestParam("ids") List<Long> ids) {
cartService.deleteCart(LoginHelper.getUserId(), ids);
return R.ok(true);
}
@GetMapping("get-count")
@Operation(summary = "查询用户在购物车中的商品数量")
public R<Integer> getCartCount() {
return R.ok(cartService.getCartCount(LoginHelper.getUserId()));
}
@GetMapping("/list")
@Operation(summary = "查询用户的购物车列表")
public R<AppCartListRespVO> getCartList() {
return R.ok(cartService.getCartList(LoginHelper.getUserId()));
}
}
package org.dromara.mall.controller.trade.app.cart.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.experimental.Accessors;
@Schema(description = "用户 App - 购物车添加购物项 Request VO")
@Data
@Accessors(chain = true)
public class AppCartAddReqVO {
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED,example = "1024")
@NotNull(message = "商品 SKU 编号不能为空")
private Long skuId;
@Schema(description = "新增商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "数量不能为空")
@Min(value = 1, message = "商品数量必须大于等于 1")
private Integer count;
}
package org.dromara.mall.controller.trade.app.cart.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.dromara.mall.controller.trade.app.base.sku.AppProductSkuBaseRespVO;
import java.util.List;
@Schema(description = "用户 App - 用户的购物车明细 Response VO")
@Data
public class AppCartDetailRespVO {
/**
* 商品分组数组
*/
private List<ItemGroup> itemGroups;
/**
* 费用
*/
private Order order;
@Schema(description = "商品分组") // 多个商品,参加同一个活动,从而形成分组
@Data
public static class ItemGroup {
/**
* 商品数组
*/
private List<Sku> items;
/**
* 营销活动,订单级别
*/
private Promotion promotion;
}
@Schema(description = "商品 SKU")
@Data
public static class Sku extends AppProductSkuBaseRespVO {
/**
* SPU 信息
*/
private AppProductSkuBaseRespVO spu;
// ========== 购物车相关的字段 ==========
@Schema(description = "商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer count;
@Schema(description = "是否选中", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean selected;
// ========== 价格相关的字段,对应 PriceCalculateRespDTO.OrderItem 的属性 ==========
// TODO 芋艿:后续可以去除一些无用的字段
@Schema(description = "商品原价(单)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer originalPrice;
@Schema(description = "商品原价(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "200")
private Integer totalOriginalPrice;
@Schema(description = "商品级优惠(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "300")
private Integer totalPromotionPrice;
@Schema(description = "最终购买金额(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "400")
private Integer totalPresentPrice;
@Schema(description = "最终购买金额(单)", requiredMode = Schema.RequiredMode.REQUIRED, example = "500")
private Integer presentPrice;
@Schema(description = "应付金额(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "600")
private Integer totalPayPrice;
// ========== 营销相关的字段 ==========
/**
* 营销活动,商品级别
*/
private Promotion promotion;
}
@Schema(description = "订单") // 对应 PriceCalculateRespDTO.Order 类,用于费用(合计)
@Data
public static class Order {
// TODO 芋艿:后续可以去除一些无用的字段
@Schema(description = "商品原价(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer skuOriginalPrice;
@Schema(description = "商品优惠(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "200")
private Integer skuPromotionPrice;
@Schema(description = "订单优惠(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "300")
private Integer orderPromotionPrice;
@Schema(description = "运费金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "400")
private Integer deliveryPrice;
@Schema(description = "应付金额(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "500")
private Integer payPrice;
}
@Schema(description = "营销活动") // 对应 PriceCalculateRespDTO.Promotion 类的属性
@Data
public static class Promotion {
@Schema(description = "营销编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") // 营销活动的编号、优惠劵的编号
private Long id;
@Schema(description = "营销名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "xx 活动")
private String name;
@Schema(description = "营销类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer type;
// ========== 匹配情况 ==========
@Schema(description = "是否满足优惠条件", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean meet;
@Schema(description = "满足条件的提示", requiredMode = Schema.RequiredMode.REQUIRED, example = "圣诞价:省 150.00 元")
private String meetTip;
}
}
package org.dromara.mall.controller.trade.app.cart.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import org.dromara.mall.controller.trade.app.base.sku.AppProductSkuBaseRespVO;
import org.dromara.mall.controller.trade.app.base.spu.AppProductSpuBaseRespVO;
import java.util.List;
@Schema(description = "用户 App - 用户的购物列表 Response VO")
@Data
@Accessors(chain = true)
public class AppCartListRespVO {
/**
* 有效的购物项数组
*/
private List<Cart> validList;
/**
* 无效的购物项数组
*/
private List<Cart> invalidList;
@Schema(description = "购物项")
@Data
@Accessors(chain = true)
public static class Cart {
@Schema(description = "购物项的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer count;
@Schema(description = "是否选中", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean selected;
/**
* 商品 SPU
*/
private AppProductSpuBaseRespVO spu;
/**
* 商品 SKU
*/
private AppProductSkuBaseRespVO sku;
}
}
package org.dromara.mall.controller.trade.app.cart.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "用户 App - 购物车重置 Request VO")
@Data
public class AppCartResetReqVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "编号不能为空")
private Long id;
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED,example = "1024")
@NotNull(message = "商品 SKU 编号不能为空")
private Long skuId;
@Schema(description = "商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "数量不能为空")
@Min(message = "数量必须大于 0", value = 1L)
private Integer count;
}
package org.dromara.mall.controller.trade.app.cart.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.experimental.Accessors;
@Schema(description = "用户 App - 购物车更新数量 Request VO")
@Data
@Accessors(chain = true)
public class AppCartUpdateCountReqVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "编号不能为空")
private Long id;
@Schema(description = "商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "数量不能为空")
@Min(message = "数量必须大于 0", value = 1L)
private Integer count;
}
package org.dromara.mall.controller.trade.app.cart.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.util.Collection;
@Schema(description = "用户 App - 购物车更新是否选中 Request VO")
@Data
public class AppCartUpdateSelectedReqVO {
@Schema(description = "编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024,2048")
@NotNull(message = "编号列表不能为空")
private Collection<Long> ids;
@Schema(description = "是否选中", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否选中不能为空")
private Boolean selected;
}
package org.dromara.mall.controller.trade.app.config;
import cn.hutool.core.util.ObjUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.mall.controller.trade.app.config.vo.AppTradeConfigRespVO;
import org.dromara.mall.convert.trade.config.TradeConfigConvert;
import org.dromara.mall.domain.trade.TradeConfigDO;
import org.dromara.mall.service.trade.config.TradeConfigService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Tag(name = "用户 App - 交易配置")
@RestController
@RequestMapping("/app/trade/config")
@RequiredArgsConstructor
@Validated
@Slf4j
public class AppTradeConfigController {
@Resource
private TradeConfigService tradeConfigService;
@Value("${yudao.tencent-lbs-key}")
private String tencentLbsKey;
@GetMapping("/get")
@Operation(summary = "获得交易配置")
@PermitAll
public R<AppTradeConfigRespVO> getTradeConfig() {
TradeConfigDO config = ObjUtil.defaultIfNull(tradeConfigService.getTradeConfig(), new TradeConfigDO());
return R.ok(TradeConfigConvert.INSTANCE.convert02(config).setTencentLbsKey(tencentLbsKey));
}
}
package org.dromara.mall.controller.trade.app.config.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@Schema(description = "用户 App - 交易配置 Response VO")
@Data
@Accessors(chain = true)
public class AppTradeConfigRespVO {
@Schema(description = "腾讯地图 KEY", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
private String tencentLbsKey;
// ========== 配送相关 ==========
@Schema(description = "是否开启自提", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否开启自提不能为空")
private Boolean deliveryPickUpEnabled;
// ========== 售后相关 ==========
@Schema(description = "售后的退款理由", requiredMode = Schema.RequiredMode.REQUIRED)
private List<String> afterSaleRefundReasons;
@Schema(description = "售后的退货理由", requiredMode = Schema.RequiredMode.REQUIRED)
private List<String> afterSaleReturnReasons;
// ========== 分销相关 ==========
@Schema(description = "分销海报地址数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<String> brokeragePosterUrls;
@Schema(description = "佣金冻结时间(天)", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer brokerageFrozenDays;
@Schema(description = "佣金提现最小金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer brokerageWithdrawMinPrice;
@Schema(description = "提现方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 2]")
private List<Integer> brokerageWithdrawTypes;
}
package org.dromara.mall.controller.trade.app.delivery;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import org.dromara.common.core.domain.R;
import org.dromara.common.mall.enums.CommonStatusEnum;
import org.dromara.mall.controller.trade.app.delivery.vo.express.AppDeliveryExpressRespVO;
import org.dromara.mall.convert.trade.delivery.DeliveryExpressConvert;
import org.dromara.mall.domain.trade.DeliveryExpressDO;
import org.dromara.mall.service.trade.delivery.DeliveryExpressService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Comparator;
import java.util.List;
@Tag(name = "用户 App - 快递公司")
@RestController
@RequestMapping("/app/trade/delivery/express")
@Validated
public class AppDeliverExpressController {
@Resource
private DeliveryExpressService deliveryExpressService;
@GetMapping("/list")
@Operation(summary = "获得快递公司列表")
@PermitAll
public R<List<AppDeliveryExpressRespVO>> getDeliveryExpressList() {
List<DeliveryExpressDO> list = deliveryExpressService.getDeliveryExpressListByStatus(CommonStatusEnum.ENABLE.getStatus());
list.sort(Comparator.comparing(DeliveryExpressDO::getSort));
return R.ok(DeliveryExpressConvert.INSTANCE.convertList03(list));
}
}
package org.dromara.mall.controller.trade.app.delivery;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import org.dromara.common.core.domain.R;
import org.dromara.common.mall.enums.CommonStatusEnum;
import org.dromara.mall.controller.trade.app.delivery.vo.pickup.AppDeliveryPickUpStoreRespVO;
import org.dromara.mall.convert.trade.delivery.DeliveryPickUpStoreConvert;
import org.dromara.mall.domain.trade.DeliveryPickUpStoreDO;
import org.dromara.mall.service.trade.delivery.DeliveryPickUpStoreService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Tag(name = "用户 App - 自提门店")
@RestController
@RequestMapping("/app/trade/delivery/pick-up-store")
@Validated
public class AppDeliverPickUpStoreController {
@Resource
private DeliveryPickUpStoreService deliveryPickUpStoreService;
@GetMapping("/list")
@Operation(summary = "获得自提门店列表")
@Parameters({
@Parameter(name = "latitude", description = "精度", example = "110"),
@Parameter(name = "longitude", description = "纬度", example = "120")
})
@PermitAll
public R<List<AppDeliveryPickUpStoreRespVO>> getDeliveryPickUpStoreList(
@RequestParam(value = "latitude", required = false) Double latitude,
@RequestParam(value = "longitude", required = false) Double longitude) {
List<DeliveryPickUpStoreDO> list = deliveryPickUpStoreService.getDeliveryPickUpStoreListByStatus(
CommonStatusEnum.ENABLE.getStatus());
return R.ok(DeliveryPickUpStoreConvert.INSTANCE.convertList(list, latitude, longitude));
}
@GetMapping("/get")
@Operation(summary = "获得自提门店")
@Parameter(name = "id", description = "门店编号")
@PermitAll
public R<AppDeliveryPickUpStoreRespVO> getOrder(@RequestParam("id") Long id) {
DeliveryPickUpStoreDO store = deliveryPickUpStoreService.getDeliveryPickUpStore(id);
return R.ok(DeliveryPickUpStoreConvert.INSTANCE.convert03(store));
}
}
package org.dromara.mall.controller.trade.app.delivery.vo.config;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
// TODO 芋艿:后续要实现下,配送配置;后续融合到 AppTradeConfigRespVO 中
@Schema(description = "用户 App - 配送配置 Response VO")
@Data
public class AppDeliveryConfigRespVO {
@Schema(description = "腾讯地图 KEY", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
private String tencentLbsKey;
@Schema(description = "是否开启自提", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean pickUpEnable;
}
package org.dromara.mall.controller.trade.app.delivery.vo.express;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "用户 App - 快递公司 Response VO")
@Data
public class AppDeliveryExpressRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "门店名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "顺丰")
private String name;
}
package org.dromara.mall.controller.trade.app.delivery.vo.pickup;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "用户 App - 自提门店 Response VO")
@Data
public class AppDeliveryPickUpStoreRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23128")
private Long id;
@Schema(description = "门店名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
private String name;
@Schema(description = "门店 logo", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
private String logo;
@Schema(description = "门店手机", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601892312")
private String phone;
@Schema(description = "区域编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18733")
private Integer areaId;
@Schema(description = "地区名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "上海上海市普陀区")
private String areaName;
@Schema(description = "门店详细地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "复旦大学路 188 号")
private String detailAddress;
@Schema(description = "纬度", requiredMode = Schema.RequiredMode.REQUIRED, example = "5.88")
private Double latitude;
@Schema(description = "经度", requiredMode = Schema.RequiredMode.REQUIRED, example = "6.99")
private Double longitude;
@Schema(description = "距离,单位:千米", example = "100") // 只有在用户传递了经纬度时,才进行计算
private Double distance;
}
### /trade-order/settlement 获得订单结算信息(基于商品)
GET {{appApi}}/trade/order/settlement?type=0&items[0].skuId=1&items[0].count=2&items[1].skuId=2&items[1].count=3&couponId=1
Authorization: Bearer {{appToken}}
tenant-id: {{appTenentId}}
### /trade-order/settlement 获得订单结算信息(基于购物车)
GET {{appApi}}/trade/order/settlement?type=0&items[0].cartId=50&couponId=1
Authorization: Bearer {{appToken}}
tenant-id: {{appTenentId}}
### /trade-order/create 创建订单(基于商品)【快递】
POST {{appApi}}/trade/order/create
Content-Type: application/json
Authorization: Bearer {{appToken}}
tenant-id: {{appTenentId}}
{
"pointStatus": true,
"deliveryType": 1,
"addressId": 21,
"items": [
{
"skuId": 1,
"count": 2
}
],
"remark": "我是备注"
}
### /trade-order/create 创建订单(基于商品)【自提】
POST {{appApi}}/trade/order/create
Content-Type: application/json
Authorization: Bearer {{appToken}}
tenant-id: {{appTenentId}}
{
"pointStatus": true,
"deliveryType": 2,
"pickUpStoreId": 1,
"items": [
{
"skuId": 1,
"count": 2
}
],
"remark": "我是备注",
"receiverName": "土豆",
"receiverMobile": "15601691300"
}
### 获得订单交易的分页
GET {{appApi}}/trade/order/page?pageNo=1&pageSize=10
Authorization: Bearer {{appToken}}
tenant-id: {{appTenentId}}
### 获得订单交易的详细
GET {{appApi}}/trade/order/get-detail?id=21
Authorization: Bearer {{appToken}}
tenant-id: {{appTenentId}}
### 获得交易订单的物流轨迹
GET {{appApi}}/trade/order/get-express-track-list?id=70
Authorization: Bearer {{appToken}}
tenant-id: {{appTenentId}}
### /trade-order/settlement-product 获得商品结算信息
GET {{appApi}}/trade/order/settlement-product?spuIds=633
Authorization: Bearer {{appToken}}
tenant-id: {{appTenentId}}
\ No newline at end of file
package org.dromara.mall.controller.trade.app.order;
import com.google.common.collect.Maps;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.mybatis.core.page.PageResult;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.mall.api.dto.pay.PayOrderNotifyReqDTO;
import org.dromara.mall.controller.trade.app.order.vo.*;
import org.dromara.mall.controller.trade.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
import org.dromara.mall.controller.trade.app.order.vo.item.AppTradeOrderItemRespVO;
import org.dromara.mall.convert.trade.order.TradeOrderConvert;
import org.dromara.mall.domain.trade.DeliveryExpressDO;
import org.dromara.mall.domain.trade.TradeOrderDO;
import org.dromara.mall.domain.trade.TradeOrderItemDO;
import org.dromara.mall.enums.trade.order.TradeOrderStatusEnum;
import org.dromara.mall.framework.trade.order.config.TradeOrderProperties;
import org.dromara.mall.service.trade.aftersale.AfterSaleService;
import org.dromara.mall.service.trade.delivery.DeliveryExpressService;
import org.dromara.mall.service.trade.order.TradeOrderQueryService;
import org.dromara.mall.service.trade.order.TradeOrderUpdateService;
import org.dromara.mall.service.trade.price.TradePriceService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
import static org.dromara.common.mall.util.collection.CollectionUtils.convertSet;
@Tag(name = "用户 App - 交易订单")
@RestController
@RequestMapping("/app/trade/order")
@Validated
@Slf4j
public class AppTradeOrderController {
@Resource
private TradeOrderUpdateService tradeOrderUpdateService;
@Resource
private TradeOrderQueryService tradeOrderQueryService;
@Resource
private DeliveryExpressService deliveryExpressService;
@Resource
private AfterSaleService afterSaleService;
@Resource
private TradePriceService priceService;
@Resource
private TradeOrderProperties tradeOrderProperties;
@GetMapping("/settlement")
@Operation(summary = "获得订单结算信息")
public R<AppTradeOrderSettlementRespVO> settlementOrder(@Valid AppTradeOrderSettlementReqVO settlementReqVO) {
return R.ok(tradeOrderUpdateService.settlementOrder(LoginHelper.getMemberId(), settlementReqVO));
}
@GetMapping("/settlement-product")
@Operation(summary = "获得商品结算信息", description = "用于商品列表、商品详情,获得参与活动后的价格信息")
@Parameter(name = "spuIds", description = "商品 SPU 编号数组")
@PermitAll
public R<List<AppTradeProductSettlementRespVO>> settlementProduct(@RequestParam("spuIds") List<Long> spuIds) {
return R.ok(priceService.calculateProductPrice(LoginHelper.getMemberId(), spuIds));
}
@PostMapping("/create")
@Operation(summary = "创建订单")
public R<AppTradeOrderCreateRespVO> createOrder(@Valid @RequestBody AppTradeOrderCreateReqVO createReqVO) {
TradeOrderDO order = tradeOrderUpdateService.createOrder(LoginHelper.getMemberId(), createReqVO);
return R.ok(new AppTradeOrderCreateRespVO().setId(order.getId()).setPayOrderId(order.getPayOrderId()));
}
@PostMapping("/update-paid")
@Operation(summary = "更新订单为已支付") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob
@PermitAll
public R<Boolean> updateOrderPaid(@RequestBody PayOrderNotifyReqDTO notifyReqDTO) {
tradeOrderUpdateService.updateOrderPaid(Long.valueOf(notifyReqDTO.getMerchantOrderId()),
notifyReqDTO.getPayOrderId());
return R.ok(true);
}
@GetMapping("/get-detail")
@Operation(summary = "获得交易订单")
@Parameters({
@Parameter(name = "id", description = "交易订单编号"),
@Parameter(name = "sync", description = "是否同步支付状态", example = "true")
})
public R<AppTradeOrderDetailRespVO> getOrderDetail(@RequestParam("id") Long id,
@RequestParam(value = "sync", required = false) Boolean sync) {
// 1.1 查询订单
TradeOrderDO order = tradeOrderQueryService.getOrder(LoginHelper.getMemberId(), id);
if (order == null) {
return R.ok(null);
}
// 1.2 sync 仅在等待支付
if (Boolean.TRUE.equals(sync)
&& TradeOrderStatusEnum.isUnpaid(order.getStatus()) && !order.getPayStatus()) {
tradeOrderUpdateService.syncOrderPayStatusQuietly(order.getId(), order.getPayOrderId());
// 重新查询,因为同步后,可能会有变化
order = tradeOrderQueryService.getOrder(id);
}
// 2.1 查询订单项
List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(order.getId());
// 2.2 查询物流公司
DeliveryExpressDO express = order.getLogisticsId() != null && order.getLogisticsId() > 0 ?
deliveryExpressService.getDeliveryExpress(order.getLogisticsId()) : null;
// 2.3 最终组合
return R.ok(TradeOrderConvert.INSTANCE.convert02(order, orderItems, tradeOrderProperties, express));
}
@GetMapping("/get-express-track-list")
@Operation(summary = "获得交易订单的物流轨迹")
@Parameter(name = "id", description = "交易订单编号")
public R<List<AppOrderExpressTrackRespDTO>> getOrderExpressTrackList(@RequestParam("id") Long id) {
return R.ok(TradeOrderConvert.INSTANCE.convertList02(
tradeOrderQueryService.getExpressTrackList(id, LoginHelper.getMemberId())));
}
@GetMapping("/page")
@Operation(summary = "获得交易订单分页")
public R<PageResult<AppTradeOrderPageItemRespVO>> getOrderPage(AppTradeOrderPageReqVO reqVO) {
// 查询订单
PageResult<TradeOrderDO> pageResult = tradeOrderQueryService.getOrderPage(LoginHelper.getMemberId(), reqVO);
// 查询订单项
List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(
convertSet(pageResult.getList(), TradeOrderDO::getId));
// 最终组合
return R.ok(TradeOrderConvert.INSTANCE.convertPage02(pageResult, orderItems));
}
@GetMapping("/get-count")
@Operation(summary = "获得交易订单数量")
public R<Map<String, Long>> getOrderCount() {
Map<String, Long> orderCount = Maps.newLinkedHashMapWithExpectedSize(5);
// 全部
orderCount.put("allCount", tradeOrderQueryService.getOrderCount(LoginHelper.getMemberId(), null, null));
// 待付款(未支付)
orderCount.put("unpaidCount", tradeOrderQueryService.getOrderCount(LoginHelper.getMemberId(),
TradeOrderStatusEnum.UNPAID.getStatus(), null));
// 待发货
orderCount.put("undeliveredCount", tradeOrderQueryService.getOrderCount(LoginHelper.getMemberId(),
TradeOrderStatusEnum.UNDELIVERED.getStatus(), null));
// 待收货
orderCount.put("deliveredCount", tradeOrderQueryService.getOrderCount(LoginHelper.getMemberId(),
TradeOrderStatusEnum.DELIVERED.getStatus(), null));
// 待评价
orderCount.put("uncommentedCount", tradeOrderQueryService.getOrderCount(LoginHelper.getMemberId(),
TradeOrderStatusEnum.COMPLETED.getStatus(), false));
// 售后数量
orderCount.put("afterSaleCount", afterSaleService.getApplyingAfterSaleCount(LoginHelper.getMemberId()));
return R.ok(orderCount);
}
@PutMapping("/receive")
@Operation(summary = "确认交易订单收货")
@Parameter(name = "id", description = "交易订单编号")
public R<Boolean> receiveOrder(@RequestParam("id") Long id) {
tradeOrderUpdateService.receiveOrderByMember(LoginHelper.getMemberId(), id);
return R.ok(true);
}
@DeleteMapping("/cancel")
@Operation(summary = "取消交易订单")
@Parameter(name = "id", description = "交易订单编号")
public R<Boolean> cancelOrder(@RequestParam("id") Long id) {
tradeOrderUpdateService.cancelOrderByMember(LoginHelper.getMemberId(), id);
return R.ok(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除交易订单")
@Parameter(name = "id", description = "交易订单编号")
public R<Boolean> deleteOrder(@RequestParam("id") Long id) {
tradeOrderUpdateService.deleteOrder(LoginHelper.getMemberId(), id);
return R.ok(true);
}
// ========== 订单项 ==========
@GetMapping("/item/get")
@Operation(summary = "获得交易订单项")
@Parameter(name = "id", description = "交易订单项编号")
public R<AppTradeOrderItemRespVO> getOrderItem(@RequestParam("id") Long id) {
TradeOrderItemDO item = tradeOrderQueryService.getOrderItem(LoginHelper.getMemberId(), id);
return R.ok(TradeOrderConvert.INSTANCE.convert03(item));
}
@PostMapping("/item/create-comment")
@Operation(summary = "创建交易订单项的评价")
public R<Long> createOrderItemComment(@RequestBody AppTradeOrderItemCommentCreateReqVO createReqVO) {
return R.ok(tradeOrderUpdateService.createOrderItemCommentByMember(LoginHelper.getMemberId(), createReqVO));
}
}
package org.dromara.mall.controller.trade.app.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 快递查询的轨迹 Resp DTO
*
* @author jason
*/
@Schema(description = "用户 App - 快递查询的轨迹 Response VO")
@Data
public class AppOrderExpressTrackRespDTO {
@Schema(description = "发生时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime time;
@Schema(description = "快递状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "已签收")
private String content;
}
package org.dromara.mall.controller.trade.app.order.vo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.AssertTrue;
import lombok.Data;
@Schema(description = "用户 App - 交易订单创建 Request VO")
@Data
public class AppTradeOrderCreateReqVO extends AppTradeOrderSettlementReqVO {
@Schema(description = "备注", example = "这个是我的订单哟")
private String remark;
@AssertTrue(message = "配送方式不能为空")
@JsonIgnore
public boolean isDeliveryTypeNotNull() {
return getDeliveryType() != null;
}
}
package org.dromara.mall.controller.trade.app.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
@Schema(description = "用户 App - 交易订单创建 Response VO")
@Data
@Accessors(chain = true)
public class AppTradeOrderCreateRespVO {
@Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "支付订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long payOrderId;
}
package org.dromara.mall.controller.trade.app.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import org.dromara.mall.controller.trade.app.order.vo.item.AppTradeOrderItemRespVO;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "用户 App - 订单交易的明细 Response VO")
@Data
@Accessors(chain = true)
public class AppTradeOrderDetailRespVO {
// ========== 订单基本信息 ==========
@Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "订单流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1146347329394184195")
private String no;
@Schema(description = "订单类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
private Integer type;
@Schema(description = "下单时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
@Schema(description = "用户备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "你猜")
private String userRemark;
@Schema(description = "订单状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
@Schema(description = "购买的商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer productCount;
@Schema(description = "订单完成时间")
private LocalDateTime finishTime;
@Schema(description = "订单取消时间")
private LocalDateTime cancelTime;
@Schema(description = "是否评价", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean commentStatus;
// ========== 价格 + 支付基本信息 ==========
@Schema(description = "是否已支付", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean payStatus;
@Schema(description = "支付订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long payOrderId;
@Schema(description = "付款时间")
private LocalDateTime payTime;
@Schema(description = "付款超时时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime payExpireTime;
@Schema(description = "支付渠道", example = "wx_lite_pay")
private String payChannelCode;
@Schema(description = "支付渠道名", example = "微信小程序支付")
private String payChannelName;
@Schema(description = "商品原价(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
private Integer totalPrice;
@Schema(description = "订单优惠(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer discountPrice;
@Schema(description = "运费金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer deliveryPrice;
@Schema(description = "订单调价(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer adjustPrice;
@Schema(description = "应付金额(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
private Integer payPrice;
// ========== 收件 + 物流基本信息 ==========
@Schema(description = "配送方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer deliveryType;
@Schema(description = "发货物流公司编号", example = "10")
private Long logisticsId;
@Schema(description = "发货物流名称", example = "顺丰快递")
private String logisticsName;
@Schema(description = "发货物流单号", example = "1024")
private String logisticsNo;
@Schema(description = "发货时间")
private LocalDateTime deliveryTime;
@Schema(description = "收货时间")
private LocalDateTime receiveTime;
@Schema(description = "收件人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
private String receiverName;
@Schema(description = "收件人手机", requiredMode = Schema.RequiredMode.REQUIRED, example = "13800138000")
private String receiverMobile;
@Schema(description = "收件人地区编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "110000")
private Integer receiverAreaId;
@Schema(description = "收件人地区名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "上海 上海市 普陀区")
private String receiverAreaName;
@Schema(description = "收件人详细地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "中关村大街 1 号")
private String receiverDetailAddress;
@Schema(description = "自提门店编号", example = "1088")
private Long pickUpStoreId;
@Schema(description = "自提核销码", example = "40964096")
private String pickUpVerifyCode;
// ========== 售后基本信息 ==========
@Schema(description = "售后状态", example = "0")
private Integer refundStatus;
@Schema(description = "退款金额,单位:分", example = "100")
private Integer refundPrice;
// ========== 营销基本信息 ==========
@Schema(description = "优惠劵编号", example = "1024")
private Long couponId;
@Schema(description = "优惠劵减免金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer couponPrice;
@Schema(description = "积分抵扣的金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer pointPrice;
@Schema(description = "VIP 减免金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "888")
private Integer vipPrice;
@Schema(description = "拼团记录编号", example = "100")
private Long combinationRecordId;
/**
* 订单项数组
*/
private List<AppTradeOrderItemRespVO> items;
}
package org.dromara.mall.controller.trade.app.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.dromara.mall.controller.trade.app.order.vo.item.AppTradeOrderItemRespVO;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "用户 App - 订单交易的分页项 Response VO")
@Data
public class AppTradeOrderPageItemRespVO {
@Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "订单流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1146347329394184195")
private String no;
@Schema(description = "订单类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
private Integer type;
@Schema(description = "订单状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
@Schema(description = "购买的商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer productCount;
@Schema(description = "是否评价", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean commentStatus;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
// ========== 价格 + 支付基本信息 ==========
@Schema(description = "支付订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long payOrderId;
@Schema(description = "应付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
private Integer payPrice;
// ========== 收件 + 物流基本信息 ==========
@Schema(description = "配送方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer deliveryType;
/**
* 订单项数组
*/
private List<AppTradeOrderItemRespVO> items;
// ========== 营销基本信息 ==========
@Schema(description = "拼团记录编号", example = "100")
private Long combinationRecordId;
}
package org.dromara.mall.controller.trade.app.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.dromara.common.mall.validation.InEnum;
import org.dromara.common.mybatis.core.page.PageParam;
import org.dromara.mall.enums.trade.order.TradeOrderStatusEnum;
@Schema(description = "交易订单分页 Request VO")
@Data
public class AppTradeOrderPageReqVO extends PageParam {
@Schema(description = "订单状态", example = "1")
@InEnum(value = TradeOrderStatusEnum.class, message = "订单状态必须是 {value}")
private Integer status;
@Schema(description = "是否评价", example = "true")
private Boolean commentStatus;
}
package org.dromara.mall.controller.trade.app.order.vo;
import cn.hutool.core.util.ObjUtil;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.AssertTrue;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.dromara.common.mall.validation.InEnum;
import org.dromara.common.mall.validation.Mobile;
import org.dromara.mall.enums.trade.delivery.DeliveryTypeEnum;
import java.util.List;
@Schema(description = "用户 App - 交易订单结算 Request VO")
@Data
@Valid
public class AppTradeOrderSettlementReqVO {
@Schema(description = "商品项数组", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "商品不能为空")
private List<Item> items;
@Schema(description = "优惠劵编号", example = "1024")
private Long couponId;
@Schema(description = "是否使用积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否使用积分不能为空")
private Boolean pointStatus;
// ========== 配送相关相关字段 ==========
@Schema(description = "配送方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@InEnum(value = DeliveryTypeEnum.class, message = "配送方式不正确")
private Integer deliveryType;
@Schema(description = "收件地址编号", example = "1")
private Long addressId;
@Schema(description = "自提门店编号", example = "1088")
private Long pickUpStoreId;
@Schema(description = "收件人名称", example = "芋艿") // 选择门店自提时,该字段为联系人名
private String receiverName;
@Schema(description = "收件人手机", example = "15601691300") // 选择门店自提时,该字段为联系人手机
@Mobile(message = "收件人手机格式不正确")
private String receiverMobile;
// ========== 秒杀活动相关字段 ==========
@Schema(description = "秒杀活动编号", example = "1024")
private Long seckillActivityId;
// ========== 拼团活动相关字段 ==========
@Schema(description = "拼团活动编号", example = "1024")
private Long combinationActivityId;
@Schema(description = "拼团团长编号", example = "2048")
private Long combinationHeadId;
// ========== 砍价活动相关字段 ==========
@Schema(description = "砍价记录编号", example = "123")
private Long bargainRecordId;
// ========== 积分商城活动相关字段 ==========
@Schema(description = "积分商城活动编号", example = "123")
private Long pointActivityId;
@AssertTrue(message = "活动商品每次只能购买一种规格")
@JsonIgnore
public boolean isValidActivityItems() {
// 校验是否是活动订单
if (ObjUtil.isAllEmpty(seckillActivityId, combinationActivityId, combinationHeadId, bargainRecordId)) {
return true;
}
// 校验订单项是否超出
return items.size() == 1;
}
@Data
@Schema(description = "用户 App - 商品项")
@Valid
public static class Item {
@Schema(description = "商品 SKU 编号", example = "2048")
@NotNull(message = "商品 SKU 编号不能为空")
private Long skuId;
@Schema(description = "购买数量", example = "1")
@Min(value = 1, message = "购买数量最小值为 {value}")
private Integer count;
@Schema(description = "购物车项的编号", example = "1024")
private Long cartId;
@AssertTrue(message = "商品不正确")
@JsonIgnore
public boolean isValid() {
// 组合一:skuId + count 使用商品 SKU
if (skuId != null && count != null) {
return true;
}
// 组合二:cartId 使用购物车项
return cartId != null;
}
}
}
package org.dromara.mall.controller.trade.app.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.dromara.mall.controller.trade.app.base.property.AppProductPropertyValueDetailRespVO;
import org.dromara.mall.service.trade.price.bo.TradePriceCalculateRespBO;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "用户 App - 交易订单结算信息 Response VO")
@Data
public class AppTradeOrderSettlementRespVO {
@Schema(description = "交易类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") // 对应 TradeOrderTypeEnum 枚举
private Integer type;
@Schema(description = "购物项数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<Item> items;
@Schema(description = "优惠劵数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<Coupon> coupons; // 可用 + 不可用
@Schema(description = "费用", requiredMode = Schema.RequiredMode.REQUIRED)
private Price price;
@Schema(description = "收件地址", requiredMode = Schema.RequiredMode.REQUIRED)
private Address address;
@Schema(description = "已使用的积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer usePoint;
@Schema(description = "总积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer totalPoint;
/**
* 营销活动数组
*
* 只对应 {@link TradePriceCalculateRespBO.Price#items} 商品匹配的活动
*/
private List<TradePriceCalculateRespBO.Promotion> promotions;
@Schema(description = "购物项")
@Data
public static class Item {
// ========== SPU 信息 ==========
@Schema(description = "品类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
private Long categoryId;
@Schema(description = "SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
private Long spuId;
@Schema(description = "SPU 名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "Apple iPhone 12")
private String spuName;
// ========== SKU 信息 ==========
@Schema(description = "SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer skuId;
@Schema(description = "价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer price;
@Schema(description = "图片地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
private String picUrl;
@Schema(description = "属性数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private List<AppProductPropertyValueDetailRespVO> properties;
// ========== 购物车信息 ==========
@Schema(description = "购物车编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Long cartId;
@Schema(description = "购买数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer count;
}
@Schema(description = "费用(合计)")
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Price {
@Schema(description = "商品原价(总),单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "500")
private Integer totalPrice;
@Schema(description = "订单优惠(总),单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "66")
private Integer discountPrice;
@Schema(description = "运费金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "50")
private Integer deliveryPrice;
@Schema(description = "优惠劵减免金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer couponPrice;
@Schema(description = "积分抵扣的金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "50")
private Integer pointPrice;
@Schema(description = "VIP 减免金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "30")
private Integer vipPrice;
@Schema(description = "实际支付金额(总),单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "450")
private Integer payPrice;
}
@Schema(description = "地址信息")
@Data
public static class Address {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "收件人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小王")
private String name;
@Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300")
private String mobile;
@Schema(description = "地区编号", requiredMode = Schema.RequiredMode.REQUIRED)
private Long areaId;
@Schema(description = "地区名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "上海上海市普陀区")
private String areaName;
@Schema(description = "详细地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "望京悠乐汇 A 座")
private String detailAddress;
@Schema(description = "是否默认收件地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean defaultStatus;
}
@Schema(description = "优惠劵信息")
@Data
public static class Coupon {
@Schema(description = "优惠劵编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "优惠劵名", requiredMode = Schema.RequiredMode.REQUIRED, example = "春节送送送")
private String name;
@Schema(description = "是否设置满多少金额可用", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") // 单位:分;0 - 不限制
private Integer usePrice;
@Schema(description = "固定日期 - 生效开始时间")
private LocalDateTime validStartTime;
@Schema(description = "固定日期 - 生效结束时间")
private LocalDateTime validEndTime;
@Schema(description = "优惠类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer discountType;
@Schema(description = "折扣百分比", example = "80") // 例如说,80% 为 80
private Integer discountPercent;
@Schema(description = "优惠金额", example = "10")
private Integer discountPrice;
@Schema(description = "折扣上限", example = "100") // 单位:分,仅在 discountType 为 PERCENT 使用
private Integer discountLimitPrice;
@Schema(description = "是否可用", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean match;
@Schema(description = "不可用原因", example = "优惠劵已过期")
private String mismatchReason;
}
}
package org.dromara.mall.controller.trade.app.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
@Schema(description = "用户 App - 商品结算信息 Response VO")
@Data
@Accessors(chain = true)
public class AppTradeProductSettlementRespVO {
@Schema(description = "SPU 商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long spuId;
@Schema(description = "SKU 价格信息数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private List<Sku> skus;
@Schema(description = "满减送活动信息", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private RewardActivity rewardActivity;
@Schema(description = "SKU 价格信息")
@Data
public static class Sku implements Serializable {
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "优惠后价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer promotionPrice;
@Schema(description = "营销类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "4")
private Integer promotionType; // 对应 PromotionTypeEnum 枚举,目前只有 4 和 6 两种
@Schema(description = "营销编号", requiredMode = Schema.RequiredMode.REQUIRED)
private Long promotionId; // 目前只有限时折扣活动的编号
@Schema(description = "活动结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime promotionEndTime;
}
@Schema(description = "满减送活动信息")
@Data
public static class RewardActivity {
@Schema(description = "满减活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "条件类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer conditionType;
@Schema(description = "优惠规则的数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<RewardActivityRule> rules;
}
@Schema(description = "优惠规则")
@Data
public static class RewardActivityRule {
@Schema(description = "优惠门槛", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") // 1. 满 N 元,单位:分; 2. 满 N 件
private Integer limit;
@Schema(description = "优惠价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer discountPrice;
@Schema(description = "是否包邮", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean freeDelivery;
@Schema(description = "赠送的积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer point;
@Schema(description = "赠送的优惠劵编号的数组")
private Map<Long, Integer> giveCouponTemplateCounts;
}
}
package org.dromara.mall.controller.trade.app.order.vo.item;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@Schema(description = "用户 App - 商品评价创建 Request VO")
@Data
@Accessors(chain = true)
public class AppTradeOrderItemCommentCreateReqVO {
@Schema(description = "是否匿名", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否匿名不能为空")
private Boolean anonymous;
@Schema(description = "交易订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2312312")
@NotNull(message = "交易订单项编号不能为空")
private Long orderItemId;
@Schema(description = "描述星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
@NotNull(message = "描述星级 1-5 分不能为空")
private Integer descriptionScores;
@Schema(description = "服务星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
@NotNull(message = "服务星级 1-5 分不能为空")
private Integer benefitScores;
@Schema(description = "评论内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "穿身上很漂亮诶(*^▽^*)")
@NotNull(message = "评论内容不能为空")
private String content;
@Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png]")
@Size(max = 9, message = "评论图片地址数组长度不能超过 9 张")
private List<String> picUrls;
}
package org.dromara.mall.controller.trade.app.order.vo.item;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.dromara.mall.controller.trade.app.base.property.AppProductPropertyValueDetailRespVO;
import java.util.List;
@Schema(description = "用户 App - 订单交易项 Response VO")
@Data
public class AppTradeOrderItemRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long orderId;
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long spuId;
@Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
private String spuName;
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long skuId;
/**
* 属性数组
*/
private List<AppProductPropertyValueDetailRespVO> properties;
@Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
private String picUrl;
@Schema(description = "购买数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer count;
@Schema(description = "是否评价", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean commentStatus;
// ========== 价格 + 支付基本信息 ==========
@Schema(description = "商品原价(单)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer price;
@Schema(description = "应付金额(总),单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "50")
private Integer payPrice;
// ========== 营销基本信息 ==========
// TODO 芋艿:在捉摸一下
// ========== 售后基本信息 ==========
@Schema(description = "售后编号", example = "1024")
private Long afterSaleId;
@Schema(description = "售后状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer afterSaleStatus;
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论