Merge remote-tracking branch 'origin/master'

This commit is contained in:
zjf committed 2025-11-03 18:30:07 +08:00
commit 207d90b48a
30 files changed
+443 -96

No files matched your search

+19 -22
View File
@@ -1,26 +1,23 @@
-- ----------------------------
-- Table structure for act_cancel
-- ----------------------------
DROP TABLE IF EXISTS act_cancel;
CREATE TABLE act_cancel
create table act_cancel
(
id bigint NOT NULL AUTO_INCREMENT COMMENT '活动项id',
mch_id bigint NOT NULL COMMENT '活动商户id',
notice_id bigint NOT NULL COMMENT '公告id',
active_org_price int DEFAULT NULL COMMENT '活动原价',
active_cancel_price int NOT NULL COMMENT '活动核销价',
expire_time datetime NOT NULL COMMENT '到期时间',
act_status char(32) NOT NULL COMMENT '活动状态(1:正常 2:关闭)',
act_title char(32) NOT NULL COMMENT '活动标题',
act_content char(32) DEFAULT NULL COMMENT '活动内容',
create_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
create_time datetime DEFAULT NULL COMMENT '创建时间',
update_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '修改人',
update_time datetime DEFAULT NULL COMMENT '修改时间',
del_flag char(1) COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标记',
tenant_id bigint DEFAULT NULL COMMENT '租户ID',
PRIMARY KEY (id)
) ENGINE = InnoDB COMMENT ='核销活动';
id BIGINT(19) auto_increment comment '活动项id'
primary key,
mch_id BIGINT(19) not null comment '活动商户id',
notice_id BIGINT(19) not null comment '公告id',
active_org_price INT(10) null comment '活动原价',
active_cancel_price INT(10) not null comment '活动核销价',
start_time DATETIME null comment '开始时间',
expire_time DATETIME not null comment '到期时间',
act_status CHAR(32) not null comment '活动状态(1:正常 2:关闭)',
act_title CHAR(32) not null comment '活动标题',
act_content CHAR(32) null comment '活动内容',
create_by VARCHAR(64) null comment '创建人',
create_time DATETIME null comment '创建时间',
update_by VARCHAR(64) null comment '修改人',
update_time DATETIME null comment '修改时间',
del_flag CHAR default '0' null comment '删除标记',
tenant_id BIGINT(19) null comment '租户ID'
);
-- ----------------------------
-- Table structure for act_cancel_item
@@ -28,7 +28,7 @@ public enum HardTypeEnum {
private final String description;
// 是否能预定
public static final List<HardTypeEnum> isReserveList = List.of(SUPERMARKET, CANTEEN);
public static final List<HardTypeEnum> isReserveList = List.of(SUPERMARKET, CANTEEN, FARMER);
// 不需要创建购物车
public static final List<HardTypeEnum> isNoneCar = List.of(MERCHANT_QR_CODE);
@@ -29,7 +29,7 @@ public enum HardOrderTypeEnum {
return Arrays.stream(values()).filter(v -> ObjectUtil.equals(type, v.getType())).findFirst().get();
}
public static final List<HardOrderTypeEnum> refundList = List.of(BELOW, RESERVE, FOREIGN_TICKET, ZY, LB);
public static final List<HardOrderTypeEnum> refundList = List.of(BELOW, RESERVE, FOREIGN_TICKET, ZY, LB, FARMER);
public static final List<HardOrderTypeEnum> payList = List.of(BELOW, RESERVE);
@@ -10,13 +10,9 @@ public class HardCreateActOrderDto {
@Schema(description = "活动类型")
private String actType;
@Schema(description = "活动id")
@NotNull(message = "活动id")
private Long actId;
@Schema(description = "总金额不能为空")
@NotNull(message = "总金额")
private Integer totalPrice;
@Schema(description = "核销id")
@NotNull(message = "核销id不能为空")
private Long cancelId;
@Schema(description = "核销用户id")
private Long cancelUserId;
@@ -19,7 +19,7 @@ public class HardAppCreateFarmerOrderDto {
@NotNull(message = "购物车id不能为空")
private Long carParentId;
@NotNull(message = "钱包类型id")
// @NotNull(message = "钱包类型id")
private Long walletTypeId;
@NotNull(message = "自提点id不能为空")
@@ -114,7 +114,7 @@ public class HardAfterSaleController {
@PostMapping(value = "/admin-reinforce-refund")
@Operation(summary = "后台强化退款")
@Idempotent(expireTime = 5, info = "正在退款中,请勿重复操作")
@Idempotent(expireTime = 5, key = "'/hard-after-sale/admin-reinforce-refund' + #dto.getOrderId() ", info = "正在退款中,请勿重复操作")
@PreAuthorize("@pms.hasPermission('hard_hardAfterSale_adminRefund')")
public R<Boolean> adminReinforceRefund(@RequestBody HardAdminRefundReinforceDto dto) {
PjcloudUser user = SecurityUtils.getUser();
@@ -135,6 +135,16 @@ public class HardOrderController {
return R.ok(hardwareOrderService.pagejoin(page, dto));
}
@Operation(summary = "app查询共富商城列表", description = "app查询共富商城列表")
@GetMapping("/app/farmer-page-join")
public R appFarmerPageJoin(@ParameterObject Page page, @ParameterObject HardOrderDto dto) {
PjcloudUser user = SecurityUtils.getUser();
dto.setUserId(user.getId());
dto.setIsFindCarList(true);
dto.setMchTypeCodes(List.of(MerchantTypeEnum.FARMER.getType()));
return R.ok(hardwareOrderService.pagejoin(page, dto));
}
@Operation(summary = "app商户查询订单列表", description = "app商户查询订单列表")
@GetMapping("/app/mch-page-join")
public R appMchPageJoin(@ParameterObject Page page, @ParameterObject HardOrderDto dto) {
@@ -165,7 +175,7 @@ public class HardOrderController {
@Operation(summary = "app创建食堂预定订单", description = "app创建食堂预定订单")
@GetMapping("/app/create-order")
@Idempotent(expireTime = 3, info = "正在创建订单中,请勿重复操作")
@Idempotent(expireTime = 3, key = "'/app/hard-order/app/create-order' + #carParentId ", info = "正在创建订单中,请勿重复操作")
public R appCreateOrder(@RequestParam Long carParentId, @RequestParam Long apptId, @RequestParam HardTypeEnum hardType) {
PjcloudUser user = SecurityUtils.getUser();
HardAppCreateOrderDto dto = HardAppCreateOrderDto.builder().carParentId(carParentId).walletType(WalletTypeEnum.EAT).hardType(hardType).userId(user.getId()).orderType(HardOrderTypeEnum.RESERVE).payType(HardPayTypeEnum.WALLET_DEFAULT).apptId(apptId).build();
@@ -174,7 +184,7 @@ public class HardOrderController {
@Operation(summary = "app创建线上超市预定订单", description = "app创建线上超市预定订单")
@GetMapping("/app/create-supermarket-order")
@Idempotent(expireTime = 3, info = "正在创建订单中,请勿重复操作")
@Idempotent(expireTime = 3, key = "'/app/hard-order/app/create-supermarket-order' + #carParentId ", info = "正在创建订单中,请勿重复操作")
public R<Long> appCreateSupermarketReserveOrder(@RequestParam Long carParentId, @RequestParam HardTypeEnum hardType) {
PjcloudUser user = SecurityUtils.getUser();
HardAppCreateOrderDto dto = HardAppCreateOrderDto.builder()
@@ -220,7 +230,7 @@ public class HardOrderController {
@Operation(summary = "app创建活动订单", description = "app创建活动订单")
@PostMapping("/app/create-act-order")
@Idempotent(expireTime = 5, info = "正在创建订单中,请勿重复操作")
@Idempotent(expireTime = 3, key = "'/hard-order/app/create-act-order' + #body.getCancelId() ", info = "正在创建订单中,请勿重复操作")
public R<Long> appCreateActOrder(@Validated @RequestBody HardCreateActOrderDto body) {
PjcloudUser user = SecurityUtils.getUser();
body.setCancelUserId(user.getId());
@@ -239,6 +239,37 @@ public class HardCarServiceImpl extends ServiceImpl<HardCarMapper, HardCarEntity
}
yield doorTotalPrice.get();
}
case FARMER -> {
AtomicInteger doorTotalPrice = new AtomicInteger();
List<MallProductDetailAppVo> spuList = remoteMallProductService.getSkusWithSpuBySkuIds(productIds).getData();
for (HardCreateCarDto v : list) {
spu:
for (MallProductDetailAppVo spu : spuList) {
if (ObjectUtil.isEmpty(spu) || ObjectUtil.isEmpty(spu.getSkuList())) {
continue spu;
}
MallProductSkuAppVo sku = spu.getSkuList().stream().filter(_item -> ObjectUtil.equals(_item.getId(), v.getProductId())).findFirst().orElse(null);
if (ObjectUtil.isEmpty(sku)) {
continue spu;
}
if (ObjectUtil.isEmpty(spu.getSkuList())) {
throw new RuntimeException("共富商城商品无SKU信息商品名字:" + spu.getTitle() + "商品ID:" + spu.getId() + "请联系管理员");
}
Integer price = sku.getPrice();
if (ObjectUtil.isNotEmpty(v.getProductCount()) && !ObjectUtil.equals(v.getProductCount(), 0)) {
// 按数量
int itemTotalPrice = v.getProductCount() * price;
doorTotalPrice.addAndGet(itemTotalPrice);
} else if (ObjectUtil.isNotEmpty(v.getProductWeight()) && v.getProductWeight().compareTo(BigDecimal.valueOf(0)) != 0) {
// 按重量
// 向上取整
int itemTotalPrice = v.getProductWeight().multiply(BigDecimal.valueOf(price)).setScale(0, RoundingMode.CEILING).intValue();
doorTotalPrice.addAndGet(itemTotalPrice);
}
}
}
yield doorTotalPrice.get();
}
default -> null;
};
}
@@ -452,8 +483,10 @@ public class HardCarServiceImpl extends ServiceImpl<HardCarMapper, HardCarEntity
item.setProductPrice(price);
item.setProductPic(spu.getCoverImage());
item.setTotalPrice((long) totalPrice);
if (ObjectUtil.isNotEmpty(v.getProductNature())) {
item.setProductNature(v.getProductNature().getType());
if (ObjectUtil.isNotEmpty(spu.getProductNature())) {
item.setProductNature(spu.getProductNature());
} else {
item.setProductNature(HardProductNatureEnum.DEFAULT.getType());
}
item.setProductCount(v.getProductCount());
item.setProductWeight(v.getProductWeight());
@@ -511,17 +544,22 @@ public class HardCarServiceImpl extends ServiceImpl<HardCarMapper, HardCarEntity
}
// 共富商城
if (ObjectUtil.equals(sysType, HardTypeEnum.FARMER)) {
List<MallProductDetailAppVo> supList = remoteMallProductService.getDetailByIds(productIds).getData();
List<MallProductDetailAppVo> spuList = remoteMallProductService.getSkusWithSpuBySkuIds(productIds).getData();
for (HardCreateCarDto v : list) {
supList.stream().filter(i -> ObjectUtil.equals(i.getId(), v.getProductId())).findFirst().ifPresent(spu -> {
str.append(spu.getTitle()).append("x");
if (ObjectUtil.equals(spu.getProductNature(), HardProductNatureEnum.DEFAULT.getType())) {
str.append(v.getProductCount());
} else if (ObjectUtil.equals(spu.getProductNature(), HardProductNatureEnum.WEIGHT.getType())) {
str.append(v.getProductWeight()).append("/kg");
spu:
for (MallProductDetailAppVo spu : spuList) {
if (ObjectUtil.isEmpty(spu) || ObjectUtil.isEmpty(spu.getSkuList())) {
continue spu;
}
str.append(";");
});
MallProductSkuAppVo sku = spu.getSkuList().stream().filter(_item -> ObjectUtil.equals(_item.getId(), v.getProductId())).findFirst().orElse(null);
if (ObjectUtil.isEmpty(sku)) {
continue spu;
}
if (ObjectUtil.isEmpty(spu.getSkuList())) {
throw new RuntimeException("共富商城商品无SKU信息商品名字:" + spu.getTitle() + "商品ID:" + spu.getId() + "请联系管理员");
}
str.append(spu.getTitle()).append("/").append(sku.getSkuName()).append("x").append(v.getProductCount()).append(";");
}
}
}
return str.toString();
@@ -92,6 +92,7 @@ import com.bsd.pjcloud.wallet.api.utils.WalletDataUtil;
import com.bsd.pjcloud.wallet.api.vo.MchManageVo;
import com.bsd.pjcloud.wallet.api.vo.WalletManageVo;
import com.bsd.pjcloud.wallet.api.vo.WalletSettingVo;
import com.bsd.pjcloud.wallet.api.vo.act.ActCancelItemVo;
import com.bsd.pjcloud.wallet.api.vo.mch.MchPickUpVo;
import com.bsd.pjcloud.wallet.api.vo.mch.MchRuleJoinDtoVo;
import jakarta.validation.Valid;
@@ -645,7 +646,12 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
UserInfo userDetail = userService.getInnerByUserId(dto.getUserId()).getData();
if (ObjectUtil.isEmpty(userDetail)) throw new RuntimeException("用户不存在不存在");
// 钱包
WalletManageEntity wallet = remoteWalletService.getWalletByWalletTypeId(dto.getUserId(), dto.getWalletTypeId()).getData();
WalletManageEntity wallet = null;
if (ObjectUtil.isEmpty(dto.getWalletTypeId())) {
wallet = remoteWalletService.getWallet(dto.getUserId(), WalletTypeEnum.PAY).getData();
} else {
wallet = remoteWalletService.getWalletByWalletTypeId(dto.getUserId(), dto.getWalletTypeId()).getData();
}
if (ObjectUtil.isEmpty(wallet)) throw new RuntimeException("用户钱包不存在");
// 查询父订单
HardParentCarEntity parentCar = hardCarService.getParentCarById(dto.getCarParentId());
@@ -764,16 +770,18 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
* 创建活动订单
*/
@Override
@Lock4j(keys = {"#dto.getActId()"})
@Transactional(rollbackFor = Exception.class)
public Long appCreateActOrder(HardCreateActOrderDto dto) {
if (ObjectUtil.isEmpty(dto.getCancelUserId())) throw new RuntimeException("核销用户不能为空");
// 查询活动详情
ActCancelItemEntity actDetail = remoteActCancelService.getDetail(dto.getActId()).getData();
ActCancelItemVo actDetail = remoteActCancelService.getDetail(dto.getCancelId()).getData();
if (ObjectUtil.isEmpty(actDetail)) throw new RuntimeException("活动不存在");
if (ObjectUtil.isNotEmpty(actDetail.getExpireTime())) {
if (actDetail.getExpireTime().isBefore(LocalDateTime.now())) {
throw new RuntimeException("核销失败,您领取的优惠券已过期");
if (actDetail.getActExpireTime().isBefore(LocalDateTime.now())) {
throw new RuntimeException("核销失败,活动已结束");
}
if (actDetail.getActStartTime().isAfter(LocalDateTime.now())) {
throw new RuntimeException("核销失败,活动未开始");
}
}
if (ObjectUtil.equals(actDetail.getActStatus(), ActCancelStatusEnum.CANCEL_SUCCESS.getCode())) {
@@ -804,7 +812,7 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
WalletManageEntity wallet = remoteWalletService.getWallet(userDetail.getSysUser().getUserId(), WalletTypeEnum.PAY).getData();
if (ObjectUtil.isEmpty(wallet)) throw new RuntimeException("用户钱包不存在");
Integer balance = wallet.getBalance();
int totalPrice = 1 * 100;
int totalPrice = actDetail.getActiveCancelPrice();
String subject = "活动商品x?";
if (balance < totalPrice) throw new RuntimeException("钱包余额不足");
@@ -820,7 +828,7 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
.orderStatus(HardOrderStatusEnum.CREATE.getType())
.orderType(HardOrderTypeEnum.RESERVE.getType())
.payType(HardPayTypeEnum.ACT_CANCEL.getType())
.orderSourceTypeId(dto.getActId())
.orderSourceTypeId(dto.getCancelId())
.totalPrice(totalPrice)
.extraPrice(0)
.payPrice(totalPrice)
@@ -831,7 +839,7 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
baseMapper.insert(orderObj);
// 核销
ActCancelItemDto cancelDto = new ActCancelItemDto();
cancelDto.setActId(dto.getActId());
cancelDto.setId(dto.getCancelId());
cancelDto.setCancelUserId(dto.getCancelUserId());
R<Boolean> cancelVo = remoteActCancelService.cancel(cancelDto);
if (ObjectUtil.notEqual(cancelVo.getCode(), CommonConstants.SUCCESS)) {
@@ -1136,6 +1144,10 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
if (ObjectUtil.equals(hardTypeEnum, HardTypeEnum.SUPERMARKET) && ObjectUtil.equals(orderTypeEnum, HardOrderTypeEnum.RESERVE)) {
codeType = WalletCodeBizEnum.SUPERMARKET_RESERVE;
}
// 共富商城预定核销
if (ObjectUtil.equals(hardTypeEnum, HardTypeEnum.FARMER) && ObjectUtil.equals(orderTypeEnum, HardOrderTypeEnum.FARMER)) {
codeType = WalletCodeBizEnum.FARMER_RESERVE;
}
if (ObjectUtil.isEmpty(codeType)) return;
R<Boolean> res = remoteCodeUseService.generateCode(order.getId(), order.getUserId(), codeType, 1);
if (res.getCode() != 0 || !res.getData()) {
@@ -1455,7 +1467,8 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
private Boolean isHaveCode(HardOrderEntity order) {
HardOrderTypeEnum orderTypeEnum = HardOrderTypeEnum.valueOfByType(order.getOrderType());
if (ObjectUtil.isEmpty(orderTypeEnum)) return false;
if (!ObjectUtil.equals(HardOrderTypeEnum.RESERVE, orderTypeEnum)) {
List<HardOrderTypeEnum> typeList = List.of(HardOrderTypeEnum.RESERVE, HardOrderTypeEnum.FARMER);
if (!typeList.contains(orderTypeEnum)) {
return false;
}
HardTypeEnum hardTypeEnum = HardTypeEnum.valueOfByType(order.getSysType());
@@ -187,8 +187,8 @@ public class HardSpuServiceImpl extends ServiceImpl<HardSpuMapper, HardSpuEntity
if (ObjectUtil.isNotEmpty(v.getKsSkuId())) {
KsSkuDeleteDto dto = new KsSkuDeleteDto();
dto.setKs_sku_id(v.getKsSkuId());
KsSkuDeleteVo data = remoterThirdKsService.skuDelete(dto).getData();
if (ObjectUtil.isEmpty(data) || !data.isSuccess()) throw new RuntimeException(data.getMessage());
// KsSkuDeleteVo data = remoterThirdKsService.skuDelete(dto).getData();
// if (ObjectUtil.isEmpty(data) || !data.isSuccess()) throw new RuntimeException(data.getMessage());
}
}
baseMapper.deleteByIds(list);
@@ -83,7 +83,7 @@
<if test="dto.spuCategoryIdIsNotNull != null ">
<if test="dto.spuCategoryIdIsNotNull == true ">
and a.spu_category_id is not null
and a.ks_status = 5
and a.ks_status in ('5','2')
</if>
</if>
<if test="dto.status != null and dto.status != '' ">
@@ -14,6 +14,7 @@ public enum WalletCodeBizEnum {
CANTEEN_RESERVE("3", "食堂线上预订"),
SUPERMARKET_RESERVE("4", "超市线上预订"),
USER_WALLET("5", "用户钱包二维码"),
FARMER_RESERVE("6", "用户钱包二维码"),
;
private final String code;
@@ -3,7 +3,10 @@ package com.bsd.pjcloud.wallet.api.dto.act;
import com.bsd.pjcloud.wallet.api.entity.act.ActCancelEntity;
import lombok.Data;
import java.util.List;
@Data
public class ActCancelDto extends ActCancelEntity {
}
@@ -4,10 +4,15 @@ import com.bsd.pjcloud.wallet.api.entity.act.ActCancelItemEntity;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class ActCancelItemDto extends ActCancelItemEntity {
private List<Long> actIdList;
private List<Long> mchIdList;
private LocalDateTime[] cancelTimeList;
}
@@ -51,6 +51,12 @@ public class ActCancelEntity extends Model<ActCancelEntity> {
@Schema(description = "活动核销价")
private Integer activeCancelPrice;
/**
* 开始时间
*/
@Schema(description = "开始时间")
private LocalDateTime startTime;
/**
* 到期时间
*/
@@ -5,6 +5,7 @@ import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.feign.annotation.NoToken;
import com.bsd.pjcloud.wallet.api.dto.act.ActCancelItemDto;
import com.bsd.pjcloud.wallet.api.entity.act.ActCancelItemEntity;
import com.bsd.pjcloud.wallet.api.vo.act.ActCancelItemVo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@@ -17,7 +18,7 @@ public interface RemoteActCancelService {
@NoToken
@GetMapping("/act/cancel-item/get-detail")
R<ActCancelItemEntity> getDetail(@RequestParam Long id);
R<ActCancelItemVo> getDetail(@RequestParam Long cancelId);
@NoToken
@PostMapping("/act/cancel-item/cancel")
@@ -0,0 +1,25 @@
package com.bsd.pjcloud.wallet.api.vo.act;
import lombok.Data;
@Data
public class ActCancelItemCountVo {
private Long actId;
/**
* 预约总数
*/
private Long totalCount;
/**
* 核销总数
*/
private Long cancelCount;
/**
* 未核销总数
*/
private Long cancelAwaitCount;
}
@@ -3,6 +3,8 @@ package com.bsd.pjcloud.wallet.api.vo.act;
import com.bsd.pjcloud.wallet.api.entity.act.ActCancelItemEntity;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class ActCancelItemVo extends ActCancelItemEntity {
@@ -21,4 +23,24 @@ public class ActCancelItemVo extends ActCancelItemEntity {
*/
private String mchName;
/**
* 活动核销价格
*/
private Integer activeCancelPrice;
/**
* 活动名称
*/
private String actTitlel;
/**
* 活动开始时间
*/
private LocalDateTime actStartTime;
/**
* 活动结束时间
*/
private LocalDateTime actExpireTime;
}
@@ -18,4 +18,9 @@ public class ActCancelVo extends ActCancelEntity implements BaseMchInterface {
private String merchantType;
/**
* 统计相关
*/
private ActCancelItemCountVo countVo;
}
@@ -7,6 +7,7 @@ import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import com.bsd.pjcloud.wallet.api.dto.act.ActCancelDto;
import com.bsd.pjcloud.wallet.api.entity.act.ActCancelEntity;
import com.bsd.pjcloud.wallet.api.vo.act.ActCancelVo;
import com.bsd.pjcloud.wallet.service.ActCancelService;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
@@ -30,10 +31,27 @@ public class ActCancelController {
private final ActCancelService actCancelService;
/* ************************************* start app start ************************************* */
@Operation(summary = "根据公告id查询活动", description = "根据公告id查询活动")
@GetMapping("/app/detail-by-notice-id")
public R<ActCancelEntity> getDetailByNoticeId(@RequestParam Long id) {
return R.ok(actCancelService.getDetailByNoticeId(id));
}
@Operation(summary = "根据活动id查询核销活动", description = "根据活动id查询核销活动")
@GetMapping("/app/detail-by-id")
public R<ActCancelEntity> getDetailById(@RequestParam Long id) {
return R.ok(actCancelService.getDetailById(id));
}
/* ************************************* end app end ************************************* */
@Operation(summary = "分页查询", description = "分页查询")
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('wallet_actCancel_view')")
public R getActCancelPage(@ParameterObject Page page, @ParameterObject ActCancelDto dto) {
public R<Page<ActCancelVo>> getActCancelPage(@ParameterObject Page page, @ParameterObject ActCancelDto dto) {
return R.ok(actCancelService.scopePageJoin(page, dto, DataScope.of()));
}
@@ -1,8 +1,7 @@
package com.bsd.pjcloud.wallet.controller.act;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.idempotent.annotation.Idempotent;
@@ -35,13 +34,11 @@ public class ActCancelItemController {
private final ActCancelItemService actCancelItemService;
/* ************************************* start 远程调用 start ************************************* */
@Inner()
@Operation(summary = "查询优惠券详情", description = "查询优惠券详情")
@GetMapping("/get-detail")
public R<ActCancelItemEntity> getDetail(@RequestParam Long id) {
return R.ok(actCancelItemService.getById(id));
public R<ActCancelItemVo> getDetail(@RequestParam Long cancelId) {
return R.ok(actCancelItemService.getDetail(cancelId));
}
@Inner()
@@ -59,15 +56,17 @@ public class ActCancelItemController {
@PostMapping("/app/get")
@Idempotent(expireTime = 2, key = "'/act/cancel/app/get/' + #dto.getReceiverUserId()", info = "正在领取中,请勿重复操作")
public R<Long> appGet(@RequestBody ActCancelItemDto dto) {
if (ObjectUtil.isEmpty(dto.getActId())) throw new RuntimeException("活动id不能为空");
if (ObjectUtil.isEmpty(dto.getMchId())) throw new RuntimeException("商户id不能为空");
PjcloudUser user = SecurityUtils.getUser();
return R.ok(actCancelItemService.appGet(user, dto));
}
@Operation(summary = "app查询用户的唯一优惠券", description = "app查询用户的唯一优惠券")
@GetMapping("/app/find-unique")
public R<ActCancelItemVo> appFindUnique() {
public R<ActCancelItemVo> appFindUnique(@RequestParam Long actId) {
PjcloudUser user = SecurityUtils.getUser();
return R.ok(actCancelItemService.appFindUnique(user));
return R.ok(actCancelItemService.appFindUnique(actId, user));
}
@Operation(summary = "app查询本店优惠券列表", description = "app查询本店优惠券列表")
@@ -1,11 +1,18 @@
package com.bsd.pjcloud.wallet.mapper.act;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import com.bsd.pjcloud.wallet.api.dto.act.ActCancelDto;
import com.bsd.pjcloud.wallet.api.dto.act.ActCancelItemDto;
import com.bsd.pjcloud.wallet.api.entity.act.ActCancelItemEntity;
import com.bsd.pjcloud.wallet.api.vo.act.ActCancelItemCountVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface ActCancelItemMapper extends PjcloudBaseMapper<ActCancelItemEntity> {
List<ActCancelItemCountVo> count(@Param("dto") ActCancelItemDto dto);
}
@@ -14,6 +14,6 @@ import java.util.List;
@Mapper
public interface ActCancelMapper extends PjcloudBaseMapper<ActCancelEntity> {
List<ActCancelVo> scopePageJoin(Page page, @Param("dto") ActCancelDto dto, DataScope dataScope);
Page<ActCancelVo> scopePageJoin(Page page, @Param("dto") ActCancelDto dto, DataScope dataScope);
}
@@ -20,7 +20,7 @@ public interface ActCancelItemService extends IService<ActCancelItemEntity> {
/**
* 查询用户的唯一优惠券
*/
ActCancelItemVo appFindUnique(PjcloudUser user);
ActCancelItemVo appFindUnique(Long actId, PjcloudUser user);
/**
* app查询本店优惠券列表
@@ -31,4 +31,9 @@ public interface ActCancelItemService extends IService<ActCancelItemEntity> {
* 核销
*/
Boolean cancel(ActCancelItemDto dto);
/**
* 查询详情
*/
ActCancelItemVo getDetail(Long cancelId);
}
@@ -15,13 +15,23 @@ public interface ActCancelService extends IService<ActCancelEntity> {
/**
* 分页查询
*/
List<ActCancelVo> scopePageJoin(Page page, ActCancelDto dto, DataScope dataScope);
Page<ActCancelVo> scopePageJoin(Page page, ActCancelDto dto, DataScope dataScope);
/**
* 新增
*/
Long create(ActCancelDto dto);
/**
* 根据公告id查询核销活动
*/
ActCancelEntity getDetailByNoticeId(Long noticeId);
/**
* 根据活动id查询核销活动
*/
ActCancelEntity getDetailById(Long id);
/**
* 根据ids删除
*/
@@ -100,6 +100,10 @@ public class WalletCodeUseServiceImpl extends ServiceImpl<WalletCodeUseMapper, W
orderType = HardOrderTypeEnum.RESERVE;
payType = HardPayTypeEnum.RESERVE_QR_CODE;
}
if (biz == WalletCodeBizEnum.FARMER_RESERVE) {
orderType = HardOrderTypeEnum.FARMER;
payType = HardPayTypeEnum.WALLET_DEFAULT;
}
for (int i = 0; i < count; i++) {
WalletCodeUseEntity item = WalletCodeUseEntity.builder().bizId(id).userId(userId).bizType(biz.getCode()).build();
int insert = baseMapper.insert(item);
@@ -1,6 +1,7 @@
package com.bsd.pjcloud.wallet.service.impl.act;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -10,18 +11,21 @@ import com.bsd.pjcloud.admin.api.feign.RemoteUserService;
import com.bsd.pjcloud.admin.api.vo.UserVO;
import com.bsd.pjcloud.common.core.constant.CommonRoleConstant;
import com.bsd.pjcloud.common.core.constant.enums.MerchantTypeEnum;
import com.bsd.pjcloud.common.core.util.BeanUtils;
import com.bsd.pjcloud.common.core.util.CollectionUtils;
import com.bsd.pjcloud.common.data.resolver.ParamResolver;
import com.bsd.pjcloud.common.security.service.PjcloudUser;
import com.bsd.pjcloud.wallet.api.constant.WalletTypeEnum;
import com.bsd.pjcloud.wallet.api.constant.act.ActCancelStatusEnum;
import com.bsd.pjcloud.wallet.api.constant.act.ActStatusEnum;
import com.bsd.pjcloud.wallet.api.dto.act.ActCancelItemDto;
import com.bsd.pjcloud.wallet.api.entity.WalletManageEntity;
import com.bsd.pjcloud.wallet.api.entity.act.ActCancelEntity;
import com.bsd.pjcloud.wallet.api.entity.act.ActCancelItemEntity;
import com.bsd.pjcloud.wallet.api.entity.mch.MchManageEntity;
import com.bsd.pjcloud.wallet.api.vo.MchManageVo;
import com.bsd.pjcloud.wallet.api.vo.act.ActCancelItemVo;
import com.bsd.pjcloud.wallet.mapper.act.ActCancelItemMapper;
import com.bsd.pjcloud.wallet.mapper.act.ActCancelMapper;
import com.bsd.pjcloud.wallet.service.ActCancelItemService;
import com.bsd.pjcloud.wallet.service.MchManageService;
import com.bsd.pjcloud.wallet.service.WalletManageService;
@@ -29,6 +33,8 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
@@ -48,11 +54,14 @@ public class ActCancelItemServiceImpl extends ServiceImpl<ActCancelItemMapper, A
private final MchManageService mchManageService;
private final WalletManageService walletManageService;
private final ActCancelMapper actCancelMapper;
private final RemoteUserService remoteUserService;
@Override
public Page<ActCancelItemVo> pageList(Page page, ActCancelItemDto dto) {
Page<ActCancelItemVo> pageList = baseMapper.selectPage(page, new LambdaQueryWrapper<ActCancelItemEntity>()
.eq(ObjectUtil.isNotEmpty(dto.getActId()), ActCancelItemEntity::getActId, dto.getActId())
.eq(ObjectUtil.isNotEmpty(dto.getMchId()), ActCancelItemEntity::getMchId, dto.getMchId())
.eq(ObjectUtil.isNotEmpty(dto.getReceiverUserId()), ActCancelItemEntity::getReceiverUserId, dto.getReceiverUserId())
.like(ObjectUtil.isNotEmpty(dto.getReceiverUserName()), ActCancelItemEntity::getReceiverUserName, dto.getReceiverUserName())
@@ -109,6 +118,24 @@ public class ActCancelItemServiceImpl extends ServiceImpl<ActCancelItemMapper, A
}
}
}
List<Long> actIds = list.stream().map(ActCancelItemVo::getActId).distinct().filter(ObjectUtil::isNotEmpty).toList();
if (ObjectUtil.isNotEmpty(actIds)) {
// 活动信息
List<ActCancelEntity> actList = actCancelMapper.selectList(new LambdaQueryWrapper<ActCancelEntity>()
.in(ActCancelEntity::getId, actIds)
);
if (ObjectUtil.isNotEmpty(actList)) {
Map<Long, ActCancelEntity> actMap = CollectionUtils.convertMap(actList, ActCancelEntity::getId);
for (ActCancelItemVo item : list) {
ActCancelEntity act = actMap.get(item.getActId());
if (ObjectUtil.isNotEmpty(act)) {
item.setActTitlel(act.getActTitle());
item.setActExpireTime(act.getExpireTime());
item.setActStartTime(act.getStartTime());
}
}
}
}
}
/**
@@ -116,30 +143,40 @@ public class ActCancelItemServiceImpl extends ServiceImpl<ActCancelItemMapper, A
*/
@Override
public Long appGet(PjcloudUser user, ActCancelItemDto dto) {
// 获取商户
MchManageEntity actMch = null;
try {
Long mchId = ParamResolver.getLong("ACT_CANCEL_MCH_ID");
if (ObjectUtil.isEmpty(mchId)) throw new Exception("活动商户id为空");
actMch = mchManageService.getById(mchId);
} catch (Exception e) {
e.printStackTrace();
log.error("|{}|获取商户ID失败,error:|{}|", TAG, e.getMessage());
// 查询活动
ActCancelEntity act = actCancelMapper.selectById(dto.getActId());
if (ObjectUtil.isEmpty(act)) throw new RuntimeException("核销活动不存在");
if (ObjectUtil.equals(act.getActStatus(), ActStatusEnum.ACT_CANCEL.getCode())) {
throw new RuntimeException("核销活动已关闭");
}
// 判断是否在时间内
LocalDateTime now = LocalDateTime.now();
if (act.getExpireTime().isBefore(LocalDateTime.now())) {
throw new RuntimeException("核销失败,活动已结束");
}
if (act.getStartTime().isAfter(LocalDateTime.now())) {
throw new RuntimeException("核销失败,活动未开始");
}
// 获取商户
MchManageEntity actMch = mchManageService.getById(dto.getMchId());
if (ObjectUtil.isEmpty(actMch)) throw new RuntimeException("核销活动商户不存在");
// 判断是否已经领取
if (existAct(user.getId())) throw new RuntimeException("您已经领,请勿重复领取");
if (existAct(user.getId(), dto.getActId())) throw new RuntimeException("您已经领,请勿重复领取");
// 查询余是否大于1元
// 查询余是否大于核销价格
WalletManageEntity wallet = walletManageService.getWallet(user.getId(), WalletTypeEnum.PAY);
if (wallet.getBalance() < 100) throw new RuntimeException("消费钱包余额不足1元,无法领取");
String cancelPrice = new BigDecimal(act.getActiveCancelPrice()).divide(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP).toString();
if (wallet.getBalance() < act.getActiveCancelPrice()) {
throw new RuntimeException("消费钱包余额不足" + cancelPrice + "元,无法领取");
}
LocalDateTime now = LocalDateTime.now();
LocalDateTime expireTime = now.plusDays(90);
LocalDateTime expireTime = act.getExpireTime();
ActCancelItemEntity saveObj = new ActCancelItemEntity();
saveObj.setActId(-1L);
saveObj.setActId(dto.getActId());
saveObj.setMchId(actMch.getId());
saveObj.setReceiverUserId(user.getId());
saveObj.setReceiverUserName(user.getName());
@@ -154,17 +191,24 @@ public class ActCancelItemServiceImpl extends ServiceImpl<ActCancelItemMapper, A
* 查询用户的唯一优惠券
*/
@Override
public ActCancelItemVo appFindUnique(PjcloudUser user) {
public ActCancelItemVo appFindUnique(Long actId, PjcloudUser user) {
// 查询活动
ActCancelEntity act = actCancelMapper.selectById(actId);
if (ObjectUtil.isEmpty(act)) throw new RuntimeException("核销活动不存在");
ActCancelItemEntity detail = baseMapper.selectOne(new LambdaQueryWrapper<ActCancelItemEntity>()
.eq(ActCancelItemEntity::getActId, actId)
.eq(ActCancelItemEntity::getReceiverUserId, user.getId())
);
if (ObjectUtil.isEmpty(detail)) throw new RuntimeException("您未领取优惠券,请前往领取");
if (ObjectUtil.isEmpty(detail)) return null;
if (ObjectUtil.isNotEmpty(detail.getExpireTime())) {
if (detail.getExpireTime().isBefore(LocalDateTime.now())) {
throw new RuntimeException("您领取的优惠券已过期");
}
}
return BeanUtil.toBean(detail, ActCancelItemVo.class);
ActCancelItemVo result = BeanUtil.toBean(detail, ActCancelItemVo.class);
result.setActTitlel(act.getActTitle());
result.setActExpireTime(act.getExpireTime());
return result;
}
/**
@@ -192,12 +236,12 @@ public class ActCancelItemServiceImpl extends ServiceImpl<ActCancelItemMapper, A
*/
@Override
public Boolean cancel(ActCancelItemDto dto) {
if (ObjectUtil.isEmpty(dto.getActId()) || ObjectUtil.isEmpty(dto.getCancelUserId())) {
if (ObjectUtil.isEmpty(dto.getId()) || ObjectUtil.isEmpty(dto.getCancelUserId())) {
log.error("|{}|核销失败,参数错误", TAG);
return false;
}
// 查询活动
ActCancelItemEntity detail = baseMapper.selectById(dto.getActId());
ActCancelItemEntity detail = baseMapper.selectById(dto.getId());
if (ObjectUtil.isEmpty(detail)) {
log.error("|{}|核销失败,活动不存在", TAG);
return false;
@@ -225,10 +269,32 @@ public class ActCancelItemServiceImpl extends ServiceImpl<ActCancelItemMapper, A
return true;
}
/**
* 查询详情
*/
@Override
public ActCancelItemVo getDetail(Long cancelId) {
ActCancelItemVo result = new ActCancelItemVo();
ActCancelItemEntity detail = baseMapper.selectOne(new LambdaQueryWrapper<ActCancelItemEntity>()
.eq(ActCancelItemEntity::getId, cancelId)
);
if (ObjectUtil.isEmpty(detail)) return null;
result = BeanUtils.toBean(detail, ActCancelItemVo.class);
// 查询活动
ActCancelEntity actDetail = actCancelMapper.selectById(detail.getActId());
if (ObjectUtil.isNotEmpty(actDetail)) {
result.setActiveCancelPrice(actDetail.getActiveCancelPrice());
}
result.setActStartTime(actDetail.getStartTime());
result.setActExpireTime(actDetail.getExpireTime());
return result;
}
// 判断车牌号是否重复
private boolean existAct(Long userId) {
private boolean existAct(Long userId, Long actId) {
Long count = baseMapper.selectCount(new LambdaQueryWrapper<ActCancelItemEntity>()
.eq(ObjectUtil.isNotEmpty(userId), ActCancelItemEntity::getReceiverUserId, userId)
.eq(ObjectUtil.isNotEmpty(actId), ActCancelItemEntity::getActId, actId)
);
return count > 0;
}
@@ -1,5 +1,6 @@
package com.bsd.pjcloud.wallet.service.impl.act;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -8,8 +9,11 @@ import com.bsd.pjcloud.common.core.util.BeanUtils;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.wallet.api.constant.act.ActStatusEnum;
import com.bsd.pjcloud.wallet.api.dto.act.ActCancelDto;
import com.bsd.pjcloud.wallet.api.dto.act.ActCancelItemDto;
import com.bsd.pjcloud.wallet.api.entity.WalletTypeEntity;
import com.bsd.pjcloud.wallet.api.entity.act.ActCancelEntity;
import com.bsd.pjcloud.wallet.api.entity.act.ActCancelItemEntity;
import com.bsd.pjcloud.wallet.api.vo.act.ActCancelItemCountVo;
import com.bsd.pjcloud.wallet.api.vo.act.ActCancelVo;
import com.bsd.pjcloud.wallet.mapper.act.ActCancelItemMapper;
import com.bsd.pjcloud.wallet.mapper.act.ActCancelMapper;
@@ -20,6 +24,7 @@ import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 核销活动
@@ -35,8 +40,27 @@ public class ActCancelServiceImpl extends ServiceImpl<ActCancelMapper, ActCancel
* 分页查询
*/
@Override
public List<ActCancelVo> scopePageJoin(Page page, ActCancelDto dto, DataScope dataScope) {
return baseMapper.scopePageJoin(page, dto, dataScope);
public Page<ActCancelVo> scopePageJoin(Page page, ActCancelDto dto, DataScope dataScope) {
Page<ActCancelVo> pageList = baseMapper.scopePageJoin(page, dto, dataScope);
disposeList(pageList.getRecords(), dto);
return pageList;
}
public void disposeList(List<ActCancelVo> list, ActCancelDto dto) {
if (ObjectUtil.isEmpty(list)) return;
List<Long> actIds = list.stream().map(ActCancelVo::getId).toList();
// 统计总数
ActCancelItemDto queryDto = new ActCancelItemDto();
queryDto.setActIdList(actIds);
List<ActCancelItemCountVo> countList = actCancelItemMapper.count(queryDto);
if (ObjectUtil.isNotEmpty(countList)) {
Map<Long, ActCancelItemCountVo> countMap = IterUtil.toMap(countList, ActCancelItemCountVo::getActId);
for (ActCancelVo v : list) {
if (ObjectUtil.isEmpty(countMap.get(v.getId()))) continue;
ActCancelItemCountVo targetCunt = countMap.get(v.getId());
v.setCountVo(targetCunt);
}
}
}
/**
@@ -44,6 +68,7 @@ public class ActCancelServiceImpl extends ServiceImpl<ActCancelMapper, ActCancel
*/
@Override
public Long create(ActCancelDto dto) {
if (existByNoticeId(dto.getId(), dto.getNoticeId())) throw new RuntimeException("绑定的公告已存在核销活动");
ActCancelEntity savObj = BeanUtils.toBean(dto, ActCancelEntity.class);
if (ObjectUtil.isEmpty(savObj.getActStatus())) {
savObj.setActStatus(ActStatusEnum.ACT_OPEN.getCode());
@@ -52,6 +77,26 @@ public class ActCancelServiceImpl extends ServiceImpl<ActCancelMapper, ActCancel
return savObj.getId();
}
/**
* 根据公告id查询核销活动
*/
@Override
public ActCancelEntity getDetailByNoticeId(Long noticeId) {
return baseMapper.selectOne(new LambdaQueryWrapper<ActCancelEntity>()
.eq(ActCancelEntity::getNoticeId, noticeId)
);
}
/**
* 根据公告id查询核销活动
*/
@Override
public ActCancelEntity getDetailById(Long id) {
return baseMapper.selectOne(new LambdaQueryWrapper<ActCancelEntity>()
.eq(ActCancelEntity::getId, id)
);
}
/**
* 根据ids删除
*/
@@ -70,4 +115,15 @@ public class ActCancelServiceImpl extends ServiceImpl<ActCancelMapper, ActCancel
}
}
}
public boolean existByNoticeId(Long id, Long noticeId) {
Long count = baseMapper.selectCount(new LambdaQueryWrapper<ActCancelEntity>()
.ne(ObjectUtil.isNotEmpty(id), ActCancelEntity::getId, id)
.eq(ObjectUtil.isNotEmpty(noticeId), ActCancelEntity::getNoticeId, noticeId)
);
if (ObjectUtil.isNotEmpty(id)) {
return count >= 1;
}
return count > 0;
}
}
@@ -3,4 +3,63 @@
<mapper namespace="com.bsd.pjcloud.wallet.mapper.act.ActCancelItemMapper">
<sql id="selectA">
select a.id,
a.act_id,
a.mch_id,
a.receiver_user_id,
a.receiver_user_name,
a.receiver_time,
a.act_status,
a.cancel_user_id,
a.cancel_time,
a.expire_time,
a.create_by,
a.create_time,
a.update_by,
a.update_time,
a.del_flag,
a.tenant_id
</sql>
<sql id="whereA">
a.del_flag = '0'
<if test="dto.actId != null">
and a.act_id = #{dto.actId}
</if>
<if test="dto.mchId != null">
and a.mch_id = #{dto.mchId}
</if>
<if test="dto.receiverUserId != null">
and a.receiver_user_id = #{dto.receiverUserId}
</if>
<if test="dto.actStatus != null">
and a.act_status = #{dto.actStatus}
</if>
<if test="dto.actIdList != null and dto.actIdList.size() != 0">
and a.act_id in
<foreach collection="dto.actIdList" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
<if test="dto.mchIdList != null and dto.mchIdList.size() != 0">
and a.mch_id in
<foreach collection="dto.mchIdList" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
</sql>
<select id="count" resultType="com.bsd.pjcloud.wallet.api.vo.act.ActCancelItemCountVo">
select a.act_id,
sum(1) as totalCount,
sum(if(a.act_status = '2', 1, 0)) as cancelCount,
sum(if(a.act_status != '2', 1, 0)) as cancelAwaitCount
from act_cancel_item a
<where>
<include refid="whereA"/>
</where>
group by a.act_id
</select>
</mapper>
@@ -8,6 +8,7 @@
a.notice_id,
a.active_org_price,
a.active_cancel_price,
a.start_time,
a.expire_time,
a.act_status,
a.act_title,