Merge remote-tracking branch 'origin/master'

This commit is contained in:
zjf committed 2025-10-31 15:26:17 +08:00
commit 55e81a41b6
32 files changed
+1075 -215

No files matched your search

+24
View File
@@ -1,3 +1,27 @@
-- ----------------------------
-- Table structure for act_cancel
-- ----------------------------
DROP TABLE IF EXISTS 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 ='核销活动';
-- ----------------------------
-- Table structure for act_cancel_item
-- ----------------------------
@@ -25,6 +25,13 @@ public class PanelProductDto {
private List<Long> excludeClassifyIds;
private List<String> orderStatus;
/**
* 排除当天在食堂吃饭的数据
*/
private String excludeCanteenPay;
private String hourTypeIsNull;
private String hourType;
@@ -113,6 +113,20 @@ public class PanelPorductVo {
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class ProductListByTimeItemVo {
private String timeStr;
private LocalDateTime time;
private List<PanelPorductVo> list;
}
@Data
@Builder
@AllArgsConstructor
@@ -155,7 +169,7 @@ public class PanelPorductVo {
private ProductTypeItemVo zs;
}
public static List<PanelPorductVo> generatePanelCanteenList(LocalDateTime[] totalTimeList, DateRangeTypeEnum dateRangeType) {
public static List<PanelPorductVo> generatePanelPorductVoList(LocalDateTime[] totalTimeList, DateRangeTypeEnum dateRangeType) {
List<PanelPorductVo> dateList = new LinkedList<>();
LocalDate startTime = totalTimeList[0].toLocalDate();
LocalDate endTime = totalTimeList[1].toLocalDate();
@@ -3,11 +3,18 @@ package com.bsd.pjcloud.hard.controller.panel;
import cn.hutool.core.util.ObjectUtil;
import com.bsd.pjcloud.common.core.constant.enums.DateRangeTypeEnum;
import com.bsd.pjcloud.common.core.constant.enums.MerchantTypeEnum;
import com.bsd.pjcloud.common.core.constant.enums.YesNoEnum;
import com.bsd.pjcloud.common.core.util.DateRangeTool;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.hard.api.constant.order.HardOrderStatusEnum;
import com.bsd.pjcloud.hard.api.dto.order.HardOrderDto;
import com.bsd.pjcloud.hard.api.dto.panel.PanelProductDto;
import com.bsd.pjcloud.hard.api.vo.hard.PanelPorductVo;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderCsVo;
import com.bsd.pjcloud.hard.service.HardOrderTotalService;
import com.bsd.pjcloud.hard.service.PanelNutritionService;
import com.bsd.pjcloud.wallet.api.feign.RemoteMchService;
import com.bsd.pjcloud.wallet.api.vo.MchManageVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -19,6 +26,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@RestController
@@ -29,6 +37,9 @@ import java.util.List;
public class PanelNutritionController {
private final PanelNutritionService panelNutritionService;
private final HardOrderTotalService hardOrderTotalService;
private final RemoteMchService mchService;
@PostMapping(value = "/class-count")
@Operation(summary = "食堂用餐分类统计")
@@ -37,6 +48,7 @@ public class PanelNutritionController {
dto.setTotalTimeList(DateRangeTool.transitionDateTypeToDateTimeList(dto.getDateRangeType()));
}
dto.setMchTypeCodes(List.of(MerchantTypeEnum.CANTEEN.getType()));
dto.setOrderStatus(HardOrderStatusEnum.getPayPrice());
return R.ok(panelNutritionService.classCount(dto));
}
@@ -47,6 +59,7 @@ public class PanelNutritionController {
dto.setTotalTimeList(DateRangeTool.transitionDateTypeToDateTimeList(dto.getDateRangeType()));
}
dto.setMchTypeCodes(List.of(MerchantTypeEnum.CANTEEN.getType()));
dto.setOrderStatus(HardOrderStatusEnum.getPayPrice());
return R.ok(panelNutritionService.cuisineTop(dto));
}
@@ -57,6 +70,7 @@ public class PanelNutritionController {
dto.setTotalTimeList(DateRangeTool.transitionDateTypeToDateTimeList(dto.getDateRangeType()));
}
dto.setMchTypeCodes(List.of(MerchantTypeEnum.CANTEEN.getType()));
dto.setOrderStatus(HardOrderStatusEnum.getPayPrice());
return R.ok(panelNutritionService.nutritionByTime(dto));
}
@@ -67,6 +81,7 @@ public class PanelNutritionController {
dto.setTotalTimeList(DateRangeTool.transitionDateTypeToDateTimeList(dto.getDateRangeType()));
}
dto.setMchTypeCodes(List.of(MerchantTypeEnum.CANTEEN.getType()));
dto.setOrderStatus(HardOrderStatusEnum.getPayPrice());
return R.ok(panelNutritionService.nutritionTotal(dto));
}
@@ -78,19 +93,53 @@ public class PanelNutritionController {
LocalDateTime.now().withHour(23).withMinute(59).withSecond(59)
});
dto.setMchTypeCodes(List.of(MerchantTypeEnum.CANTEEN.getType()));
dto.setOrderStatus(HardOrderStatusEnum.getPayPrice());
return R.ok(panelNutritionService.nutritionByTime(dto));
}
@PostMapping(value = "/repurchase")
@Operation(summary = "复购排行榜")
public R<List<PanelPorductVo>> repurchase(@RequestBody PanelProductDto dto) {
dto.setDateRangeType(DateRangeTypeEnum.THIS_YEAR);
dto.setDateRangeType(DateRangeTypeEnum.TODAY);
if (ObjectUtil.isNotEmpty(dto.getDateRangeType()) && ObjectUtil.isEmpty(dto.getTotalTimeList())) {
dto.setTotalTimeList(DateRangeTool.transitionDateTypeToDateTimeList(dto.getDateRangeType()));
}
dto.setMchTypeCodes(List.of(MerchantTypeEnum.CANTEEN.getType()));
dto.setOrderStatus(HardOrderStatusEnum.getPayPrice());
dto.setLimit(5L);
return R.ok(panelNutritionService.repurchase(dto));
}
@PostMapping(value = "/external")
@Operation(summary = "外部就餐情况(合作商家)")
public R<PanelPorductVo.HourTypeVo> external(@RequestBody PanelProductDto dto) {
if (ObjectUtil.isNotEmpty(dto.getDateRangeType()) && ObjectUtil.isEmpty(dto.getTotalTimeList())) {
dto.setTotalTimeList(DateRangeTool.transitionDateTypeToDateTimeList(dto.getDateRangeType()));
}
dto.setMchTypeCodes(List.of(MerchantTypeEnum.SUPERMARKET.getType()));
dto.setOrderStatus(HardOrderStatusEnum.getPayPrice());
dto.setExcludeCanteenPay(YesNoEnum.YES.getCode());
return R.ok(panelNutritionService.external(dto));
}
@PostMapping(value = "/report")
@Operation(summary = "营养分析报表")
public R<List<HardOrderCsVo>> canteenReport(@RequestBody HardOrderDto dto) {
dto.setOrderStatusCodes(HardOrderStatusEnum.getPaySuccessCodes());
dto.setMchTypeCodes(List.of(MerchantTypeEnum.SUPERMARKET.getType(), MerchantTypeEnum.SELF_SUPERMARKET.getType()));
List<Long> mchDtoIds = new ArrayList<>();
if (ObjectUtil.isNotEmpty(dto.getMerchantId())) {
List<MchManageVo> mchList = mchService.getByParentId(dto.getMerchantId()).getData();
if (ObjectUtil.isNotEmpty(mchList)) {
List<Long> mchIds = mchList.stream().map(MchManageVo::getId).toList();
mchDtoIds.add(dto.getMerchantId());
mchDtoIds.addAll(mchIds);
dto.setMerchantId(null);
dto.setMchIds(mchDtoIds);
}
}
return R.ok(hardOrderTotalService.listCs(dto));
}
}
@@ -55,6 +55,7 @@ public class PanelShopController {
}
dto.setMchTypeCodes(List.of(MerchantTypeEnum.SELF_SUPERMARKET.getType()));
dto.setHourTypeIsNull(YesNoEnum.YES.getCode());
dto.setOrderStatus(HardOrderStatusEnum.getPayPrice());
return R.ok(panelShopService.mchPayPersonCount(dto));
}
@@ -67,6 +68,7 @@ public class PanelShopController {
});
dto.setMchTypeCodes(List.of(MerchantTypeEnum.SELF_SUPERMARKET.getType()));
dto.setHourTypeIsNull(YesNoEnum.YES.getCode());
dto.setOrderStatus(HardOrderStatusEnum.getPayPrice());
return R.ok(panelShopService.mchPayCount(dto));
}
@@ -120,13 +122,43 @@ public class PanelShopController {
@PostMapping(value = "/mch-pay-count-top")
@Operation(summary = "排行榜")
public R<List<PanelPorductVo>> mchPayCountTop(@RequestBody PanelProductDto dto) {
dto.setDateRangeType(DateRangeTypeEnum.TODAY);
if (ObjectUtil.isNotEmpty(dto.getDateRangeType()) && ObjectUtil.isEmpty(dto.getTotalTimeList())) {
dto.setTotalTimeList(DateRangeTool.transitionDateTypeToDateTimeList(dto.getDateRangeType()));
}
dto.setLimit(5L);
dto.setMchTypeCodes(List.of(MerchantTypeEnum.SELF_SUPERMARKET.getType()));
dto.setHourTypeIsNull(YesNoEnum.YES.getCode());
dto.setOrderStatus(HardOrderStatusEnum.getPayPrice());
return R.ok(panelShopService.mchPayCountTop(dto));
}
@PostMapping(value = "/today-trend")
@Operation(summary = "当天超市购买次数趋势统计")
public R<List<PanelPorductVo>> todayTrend(@RequestBody PanelProductDto dto) {
dto.setDateRangeType(DateRangeTypeEnum.TODAY);
if (ObjectUtil.isNotEmpty(dto.getDateRangeType()) && ObjectUtil.isEmpty(dto.getTotalTimeList())) {
dto.setTotalTimeList(DateRangeTool.transitionDateTypeToDateTimeList(dto.getDateRangeType()));
}
dto.setMchTypeCodes(List.of(MerchantTypeEnum.SELF_SUPERMARKET.getType()));
dto.setHourTypeIsNull(YesNoEnum.YES.getCode());
dto.setOrderStatus(HardOrderStatusEnum.getPayPrice());
return R.ok(panelShopService.todayTrend(dto));
}
@PostMapping(value = "/hot-product")
@Operation(summary = "热卖商品")
public R<List<PanelPorductVo>> hotProduct(@RequestBody PanelProductDto dto) {
dto.setDateRangeType(DateRangeTypeEnum.THIS_WEEK);
if (ObjectUtil.isNotEmpty(dto.getDateRangeType()) && ObjectUtil.isEmpty(dto.getTotalTimeList())) {
dto.setTotalTimeList(DateRangeTool.transitionDateTypeToDateTimeList(dto.getDateRangeType()));
}
dto.setMchTypeCodes(List.of(MerchantTypeEnum.SELF_SUPERMARKET.getType()));
dto.setOrderStatus(HardOrderStatusEnum.getPayPrice());
dto.setLimit(10L);
return R.ok(panelShopService.hotProduct(dto));
}
}
@@ -154,8 +154,20 @@ public interface HardOrderMapper extends PjcloudBaseMapper<HardOrderEntity> {
*/
List<PanelPorductVo> groupByMch(@Param("dto") PanelProductDto dto);
List<PanelPorductVo> shopGroupByMch(@Param("dto") PanelProductDto dto);
/**
* 复购排行榜
*/
List<PanelPorductVo> repurchase(@Param("dto") PanelProductDto dto);
/**
* 超市数据统计(根据时间段和日期分类统计)
* 订单表位主表,商品表为从表
*/
List<PanelPorductVo> shopGroupByMonthAndHourType(@Param("dto") PanelProductDto dto);
List<PanelPorductVo> shopGroupByTimeAndHourType(@Param("dto") PanelProductDto dto);
List<PanelPorductVo> shopGroupByProduct(@Param("dto") PanelProductDto dto);
}
@@ -35,4 +35,9 @@ public interface PanelNutritionService {
* 复购排行榜
*/
List<PanelPorductVo> repurchase(PanelProductDto dto);
/**
* 外部就餐情况(合作商家)
*/
PanelPorductVo.HourTypeVo external(PanelProductDto dto);
}
@@ -21,4 +21,14 @@ public interface PanelShopService {
* 排行榜
*/
List<PanelPorductVo> mchPayCountTop(PanelProductDto dto);
/**
* 当天超市购买次数趋势统计
*/
List<PanelPorductVo> todayTrend(PanelProductDto dto);
/**
* 热卖商品
*/
List<PanelPorductVo> hotProduct(PanelProductDto dto);
}
@@ -426,12 +426,19 @@ public class HardCarServiceImpl extends ServiceImpl<HardCarMapper, HardCarEntity
List<MallProductDetailAppVo> spuList = remoteMallProductService.getSkusWithSpuBySkuIds(productIds).getData();
for (HardCreateCarDto v : productList) {
HardCarEntity item = HardCarEntity.builder().parentCarId(parentCarId).build();
spuList.stream().filter(i -> ObjectUtil.equals(i.getId(), v.getProductId())).findFirst().ifPresent(spu -> {
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() + "请联系管理员");
}
MallProductSkuAppVo skuDetail = spu.getSkuList().get(0);
Integer price = skuDetail.getPrice();
Integer price = sku.getPrice();
int totalPrice = 0;
if (ObjectUtil.isNotEmpty(v.getProductCount()) && !ObjectUtil.equals(v.getProductCount(), 0)) {
// 按数量
@@ -440,7 +447,7 @@ public class HardCarServiceImpl extends ServiceImpl<HardCarMapper, HardCarEntity
// 按重量
totalPrice = v.getProductWeight().multiply(BigDecimal.valueOf(price)).setScale(0, RoundingMode.CEILING).intValue();
}
item.setProductId(skuDetail.getId());
item.setProductId(sku.getId());
item.setProductName(spu.getTitle());
item.setProductPrice(price);
item.setProductPic(spu.getCoverImage());
@@ -451,7 +458,8 @@ public class HardCarServiceImpl extends ServiceImpl<HardCarMapper, HardCarEntity
item.setProductCount(v.getProductCount());
item.setProductWeight(v.getProductWeight());
carObjectList.add(item);
});
}
}
baseMapper.insert(carObjectList);
return;
@@ -38,7 +38,7 @@ public class PanelCanteenServiceImpl implements PanelCanteenService {
@Override
public PanelPorductVo.HourTypeVo groupByTimeAndHourType(PanelProductDto dto) {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
List<PanelPorductVo> dateList = PanelPorductVo.generatePanelCanteenList(dto.getTotalTimeList(), dto.getDateRangeType());
List<PanelPorductVo> dateList = PanelPorductVo.generatePanelPorductVoList(dto.getTotalTimeList(), dto.getDateRangeType());
PanelPorductVo.HourTypeVo result = new PanelPorductVo.HourTypeVo();
List<HardHourTypeEnum> hourTypeList = List.of(HardHourTypeEnum.MORNING, HardHourTypeEnum.NOONING, HardHourTypeEnum.NIGHT);
@@ -4,6 +4,8 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.bsd.pjcloud.canteen.api.feign.RemoteCanteenCategoryService;
import com.bsd.pjcloud.canteen.entity.CanteenCategoryEntity;
import com.bsd.pjcloud.common.core.constant.enums.DateRangeTypeEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardHourTypeEnum;
import com.bsd.pjcloud.hard.api.dto.order.app.HardAppProductByClassifyDto;
import com.bsd.pjcloud.hard.api.dto.order.app.HardAppProductLikeTopDto;
import com.bsd.pjcloud.hard.api.dto.panel.PanelProductDto;
@@ -102,7 +104,7 @@ public class PanelNutritionServiceImpl implements PanelNutritionService {
PanelPorductVo.NutritionTypeVo result = new PanelPorductVo.NutritionTypeVo();
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
List<PanelPorductVo> dateList = PanelPorductVo.generatePanelCanteenList(dto.getTotalTimeList(), dto.getDateRangeType());
List<PanelPorductVo> dateList = PanelPorductVo.generatePanelPorductVoList(dto.getTotalTimeList(), dto.getDateRangeType());
List<Map<String, Object>> futureList = nutritionSetting();
// 查询配置
HardPanelSettingEntity setting = panelSettingService.getSetting();
@@ -207,6 +209,55 @@ public class PanelNutritionServiceImpl implements PanelNutritionService {
return list;
}
/**
* 外部就餐情况(合作商家)
*/
@Override
public PanelPorductVo.HourTypeVo external(PanelProductDto dto) {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
List<PanelPorductVo> dateList = PanelPorductVo.generatePanelPorductVoList(dto.getTotalTimeList(), dto.getDateRangeType());
PanelPorductVo.HourTypeVo result = new PanelPorductVo.HourTypeVo();
List<HardHourTypeEnum> hourTypeList = List.of(HardHourTypeEnum.MORNING, HardHourTypeEnum.NOONING, HardHourTypeEnum.NIGHT);
for (CompletableFuture<Void> voidCompletableFuture : hourTypeList.stream().map(hourType -> CompletableFuture.runAsync(() -> {
RequestContextHolder.setRequestAttributes(requestAttributes);
PanelProductDto queryDto = BeanUtil.toBean(dto, PanelProductDto.class);
List<PanelPorductVo> sqlList = new ArrayList<>();
if (ObjectUtil.equals(dto.getDateRangeType(), DateRangeTypeEnum.THIS_YEAR)) {
sqlList = hardOrderMapper.shopGroupByMonthAndHourType(queryDto);
} else {
sqlList = hardOrderMapper.shopGroupByTimeAndHourType(queryDto);
}
// 处理查询出来的数据
List<PanelPorductVo> resultList = BeanUtil.copyToList(dateList, PanelPorductVo.class);
for (PanelPorductVo v : resultList) {
sqlList.stream().filter(item -> ObjectUtil.equals(item.getTime(), v.getTime())).forEach(target -> {
v.setHourType(target.getHourType());
v.setPersonCount(target.getPersonCount());
v.setBuyCount(target.getBuyCount());
v.setBuyProductCount(target.getBuyProductCount());
v.setTotalPrice(target.getTotalPrice());
});
}
// 组装数据
PanelPorductVo.ProductTypeItemVo vo = PanelPorductVo.ProductTypeItemVo.builder().list(resultList).type(hourType.getType()).typeStr(hourType.getDescription()).build();
switch (hourType) {
case MORNING:
result.setMorning(vo);
break;
case NOONING:
result.setNoon(vo);
break;
case NIGHT:
result.setEvening(vo);
break;
}
})).toList()) {
voidCompletableFuture.join();
}
return result;
}
private void disposeRepurchaseList(List<PanelPorductVo> list, PanelProductDto dto) {
if (ObjectUtil.isEmpty(list)) return;
// 处理菜品分类
@@ -15,10 +15,15 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
@Validated
@Slf4j
@@ -35,7 +40,7 @@ public class PanelShopServiceImpl implements PanelShopService {
*/
@Override
public List<PanelPorductVo> mchPayPersonCount(PanelProductDto dto) {
List<PanelPorductVo> list = hardOrderMapper.groupByMch(dto);
List<PanelPorductVo> list = hardOrderMapper.shopGroupByMch(dto);
disposePanelCanteenVoSetMchName(list);
return list;
}
@@ -47,7 +52,7 @@ public class PanelShopServiceImpl implements PanelShopService {
public List<PanelPorductVo.ProductTypeItemVo> mchPayCount(PanelProductDto dto) {
List<PanelPorductVo.ProductTypeItemVo> result = new ArrayList<>();
// 处理时间
List<PanelPorductVo> dateList = PanelPorductVo.generatePanelCanteenList(dto.getTotalTimeList(), dto.getDateRangeType());
List<PanelPorductVo> dateList = PanelPorductVo.generatePanelPorductVoList(dto.getTotalTimeList(), dto.getDateRangeType());
// 查询商户
MchManageDto mchDto = new MchManageDto();
mchDto.setTypesList(List.of(MerchantTypeEnum.SELF_SUPERMARKET.getType()));
@@ -59,7 +64,7 @@ public class PanelShopServiceImpl implements PanelShopService {
return entity;
}).toList();
// 查询商户订单
List<PanelPorductVo> list = hardOrderMapper.groupByMch(dto);
List<PanelPorductVo> list = hardOrderMapper.shopGroupByMch(dto);
for (PanelPorductVo.ProductTypeItemVo v : result) {
List<PanelPorductVo> targetMchTotalList = list.stream().filter(item -> ObjectUtil.equals(v.getType(), String.valueOf(item.getMchId()))).toList();
if (ObjectUtil.isEmpty(targetMchTotalList)) {
@@ -86,11 +91,56 @@ public class PanelShopServiceImpl implements PanelShopService {
*/
@Override
public List<PanelPorductVo> mchPayCountTop(PanelProductDto dto) {
List<PanelPorductVo> list = hardOrderMapper.groupByMch(dto);
List<PanelPorductVo> list = hardOrderMapper.shopGroupByMch(dto);
disposePanelCanteenVoSetMchName(list);
return list;
}
/**
* 当天超市购买次数趋势统计
*/
@Override
public List<PanelPorductVo> todayTrend(PanelProductDto dto) {
List<PanelPorductVo> result = new ArrayList<>();
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
LocalDateTime now = LocalDateTime.now();
List<List<Integer>> customHour = List.of(
// 早
List.of(7, 8),
List.of(8, 9),
// 中
List.of(11, 12),
List.of(12, 13),
// 晚
List.of(17, 18),
List.of(18, 19)
);
customHour.stream().map(customList -> CompletableFuture.runAsync(() -> {
RequestContextHolder.setRequestAttributes(requestAttributes);
Integer targetHour = customList.get(0);
PanelProductDto queryDto = PanelProductDto
.builder()
.totalTimeList(new LocalDateTime[]{
now.withHour(targetHour).withMinute(0).withSecond(0),
now.withHour(targetHour).withMinute(59).withSecond(59)
})
.build();
List<PanelPorductVo> sqlList = hardOrderMapper.shopGroupByTimeAndHourType(queryDto);
PanelPorductVo build = PanelPorductVo.builder().hourType(customList.get(0) + "-" + customList.get(1)).personCount(0L).order(targetHour).build();
if (ObjectUtil.isNotEmpty(sqlList)) build.setPersonCount(sqlList.get(0).getPersonCount());
result.add(build);
})).toList().forEach(CompletableFuture::join);
return result.stream().sorted(Comparator.comparingInt(PanelPorductVo::getOrder)).toList();
}
/**
* 热卖商品
*/
@Override
public List<PanelPorductVo> hotProduct(PanelProductDto dto) {
return hardOrderMapper.shopGroupByProduct(dto);
}
private void disposePanelCanteenVoSetMchName(List<PanelPorductVo> list) {
if (ObjectUtil.isEmpty(list)) return;
// 商户名
@@ -592,40 +592,56 @@
</where>
</select>
<sql id="groupWhereByPanelProductDto">
c.del_flag = '0'
<if test="dto.totalTimeList != null and dto.totalTimeList.length == 2">
and o.create_time between #{dto.totalTimeList[0]} and #{dto.totalTimeList[1]}
</if>
<if test="dto.hourType != null and dto.hourType != '' ">
and o.hour_type = #{dto.hourType}
</if>
<if test="dto.mchTypeCodes != null and dto.mchTypeCodes.size() != 0">
and o.merchant_type in
<foreach collection="dto.mchTypeCodes" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
<if test="dto.classifyIds != null and dto.classifyIds.size() != 0">
and s.category_id in
<foreach collection="dto.classifyIds" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
<if test="dto.excludeClassifyIds != null and dto.excludeClassifyIds.size() != 0">
and s.category_id not in
<foreach collection="dto.excludeClassifyIds" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
<if test="dto.orderStatus != null and dto.orderStatus.size() != 0">
and o.order_status in
<foreach collection="dto.orderStatus" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
</sql>
<select id="groupCount" resultType="com.bsd.pjcloud.hard.api.vo.hard.PanelPorductVo">
select SUM(a.product_count) as buyProductCount,
SUM(a.total_price) as totalPrice,
select SUM(c.product_count) as buyProductCount,
SUM(c.total_price) as totalPrice,
count(distinct o.id) as buyCount,
count(distinct o.user_id) as personCount,
s.category_id as classifyId
from hard_car a
inner join hard_parent_car p on a.parent_car_id = p.id and p.del_flag = '0'
from hard_car c
inner join hard_parent_car p on c.parent_car_id = p.id and p.del_flag = '0'
inner join hard_order o on o.parent_car_id = p.id and o.del_flag = '0' and o.hour_type is not null and
o.hour_type not in ('-1', 'null')
<if test="dto.hourTypeIsNull == null">
and o.hour_type is not null and o.hour_type not in ('-1', 'null')
</if>
left join pjcloudx_canteen.canteen_spu s on a.product_id = s.id
left join pjcloudx_canteen.canteen_spu s on c.product_id = s.id
<where>
a.del_flag = '0'
<if test="dto.totalTimeList != null and dto.totalTimeList.length == 2">
and o.create_time between #{dto.totalTimeList[0]} and #{dto.totalTimeList[1]}
</if>
<if test="dto.hourType != null and dto.hourType != '' ">
and o.hour_type = #{dto.hourType}
</if>
<if test="dto.mchTypeCodes != null and dto.mchTypeCodes.size() != 0">
and o.merchant_type in
<foreach collection="dto.mchTypeCodes" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
<if test="dto.classifyIds != null and dto.classifyIds.size() != 0">
and s.category_id in
<foreach collection="dto.classifyIds" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
<include refid="groupWhereByPanelProductDto"/>
</where>
</select>
@@ -633,38 +649,20 @@
select
date(o.create_time) as time,
o.hour_type as hourType,
SUM(a.product_count) as buyProductCount,
SUM(a.total_price) as totalPrice,
SUM(c.product_count) as buyProductCount,
SUM(c.total_price) as totalPrice,
count(distinct o.id) as buyCount,
count(distinct o.user_id) as personCount,
s.category_id as classifyId
from hard_car a
inner join hard_parent_car p on a.parent_car_id = p.id and p.del_flag = '0'
from hard_car c
inner join hard_parent_car p on c.parent_car_id = p.id and p.del_flag = '0'
inner join hard_order o on o.parent_car_id = p.id and o.del_flag = '0'
<if test="dto.hourTypeIsNull == null">
and o.hour_type is not null and o.hour_type not in ('-1', 'null')
</if>
left join pjcloudx_canteen.canteen_spu s on a.product_id = s.id
left join pjcloudx_canteen.canteen_spu s on c.product_id = s.id
<where>
a.del_flag = '0'
<if test="dto.totalTimeList != null and dto.totalTimeList.length == 2">
and o.create_time between #{dto.totalTimeList[0]} and #{dto.totalTimeList[1]}
</if>
<if test="dto.hourType != null and dto.hourType != '' ">
and o.hour_type = #{dto.hourType}
</if>
<if test="dto.mchTypeCodes != null and dto.mchTypeCodes.size() != 0">
and o.merchant_type in
<foreach collection="dto.mchTypeCodes" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
<if test="dto.classifyIds != null and dto.classifyIds.size() != 0">
and s.category_id in
<foreach collection="dto.classifyIds" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
<include refid="groupWhereByPanelProductDto"/>
</where>
group by date(o.create_time)
order by date(o.create_time) desc
@@ -677,38 +675,20 @@
select
date(o.create_time) as time,
o.hour_type as hourType,
SUM(a.product_count) as buyProductCount,
SUM(a.total_price) as totalPrice,
SUM(c.product_count) as buyProductCount,
SUM(c.total_price) as totalPrice,
count(distinct o.id) as buyCount,
count(distinct o.user_id) as personCount,
s.category_id as classifyId
from hard_car a
inner join hard_parent_car p on a.parent_car_id = p.id and p.del_flag = '0'
from hard_car c
inner join hard_parent_car p on c.parent_car_id = p.id and p.del_flag = '0'
inner join hard_order o on o.parent_car_id = p.id and o.del_flag = '0'
<if test="dto.hourTypeIsNull == null">
and o.hour_type is not null and o.hour_type not in ('-1', 'null')
</if>
left join pjcloudx_canteen.canteen_spu s on a.product_id = s.id
left join pjcloudx_canteen.canteen_spu s on c.product_id = s.id
<where>
a.del_flag = '0'
<if test="dto.totalTimeList != null and dto.totalTimeList.length == 2">
and o.create_time between #{dto.totalTimeList[0]} and #{dto.totalTimeList[1]}
</if>
<if test="dto.hourType != null and dto.hourType != '' ">
and o.hour_type = #{dto.hourType}
</if>
<if test="dto.mchTypeCodes != null and dto.mchTypeCodes.size() != 0">
and o.merchant_type in
<foreach collection="dto.mchTypeCodes" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
<if test="dto.classifyIds != null and dto.classifyIds.size() != 0">
and s.category_id in
<foreach collection="dto.classifyIds" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
<include refid="groupWhereByPanelProductDto"/>
</where>
group by date(o.create_time), o.hour_type
order by date(o.create_time) desc
@@ -721,38 +701,20 @@
select
date(o.create_time) as time,
o.hour_type as hourType,
SUM(a.product_count) as buyProductCount,
SUM(a.total_price) as totalPrice,
SUM(c.product_count) as buyProductCount,
SUM(c.total_price) as totalPrice,
count(distinct o.id) as buyCount,
count(distinct o.user_id) as personCount,
s.category_id as classifyId
from hard_car a
inner join hard_parent_car p on a.parent_car_id = p.id and p.del_flag = '0'
from hard_car c
inner join hard_parent_car p on c.parent_car_id = p.id and p.del_flag = '0'
inner join hard_order o on o.parent_car_id = p.id and o.del_flag = '0'
<if test="dto.hourTypeIsNull == null">
and o.hour_type is not null and o.hour_type not in ('-1', 'null')
</if>
left join pjcloudx_canteen.canteen_spu s on a.product_id = s.id
left join pjcloudx_canteen.canteen_spu s on c.product_id = s.id
<where>
a.del_flag = '0'
<if test="dto.totalTimeList != null and dto.totalTimeList.length == 2">
and o.create_time between #{dto.totalTimeList[0]} and #{dto.totalTimeList[1]}
</if>
<if test="dto.hourType != null and dto.hourType != '' ">
and o.hour_type = #{dto.hourType}
</if>
<if test="dto.mchTypeCodes != null and dto.mchTypeCodes.size() != 0">
and o.merchant_type in
<foreach collection="dto.mchTypeCodes" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
<if test="dto.classifyIds != null and dto.classifyIds.size() != 0">
and s.category_id in
<foreach collection="dto.classifyIds" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
<include refid="groupWhereByPanelProductDto"/>
</where>
group by date_format(o.create_time, '%Y-%m'), o.hour_type
order by date_format(o.create_time, '%Y-%m') desc
@@ -763,41 +725,45 @@
<select id="groupByMch" resultType="com.bsd.pjcloud.hard.api.vo.hard.PanelPorductVo">
select o.merchant_id as mchId,
sum(a.product_count) as buyProductCount,
SUM(a.total_price) as totalPrice,
sum(c.product_count) as buyProductCount,
SUM(c.total_price) as totalPrice,
count(distinct o.id) as buyCount,
count(distinct o.user_id) as personCount,
s.category_id as classifyId
from hard_car a
inner join hard_parent_car p on a.parent_car_id = p.id and p.del_flag = '0'
from hard_car c
inner join hard_parent_car p on c.parent_car_id = p.id and p.del_flag = '0'
inner join hard_order o on o.parent_car_id = p.id and o.del_flag = '0'
<if test="dto.hourTypeIsNull == null">
and o.hour_type is not null and o.hour_type not in ('-1', 'null')
</if>
left join pjcloudx_canteen.canteen_spu s on a.product_id = s.id
left join pjcloudx_canteen.canteen_spu s on c.product_id = s.id
<where>
a.del_flag = '0'
<if test="dto.totalTimeList != null and dto.totalTimeList.length == 2">
and o.create_time between #{dto.totalTimeList[0]} and #{dto.totalTimeList[1]}
</if>
<if test="dto.hourType != null and dto.hourType != '' ">
and o.hour_type = #{dto.hourType}
</if>
<if test="dto.mchTypeCodes != null and dto.mchTypeCodes.size() != 0">
and o.merchant_type in
<foreach collection="dto.mchTypeCodes" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
<if test="dto.classifyIds != null and dto.classifyIds.size() != 0">
and s.category_id in
<foreach collection="dto.classifyIds" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
<include refid="groupWhereByPanelProductDto"/>
</where>
group by o.merchant_id
order by sum(c.product_count) desc
<if test="dto.limit != null">
limit #{dto.limit}
</if>
</select>
<select id="shopGroupByMch" resultType="com.bsd.pjcloud.hard.api.vo.hard.PanelPorductVo">
select o.merchant_id as mchId,
sum(c.product_count) as buyProductCount,
SUM(c.total_price) as totalPrice,
count(distinct o.id) as buyCount,
count(distinct o.user_id) as personCount
from hard_order o
left join hard_parent_car p on p.id = o.parent_car_id
left join hard_car c on c.parent_car_id = p.id
<where>
<include refid="groupWhereByPanelProductDto"/>
<if test="dto.hourTypeIsNull == null">
and o.hour_type is not null and o.hour_type not in ('-1', 'null')
</if>
</where>
group by o.merchant_id
order by sum(a.product_count) desc
order by sum(c.product_count) desc
<if test="dto.limit != null">
limit #{dto.limit}
</if>
@@ -805,52 +771,99 @@
<select id="repurchase" resultType="com.bsd.pjcloud.hard.api.vo.hard.PanelPorductVo">
select o.merchant_id as mchId,
a.product_name as productName,
sum(a.product_count) as buyProductCount,
SUM(a.total_price) as totalPrice,
c.product_name as productName,
sum(c.product_count) as buyProductCount,
SUM(c.total_price) as totalPrice,
count(distinct o.id) as buyCount,
count(distinct o.user_id) as personCount,
s.category_id as classifyId
from hard_car a
inner join hard_parent_car p on a.parent_car_id = p.id and p.del_flag = '0'
from hard_car c
inner join hard_parent_car p on c.parent_car_id = p.id and p.del_flag = '0'
inner join hard_order o on o.parent_car_id = p.id and o.del_flag = '0'
<if test="dto.hourTypeIsNull == null">
and o.hour_type is not null and o.hour_type not in ('-1', 'null')
</if>
left join pjcloudx_canteen.canteen_spu s on a.product_id = s.id
left join pjcloudx_canteen.canteen_spu s on c.product_id = s.id
<where>
a.del_flag = '0'
<if test="dto.totalTimeList != null and dto.totalTimeList.length == 2">
and o.create_time between #{dto.totalTimeList[0]} and #{dto.totalTimeList[1]}
</if>
<if test="dto.hourType != null and dto.hourType != '' ">
and o.hour_type = #{dto.hourType}
</if>
<if test="dto.mchTypeCodes != null and dto.mchTypeCodes.size() != 0">
and o.merchant_type in
<foreach collection="dto.mchTypeCodes" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
<if test="dto.classifyIds != null and dto.classifyIds.size() != 0">
and s.category_id in
<foreach collection="dto.classifyIds" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
<if test="dto.excludeClassifyIds != null and dto.excludeClassifyIds.size() != 0">
and s.category_id not in
<foreach collection="dto.excludeClassifyIds" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
<include refid="groupWhereByPanelProductDto"/>
</where>
GROUP BY a.product_id, o.user_id, o.hour_type
GROUP BY c.product_id, o.user_id, o.hour_type
having COUNT(DISTINCT o.id) >= 2
order by sum(a.product_count) desc
order by sum(c.product_count) desc
<if test="dto.limit != null">
limit #{dto.limit}
</if>
</select>
<select id="shopGroupByMonthAndHourType" resultType="com.bsd.pjcloud.hard.api.vo.hard.PanelPorductVo">
select o.merchant_id as mchId,
c.product_name as productName,
sum(c.product_count) as buyProductCount,
SUM(c.total_price) as totalPrice,
count(distinct o.id) as buyCount,
count(distinct o.user_id) as personCount
from hard_order o
left join hard_parent_car p on p.id = o.parent_car_id
left join hard_car c on c.parent_car_id = p.id
<where>
<include refid="groupWhereByPanelProductDto"/>
<if test="dto.excludeCanteenPay != null and dto.excludeCanteenPay = '1' ">
and o.id not in (select o.id
from hard_order a
where a.del_flag = 0
and a.merchant_type in ('1')
and a.order_status in ('5', '20', '10')
and o.create_time between a.create_time - interval 1 hour and a.create_time + interval 1 hour
group by a.user_id)
</if>
</where>
group by date_format(o.create_time, '%Y-%m'), o.merchant_id
order by date_format(o.create_time, '%Y-%m'), sum(c.product_count) desc
</select>
<select id="shopGroupByTimeAndHourType" resultType="com.bsd.pjcloud.hard.api.vo.hard.PanelPorductVo">
select o.merchant_id as mchId,
c.product_name as productName,
sum(c.product_count) as buyProductCount,
SUM(c.total_price) as totalPrice,
count(distinct o.id) as buyCount,
count(distinct o.user_id) as personCount
from hard_order o
left join hard_parent_car p on p.id = o.parent_car_id
left join hard_car c on c.parent_car_id = p.id
<where>
<include refid="groupWhereByPanelProductDto"/>
<if test="dto.excludeCanteenPay != null and dto.excludeCanteenPay = '1' ">
and o.id not in (select o.id
from hard_order a
where a.del_flag = 0
and a.merchant_type in ('1')
and a.order_status in ('5', '20', '10')
and o.create_time between a.create_time - interval 1 hour and a.create_time + interval 1 hour
group by a.user_id)
</if>
</where>
group by date(o.create_time), o.merchant_id
order by date(o.create_time), sum(c.product_count) desc
</select>
<select id="shopGroupByProduct" resultType="com.bsd.pjcloud.hard.api.vo.hard.PanelPorductVo">
select c.product_id as productId,
c.product_name as productName,
SUM(c.product_count) as buyProductCount,
SUM(c.total_price) as totalPrice,
count(distinct o.id) as buyCount,
count(distinct o.user_id) as personCount
from hard_car c
inner join hard_parent_car p on c.parent_car_id = p.id and p.del_flag = '0'
inner join hard_order o on o.parent_car_id = p.id and o.del_flag = '0'
<where>
<include refid="groupWhereByPanelProductDto"/>
</where>
group by c.product_id
order by sum(c.product_count) desc
<if test="dto.limit!= null">
limit #{dto.limit}
</if>
</select>
</mapper>
@@ -0,0 +1,27 @@
package com.bsd.pjcloud.admin.api.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "qn")
@Data
public class QnOssConfig {
private Oss oss;
@Data
public static class Oss {
private String accessKey;
private String secretKey;
private String bucketName;
private String domain;
}
}
@@ -0,0 +1,14 @@
package com.bsd.pjcloud.admin.api.vo.third;
import lombok.Data;
@Data
public class QnUploadVo {
public String fileHash;
public String fileName;
public String fullUrl;
}
+5
View File
@@ -33,6 +33,11 @@
<description>pjcloud 通用用户权限管理系统业务处理模块</description>
<dependencies>
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>qiniu-java-sdk</artifactId>
<version>[7.19.0, 7.19.99]</version>
</dependency>
<!-- 引入分布式事务-->
<dependency>
<groupId>com.bsd</groupId>
@@ -42,6 +42,7 @@ import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.Map;
import java.util.Objects;
/**
@@ -122,6 +123,14 @@ public class SysFileController {
return sysFileService.uploadFile(file, dir, groupId, type);
}
/**
* 七牛云上传
*/
@PostMapping(value = "/qn/upload")
public R<Map<String, String>> qnUpload(@RequestPart("file") MultipartFile file, @RequestParam(value = "dir", required = false) String dir, @RequestParam(value = "groupId", required = false) Long groupId, @RequestParam(value = "type", required = false) String type) {
return sysFileService.qnUpload(file, dir, groupId, type);
}
/**
* 获取文件
*
@@ -0,0 +1,11 @@
package com.bsd.pjcloud.admin.service;
import com.bsd.pjcloud.admin.api.vo.third.QnUploadVo;
import org.springframework.web.multipart.MultipartFile;
public interface QnOssService {
QnUploadVo upload(MultipartFile file, String fileName);
}
@@ -27,6 +27,7 @@ import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import java.util.Map;
/**
* 文件管理
@@ -36,57 +37,66 @@ import java.util.List;
*/
public interface SysFileService extends IService<SysFile> {
/**
* 上传文件
* @param file 文件流
* @param dir 文件夹
* @param groupId 分组ID
* @param type 类型
* @return
*/
R uploadFile(MultipartFile file, String dir, Long groupId, String type);
/**
* 上传文件
*
* @param file 文件流
* @param dir 文件夹
* @param groupId 分组ID
* @param type 类型
* @return
*/
R uploadFile(MultipartFile file, String dir, Long groupId, String type);
R innerUpload(MultipartFile file, String dir, Long groupId, String type);
R innerUpload(MultipartFile file, String dir, Long groupId, String type);
/**
* 读取文件
* @param fileName 文件名称
* @param response 输出流
*/
void getFile(String fileName, HttpServletResponse response);
R<Map<String, String>> qnUpload(MultipartFile file, String dir, Long groupId, String type);
/**
* 删除文件
* @param id
* @return
*/
Boolean deleteFile(Long id);
/**
* 读取文件
*
* @param fileName 文件名称
* @param response 输出流
*/
void getFile(String fileName, HttpServletResponse response);
/**
* 查询文件组列表
* @param fileGroup SysFileGroup对象,用于筛选条件
* @return 包含文件组列表的Tree对象列表
*/
List<Tree<Long>> listFileGroup(SysFileGroup fileGroup);
/**
* 删除文件
*
* @param id
* @return
*/
Boolean deleteFile(Long id);
/**
* 添加或更新文件组
* @param fileGroup SysFileGroup对象,要添加或更新的文件组信息
* @return 添加或更新成功返回true,否则返回false
*/
Boolean saveOrUpdateGroup(SysFileGroup fileGroup);
/**
* 查询文件组列表
*
* @param fileGroup SysFileGroup对象,用于筛选条件
* @return 包含文件组列表的Tree对象列表
*/
List<Tree<Long>> listFileGroup(SysFileGroup fileGroup);
/**
* 删除文件组
* @param id 待删除文件组的ID
* @return 删除成功返回true,否则返回false
*/
Boolean deleteGroup(Long id);
/**
* 添加或更新文件组
*
* @param fileGroup SysFileGroup对象,要添加或更新的文件组信息
* @return 添加或更新成功返回true,否则返回false
*/
Boolean saveOrUpdateGroup(SysFileGroup fileGroup);
/**
* 移动文件组
* @param fileGroupDTO SysFileGroupDTO对象,要移动的文件组信息
* @return 移动成功返回true,否则返回false
*/
Boolean moveFileGroup(SysFileGroupDTO fileGroupDTO);
/**
* 删除文件组
*
* @param id 待删除文件组的ID
* @return 删除成功返回true,否则返回false
*/
Boolean deleteGroup(Long id);
/**
* 移动文件组
*
* @param fileGroupDTO SysFileGroupDTO对象,要移动的文件组信息
* @return 移动成功返回true,否则返回false
*/
Boolean moveFileGroup(SysFileGroupDTO fileGroupDTO);
}
@@ -29,11 +29,14 @@ import cn.hutool.crypto.SecureUtil;
import com.amazonaws.services.s3.model.S3Object;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsd.pjcloud.admin.api.config.QnOssConfig;
import com.bsd.pjcloud.admin.api.dto.SysFileGroupDTO;
import com.bsd.pjcloud.admin.api.entity.SysFile;
import com.bsd.pjcloud.admin.api.entity.SysFileGroup;
import com.bsd.pjcloud.admin.api.vo.third.QnUploadVo;
import com.bsd.pjcloud.admin.mapper.SysFileGroupMapper;
import com.bsd.pjcloud.admin.mapper.SysFileMapper;
import com.bsd.pjcloud.admin.service.QnOssService;
import com.bsd.pjcloud.admin.service.SysFileService;
import com.bsd.pjcloud.common.core.constant.CommonConstants;
import com.bsd.pjcloud.common.core.util.R;
@@ -70,6 +73,10 @@ public class SysFileServiceImpl extends ServiceImpl<SysFileMapper, SysFile> impl
private final FileProperties properties;
private final QnOssConfig qnOssConfig;
private final QnOssService qnOssService;
/**
* 上传文件
*
@@ -116,10 +123,25 @@ public class SysFileServiceImpl extends ServiceImpl<SysFileMapper, SysFile> impl
return R.ok(resultMap);
}
/**
* 七牛云上传
*/
@Override
public R<Map<String, String>> qnUpload(MultipartFile file, String dir, Long groupId, String type) {
String fileName = IdUtil.simpleUUID() + StrUtil.DOT + FileUtil.extName(file.getOriginalFilename());
Map<String, String> resultMap = new HashMap<>(4);
QnUploadVo upload = qnOssService.upload(file, fileName);
resultMap.put("bucketName", qnOssConfig.getOss().getBucketName());
resultMap.put("fileName", fileName);
resultMap.put("url", upload.getFullUrl());
return R.ok(resultMap);
}
/**
* 读取文件
*
* @param bucket
* @param fileName
* @param response
*/
@@ -0,0 +1,54 @@
package com.bsd.pjcloud.admin.service.impl.third;
import com.alibaba.nacos.shaded.com.google.gson.Gson;
import com.bsd.pjcloud.admin.api.config.QnOssConfig;
import com.bsd.pjcloud.admin.api.vo.third.QnUploadVo;
import com.bsd.pjcloud.admin.service.QnOssService;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
@Slf4j
@Service
@RequiredArgsConstructor
public class QnOssServiceImpl implements QnOssService {
private final QnOssConfig qnOssConfig;
@Override
public QnUploadVo upload(MultipartFile file, String fileName) {
QnOssConfig.Oss oss = qnOssConfig.getOss();
Auth auth = Auth.create(oss.getAccessKey(), oss.getSecretKey());
String upToken = auth.uploadToken(oss.getBucketName());
Configuration config = Configuration.create(Region.region0());
config.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;
UploadManager uploadManager = new UploadManager(config);
try (InputStream inputStream = file.getInputStream()) {
Response response = uploadManager.put(inputStream, fileName, upToken, null, null);
DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
QnUploadVo result = new QnUploadVo();
result.setFileHash(putRet.hash);
result.setFileName(fileName);
result.setFullUrl(oss.getDomain() + "/" + putRet.key);
return result;
} catch (Exception e) {
e.printStackTrace();
log.error("七牛云上传视频错误:{}", e.getMessage());
return null;
}
}
}
@@ -18,4 +18,9 @@ spring:
- optional:nacos:${spring.application.name}-@profiles.active@.yml
qn:
oss:
accessKey: IVrAjjdrTeZi14pqDd2s5kb_iAIGXATEMtOgmQUF
secretKey: SNhPscR3_xqX3E_B1XtMMWmLMrz7ipcguzNykQvo
bucketName: bizcabinet
domain: https://bizcabinet.zianxin.com
@@ -18,7 +18,6 @@ public enum ActCancelStatusEnum {
CANCEL_EXPIRE("3", "已过期"),
;
private final String code;
private final String desc;
public static ActCancelStatusEnum valueOfByType(String code) {
@@ -0,0 +1,35 @@
package com.bsd.pjcloud.wallet.api.constant.act;
import cn.hutool.core.util.ObjectUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 核销活动状体啊
*/
@Getter
@AllArgsConstructor
public enum ActStatusEnum {
ACT_OPEN("1", "开启"),
ACT_CANCEL("2", "关闭活动"),
;
private final String code;
private final String desc;
public static ActStatusEnum valueOfByType(String code) {
return Arrays.stream(ActStatusEnum.values())
.filter(v -> ObjectUtil.equal(v.getCode(), code))
.findFirst().get();
}
public static ActStatusEnum descOf(String description) {
return Arrays.stream(ActStatusEnum.values())
.filter(v -> ObjectUtil.equal(v.getDesc(), description))
.findFirst().get();
}
}
@@ -0,0 +1,9 @@
package com.bsd.pjcloud.wallet.api.dto.act;
import com.bsd.pjcloud.wallet.api.entity.act.ActCancelEntity;
import lombok.Data;
@Data
public class ActCancelDto extends ActCancelEntity {
}
@@ -0,0 +1,119 @@
package com.bsd.pjcloud.wallet.api.entity.act;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import com.bsd.pjcloud.common.core.util.TenantTable;
import java.time.LocalDateTime;
/**
* 核销活动
*/
@Data
@TenantTable
@TableName("act_cancel")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "核销活动")
public class ActCancelEntity extends Model<ActCancelEntity> {
/**
* 活动项id
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "活动项id")
private Long id;
/**
* 活动商户id
*/
@Schema(description = "活动商户id")
private Long mchId;
/**
* 公告id
*/
@Schema(description = "公告id")
private Long noticeId;
/**
* 活动原价
*/
@Schema(description = "活动原价")
private Integer activeOrgPrice;
/**
* 活动核销价
*/
@Schema(description = "活动核销价")
private Integer activeCancelPrice;
/**
* 到期时间
*/
@Schema(description = "到期时间")
private LocalDateTime expireTime;
/**
* 活动状态(1:正常 2:关闭)
*/
@Schema(description = "活动状态(1:正常 2:关闭)")
private String actStatus;
/**
* 活动标题
*/
@Schema(description = "活动标题")
private String actTitle;
/**
* 活动内容
*/
@Schema(description = "活动内容")
private String actContent;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建人")
private String createBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建时间")
private LocalDateTime createTime;
/**
* 修改人
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "修改人")
private String updateBy;
/**
* 修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "修改时间")
private LocalDateTime updateTime;
/**
* 删除标记
*/
@TableLogic
@TableField(fill = FieldFill.INSERT)
@Schema(description = "删除标记")
private String delFlag;
/**
* 租户ID
*/
@Schema(description = "租户ID")
private Long tenantId;
}
@@ -0,0 +1,21 @@
package com.bsd.pjcloud.wallet.api.vo.act;
import com.bsd.pjcloud.wallet.api.entity.act.ActCancelEntity;
import com.bsd.pjcloud.wallet.api.vo.base.BaseMchInterface;
import lombok.Data;
@Data
public class ActCancelVo extends ActCancelEntity implements BaseMchInterface {
/**
* 商户相关
*/
private Long merchantId;
private String merchantName;
private String logoPic;
private String merchantType;
}
@@ -0,0 +1,72 @@
package com.bsd.pjcloud.wallet.controller.act;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.common.core.util.R;
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.service.ActCancelService;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
/**
* 核销活动
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/act/act-cancel")
@Tag(description = "act-cancel", name = "核销活动管理")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class ActCancelController {
private final ActCancelService actCancelService;
@Operation(summary = "分页查询", description = "分页查询")
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('wallet_actCancel_view')")
public R getActCancelPage(@ParameterObject Page page, @ParameterObject ActCancelDto dto) {
return R.ok(actCancelService.scopePageJoin(page, dto, DataScope.of()));
}
@Operation(summary = "通过id查询", description = "通过id查询")
@GetMapping("/{id}")
@PreAuthorize("@pms.hasPermission('wallet_actCancel_view')")
public R getById(@PathVariable("id") Long id) {
return R.ok(actCancelService.getById(id));
}
@Operation(summary = "新增核销活动", description = "新增核销活动")
@SysLog("新增核销活动")
@PostMapping
@PreAuthorize("@pms.hasPermission('wallet_actCancel_add')")
public R<Long> save(@RequestBody ActCancelDto dto) {
return R.ok(actCancelService.create(dto));
}
@Operation(summary = "修改核销活动", description = "修改核销活动")
@SysLog("修改核销活动")
@PutMapping
@PreAuthorize("@pms.hasPermission('wallet_actCancel_edit')")
public R updateById(@RequestBody ActCancelEntity actCancel) {
return R.ok(actCancelService.updateById(actCancel));
}
@Operation(summary = "通过id删除核销活动", description = "通过id删除核销活动")
@SysLog("通过id删除核销活动")
@DeleteMapping
@PreAuthorize("@pms.hasPermission('wallet_actCancel_del')")
public R removeById(@RequestBody Long[] ids) {
actCancelService.delByIds(CollUtil.toList(ids));
return R.ok();
}
}
@@ -0,0 +1,19 @@
package com.bsd.pjcloud.wallet.mapper.act;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
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 org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface ActCancelMapper extends PjcloudBaseMapper<ActCancelEntity> {
List<ActCancelVo> scopePageJoin(Page page, @Param("dto") ActCancelDto dto, DataScope dataScope);
}
@@ -0,0 +1,29 @@
package com.bsd.pjcloud.wallet.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bsd.pjcloud.common.data.datascope.DataScope;
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 java.util.ArrayList;
import java.util.List;
public interface ActCancelService extends IService<ActCancelEntity> {
/**
* 分页查询
*/
List<ActCancelVo> scopePageJoin(Page page, ActCancelDto dto, DataScope dataScope);
/**
* 新增
*/
Long create(ActCancelDto dto);
/**
* 根据ids删除
*/
void delByIds(ArrayList<Long> list);
}
@@ -0,0 +1,73 @@
package com.bsd.pjcloud.wallet.service.impl.act;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
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.entity.act.ActCancelEntity;
import com.bsd.pjcloud.wallet.api.entity.act.ActCancelItemEntity;
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;
import com.bsd.pjcloud.wallet.service.ActCancelService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* 核销活动
*/
@Service
@Slf4j
@RequiredArgsConstructor
public class ActCancelServiceImpl extends ServiceImpl<ActCancelMapper, ActCancelEntity> implements ActCancelService {
private final ActCancelItemMapper actCancelItemMapper;
/**
* 分页查询
*/
@Override
public List<ActCancelVo> scopePageJoin(Page page, ActCancelDto dto, DataScope dataScope) {
return baseMapper.scopePageJoin(page, dto, dataScope);
}
/**
* 新增
*/
@Override
public Long create(ActCancelDto dto) {
ActCancelEntity savObj = BeanUtils.toBean(dto, ActCancelEntity.class);
if (ObjectUtil.isEmpty(savObj.getActStatus())) {
savObj.setActStatus(ActStatusEnum.ACT_OPEN.getCode());
}
baseMapper.insert(savObj);
return savObj.getId();
}
/**
* 根据ids删除
*/
@Override
public void delByIds(ArrayList<Long> actIds) {
if (ObjectUtil.isEmpty(actIds)) return;
List<ActCancelEntity> list = baseMapper.selectList(new LambdaQueryWrapper<ActCancelEntity>().in(ActCancelEntity::getId, actIds));
if (ObjectUtil.isEmpty(list)) return;
for (ActCancelEntity v : list) {
if (ObjectUtil.equals(v.getActStatus(), ActStatusEnum.ACT_OPEN.getCode())) {
throw new RuntimeException("<" + v.getActTitle() + ">,该活动未关闭,无法删除!");
}
Long cout = actCancelItemMapper.selectCount(new LambdaQueryWrapper<ActCancelItemEntity>().eq(ActCancelItemEntity::getActId, v.getId()));
if (ObjectUtil.isNotEmpty(cout) && cout > 0) {
throw new RuntimeException("<" + v.getActTitle() + ">,该活动已有人参加活动,无法删除!");
}
}
}
}
@@ -0,0 +1,52 @@
<?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="com.bsd.pjcloud.wallet.mapper.act.ActCancelMapper">
<sql id="selectA">
select a.id,
a.mch_id,
a.notice_id,
a.active_org_price,
a.active_cancel_price,
a.expire_time,
a.act_status,
a.act_title,
a.act_content,
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.mchId != null">
and a.mch_id = #{dto.mchId}
</if>
<if test="dto.noticeId != null">
and a.notice_id = #{dto.noticeId}
</if>
<if test="dto.actStatus != null and dto.actStatus != '' ">
and a.act_status = #{dto.noticeId}
</if>
<if test="dto.actTitle != null">
and a.actTitle LIKE concat('%',#{dto.actTitle},'%')
</if>
</sql>
<select id="scopePageJoin" resultType="com.bsd.pjcloud.wallet.api.vo.act.ActCancelVo">
<include refid="selectA"/>,
m.id as merchantId,
m.name merchantName,
m.logo_pic as logoPic,
m.types as merchantType
from act_cancel a
left join mch_manage m on m.id = a.mch_id
<where>
<include refid="whereA"/>
</where>
</select>
</mapper>