Merge branch 'dev' into user_action
| New file |
| | |
| | | package cn.lili.controller.lmk; |
| | | |
| | | import cn.lili.base.Result; |
| | | import cn.lili.modules.lmk.service.CouponVirtualService; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.PathVariable; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | @Validated |
| | | @RequiredArgsConstructor |
| | | @Api(value = "小程序购物卡接口", tags = "小程序购物卡接口") |
| | | @RestController |
| | | @RequestMapping("/buyer/lmk/coupon/card") |
| | | public class CouponCardController { |
| | | private final CouponVirtualService couponVirtualService; |
| | | |
| | | @PostMapping("/{cardId}") |
| | | @ApiOperation(value = "领取购物卡", notes = "领取购物卡") |
| | | public Result tackCardById(@PathVariable String cardId){ |
| | | return couponVirtualService.tackCardById(cardId); |
| | | } |
| | | @PostMapping("/changShareStatus/{cardId}") |
| | | @ApiOperation(value = "更改分享状态", notes = "更改分享状态") |
| | | public Result changShareStatus(@PathVariable String cardId){ |
| | | return couponVirtualService.changShareStatus(cardId); |
| | | } |
| | | @PostMapping("/couponCardInfo/{cardId}") |
| | | @ApiOperation(value = "获取领取信息", notes = "获取领取信息") |
| | | public Result couponCardInfo(@PathVariable String cardId){ |
| | | return couponVirtualService.couponCardInfo(cardId); |
| | | } |
| | | } |
| New file |
| | |
| | | package cn.lili.controller.lmk; |
| | | |
| | | |
| | | import cn.lili.base.Result; |
| | | import cn.lili.modules.lmk.domain.query.CouponVirtualQuery; |
| | | import cn.lili.modules.lmk.service.CouponVirtualService; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import lombok.RequiredArgsConstructor; |
| | | 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; |
| | | |
| | | /** |
| | | * lmk-shop-java |
| | | * 虚拟优惠卷商品 |
| | | * |
| | | * @author : zxl |
| | | * @date : 2025-09-12 09:41 |
| | | **/ |
| | | @Validated |
| | | @RequiredArgsConstructor |
| | | @RestController |
| | | @RequestMapping("/buyer/lmk/couponVirtual") |
| | | public class CouponVirtualController { |
| | | |
| | | private final CouponVirtualService couponVirtualService; |
| | | |
| | | @GetMapping() |
| | | @ApiOperation(value = "列表", notes = "列表") |
| | | public Result getPage(CouponVirtualQuery query){ |
| | | //更具订单id查询 |
| | | return couponVirtualService.page(query); |
| | | } |
| | | |
| | | } |
| | |
| | | @GetMapping(value = "/get/{sn}") |
| | | public ResultMessage<AfterSaleVO> get(@NotNull(message = "售后单号") @PathVariable("sn") String sn) { |
| | | AfterSaleVO afterSale = OperationalJudgment.judgment(afterSaleService.getAfterSale(sn)); |
| | | String goodsImage = afterSale.getGoodsImage(); |
| | | if (StringUtils.isNotBlank(goodsImage)&&!goodsImage.contains("http")) { |
| | | afterSale.setGoodsImage(cosUtil.getPreviewUrl(goodsImage)); |
| | | } |
| | | return ResultUtil.data(afterSale); |
| | | } |
| | | |
| | |
| | | import cn.lili.common.utils.StringUtils; |
| | | import cn.lili.common.vo.ResultMessage; |
| | | import cn.lili.modules.lmk.enums.general.AdminRoleEnum; |
| | | import cn.lili.modules.member.entity.dto.MemberAddressDTO; |
| | | import cn.lili.modules.order.order.entity.dos.Order; |
| | | import cn.lili.modules.order.order.entity.dos.OrderPackage; |
| | | import cn.lili.modules.order.order.entity.dto.OrderSearchParams; |
| | | import cn.lili.modules.order.order.entity.dto.OrderSearchXcxParams; |
| | | import cn.lili.modules.order.order.entity.enums.ModifyAddressEnums; |
| | | import cn.lili.modules.order.order.entity.enums.OrderStatusEnum; |
| | | import cn.lili.modules.order.order.entity.vo.OrderDetailVO; |
| | | import cn.lili.modules.order.order.entity.vo.OrderSimpleVO; |
| | |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import springfox.documentation.annotations.ApiIgnore; |
| | | |
| | | import javax.validation.Valid; |
| | | import javax.validation.constraints.NotBlank; |
| | | import javax.validation.constraints.NotNull; |
| | | import java.util.ArrayList; |
| | |
| | | * @author Chopper |
| | | * @since 2020/11/16 10:08 下午 |
| | | */ |
| | | @Slf4j |
| | | @RestController |
| | | @Api(tags = "买家端,订单接口") |
| | | @RequestMapping("/buyer/order/order") |
| | |
| | | }); |
| | | return ResultUtil.data(orderDetailVO); |
| | | } |
| | | |
| | | @ApiOperation(value = "订单明细") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "orderSn", value = "订单编号", required = true, paramType = "path") |
| | | }) |
| | | @GetMapping(value = "/editAddress/{orderSn}") |
| | | public ResultMessage<OrderDetailVO> editAddress(@NotNull(message = "订单编号不能为空") @PathVariable("orderSn") String orderSn) { |
| | | OrderDetailVO orderDetailVO = orderService.queryEditAddressDetail(orderSn); |
| | | Order order = orderDetailVO.getOrder(); |
| | | if (!OrderStatusEnum.UNDELIVERED.name().equals(order.getOrderStatus())) { |
| | | log.error("订单号为{}------------------->状态异常为{}",orderSn,order.getOrderStatus()); |
| | | throw new ServiceException("订单状态异常无法领取"); |
| | | } |
| | | String modifyAddressFlag = order.getModifyAddressFlag(); |
| | | if (ModifyAddressEnums.USED.name().equals(modifyAddressFlag)) { |
| | | throw new ServiceException("订单已被领取"); |
| | | } |
| | | orderDetailVO.getOrderItems().forEach(orderItem -> { |
| | | String image = orderItem.getImage(); |
| | | if (StringUtils.isNotBlank(image)&&!image.contains("http")) { |
| | | orderItem.setImage(cosUtil.getPreviewUrl(image)); |
| | | } |
| | | }); |
| | | return ResultUtil.data(orderDetailVO); |
| | | } |
| | | @ApiOperation(value = "修改收货人信息") |
| | | @ApiImplicitParam(name = "orderSn", value = "订单sn", required = true, dataType = "String", paramType = "path") |
| | | @PostMapping(value = "/update/editAddress/{orderSn}/consignee") |
| | | public ResultMessage<Object> consignee(@NotNull(message = "参数非法") @PathVariable String orderSn, |
| | | @Valid @RequestBody MemberAddressDTO memberAddressDTO) { |
| | | return ResultUtil.data(orderService.updateAddressConsignee(orderSn, memberAddressDTO)); |
| | | } |
| | | @PreventDuplicateSubmissions |
| | | @ApiOperation(value = "确认收货") |
| | | @ApiImplicitParams({ |
| | |
| | | |
| | | @ApiModelProperty(value = "商品排序") |
| | | private Integer goodsSort; |
| | | |
| | | @ApiModelProperty(value ="表示虚拟商品类型 现有类型:COUPON优惠劵") |
| | | private String virtualGoodsType; |
| | | |
| | | public Goods() { |
| | | } |
| | | |
| | |
| | | this.mobileIntro = goodsOperationDTO.getMobileIntro(); |
| | | this.goodsVideo = goodsOperationDTO.getGoodsVideo(); |
| | | this.price = goodsOperationDTO.getPrice(); |
| | | this.virtualGoodsType = goodsOperationDTO.getVirtualGoodsType(); |
| | | |
| | | //不是预售商品预售时间置空 |
| | | if (!GoodsSalesModeEnum.PRESALE.name().equals(goodsOperationDTO.getSalesModel())) { |
| | | goodsOperationDTO.setPreSaleBeginDate(null); |
| | |
| | | if (!sku.containsKey("quantity") || StringUtil.isEmpty(sku.get("quantity").toString()) || Convert.toInt(sku.get("quantity").toString()) < 0) { |
| | | throw new ServiceException(ResultCode.GOODS_SKU_QUANTITY_ERROR); |
| | | } |
| | | //没有优惠卷的商品需要移除优惠卷信息 |
| | | Object couponId = sku.get("couponId"); |
| | | if (couponId == null || StringUtil.isEmpty(couponId.toString())) { |
| | | sku.remove("couponId"); |
| | | sku.remove("couponName"); |
| | | } |
| | | sku.values().forEach(i -> { |
| | | if (CharSequenceUtil.isBlank(i.toString())) { |
| | | throw new ServiceException(ResultCode.MUST_HAVE_GOODS_SKU_VALUE); |
| | |
| | | @ApiModelProperty(value = "预警数量") |
| | | private Integer alertQuantity; |
| | | |
| | | @ApiModelProperty(value ="优惠劵id") |
| | | private String couponId; |
| | | |
| | | @ApiModelProperty(value ="优惠劵名") |
| | | private String couponName; |
| | | |
| | | public Double getWeight() { |
| | | if (weight == null) { |
| | | return 0d; |
| | |
| | | this.storeCategoryPath = goods.getStoreCategoryPath(); |
| | | this.freightTemplateId = goods.getTemplateId(); |
| | | this.recommend = goods.getRecommend(); |
| | | |
| | | } |
| | | |
| | | } |
| | |
| | | private BigDecimal commission; |
| | | @ApiModelProperty(value = "商品排序") |
| | | private Integer goodsSort; |
| | | @ApiModelProperty(value = "优惠劵id") |
| | | private String couponId; |
| | | @ApiModelProperty(value = "优惠劵名") |
| | | private String couponName; |
| | | |
| | | @ApiModelProperty(value ="表示虚拟商品类型 现有类型:COUPON优惠劵") |
| | | private String virtualGoodsType; |
| | | |
| | | |
| | | public String getGoodsName() { |
| | | //对商品对名称做一个极限处理。这里没有用xss过滤是因为xss过滤为全局过滤,影响很大。 |
| | |
| | | // 检查是否需要生成索引 |
| | | List<GoodsSku> goodsSkus = GoodsSkuBuilder.buildBatch(goods, goodsOperationDTO.getSkuList()); |
| | | renderGoodsSkuList(goodsSkus, goodsOperationDTO); |
| | | |
| | | System.out.println(goodsSkus); |
| | | if (!goodsSkus.isEmpty()) { |
| | | this.saveOrUpdateBatch(goodsSkus); |
| | | this.updateGoodsStock(goodsSkus); |
| | |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.core.lang.Assert; |
| | | import cn.hutool.json.JSONUtil; |
| | | import cn.lili.common.utils.StringUtils; |
| | | import cn.lili.modules.goods.entity.dos.Goods; |
| | | import cn.lili.modules.goods.entity.dos.GoodsSku; |
| | | import org.springframework.stereotype.Component; |
| | |
| | | Map<String, Object> specMap = new LinkedHashMap<>(); |
| | | |
| | | // 原始规格项 |
| | | String[] ignoreOriginKeys = {"id", "sn", "cost", "price", "quantity", "weight", "alertQuantity"}; |
| | | String[] ignoreOriginKeys = {"id", "sn", "cost", "price", "quantity", "weight", "alertQuantity","couponId","couponName"}; |
| | | //获取规格信息 |
| | | for (Map.Entry<String, Object> spec : skuInfo.entrySet()) { |
| | | //保存新增规格信息 |
| | |
| | | |
| | | |
| | | //规格信息 |
| | | if(StringUtils.isNotBlank(Convert.toStr(skuInfo.get("couponId")))){ |
| | | goodsSku.setCouponId(Convert.toStr(skuInfo.get("couponId"),"")); |
| | | } |
| | | |
| | | goodsSku.setCouponName(Convert.toStr(skuInfo.get("couponName"),"")); |
| | | goodsSku.setId(Convert.toStr(skuInfo.get("id"), "")); |
| | | goodsSku.setSn(Convert.toStr(skuInfo.get("sn"))); |
| | | goodsSku.setWeight(Convert.toDouble(skuInfo.get("weight"), 0D)); |
| New file |
| | |
| | | package cn.lili.modules.lmk.domain.entity; |
| | | |
| | | import cn.lili.mybatis.BaseEntity; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import lombok.Data; |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * 虚拟商品优惠卷 |
| | | * |
| | | * @author zxl |
| | | * @since 2025-09-10 |
| | | */ |
| | | @Data |
| | | @TableName("lmk_coupon_virtual") |
| | | public class CouponVirtual extends BaseEntity { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @TableField("order_id") |
| | | /** 订单id */ |
| | | private String orderId; |
| | | |
| | | |
| | | @TableField("item_order_id") |
| | | /** 订单id */ |
| | | private String itemOrderId; |
| | | |
| | | @TableField("goods_id") |
| | | /** 商品id */ |
| | | private String goodsId; |
| | | |
| | | @TableField("sku_id") |
| | | /** 商品id */ |
| | | private String skuId; |
| | | |
| | | @TableField("sku_name") |
| | | /** 商品名称 */ |
| | | private String skuName; |
| | | |
| | | @TableField("coupon_id") |
| | | /** 优惠卷id */ |
| | | private String couponId; |
| | | |
| | | @TableField("coupon_no") |
| | | /** 编号 */ |
| | | private String couponNo; |
| | | |
| | | @TableField("coupon_name") |
| | | /** 优惠卷名称 */ |
| | | private String couponName; |
| | | |
| | | @TableField("user_id") |
| | | /** 用户id */ |
| | | private String userId; |
| | | |
| | | @TableField("user_nickname") |
| | | /** 用户昵称 */ |
| | | private String userNickname; |
| | | |
| | | @TableField("claim_time") |
| | | /** 领取时间 */ |
| | | @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private Date claimTime; |
| | | |
| | | @TableField("name") |
| | | /** 名称 */ |
| | | private String name; |
| | | |
| | | @TableField("share_status") |
| | | /** 是否分享 */ |
| | | private String shareStatus; |
| | | |
| | | @TableField("claim_status") |
| | | /** 是否领取 */ |
| | | private String claimStatus; |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | package cn.lili.modules.lmk.domain.form; |
| | | |
| | | |
| | | import cn.lili.base.AbsForm; |
| | | import cn.lili.group.Add; |
| | | import cn.lili.group.Update; |
| | | import cn.lili.modules.lmk.domain.entity.CouponVirtual; |
| | | import org.springframework.beans.BeanUtils; |
| | | import javax.validation.constraints.NotBlank; |
| | | import javax.validation.constraints.NotNull; |
| | | import org.springframework.lang.NonNull; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * 虚拟商品优惠卷表单 |
| | | * |
| | | * @author zxl |
| | | * @since 2025-09-10 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "CouponVirtual表单", description = "虚拟商品优惠卷表单") |
| | | public class CouponVirtualForm extends AbsForm { |
| | | |
| | | @NotNull(message = "订单id不能为空", groups = {Add.class, Update.class}) |
| | | @ApiModelProperty("订单id") |
| | | private Long orderId; |
| | | |
| | | @NotNull(message = "商品id不能为空", groups = {Add.class, Update.class}) |
| | | @ApiModelProperty("商品id") |
| | | private Long goodsId; |
| | | |
| | | @NotBlank(message = "商品名称不能为空", groups = {Add.class, Update.class}) |
| | | @ApiModelProperty("商品名称") |
| | | private String skuName; |
| | | |
| | | @NotNull(message = "优惠卷id不能为空", groups = {Add.class, Update.class}) |
| | | @ApiModelProperty("优惠卷id") |
| | | private Long couponId; |
| | | |
| | | @NotBlank(message = "编号不能为空", groups = {Add.class, Update.class}) |
| | | @ApiModelProperty("编号") |
| | | private String couponNo; |
| | | |
| | | @NotBlank(message = "优惠卷名称不能为空", groups = {Add.class, Update.class}) |
| | | @ApiModelProperty("优惠卷名称") |
| | | private String couponName; |
| | | |
| | | @NotBlank(message = "名称不能为空", groups = {Add.class, Update.class}) |
| | | @ApiModelProperty("名称") |
| | | private String name; |
| | | |
| | | @NotBlank(message = "是否分享不能为空", groups = {Add.class, Update.class}) |
| | | @ApiModelProperty("是否分享") |
| | | private String shareStatus; |
| | | |
| | | @NotBlank(message = "是否领取不能为空", groups = {Add.class, Update.class}) |
| | | @ApiModelProperty("是否领取") |
| | | private String claimStatus; |
| | | |
| | | |
| | | public static CouponVirtual getEntityByForm(@NonNull CouponVirtualForm form, CouponVirtual entity) { |
| | | if(entity == null) { |
| | | entity = new CouponVirtual(); |
| | | } |
| | | BeanUtils.copyProperties(form, entity); |
| | | return entity; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package cn.lili.modules.lmk.domain.query; |
| | | |
| | | |
| | | import java.util.List; |
| | | |
| | | import cn.lili.base.AbsQuery; |
| | | import org.springframework.lang.NonNull; |
| | | import javax.validation.constraints.NotBlank; |
| | | import javax.validation.constraints.NotNull; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * 虚拟商品优惠卷查询 |
| | | * |
| | | * @author zxl |
| | | * @since 2025-09-10 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "CouponVirtual查询参数", description = "虚拟商品优惠卷查询参数") |
| | | public class CouponVirtualQuery extends AbsQuery { |
| | | private String orderId; |
| | | private String userNickName; |
| | | |
| | | private String skuName; |
| | | } |
| | | |
| New file |
| | |
| | | package cn.lili.modules.lmk.domain.vo; |
| | | |
| | | |
| | | import java.util.List; |
| | | |
| | | import cn.lili.base.AbsVo; |
| | | import cn.lili.modules.lmk.domain.entity.CouponVirtual; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import org.springframework.lang.NonNull; |
| | | import org.springframework.beans.BeanUtils; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * 虚拟商品优惠卷展示 |
| | | * |
| | | * @author zxl |
| | | * @since 2025-09-10 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "虚拟商品优惠卷响应数据", description = "虚拟商品优惠卷响应数据") |
| | | public class CouponVirtualVO extends AbsVo { |
| | | |
| | | /** 订单id */ |
| | | @ApiModelProperty("订单id") |
| | | private String orderId; |
| | | |
| | | /** 商品id */ |
| | | @ApiModelProperty("商品id") |
| | | private String goodsId; |
| | | |
| | | /** 商品名称 */ |
| | | @ApiModelProperty("商品名称") |
| | | private String skuName; |
| | | |
| | | /** 优惠卷id */ |
| | | @ApiModelProperty("优惠卷id") |
| | | private String couponId; |
| | | |
| | | /** 编号 */ |
| | | @ApiModelProperty("编号") |
| | | private String couponNo; |
| | | |
| | | /** 优惠卷名称 */ |
| | | @ApiModelProperty("优惠卷名称") |
| | | private String couponName; |
| | | |
| | | /** 名称 */ |
| | | @ApiModelProperty("名称") |
| | | private String name; |
| | | |
| | | /** 是否分享 */ |
| | | @ApiModelProperty("是否分享") |
| | | private String shareStatus; |
| | | |
| | | /** 是否领取 */ |
| | | @ApiModelProperty("是否领取") |
| | | private String claimStatus; |
| | | |
| | | |
| | | private Boolean deleteFlag; |
| | | |
| | | private String original; |
| | | |
| | | private String userNickName; |
| | | |
| | | public static CouponVirtualVO getVoByEntity(@NonNull CouponVirtual entity, CouponVirtualVO vo) { |
| | | if(vo == null) { |
| | | vo = new CouponVirtualVO(); |
| | | } |
| | | BeanUtils.copyProperties(entity, vo); |
| | | return vo; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package cn.lili.modules.lmk.domain.vo; |
| | | |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import lombok.Data; |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * lmk-shop-java |
| | | * |
| | | * @author : zxl |
| | | * @date : 2025-09-12 15:19 |
| | | **/ |
| | | @Data |
| | | public class CouponVirtualVOInfo { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | private String id; |
| | | |
| | | private String orderId; |
| | | |
| | | |
| | | |
| | | private String itemOrderId; |
| | | |
| | | |
| | | private String goodsId; |
| | | |
| | | |
| | | private String skuId; |
| | | |
| | | |
| | | private String skuName; |
| | | |
| | | |
| | | private String couponId; |
| | | |
| | | |
| | | private String couponNo; |
| | | |
| | | |
| | | private String couponName; |
| | | |
| | | |
| | | private String userId; |
| | | |
| | | |
| | | private String userNickname; |
| | | |
| | | /** 领取时间 */ |
| | | @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private Date claimTime; |
| | | |
| | | /** 领取时间 */ |
| | | @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private Date createTime; |
| | | /** 名称 */ |
| | | private String name; |
| | | |
| | | /** 是否分享 */ |
| | | private String shareStatus; |
| | | |
| | | /** 是否领取 */ |
| | | private String claimStatus; |
| | | |
| | | private String goodsUrl; |
| | | } |
| New file |
| | |
| | | package cn.lili.modules.lmk.enums.general; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | @AllArgsConstructor |
| | | @Getter |
| | | public enum VirtualGoodsTypeEnum { |
| | | |
| | | COUPON("虚拟优惠劵"); |
| | | private String description; |
| | | |
| | | } |
| New file |
| | |
| | | package cn.lili.modules.lmk.mapper; |
| | | |
| | | |
| | | import cn.lili.modules.lmk.domain.entity.CouponVirtual; |
| | | import cn.lili.modules.lmk.domain.query.CouponVirtualQuery; |
| | | import cn.lili.modules.lmk.domain.vo.CouponVirtualVO; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | |
| | | import java.util.List; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | /** |
| | | * 虚拟商品优惠卷 Mapper 接口 |
| | | * |
| | | * @author zxl |
| | | * @since 2025-09-10 |
| | | */ |
| | | @Mapper |
| | | public interface CouponVirtualMapper extends BaseMapper<CouponVirtual> { |
| | | |
| | | /** |
| | | * id查找虚拟商品优惠卷 |
| | | * @param id |
| | | * @return |
| | | */ |
| | | CouponVirtualVO getById(Integer id); |
| | | |
| | | /** |
| | | * 分页 |
| | | */ |
| | | IPage getPage(IPage page, @Param("query") CouponVirtualQuery query); |
| | | |
| | | } |
| New file |
| | |
| | | package cn.lili.modules.lmk.service; |
| | | |
| | | |
| | | import cn.lili.base.Result; |
| | | import cn.lili.modules.lmk.domain.entity.CouponVirtual; |
| | | import cn.lili.modules.lmk.domain.form.CouponVirtualForm; |
| | | import cn.lili.modules.lmk.domain.query.CouponVirtualQuery; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import org.springframework.web.bind.annotation.PathVariable; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 虚拟商品优惠卷 服务类 |
| | | * |
| | | * @author zxl |
| | | * @since 2025-09-10 |
| | | */ |
| | | public interface CouponVirtualService extends IService<CouponVirtual> { |
| | | |
| | | /** |
| | | * 添加 |
| | | * @param form |
| | | * @return |
| | | */ |
| | | Result add(CouponVirtualForm form); |
| | | |
| | | /** |
| | | * 修改 |
| | | * @param form |
| | | * @return |
| | | */ |
| | | Result update(CouponVirtualForm form); |
| | | |
| | | /** |
| | | * 批量删除 |
| | | * @param ids |
| | | * @return |
| | | */ |
| | | Result remove(List<String> ids); |
| | | |
| | | /** |
| | | * id删除 |
| | | * @param id |
| | | * @return |
| | | */ |
| | | Result removeById(String id); |
| | | |
| | | /** |
| | | * 分页查询 |
| | | * @param query |
| | | * @return |
| | | */ |
| | | Result page(CouponVirtualQuery query); |
| | | |
| | | /** |
| | | * 根据id查找 |
| | | * @param id |
| | | * @return |
| | | */ |
| | | Result detail(Integer id); |
| | | |
| | | /** |
| | | * 列表 |
| | | * @return |
| | | */ |
| | | Result all(); |
| | | |
| | | Result tackCardById( String cardId); |
| | | |
| | | Result changShareStatus( String cardId); |
| | | |
| | | Result couponCardInfo(String cardId); |
| | | } |
| New file |
| | |
| | | package cn.lili.modules.lmk.service.impl; |
| | | |
| | | import cn.lili.base.Result; |
| | | import cn.lili.common.exception.ServiceException; |
| | | import cn.lili.common.security.AuthUser; |
| | | import cn.lili.common.security.context.UserContext; |
| | | import cn.lili.modules.goods.service.GoodsService; |
| | | import cn.lili.modules.lmk.domain.entity.CouponVirtual; |
| | | import cn.lili.modules.lmk.domain.form.CouponVirtualForm; |
| | | import cn.lili.modules.lmk.domain.query.CouponVirtualQuery; |
| | | import cn.lili.modules.lmk.domain.vo.CouponVirtualVO; |
| | | import cn.lili.modules.lmk.domain.vo.CouponVirtualVOInfo; |
| | | import cn.lili.modules.lmk.mapper.CouponVirtualMapper; |
| | | import cn.lili.modules.lmk.service.CouponVirtualService; |
| | | import cn.lili.modules.order.order.entity.dos.Order; |
| | | import cn.lili.modules.order.order.entity.dos.OrderItem; |
| | | import cn.lili.modules.order.order.entity.enums.ClaimStatusEnum; |
| | | import cn.lili.modules.order.order.entity.enums.OrderStatusEnum; |
| | | import cn.lili.modules.order.order.entity.enums.RefundStatusEnum; |
| | | import cn.lili.modules.order.order.entity.enums.ShareStatusEnum; |
| | | import cn.lili.modules.order.order.service.OrderItemService; |
| | | import cn.lili.modules.order.order.service.OrderService; |
| | | import cn.lili.modules.promotion.service.MemberCouponService; |
| | | import cn.lili.utils.COSUtil; |
| | | import cn.lili.utils.PageUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | |
| | | import com.baomidou.mybatisplus.core.toolkit.StringUtils; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.redisson.api.RLock; |
| | | import org.redisson.api.RedissonClient; |
| | | import org.springframework.stereotype.Service; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.Assert; |
| | | |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * 虚拟商品优惠卷 服务实现类 |
| | | * |
| | | * @author zxl |
| | | * @since 2025-09-10 |
| | | */ |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | @Slf4j |
| | | public class CouponVirtualServiceImpl extends ServiceImpl<CouponVirtualMapper, CouponVirtual> implements CouponVirtualService { |
| | | |
| | | private final CouponVirtualMapper couponVirtualMapper; |
| | | |
| | | private final RedissonClient redissonClient; |
| | | |
| | | private final static String LOCK_COUPON_VIRTUAL_CARD_ID = "lock_coupon_virtual_card_id:"; |
| | | |
| | | private final OrderItemService orderItemService; |
| | | |
| | | private final OrderService orderService; |
| | | |
| | | private final MemberCouponService memberCouponService; |
| | | |
| | | private final GoodsService goodsService; |
| | | |
| | | private final COSUtil cosUtil; |
| | | /** |
| | | * 添加 |
| | | * |
| | | * @param form |
| | | * @return |
| | | */ |
| | | @Override |
| | | public Result add(CouponVirtualForm form) { |
| | | CouponVirtual entity = CouponVirtualForm.getEntityByForm(form, null); |
| | | baseMapper.insert(entity); |
| | | return Result.ok("添加成功"); |
| | | } |
| | | |
| | | /** |
| | | * 修改 |
| | | * |
| | | * @param form |
| | | * @return |
| | | */ |
| | | @Override |
| | | public Result update(CouponVirtualForm form) { |
| | | CouponVirtual entity = baseMapper.selectById(form.getId()); |
| | | |
| | | // 为空抛IllegalArgumentException,做全局异常处理 |
| | | Assert.notNull(entity, "记录不存在"); |
| | | BeanUtils.copyProperties(form, entity); |
| | | baseMapper.updateById(entity); |
| | | return Result.ok("修改成功"); |
| | | } |
| | | |
| | | /** |
| | | * 批量删除 |
| | | * |
| | | * @param ids |
| | | * @return |
| | | */ |
| | | @Override |
| | | public Result remove(List<String> ids) { |
| | | baseMapper.deleteBatchIds(ids); |
| | | return Result.ok("删除成功"); |
| | | } |
| | | |
| | | /** |
| | | * id删除 |
| | | * |
| | | * @param id |
| | | * @return |
| | | */ |
| | | @Override |
| | | public Result removeById(String id) { |
| | | baseMapper.deleteById(id); |
| | | return Result.ok("删除成功"); |
| | | } |
| | | |
| | | /** |
| | | * 分页查询 |
| | | * |
| | | * @param query |
| | | * @return |
| | | */ |
| | | @Override |
| | | public Result page(CouponVirtualQuery query) { |
| | | IPage<CouponVirtualVO> page = PageUtil.getPage(query, CouponVirtualVO.class); |
| | | baseMapper.getPage(page, query); |
| | | for (CouponVirtualVO record : page.getRecords()) { |
| | | String original = record.getOriginal(); |
| | | if (StringUtils.isNotBlank(original) && !original.contains("http")) { |
| | | record.setOriginal(cosUtil.getPreviewUrl(original)); |
| | | } |
| | | } |
| | | return Result.ok().data(page.getRecords()).total(page.getTotal()); |
| | | } |
| | | |
| | | /** |
| | | * 根据id查找 |
| | | * |
| | | * @param id |
| | | * @return |
| | | */ |
| | | @Override |
| | | public Result detail(Integer id) { |
| | | CouponVirtualVO vo = baseMapper.getById(id); |
| | | Assert.notNull(vo, "记录不存在"); |
| | | return Result.ok().data(vo); |
| | | } |
| | | |
| | | /** |
| | | * 列表 |
| | | * |
| | | * @return |
| | | */ |
| | | @Override |
| | | public Result all() { |
| | | List<CouponVirtual> entities = baseMapper.selectList(null); |
| | | List<CouponVirtualVO> vos = entities.stream() |
| | | .map(entity -> CouponVirtualVO.getVoByEntity(entity, null)) |
| | | .collect(Collectors.toList()); |
| | | return Result.ok().data(vos); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Result tackCardById(String cardId) { |
| | | log.info("被领取的礼品卡的id为--------------------------->{}",cardId); |
| | | AuthUser currentUser = UserContext.getCurrentUser(); |
| | | if (currentUser == null) { |
| | | throw new ServiceException("当前用户没有登录"); |
| | | } |
| | | String userId = currentUser.getId(); |
| | | String nickName = currentUser.getNickName(); |
| | | RLock lock = null; |
| | | try { |
| | | lock = redissonClient.getLock(LOCK_COUPON_VIRTUAL_CARD_ID + cardId); |
| | | lock.lock(); |
| | | LambdaQueryWrapper<CouponVirtual> forUpdate = Wrappers.<CouponVirtual>lambdaQuery().eq(CouponVirtual::getId, cardId).last("FOR UPDATE"); |
| | | CouponVirtual cardInfo = this.getOne(forUpdate); |
| | | if (cardInfo == null) { |
| | | throw new ServiceException("当前优惠卷不存在"); |
| | | } |
| | | if (ClaimStatusEnum.CLAIM.name().equals(cardInfo.getClaimStatus())) { |
| | | throw new ServiceException("当前购物卡已经被领取"); |
| | | } |
| | | //校验订单状态是否正常 |
| | | String orderNo = cardInfo.getOrderId(); |
| | | if (StringUtils.isBlank(orderNo)) { |
| | | throw new ServiceException("当前订单不存在无法领取"); |
| | | } |
| | | String itemOrderId = cardInfo.getItemOrderId(); |
| | | Order order = orderService.getBySn(orderNo); |
| | | if (order == null) { |
| | | throw new ServiceException("当前订单不存在无法领取"); |
| | | } |
| | | if (!OrderStatusEnum.COMPLETED.name().equals(order.getOrderStatus())) { |
| | | throw new ServiceException("订单状态异常无法领取"); |
| | | } |
| | | OrderItem orderItem = orderItemService.getById(itemOrderId); |
| | | if (orderItem == null) { |
| | | throw new ServiceException("当前订单不存在"); |
| | | } |
| | | String orderSn = orderItem.getOrderSn(); |
| | | if (!orderNo.equals(orderSn)) { |
| | | throw new ServiceException("订单无法对应无法领取"); |
| | | } |
| | | if (!RefundStatusEnum.NO_REFUND.name().equals(orderItem.getIsRefund())) { |
| | | throw new ServiceException("当前订单已退款无法领取"); |
| | | } |
| | | //领取对应的优惠卷 |
| | | memberCouponService.receiveCoupon(cardInfo.getCouponId(),userId , nickName); |
| | | cardInfo.setUserNickname(nickName); |
| | | cardInfo.setUserId(userId); |
| | | cardInfo.setClaimStatus(ClaimStatusEnum.CLAIM.name()); |
| | | cardInfo.setShareStatus(ShareStatusEnum.SHARE.name()); |
| | | cardInfo.setClaimTime(new Date()); |
| | | boolean b = this.updateById(cardInfo); |
| | | //去领取优惠卷 |
| | | if (!b) { |
| | | throw new RuntimeException("领取失败"); |
| | | } |
| | | return Result.ok().data(cardInfo.getCouponId()); |
| | | } finally { |
| | | if ( lock != null && lock.isHeldByCurrentThread()) { |
| | | lock.unlock(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public Result changShareStatus(String cardId) { |
| | | CouponVirtual couponVirtual = this.getById(cardId); |
| | | couponVirtual.setShareStatus(ShareStatusEnum.SHARE.name()); |
| | | this.updateById(couponVirtual); |
| | | return Result.ok(); |
| | | } |
| | | |
| | | @Override |
| | | public Result couponCardInfo(String cardId) { |
| | | CouponVirtual couponVirtual = this.getById(cardId); |
| | | if (couponVirtual == null) { |
| | | throw new ServiceException("当前购物卡不存在"); |
| | | } |
| | | CouponVirtualVOInfo virtualVOInfo = new CouponVirtualVOInfo(); |
| | | BeanUtils.copyProperties(couponVirtual, virtualVOInfo); |
| | | |
| | | String goodsId = virtualVOInfo.getGoodsId(); |
| | | String url = goodsService.getById(goodsId).getOriginal(); |
| | | if (StringUtils.isNotBlank(url) && !url.contains("http")) { |
| | | virtualVOInfo.setGoodsUrl(cosUtil.getPreviewUrl(url)); |
| | | } |
| | | return Result.ok().data(virtualVOInfo); |
| | | } |
| | | } |
| New file |
| | |
| | | package cn.lili.modules.order.cart.entity.dto; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | @AllArgsConstructor |
| | | |
| | | public class SkuMapDTO { |
| | | private String skuId; |
| | | private Double price; |
| | | } |
| | |
| | | import cn.lili.common.utils.CurrencyUtil; |
| | | import cn.lili.common.utils.StringUtils; |
| | | import cn.lili.modules.order.cart.entity.dto.MemberCouponDTO; |
| | | import cn.lili.modules.order.cart.entity.dto.SkuMapDTO; |
| | | import cn.lili.modules.order.cart.entity.dto.TradeDTO; |
| | | import cn.lili.modules.order.cart.entity.enums.RenderStepEnums; |
| | | import cn.lili.modules.order.cart.entity.vo.CartSkuVO; |
| | |
| | | |
| | | //接收具体优惠券信息 |
| | | MemberCoupon coupon = memberCouponDTO.getMemberCoupon(); |
| | | |
| | | Integer goodsNum = tradeDTO.getSkuList().stream().map(CartSkuVO::getNum).reduce(Integer::sum).get(); |
| | | |
| | | //处理一个极端情况,如果优惠券满减金额大于订单金额 |
| | | if (coupon.getCouponType().equals(CouponTypeEnum.PRICE.name()) && coupon.getPrice() > countPrice) { |
| | | if (coupon.getCouponType().equals(CouponTypeEnum.PRICE.name()) |
| | | && coupon.getPrice() > countPrice |
| | | && coupon.getGoodsUseLimitNum() >= goodsNum) { |
| | | //将符合优惠券的金额写入,即最大扣减金额 |
| | | coupon.setPrice(countPrice); |
| | | } |
| | |
| | | * @param memberCouponDTO 用于计算优惠券结算详情 |
| | | */ |
| | | private void renderCouponPrice(Map<String, Double> couponMap, TradeDTO tradeDTO, MemberCoupon coupon, MemberCouponDTO memberCouponDTO) { |
| | | List<SkuMapDTO> skuMapDTOList = new ArrayList<>(); |
| | | for (String skuId : couponMap.keySet()) { |
| | | skuMapDTOList.add(new SkuMapDTO(skuId, couponMap.get(skuId))); |
| | | } |
| | | skuMapDTOList.sort((o1, o2) -> o2.getPrice().compareTo(o1.getPrice())); |
| | | //分发优惠券 |
| | | PromotionPriceUtil.recountPrice(tradeDTO, memberCouponDTO.getSkuDetail(), memberCouponDTO.getMemberCoupon().getPrice(), |
| | | Boolean.TRUE.equals(coupon.getPlatformFlag()) ? |
| | | PromotionTypeEnum.PLATFORM_COUPON : PromotionTypeEnum.COUPON, memberCouponDTO.getMemberCoupon().getCouponId()); |
| | | PromotionPriceUtil.recountPrice(tradeDTO, memberCouponDTO.getSkuDetail(), |
| | | memberCouponDTO.getMemberCoupon().getPrice(), |
| | | Boolean.TRUE.equals(coupon.getPlatformFlag()) ? PromotionTypeEnum.PLATFORM_COUPON : PromotionTypeEnum.COUPON, |
| | | memberCouponDTO.getMemberCoupon().getCouponId(), |
| | | memberCouponDTO.getMemberCoupon().getGoodsUseLimitNum()); |
| | | //如果是平台券 则需要计算商家承担比例 |
| | | if (Boolean.TRUE.equals(coupon.getPlatformFlag()) && coupon.getStoreCommission() > 0) { |
| | | |
| | | Integer i = coupon.getGoodsUseLimitNum(); |
| | | //循环所有优惠券 |
| | | for (String skuId : couponMap.keySet()) { |
| | | for (SkuMapDTO skuMapDTO : skuMapDTOList) { |
| | | |
| | | for (CartSkuVO cartSkuVO : tradeDTO.getSkuList()) { |
| | | //写入平台优惠券承担比例 |
| | | if (cartSkuVO.getGoodsSku().getId().equals(skuId)) { |
| | | //写入店铺承担比例 |
| | | cartSkuVO.getPriceDetailDTO().setSiteCouponPoint(coupon.getStoreCommission()); |
| | | if (cartSkuVO.getGoodsSku().getId().equals(skuMapDTO.getSkuId())) { |
| | | if (i == null) { |
| | | cartSkuVO.getPriceDetailDTO().setSiteCouponPoint(coupon.getStoreCommission()); |
| | | } else { |
| | | if (i > 0) { |
| | | //写入店铺承担比例 |
| | | if (i >= cartSkuVO.getNum()) { |
| | | cartSkuVO.getPriceDetailDTO().setSiteCouponPoint(coupon.getStoreCommission()); |
| | | } else { |
| | | cartSkuVO.getPriceDetailDTO().setSiteCouponPoint(coupon.getStoreCommission() * i / cartSkuVO.getNum()); |
| | | } |
| | | i = i - cartSkuVO.getNum(); |
| | | } else { |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | * @param coupon 优惠券信息 |
| | | */ |
| | | private void renderCouponDiscount(Map<String, Double> couponMap, TradeDTO tradeDTO, MemberCoupon coupon) { |
| | | |
| | | //循环所有优惠券 |
| | | for (String skuId : couponMap.keySet()) { |
| | | |
| | |
| | | } |
| | | priceDetailDTO.setCouponPrice(CurrencyUtil.add(priceDetailDTO.getCouponPrice(), discountCouponPrice)); |
| | | |
| | | } else { |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | if (isFull(countPrice, cart)) { |
| | | //如果减现金 |
| | | if (Boolean.TRUE.equals(fullDiscount.getFullMinusFlag())) { |
| | | PromotionPriceUtil.recountPrice(tradeDTO, skuPriceDetail, fullDiscount.getFullMinus(), PromotionTypeEnum.FULL_DISCOUNT, fullDiscountVO.getId()); |
| | | PromotionPriceUtil.recountPrice(tradeDTO, skuPriceDetail, fullDiscount.getFullMinus(), PromotionTypeEnum.FULL_DISCOUNT, fullDiscountVO.getId(), 0); |
| | | } |
| | | //打折 |
| | | else if (Boolean.TRUE.equals(fullDiscount.getFullRateFlag())) { |
| | |
| | | import cn.hutool.core.map.MapUtil; |
| | | import cn.lili.common.enums.PromotionTypeEnum; |
| | | import cn.lili.common.utils.CurrencyUtil; |
| | | import cn.lili.modules.order.cart.entity.dto.SkuMapDTO; |
| | | import cn.lili.modules.order.cart.entity.dto.TradeDTO; |
| | | import cn.lili.modules.order.cart.entity.vo.CartSkuVO; |
| | | import cn.lili.modules.order.order.entity.dto.DiscountPriceItem; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | |
| | | * @param promotionTypeEnum 促销类型 |
| | | */ |
| | | public static void recountPrice(TradeDTO tradeDTO, Map<String, Double> skuPromotionDetail, Double discountPrice, |
| | | PromotionTypeEnum promotionTypeEnum, String activityId) { |
| | | PromotionTypeEnum promotionTypeEnum, String activityId, Integer goodsUseLimitNum) { |
| | | |
| | | // sku 促销信息非空判定 |
| | | if (skuPromotionDetail == null || skuPromotionDetail.isEmpty()) { |
| | | return; |
| | | } |
| | | |
| | | //计算总金额 |
| | | Double totalPrice = 0D; |
| | | for (Double value : skuPromotionDetail.values()) { |
| | | totalPrice = CurrencyUtil.add(totalPrice, value); |
| | | } |
| | | |
| | | //极端情况,如果扣减金额小于需要支付的金额,则扣减金额=支付金额,不能成为负数 |
| | | if (discountPrice > totalPrice) { |
| | | discountPrice = totalPrice; |
| | | |
| | | for (String skuId : skuPromotionDetail.keySet()) { |
| | | |
| | | //获取对应商品进行计算 |
| | | for (CartSkuVO cartSkuVO : tradeDTO.getSkuList()) { |
| | | |
| | | if (cartSkuVO.getGoodsSku().getId().equals(skuId)) { |
| | | //优惠券金额,则计入优惠券 ,其他则计入总的discount price |
| | | if (promotionTypeEnum == PromotionTypeEnum.COUPON) { |
| | | cartSkuVO.getPriceDetailDTO().setCouponPrice(cartSkuVO.getPriceDetailDTO().getGoodsPrice()); |
| | | } else { |
| | | cartSkuVO.getPriceDetailDTO().setDiscountPrice(cartSkuVO.getPriceDetailDTO().getGoodsPrice()); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | //获取购物车信息 |
| | | List<CartSkuVO> skuVOList = tradeDTO.getSkuList(); |
| | | |
| | | // 获取map分配sku的总数,如果是最后一个商品分配金额,则将金额从百分比改为总金额扣减,避免出现小数除不尽 |
| | | AtomicInteger count = new AtomicInteger(skuPromotionDetail.size()); |
| | | |
| | | //已优惠金额 |
| | | AtomicReference<Double> deducted = new AtomicReference<>(0D); |
| | | |
| | | for (String skuId : skuPromotionDetail.keySet()) { |
| | | if (goodsUseLimitNum > 0) { |
| | | // 处理限制商品数量逻辑,只处理一个商品 |
| | | List<SkuMapDTO> skuMapDTOList = new ArrayList<>(); |
| | | for (String skuId : skuPromotionDetail.keySet()) { |
| | | skuMapDTOList.add(new SkuMapDTO(skuId, skuPromotionDetail.get(skuId))); |
| | | } |
| | | skuMapDTOList.sort((o1, o2) -> o2.getPrice().compareTo(o1.getPrice())); |
| | | |
| | | //获取对应商品进行计算 |
| | | final int[] i = {0}; |
| | | for (SkuMapDTO skuMap : skuMapDTOList) { |
| | | |
| | | Double finalDiscountPrice = discountPrice; |
| | | Double finalTotalPrice = totalPrice; |
| | | skuVOList.stream().filter(l -> l.getGoodsSku().getId().equals(skuId)).findFirst().ifPresent(cartSkuVO -> { |
| | | //sku 优惠金额 |
| | | Double skuDiscountPrice; |
| | | count.getAndDecrement(); |
| | | //获取对应商品进行计算 |
| | | Double finalDiscountPrice = discountPrice; |
| | | skuVOList.stream().filter(l -> l.getGoodsSku().getId().equals(skuMap.getSkuId())).findFirst().ifPresent(cartSkuVO -> { |
| | | //sku 优惠金额 |
| | | Double skuDiscountPrice = 0D; |
| | | if (i[0] < 1) { |
| | | |
| | | //非最后一个商品,则按照比例计算 |
| | | if (count.get() > 0) { |
| | | //商品金额占比 |
| | | double point = CurrencyUtil.div(cartSkuVO.getPriceDetailDTO().getGoodsPrice(), finalTotalPrice, 4); |
| | | //商品优惠金额 |
| | | skuDiscountPrice = CurrencyUtil.mul(finalDiscountPrice, point); |
| | | //累加已优惠金额 |
| | | deducted.set(CurrencyUtil.add(deducted.get(), skuDiscountPrice)); |
| | | if (cartSkuVO.getUtilPrice() > finalDiscountPrice) { |
| | | skuDiscountPrice = cartSkuVO.getUtilPrice() - finalDiscountPrice; |
| | | } else { |
| | | skuDiscountPrice = cartSkuVO.getUtilPrice(); |
| | | } |
| | | //累加已优惠金额 |
| | | deducted.set(CurrencyUtil.add(deducted.get(), skuDiscountPrice)); |
| | | i[0] = i[0] + 1; |
| | | } |
| | | calculateCartSkuPromotionsPrice(cartSkuVO, skuDiscountPrice, promotionTypeEnum, activityId); |
| | | }); |
| | | discountPrice = deducted.get(); |
| | | } |
| | | } else { |
| | | for (Double value : skuPromotionDetail.values()) { |
| | | totalPrice = CurrencyUtil.add(totalPrice, value); |
| | | } |
| | | |
| | | //极端情况,如果扣减金额小于需要支付的金额,则扣减金额=支付金额,不能成为负数 |
| | | if (discountPrice > totalPrice) { |
| | | discountPrice = totalPrice; |
| | | |
| | | for (String skuId : skuPromotionDetail.keySet()) { |
| | | |
| | | //获取对应商品进行计算 |
| | | for (CartSkuVO cartSkuVO : tradeDTO.getSkuList()) { |
| | | |
| | | if (cartSkuVO.getGoodsSku().getId().equals(skuId)) { |
| | | //优惠券金额,则计入优惠券 ,其他则计入总的discount price |
| | | if (promotionTypeEnum == PromotionTypeEnum.COUPON) { |
| | | cartSkuVO.getPriceDetailDTO().setCouponPrice(cartSkuVO.getPriceDetailDTO().getGoodsPrice()); |
| | | } else { |
| | | cartSkuVO.getPriceDetailDTO().setDiscountPrice(cartSkuVO.getPriceDetailDTO().getGoodsPrice()); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | // 如果是最后一个商品 则减去之前优惠的金额来进行计算 |
| | | else { |
| | | skuDiscountPrice = CurrencyUtil.sub(finalDiscountPrice, deducted.get()); |
| | | } |
| | | } |
| | | |
| | | calculateCartSkuPromotionsPrice(cartSkuVO, skuDiscountPrice, promotionTypeEnum, activityId); |
| | | }); |
| | | // 获取map分配sku的总数,如果是最后一个商品分配金额,则将金额从百分比改为总金额扣减,避免出现小数除不尽 |
| | | AtomicInteger count = new AtomicInteger(skuPromotionDetail.size()); |
| | | |
| | | |
| | | for (String skuId : skuPromotionDetail.keySet()) { |
| | | |
| | | //获取对应商品进行计算 |
| | | |
| | | Double finalDiscountPrice = discountPrice; |
| | | Double finalTotalPrice = totalPrice; |
| | | skuVOList.stream().filter(l -> l.getGoodsSku().getId().equals(skuId)).findFirst().ifPresent(cartSkuVO -> { |
| | | //sku 优惠金额 |
| | | Double skuDiscountPrice; |
| | | count.getAndDecrement(); |
| | | |
| | | //非最后一个商品,则按照比例计算 |
| | | if (count.get() > 0) { |
| | | //商品金额占比 |
| | | double point = CurrencyUtil.div(cartSkuVO.getPriceDetailDTO().getGoodsPrice(), finalTotalPrice, 4); |
| | | //商品优惠金额 |
| | | skuDiscountPrice = CurrencyUtil.mul(finalDiscountPrice, point); |
| | | //累加已优惠金额 |
| | | deducted.set(CurrencyUtil.add(deducted.get(), skuDiscountPrice)); |
| | | } |
| | | // 如果是最后一个商品 则减去之前优惠的金额来进行计算 |
| | | else { |
| | | skuDiscountPrice = CurrencyUtil.sub(finalDiscountPrice, deducted.get()); |
| | | } |
| | | |
| | | calculateCartSkuPromotionsPrice(cartSkuVO, skuDiscountPrice, promotionTypeEnum, activityId); |
| | | }); |
| | | |
| | | } |
| | | } |
| | | |
| | | calculateNotEnoughPromotionsPrice(skuVOList, skuPromotionDetail, discountPrice, totalPrice, promotionTypeEnum, activityId); |
| | | |
| | | } |
| | |
| | | // 如果还有剩余金额,则继续分摊 |
| | | if (balance.get() > 0) { |
| | | skuPromotionDetailClone.remove(lastSkuId.toString()); |
| | | double lastDiscountPrice = CurrencyUtil.sub(discountPrice, skuPromotionDetail.get(lastSkuId.toString())); |
| | | double lastTotalPrice = CurrencyUtil.sub(totalPrice, skuPromotionDetail.get(lastSkuId.toString())); |
| | | filterEnoughSku(skuVOList, skuPromotionDetailClone, lastDiscountPrice, lastTotalPrice, balance, lastSkuId, promotionTypeEnum, activityId); |
| | | if (skuPromotionDetail.containsKey(lastSkuId.toString())) { |
| | | double lastDiscountPrice = CurrencyUtil.sub(discountPrice, skuPromotionDetail.get(lastSkuId.toString())); |
| | | double lastTotalPrice = CurrencyUtil.sub(totalPrice, skuPromotionDetail.get(lastSkuId.toString())); |
| | | filterEnoughSku(skuVOList, skuPromotionDetailClone, lastDiscountPrice, lastTotalPrice, balance, lastSkuId, promotionTypeEnum, activityId); |
| | | } |
| | | } else { |
| | | break; |
| | | } |
| | |
| | | |
| | | |
| | | private static void filterEnoughSku(List<CartSkuVO> skuVOList, Map<String, Double> skuPromotionDetail, |
| | | Double discountPrice, Double totalPrice, |
| | | AtomicReference<Double> balance, StringBuilder lastSkuId, |
| | | PromotionTypeEnum promotionTypeEnum, String activityId) { |
| | | Double discountPrice, Double totalPrice, |
| | | AtomicReference<Double> balance, StringBuilder lastSkuId, |
| | | PromotionTypeEnum promotionTypeEnum, String activityId) { |
| | | AtomicInteger count = new AtomicInteger(skuPromotionDetail.size()); |
| | | AtomicReference<Double> countPrice = new AtomicReference<>(0D); |
| | | for (String skuId : skuPromotionDetail.keySet()) { |
| | |
| | | private String orderType; |
| | | |
| | | /** |
| | | * @see CouPonFlagEnum |
| | | */ |
| | | @ApiModelProperty(value = "是否是礼品卡") |
| | | private String couponFlag; |
| | | /** |
| | | * 订单地址修改状态 |
| | | */ |
| | | @ApiModelProperty(value = "订单地址修改状态") |
| | | private String modifyAddressFlag; |
| | | |
| | | /** |
| | | * @see OrderPromotionTypeEnum |
| | | */ |
| | | @ApiModelProperty(value = "订单促销类型") |
| | |
| | | @ApiModelProperty(value = "促销id") |
| | | private String promotionId; |
| | | |
| | | @ApiModelProperty(value = "优惠卷id") |
| | | private String couponId; |
| | | |
| | | @ApiModelProperty(value = "优惠卷名称") |
| | | private String couponName; |
| | | |
| | | @ApiModelProperty(value = "销售金额") |
| | | private Double goodsPrice; |
| | | |
| | |
| | | @ApiModelProperty(value = "订单促销类型") |
| | | private String orderPromotionType; |
| | | |
| | | private String couponFlag; |
| | | |
| | | |
| | | public <T> QueryWrapper<T> queryWrapper() { |
| | | AuthUser currentUser = UserContext.getCurrentUser(); |
| | | QueryWrapper<T> wrapper = new QueryWrapper<>(); |
| | |
| | | //按评价状态 |
| | | wrapper.eq(CharSequenceUtil.isNotEmpty(commentStatus), "oi.comment_status", commentStatus); |
| | | |
| | | wrapper.eq(CharSequenceUtil.isNotEmpty(couponFlag),"o.coupon_flag", couponFlag); |
| | | |
| | | //按标签查询 |
| | | if (CharSequenceUtil.isNotEmpty(tag)) { |
| | | String orderStatusColumn = "o.order_status"; |
| New file |
| | |
| | | package cn.lili.modules.order.order.entity.enums; |
| | | |
| | | /** |
| | | * 领取状态状态 |
| | | * |
| | | |
| | | **/ |
| | | public enum ClaimStatusEnum { |
| | | |
| | | /** |
| | | * 分享 |
| | | */ |
| | | CLAIM("领取"), |
| | | |
| | | /** |
| | | * 未分享 |
| | | */ |
| | | NOT_CLAIM("未领取"); |
| | | |
| | | private final String description; |
| | | |
| | | ClaimStatusEnum(String description) { |
| | | this.description = description; |
| | | } |
| | | |
| | | public String description() { |
| | | return this.description; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package cn.lili.modules.order.order.entity.enums; |
| | | |
| | | /** |
| | | * 分享状态 |
| | | * |
| | | **/ |
| | | public enum CouPonFlagEnum { |
| | | |
| | | /** |
| | | * 礼品卡 |
| | | */ |
| | | COUPON("礼品卡"), |
| | | |
| | | /** |
| | | * 不是礼品卡 |
| | | */ |
| | | NOT_COUPON("不是礼品卡"); |
| | | |
| | | private final String description; |
| | | |
| | | CouPonFlagEnum(String description) { |
| | | this.description = description; |
| | | } |
| | | |
| | | public String description() { |
| | | return this.description; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package cn.lili.modules.order.order.entity.enums; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | @AllArgsConstructor |
| | | @Getter |
| | | public enum ModifyAddressEnums { |
| | | USED("已被领取"); |
| | | private final String des; |
| | | } |
| New file |
| | |
| | | package cn.lili.modules.order.order.entity.enums; |
| | | |
| | | /** |
| | | * 分享状态 |
| | | * |
| | | **/ |
| | | public enum ShareStatusEnum { |
| | | |
| | | /** |
| | | * 分享 |
| | | */ |
| | | SHARE("分享"), |
| | | |
| | | /** |
| | | * 未分享 |
| | | */ |
| | | NOT_SHARE("未分享"); |
| | | |
| | | private final String description; |
| | | |
| | | ShareStatusEnum(String description) { |
| | | this.description = description; |
| | | } |
| | | |
| | | public String description() { |
| | | return this.description; |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | private String consigneeName; |
| | | private String consigneeMobile; |
| | | private String modifyAddressFlag; |
| | | |
| | | |
| | | private String memberId; |
| | |
| | | @Data |
| | | public class OrderSimpleXcxVO { |
| | | |
| | | private String id; |
| | | |
| | | @ApiModelProperty("sn") |
| | | private String sn; |
| | | |
| | |
| | | |
| | | @ApiModelProperty(value = "卖家订单备注") |
| | | private String sellerRemark; |
| | | |
| | | @ApiModelProperty(value = "是否是礼品卡") |
| | | private String couponFlag; |
| | | |
| | | private int i = 0; |
| | | public List<OrderItemVO> initOrderItems() { |
| | | if (CharSequenceUtil.isEmpty(groupGoodsId)) { |
| | |
| | | "o.consignee_mobile AS consigneeMobile," + |
| | | "o.member_id AS memberId," + |
| | | "m.nick_name AS nickName," + |
| | | "o.modify_address_flag AS modifyAddressFlag,"+ |
| | | " GROUP_CONCAT(oi.goods_id) as group_goods_id," + |
| | | " GROUP_CONCAT(oi.sku_id) as group_sku_id," + |
| | | " GROUP_CONCAT(oi.num) as group_num" + |
| | |
| | | "o.consignee_name AS consigneeName," + |
| | | "o.consignee_mobile AS consigneeMobile," + |
| | | "o.member_id AS memberId," + |
| | | "o.modify_address_flag AS modifyAddressFlag,"+ |
| | | " GROUP_CONCAT(oi.goods_id) as group_goods_id," + |
| | | " GROUP_CONCAT(oi.sku_id) as group_sku_id," + |
| | | " GROUP_CONCAT(oi.num) as group_num" + |
| | |
| | | * @param queryWrapper 查询条件 |
| | | * @return 简短订单分页 |
| | | */ |
| | | @Select("select o.sn,o.flow_price,o.create_time,o.order_status,o.pay_status,o.payment_method,o.payment_time,o.member_name,o.store_name as " + |
| | | "store_name,o.store_id as store_id,o.client_type,o.order_type,o.deliver_status,o.order_promotion_type,o.seller_remark " + |
| | | @Select("select o.id,o.sn,o.flow_price,o.create_time,o.order_status,o.pay_status,o.payment_method,o.payment_time,o.member_name,o.store_name as " + |
| | | "store_name,o.store_id as store_id,o.client_type,o.order_type,o.deliver_status,o.order_promotion_type,o.seller_remark,o.coupon_flag " + |
| | | ",GROUP_CONCAT(oi.goods_id) as group_goods_id," + |
| | | " GROUP_CONCAT(oi.sku_id) as group_sku_id," + |
| | | " GROUP_CONCAT(oi.num) as group_num" + |
| | |
| | | */ |
| | | OrderDetailVO queryDetail(String orderSn); |
| | | |
| | | OrderDetailVO queryEditAddressDetail(String orderSn); |
| | | |
| | | String sendMqMessage(String snNo); |
| | | /** |
| | | * 创建订单 |
| | |
| | | */ |
| | | Order updateConsignee(String orderSn, MemberAddressDTO memberAddressDTO); |
| | | |
| | | Order updateAddressConsignee(String orderSn, MemberAddressDTO memberAddressDTO); |
| | | |
| | | /** |
| | | * 订单发货 |
| | | * |
| | |
| | | import cn.lili.modules.goods.entity.dos.Goods; |
| | | import cn.lili.modules.goods.entity.dto.GoodsCompleteMessage; |
| | | import cn.lili.modules.goods.service.GoodsService; |
| | | import cn.lili.modules.lmk.domain.entity.CouponVirtual; |
| | | import cn.lili.modules.lmk.domain.vo.OrderCountVO; |
| | | import cn.lili.modules.lmk.enums.general.AdminRoleEnum; |
| | | import cn.lili.modules.lmk.service.CouponVirtualService; |
| | | import cn.lili.modules.member.entity.dos.Member; |
| | | import cn.lili.modules.member.entity.dto.MemberAddressDTO; |
| | | import cn.lili.modules.member.mapper.MemberMapper; |
| | |
| | | import cn.lili.modules.permission.entity.dos.AdminUser; |
| | | import cn.lili.modules.permission.service.AdminUserService; |
| | | import cn.lili.modules.permission.service.RoleService; |
| | | import cn.lili.modules.promotion.entity.dos.Coupon; |
| | | import cn.lili.modules.promotion.entity.dos.Pintuan; |
| | | import cn.lili.modules.promotion.service.CouponService; |
| | | import cn.lili.modules.promotion.service.PintuanService; |
| | | import cn.lili.modules.store.entity.dto.StoreDeliverGoodsAddressDTO; |
| | | import cn.lili.modules.store.service.StoreDetailService; |
| | |
| | | import org.apache.poi.ss.util.CellRangeAddressList; |
| | | import org.apache.poi.xssf.usermodel.XSSFWorkbook; |
| | | import org.apache.rocketmq.spring.core.RocketMQTemplate; |
| | | import org.redisson.api.RLock; |
| | | import org.redisson.api.RedissonClient; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.context.ApplicationEventPublisher; |
| | |
| | | @Resource |
| | | private RedisTemplate<Object,Object> redisTemplate; |
| | | |
| | | @Autowired |
| | | private CouponService couponService; |
| | | |
| | | @Autowired |
| | | private CouponVirtualService couponVirtualService; |
| | | |
| | | @Autowired |
| | | private RedissonClient redissonClient; |
| | | |
| | | private final static String LOCK_ORDER_NO_MQ="lock_order_no_mq:"; |
| | | private final static String LOCK_EDIT_ORDER_ADDRESS="lock_edit_order_address:"; |
| | | private final static String LOCK_COUPON_CARD="lock_coupon_card:"; |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void intoDB(TradeDTO tradeDTO) { |
| | |
| | | //查询订单和自订单,然后写入vo返回 |
| | | return new OrderDetailVO(order, orderItems, orderLogs, receipt); |
| | | } |
| | | @Override |
| | | public OrderDetailVO queryEditAddressDetail(String orderSn) { |
| | | Order order = this.getBySn(orderSn); |
| | | if (order == null) { |
| | | throw new ServiceException(ResultCode.ORDER_NOT_EXIST); |
| | | } |
| | | //查询订单项信息 |
| | | List<OrderItem> orderItems = orderItemService.getByOrderSn(orderSn); |
| | | |
| | | //查询订单和自订单,然后写入vo返回 |
| | | return new OrderDetailVO(order, orderItems, null, null); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | |
| | | |
| | | return order; |
| | | } |
| | | @Override |
| | | @SystemLogPoint(description = "修改订单", customerLog = "'订单[' + #orderSn + ']收货信息修改,修改为'+#memberAddressDTO.consigneeDetail") |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Order updateAddressConsignee(String orderSn, MemberAddressDTO memberAddressDTO) { |
| | | Order order = this.getBySn(orderSn); |
| | | if (order == null) { |
| | | throw new ServiceException(ResultCode.ORDER_NOT_EXIST); |
| | | } |
| | | //限制30秒只能请求一次避免出现重新提交问题 |
| | | Boolean b = redisTemplate.opsForValue().setIfAbsent(LOCK_EDIT_ORDER_ADDRESS + orderSn, orderSn,30, TimeUnit.SECONDS); |
| | | if ( Boolean.FALSE.equals(b)){ |
| | | throw new ServiceException("请在30秒后重试"); |
| | | } |
| | | String modifyAddressFlag = order.getModifyAddressFlag(); |
| | | if (StringUtils.isNotBlank(modifyAddressFlag)) { |
| | | throw new ServiceException("当前订单已经被领取"); |
| | | } |
| | | QueryWrapper<Order> wrapper = new QueryWrapper<>(); |
| | | wrapper.eq("id", order.getId()); |
| | | // 使用 last 方法拼接 FOR UPDATE 语句 |
| | | wrapper.last("FOR UPDATE"); |
| | | baseMapper.selectOne(wrapper); |
| | | //要记录之前的收货地址,所以需要以代码方式进行调用 不采用注解 |
| | | String message = "订单[" + orderSn + "]收货信息修改,由[" +order.getConsigneeAddressPath()+ order.getConsigneeDetail() + "]修改为[" + memberAddressDTO.getConsigneeAddressPath()+ memberAddressDTO.getConsigneeDetail() + "]"; |
| | | //记录订单操作日志 |
| | | BeanUtil.copyProperties(memberAddressDTO, order); |
| | | order.setModifyAddressFlag(ModifyAddressEnums.USED.name()); |
| | | this.updateById(order); |
| | | OrderLog orderLog = new OrderLog(orderSn, UserContext.getCurrentUser().getId(), UserContext.getCurrentUser().getRole().getRole(), |
| | | UserContext.getCurrentUser().getUsername(), message); |
| | | orderLogService.save(orderLog); |
| | | |
| | | return order; |
| | | } |
| | | @Override |
| | | @OrderLogPoint(description = "'订单['+#orderSn+']发货,发货单号['+#logisticsNo+']'", orderSn = "#orderSn") |
| | | @Transactional(rollbackFor = Exception.class) |
| | |
| | | @OrderLogPoint(description = "'订单['+#orderSn+']核销,核销码['+#verificationCode+']'", orderSn = "#orderSn") |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Order take(String orderSn, String verificationCode) { |
| | | Order order; |
| | | RLock lock = redissonClient.getLock(LOCK_COUPON_CARD + orderSn); |
| | | try { |
| | | lock.lock(); |
| | | //获取订单信息 |
| | | order = this.getBySn(orderSn); |
| | | //订单幂等问题 |
| | | if (OrderStatusEnum.COMPLETED.name().equals(order.getOrderStatus())) { |
| | | throw new ServiceException("当前订单已完成无法再次核验"); |
| | | } |
| | | |
| | | //获取订单信息 |
| | | Order order = this.getBySn(orderSn); |
| | | //检测虚拟订单信息 |
| | | checkVerificationOrder(order, verificationCode); |
| | | order.setOrderStatus(OrderStatusEnum.COMPLETED.name()); |
| | | //订单完成 |
| | | this.complete(orderSn); |
| | | //检测虚拟订单信息 |
| | | checkVerificationOrder(order, verificationCode); |
| | | order.setOrderStatus(OrderStatusEnum.COMPLETED.name()); |
| | | //订单完成 |
| | | //获取所有的订单子项用于生成优惠卷订单信息 |
| | | List<OrderItem> orderItems = orderItemService.getByOrderSn(orderSn); |
| | | List<CouponVirtual> couponVirtuals = new ArrayList<>(); |
| | | for (OrderItem orderItem : orderItems) { |
| | | String couponId = orderItem.getCouponId(); |
| | | if (StringUtils.isBlank(couponId)) { |
| | | continue; |
| | | } |
| | | String storeId = order.getStoreId(); |
| | | Coupon one = couponService.getOne(Wrappers.<Coupon>lambdaQuery().eq(Coupon::getStoreId, storeId).eq(Coupon::getId, couponId)); |
| | | if (one == null) { |
| | | log.error("当前订单订单号为:{}不存在中的优惠卷不存在----------------------->{}",order.getId(),orderItem.getOrderSn()); |
| | | }else { |
| | | Integer num = orderItem.getNum(); |
| | | //当购买数量不为空的时候进行 |
| | | if (num != null) { |
| | | for (int i = 1; i <= num; i++) { |
| | | CouponVirtual couponVirtual = getCouponVirtual(orderItem); |
| | | couponVirtual.setCouponNo(String.format("%08d", i)); |
| | | couponVirtuals.add(couponVirtual); |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | | if (!couponVirtuals.isEmpty()) { |
| | | order.setCouponFlag(CouPonFlagEnum.COUPON.name()); |
| | | couponVirtualService.saveBatch(couponVirtuals); |
| | | //更新状态用于后续小程序判断弹出卷列表 |
| | | this.updateById(order); |
| | | } |
| | | this.complete(orderSn); |
| | | } finally { |
| | | assert lock != null; |
| | | if (lock.isHeldByCurrentThread()) { |
| | | lock.unlock(); |
| | | } |
| | | } |
| | | return order; |
| | | } |
| | | |
| | | private static CouponVirtual getCouponVirtual(OrderItem orderItem) { |
| | | CouponVirtual couponVirtual = new CouponVirtual(); |
| | | couponVirtual.setOrderId(orderItem.getOrderSn()); |
| | | couponVirtual.setCouponId(orderItem.getCouponId()); |
| | | couponVirtual.setCouponName(orderItem.getCouponName()); |
| | | couponVirtual.setGoodsId(orderItem.getGoodsId()); |
| | | couponVirtual.setSkuId(orderItem.getSkuId()); |
| | | couponVirtual.setItemOrderId(orderItem.getId()); |
| | | couponVirtual.setSkuName(orderItem.getGoodsName()); |
| | | couponVirtual.setName(orderItem.getCouponName()); |
| | | couponVirtual.setShareStatus(ShareStatusEnum.NOT_SHARE.name()); |
| | | couponVirtual.setClaimStatus(ClaimStatusEnum.NOT_CLAIM.name()); |
| | | return couponVirtual; |
| | | } |
| | | @Override |
| | | public Order take(String verificationCode) { |
| | | String storeId = OperationalJudgment.judgment(UserContext.getCurrentUser()).getStoreId(); |
| | |
| | | @ApiModelProperty(value = "有效期") |
| | | private Integer effectiveDays; |
| | | |
| | | @ApiModelProperty(value = "商品使用限制") |
| | | private Integer goodsUseLimitNum; |
| | | |
| | | public Coupon(CouponVO couponVO) { |
| | | BeanUtils.copyProperties(couponVO, this); |
| | | } |
| | |
| | | @ApiModelProperty(value = "会员优惠券状态") |
| | | private String memberCouponStatus; |
| | | |
| | | @ApiModelProperty(value = "商品使用限制") |
| | | private Integer goodsUseLimitNum; |
| | | public MemberCoupon() { |
| | | } |
| | | |
| | |
| | | setScopeType(coupon.getScopeType()); |
| | | setScopeId(coupon.getScopeId()); |
| | | setCouponType(coupon.getCouponType()); |
| | | setGoodsUseLimitNum(coupon.getGoodsUseLimitNum()); |
| | | setStartTime(coupon.getStartTime() == null ? new Date() : coupon.getStartTime()); |
| | | |
| | | setGetType(coupon.getGetType()); |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="cn.lili.modules.lmk.mapper.CouponVirtualMapper"> |
| | | |
| | | <!-- 通用查询映射结果 --> |
| | | <resultMap id="BaseResultMap" type="cn.lili.modules.lmk.domain.vo.CouponVirtualVO"> |
| | | <result column="order_id" property="orderId" /> |
| | | <result column="goods_id" property="goodsId" /> |
| | | <result column="sku_name" property="skuName" /> |
| | | <result column="coupon_id" property="couponId" /> |
| | | <result column="coupon_no" property="couponNo" /> |
| | | <result column="coupon_name" property="couponName" /> |
| | | <result column="name" property="name" /> |
| | | <result column="share_status" property="shareStatus" /> |
| | | <result column="claim_status" property="claimStatus" /> |
| | | <result column="update_time" property="updateTime" /> |
| | | <result column="create_by" property="createBy" /> |
| | | <result column="create_time" property="createTime" /> |
| | | <result column="update_by" property="updateBy" /> |
| | | <result column="delete_flag" property="deleteFlag" /> |
| | | <result column="original" property="original" /> |
| | | <result column="user_nickname" property="userNickName" /> |
| | | </resultMap> |
| | | |
| | | <select id="getById" resultMap="BaseResultMap"> |
| | | SELECT |
| | | LCV.order_id, |
| | | LCV.goods_id, |
| | | LCV.sku_name, |
| | | LCV.coupon_id, |
| | | LCV.coupon_no, |
| | | LCV.coupon_name, |
| | | LCV.name, |
| | | LCV.share_status, |
| | | LCV.claim_status, |
| | | LCV.update_time, |
| | | LCV.create_by, |
| | | LCV.create_time, |
| | | LCV.update_by, |
| | | LCV.delete_flag, |
| | | LCV.id |
| | | FROM |
| | | lmk_coupon_virtual LCV |
| | | WHERE |
| | | LCV.id = #{id} AND LCV.deleted = 0 |
| | | </select> |
| | | |
| | | |
| | | <select id="getPage" resultMap="BaseResultMap"> |
| | | SELECT |
| | | LCV.order_id, |
| | | LCV.goods_id, |
| | | LCV.sku_name, |
| | | LCV.coupon_id, |
| | | LCV.coupon_no, |
| | | LCV.coupon_name, |
| | | LCV.name, |
| | | LCV.share_status, |
| | | LCV.claim_status, |
| | | LCV.update_time, |
| | | LCV.create_by, |
| | | LCV.create_time, |
| | | LCV.update_by, |
| | | LCV.delete_flag, |
| | | LCV.user_nickname, |
| | | LCV.id, |
| | | LGS.original |
| | | FROM |
| | | lmk_coupon_virtual LCV JOIN li_goods_sku LGS ON LGS.id = LCV.sku_id |
| | | WHERE |
| | | LCV.delete_flag = 0 AND LGS.delete_flag = 0 |
| | | <if test="query.orderId != null and query.orderId !=''"> |
| | | AND LCV.order_id = #{query.orderId} |
| | | </if> |
| | | <if test="query.userNickName != null and query.userNickName !=''"> |
| | | AND LCV.user_nickname like CONCAT('%', #{query.userNickName}, '%') |
| | | </if> |
| | | <if test="query.skuName != null and query.skuName !=''"> |
| | | AND LCV.sku_name like CONCAT('%', #{query.skuName}, '%') |
| | | </if> |
| | | </select> |
| | | |
| | | |
| | | </mapper> |
| | |
| | | LV.delete_flag = 0 |
| | | AND LV.STATUS = '1' |
| | | AND LV.video_type = #{query.videoType} |
| | | AND lm.id IS NOT NULL |
| | | AND LM.id IS NOT NULL |
| | | UNION ALL |
| | | SELECT |
| | | LV.author_id, |
| | |
| | | LV.delete_flag = 0 |
| | | AND LV.STATUS = '1' |
| | | AND LV.video_type = #{query.videoType} |
| | | AND lm.id IS NOT NULL |
| | | AND LM.id IS NOT NULL |
| | | ORDER BY |
| | | create_time DESC |
| | | </select> |
| New file |
| | |
| | | package cn.lili.controller.lmk; |
| | | |
| | | |
| | | import cn.lili.base.Result; |
| | | import cn.lili.modules.lmk.domain.query.CouponVirtualQuery; |
| | | import cn.lili.modules.lmk.service.CouponVirtualService; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import lombok.RequiredArgsConstructor; |
| | | 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; |
| | | |
| | | /** |
| | | * lmk-shop-java |
| | | * |
| | | * @author : zxl |
| | | * @date : 2025-09-12 18:11 |
| | | **/ |
| | | @Validated |
| | | @RequiredArgsConstructor |
| | | @Api(value = "礼品卡包", tags = "礼品卡包") |
| | | @RestController |
| | | @RequestMapping("/manager/cardPack") |
| | | public class CardPackController { |
| | | private final CouponVirtualService couponVirtualService; |
| | | |
| | | @GetMapping |
| | | @ApiOperation(value = "列表", notes = "列表") |
| | | public Result getPage(CouponVirtualQuery query){ |
| | | //更具订单id查询 |
| | | return couponVirtualService.page(query); |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | import cn.lili.common.aop.annotation.PreventDuplicateSubmissions; |
| | | import cn.lili.common.enums.ResultUtil; |
| | | import cn.lili.common.utils.StringUtils; |
| | | import cn.lili.common.vo.ResultMessage; |
| | | import cn.lili.modules.order.aftersale.entity.dos.AfterSale; |
| | | import cn.lili.modules.order.aftersale.entity.vo.AfterSaleSearchParams; |
| | | import cn.lili.modules.order.aftersale.entity.vo.AfterSaleVO; |
| | | import cn.lili.modules.order.aftersale.mapper.AfterSaleMapper; |
| | | import cn.lili.modules.order.aftersale.service.AfterSaleService; |
| | | import cn.lili.modules.store.entity.dto.StoreAfterSaleAddressDTO; |
| | | import cn.lili.modules.system.entity.vo.Traces; |
| | | import cn.lili.utils.COSUtil; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.validation.constraints.NotNull; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | */ |
| | | @Autowired |
| | | private AfterSaleService afterSaleService; |
| | | @Autowired |
| | | private COSUtil cosUtil; |
| | | |
| | | @ApiOperation(value = "分页获取售后服务") |
| | | @GetMapping(value = "/page") |
| | | public ResultMessage<IPage<AfterSaleVO>> getByPage(AfterSaleSearchParams searchParams) { |
| | | return ResultUtil.data(afterSaleService.getAfterSalePages(searchParams)); |
| | | IPage<AfterSaleVO> afterSalePages = afterSaleService.getAfterSalePages(searchParams); |
| | | for (AfterSaleVO record : afterSalePages.getRecords()) { |
| | | if (StringUtils.isNotBlank(record.getGoodsImage())&&!record.getGoodsImage().contains("http")) { |
| | | record.setGoodsImage(cosUtil.getPreviewUrl(record.getGoodsImage())); |
| | | } |
| | | } |
| | | return ResultUtil.data(afterSalePages); |
| | | } |
| | | |
| | | @ApiOperation(value = "获取导出售后服务列表列表") |
| | |
| | | @ApiImplicitParam(name = "sn", value = "售后单号", required = true, paramType = "path") |
| | | @GetMapping(value = "/get/{sn}") |
| | | public ResultMessage<AfterSaleVO> get(@NotNull(message = "售后单号") @PathVariable("sn") String sn) { |
| | | return ResultUtil.data(afterSaleService.getAfterSale(sn)); |
| | | AfterSaleVO afterSale = afterSaleService.getAfterSale(sn); |
| | | String afterSaleImage = afterSale.getAfterSaleImage(); |
| | | if (StringUtils.isNotBlank(afterSaleImage)) { |
| | | String[] split = afterSaleImage.split(","); |
| | | List<String> asleImages = new ArrayList<>(split.length); |
| | | for (String s : split) { |
| | | if (!s.contains("http")){ |
| | | asleImages.add(cosUtil.getPreviewUrl(s)); |
| | | } |
| | | } |
| | | String join = String.join(",", asleImages); |
| | | afterSale.setAfterSaleImage(join); |
| | | } |
| | | if (StringUtils.isNotBlank(afterSale.getGoodsImage())&&!afterSale.getGoodsImage().contains("http")) { |
| | | afterSale.setGoodsImage(cosUtil.getPreviewUrl(afterSale.getGoodsImage())); |
| | | } |
| | | return ResultUtil.data(afterSale); |
| | | } |
| | | |
| | | @ApiOperation(value = "查看买家退货物流踪迹") |
| | |
| | | import cn.lili.common.enums.ResultUtil; |
| | | import cn.lili.common.security.AuthUser; |
| | | import cn.lili.common.security.context.UserContext; |
| | | import cn.lili.common.utils.StringUtils; |
| | | import cn.lili.common.vo.PageVO; |
| | | import cn.lili.common.vo.ResultMessage; |
| | | import cn.lili.modules.order.order.entity.dos.OrderComplaint; |
| | |
| | | import cn.lili.modules.order.order.entity.vo.OrderComplaintVO; |
| | | import cn.lili.modules.order.order.service.OrderComplaintCommunicationService; |
| | | import cn.lili.modules.order.order.service.OrderComplaintService; |
| | | import cn.lili.utils.COSUtil; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | |
| | | /** |
| | |
| | | @Autowired |
| | | private OrderComplaintCommunicationService orderComplaintCommunicationService; |
| | | |
| | | @Autowired |
| | | private COSUtil cosUtil; |
| | | @ApiOperation(value = "通过id获取") |
| | | @ApiImplicitParam(name = "id", value = "投诉单ID", required = true, paramType = "path") |
| | | @GetMapping(value = "/{id}") |
| | | public ResultMessage<OrderComplaintVO> get(@PathVariable String id) { |
| | | return ResultUtil.data(orderComplaintService.getOrderComplainById(id)); |
| | | OrderComplaintVO orderComplainById = orderComplaintService.getOrderComplainById(id); |
| | | String goodsImage = orderComplainById.getGoodsImage(); |
| | | if (StringUtils.isNotBlank(goodsImage)&&!goodsImage.contains("http")) { |
| | | orderComplainById.setGoodsImage(cosUtil.getPreviewUrl(goodsImage)); |
| | | } |
| | | String[] orderComplaintImages = orderComplainById.getOrderComplaintImages(); |
| | | List<String> orderComplaintImagesList = Arrays.asList(orderComplaintImages); |
| | | for (String orderComplaintImage : orderComplaintImages) { |
| | | if (StringUtils.isNotBlank(orderComplaintImage)&&!orderComplaintImage.contains("http")) { |
| | | orderComplaintImagesList.add(cosUtil.getPreviewUrl(orderComplaintImage)); |
| | | } |
| | | } |
| | | orderComplainById.setOrderComplaintImages(orderComplaintImagesList.toArray(new String[0])); |
| | | return ResultUtil.data(orderComplainById); |
| | | } |
| | | |
| | | @ApiOperation(value = "分页获取") |
| | |
| | | @ApiOperation(value = "新增商品") |
| | | @PostMapping(value = "/create", consumes = "application/json", produces = "application/json") |
| | | public ResultMessage<GoodsOperationDTO> save(@Valid @RequestBody GoodsOperationDTO goodsOperationDTO) { |
| | | |
| | | System.err.println(JSONObject.toJSONString(goodsOperationDTO)); |
| | | goodsService.addGoods(goodsOperationDTO); |
| | | return ResultUtil.success(); |
| | |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.validation.constraints.NotNull; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | |
| | |
| | | @GetMapping(value = "/{sn}") |
| | | public ResultMessage<AfterSaleVO> get(@PathVariable String sn) { |
| | | AfterSaleVO afterSale = OperationalJudgment.judgment(afterSaleService.getAfterSale(sn)); |
| | | String afterSaleImage = afterSale.getAfterSaleImage(); |
| | | if (StringUtils.isNotBlank(afterSaleImage)) { |
| | | String[] split = afterSaleImage.split(","); |
| | | List<String> asleImages = new ArrayList<>(split.length); |
| | | for (String s : split) { |
| | | if (!s.contains("http")){ |
| | | asleImages.add(cosUtil.getPreviewUrl(s)); |
| | | } |
| | | } |
| | | String join = String.join(",", asleImages); |
| | | afterSale.setAfterSaleImage(join); |
| | | } |
| | | if (StringUtils.isNotBlank(afterSale.getGoodsImage())&&!afterSale.getGoodsImage().contains("http")) { |
| | | afterSale.setGoodsImage(cosUtil.getPreviewUrl(afterSale.getGoodsImage())); |
| | | } |
| | | return ResultUtil.data(afterSale); |
| | | } |
| | | |