Merge remote-tracking branch 'origin/master'

This commit is contained in:
zjf committed 2025-09-30 16:55:20 +08:00
commit 06d2bc5feb
27 files changed
+707 -8

No files matched your search

@@ -0,0 +1,33 @@
package com.bsd.pjcloud.common.core.constant.enums;
import cn.hutool.core.util.ObjectUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 日期范围类型
*/
@AllArgsConstructor
@Getter
public enum DateRangeTypeEnum {
YESTERDAY("0", "昨天"),
TODAY("1", "今日"),
THIS_WEEK("2", "本周"),
THIS_MONTH("3", "本月"),
CURRENT_SEASON("4", "本季度"),
HALF_YEAR("5", "近半年"),
THIS_YEAR("6", "本年"),
;
private final String type;
private final String description;
public static DateRangeTypeEnum valueOfByType(String type) {
if (ObjectUtil.isEmpty(type)) return null;
return Arrays.stream(values()).filter(v -> ObjectUtil.equals(type, v.getType())).findFirst().get();
}
}
@@ -0,0 +1,59 @@
package com.bsd.pjcloud.common.core.util;
import com.bsd.pjcloud.common.core.constant.enums.DateRangeTypeEnum;
import lombok.experimental.UtilityClass;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
/**
* 时间范围工具类
*/
@UtilityClass
public class DateRangeTool {
static public LocalDate[] transitionDateTypeToDateList(DateRangeTypeEnum dateType) {
LocalDateTime[] localDateTimes = transitionDateTypeToDateTimeList(dateType);
return new LocalDate[]{localDateTimes[0].toLocalDate(), localDateTimes[1].toLocalDate(),};
}
static public LocalDateTime[] transitionDateTypeToDateTimeList(DateRangeTypeEnum dateType) {
LocalDateTime now = LocalDateTime.now();
switch (dateType) {
case YESTERDAY:
return new LocalDateTime[]{
LocalDateTime.now().minusDays(1).withHour(0).withMinute(0).withSecond(0),
LocalDateTime.now().minusDays(1).withHour(23).withMinute(59).withSecond(59)
};
case TODAY:
return new LocalDateTime[]{
LocalDateTime.now().withHour(0).withMinute(0).withSecond(0),
LocalDateTime.now().withHour(23).withMinute(59).withSecond(59)
};
case THIS_WEEK:
LocalDateTime weekStart = now.minusDays(7).withHour(0).withMinute(0).withSecond(0);
LocalDateTime weekEnd = now.withHour(23).withMinute(59).withSecond(59);
return new LocalDateTime[]{weekStart, weekEnd};
case THIS_MONTH:
LocalDateTime monthStart = now.with(TemporalAdjusters.firstDayOfMonth()).withHour(0).withMinute(0).withSecond(0);
LocalDateTime monthEnd = now.with(TemporalAdjusters.lastDayOfMonth()).withHour(23).withMinute(59).withSecond(59);
return new LocalDateTime[]{monthStart, monthEnd};
case CURRENT_SEASON:
LocalDateTime quarterStart = now.with(now.getMonth().firstMonthOfQuarter()).with(TemporalAdjusters.firstDayOfMonth()).withHour(0).withMinute(0).withSecond(0);
LocalDateTime quarterEnd = quarterStart.plusMonths(2).with(TemporalAdjusters.lastDayOfMonth()).withHour(23).withMinute(59).withSecond(59);
return new LocalDateTime[]{quarterStart, quarterEnd};
case HALF_YEAR:
LocalDateTime halfYearStart = now.with(now.getMonth().firstMonthOfQuarter()).with(TemporalAdjusters.firstDayOfMonth()).withHour(0).withMinute(0).withSecond(0);
LocalDateTime halfYearEnd = halfYearStart.plusMonths(6).with(TemporalAdjusters.lastDayOfMonth()).withHour(23).withMinute(59).withSecond(59);
return new LocalDateTime[]{halfYearStart, halfYearEnd};
case THIS_YEAR:
LocalDateTime yearStart = now.with(TemporalAdjusters.firstDayOfYear()).withHour(0).withMinute(0).withSecond(0);
LocalDateTime yearEnd = now.with(TemporalAdjusters.lastDayOfYear()).withHour(23).withMinute(59).withSecond(59);
return new LocalDateTime[]{yearStart, yearEnd};
default:
return null;
}
}
}
@@ -65,7 +65,7 @@ public class DataScopeInnerInterceptor implements DataScopeInterceptor {
dataScope.getFunc().getType(), originalSql, dataScope.getScopeUserName(), dataScope.getUsername(), dataScope.getScopeDeptName(), join);
}
// 3. 如果为本人
else if (StrUtil.isNotBlank(dataScope.getUsername())) {
else if (StrUtil.isNotBlank(dataScope.getUsername()) && ObjectUtil.isNotEmpty(dataScope.getScopeUserName())) {
originalSql = String.format("SELECT %s FROM (%s) temp_data_scope WHERE temp_data_scope.%s = '%s'",
dataScope.getFunc().getType(), originalSql, dataScope.getScopeUserName(), dataScope.getUsername());
}
@@ -0,0 +1,25 @@
package com.bsd.pjcloud.hard.api.dto.panel;
import com.bsd.pjcloud.common.core.constant.enums.DateRangeTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class PanelCanteenDto {
private DateRangeTypeEnum dateRangeType = DateRangeTypeEnum.YESTERDAY;
private LocalDateTime[] totalTimeList;
private String hourType;
private Long limit;
}
@@ -0,0 +1,103 @@
package com.bsd.pjcloud.hard.api.vo.hard;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class PanelCanteenVo {
/**
* 商品名
*/
private String productName;
/**
* 用餐时间段(早中晚)
*/
private String hourType;
/**
* 商品名
*/
private String productStr;
/**
* 用餐人数
*/
private Long personCount;
/**
* 购买次数
*/
private Long buyCount;
/**
* 购买商品数量
*/
private Long buyProductCount;
/**
* 购买总金额(分)
*/
private Long totalPrice;
/**
* 时间
*/
private LocalDate time;
/**
* 时间字符串
*/
private LocalDate timeStr;
/**
* 周几
*/
private String weekStr;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class HourTypeItemVo {
private String type;
private String typeStr;
private List<PanelCanteenVo> list;
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class HourTypeVo {
/**
* 早
*/
private HourTypeItemVo morning;
/**
* 中
*/
private HourTypeItemVo noon;
/**
* 晚
*/
private HourTypeItemVo evening;
}
}
@@ -0,0 +1,77 @@
package com.bsd.pjcloud.hard.controller.panel;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.common.core.util.DateRangeTool;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.hard.api.dto.order.HardOrderDto;
import com.bsd.pjcloud.hard.api.dto.panel.PanelCanteenDto;
import com.bsd.pjcloud.hard.api.vo.hard.PanelCanteenVo;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderVo;
import com.bsd.pjcloud.hard.service.HardOrderService;
import com.bsd.pjcloud.hard.service.PanelCanteenService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequiredArgsConstructor
@RequestMapping("/panel-canteen")
@Tag(description = "panel-canteen", name = "食堂统计")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class PanelCanteenController {
private final PanelCanteenService panelCanteenService;
private final HardOrderService hardwareOrderService;
@PostMapping(value = "/group/by-time-and-hour-type")
@Operation(summary = "用餐数据统计(根据时间段和日期分类统计)")
public R<PanelCanteenVo.HourTypeVo> groupByTimeAndHourType(PanelCanteenDto dto) {
if (ObjectUtil.isNotEmpty(dto.getDateRangeType()) && ObjectUtil.isNotEmpty(dto.getTotalTimeList())) {
dto.setTotalTimeList(DateRangeTool.transitionDateTypeToDateTimeList(dto.getDateRangeType()));
}
return R.ok(panelCanteenService.groupByTimeAndHourType(dto));
}
@PostMapping(value = "/group/classify/by-time-and-hour-type")
@Operation(summary = "菜品分类统计(根据时间段和日期分类统计)")
public R<PanelCanteenVo.HourTypeVo> classifyGroupByTimeAndHourType(PanelCanteenDto dto) {
if (ObjectUtil.isNotEmpty(dto.getDateRangeType()) && ObjectUtil.isNotEmpty(dto.getTotalTimeList())) {
dto.setTotalTimeList(DateRangeTool.transitionDateTypeToDateTimeList(dto.getDateRangeType()));
}
return R.ok(panelCanteenService.classifyGroupByTimeAndHourType(dto));
}
@PostMapping(value = "/group/by-time-and-custom-hour")
@Operation(summary = "用餐数据统计(根据自定义时间段和日期分类统计)")
public R<List<PanelCanteenVo>> groupByTimeAndCustomHour(PanelCanteenDto dto) {
if (ObjectUtil.isNotEmpty(dto.getDateRangeType()) && ObjectUtil.isNotEmpty(dto.getTotalTimeList())) {
dto.setTotalTimeList(DateRangeTool.transitionDateTypeToDateTimeList(dto.getDateRangeType()));
}
return R.ok(panelCanteenService.groupByTimeAndCustomHour(dto));
}
@PostMapping(value = "/top")
@Operation(summary = "排行榜")
public R<List<PanelCanteenVo>> top(PanelCanteenDto dto) {
if (ObjectUtil.isNotEmpty(dto.getDateRangeType()) && ObjectUtil.isNotEmpty(dto.getTotalTimeList())) {
dto.setTotalTimeList(DateRangeTool.transitionDateTypeToDateTimeList(dto.getDateRangeType()));
}
dto.setLimit(5L);
return R.ok(panelCanteenService.top(dto));
}
@PostMapping(value = "/new-page")
@Operation(summary = "最新的吃饭数据")
public R<Page<HardOrderVo>> newPage(@ParameterObject Page page, HardOrderDto dto) {
return R.ok(hardwareOrderService.scopePageList(page, dto, null));
}
}
@@ -0,0 +1,17 @@
package com.bsd.pjcloud.hard.controller.panel;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequiredArgsConstructor
@RequestMapping("/panel-mch")
@Tag(description = "panel-mch", name = "商户统计")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class PanelMchController {
}
@@ -0,0 +1,17 @@
package com.bsd.pjcloud.hard.controller.panel;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequiredArgsConstructor
@RequestMapping("/panel-mch")
@Tag(description = "panel-mch", name = "超市统计")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class PanelSupermarketController {
}
@@ -10,8 +10,10 @@ import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
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.order.HardOrderSumAndCountDto;
import com.bsd.pjcloud.hard.api.dto.panel.PanelCanteenDto;
import com.bsd.pjcloud.hard.api.entity.manager.HardManagerEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.api.vo.hard.PanelCanteenVo;
import com.bsd.pjcloud.hard.api.vo.order.*;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
@@ -133,4 +135,14 @@ public interface HardOrderMapper extends PjcloudBaseMapper<HardOrderEntity> {
List<HardOrderSumAndCountVo> sumAndCountTotalByHourType(@Param("dto") HardOrderSumAndCountDto dto);
HardZyCardSyncVo totalYearMonthDay(@Param("dto") HardOrderDto hardOrderDto);
/**
* 用餐数据统计(根据时间段和日期分类统计)
*/
List<PanelCanteenVo> groupByTimeAndHourType(@Param("dto") PanelCanteenDto dto);
/**
* 用餐数据统计(根据时间段和日期分类统计)
*/
List<PanelCanteenVo> top(@Param("dto") PanelCanteenDto dto);
}
@@ -0,0 +1,68 @@
package com.bsd.pjcloud.hard.redis;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bsd.pjcloud.common.core.constant.CacheConstants;
import com.bsd.pjcloud.hard.api.constant.order.HardOrderStatusEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardOrderTypeEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardPayTypeEnum;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.mapper.order.HardOrderMapper;
import jakarta.annotation.Resource;
import lombok.extern.log4j.Log4j2;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
/**
* 监听Redis的Key过期事件
*/
@Component
@Log4j2
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
@Resource
private HardOrderMapper hardOrderMapper;
public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
@Override
public void onMessage(Message message, byte[] pattern) {
String expiredKey = message.toString();
String expiredPattern = new String(pattern, StandardCharsets.UTF_8);
// 过期订单(扫一扫支付)
if (expiredKey.startsWith(CacheConstants.HARDER_ORDER_NON_PAY)) {
log.info("hard模块RedisKey过期,pattern|{}|key|{}|", expiredPattern, expiredKey);
disposeExpiredQrCodeScanOrder(expiredKey);
}
}
// 删除过期的扫一扫订单
public void disposeExpiredQrCodeScanOrder(String expiredValue) {
if (ObjectUtil.isEmpty(expiredValue)) return;
String orderId = expiredValue.substring(CacheConstants.HARDER_ORDER_NON_PAY.length() + 1);
HardOrderEntity order = hardOrderMapper.selectOne(new LambdaQueryWrapper<HardOrderEntity>()
.eq(HardOrderEntity::getId, orderId)
.eq(HardOrderEntity::getPayType, HardPayTypeEnum.WALLET_QR_CODE_SCAN.getType())
.eq(HardOrderEntity::getOrderStatus, HardOrderStatusEnum.CREATE.getType())
);
if (ObjectUtil.isEmpty(order)) {
log.info("删除过期的扫一扫订单,订单不存在orderId|{}|", orderId);
return;
}
if (ObjectUtil.isEmpty(order.getWalletId()) && ObjectUtil.equals(order.getUserId(), -1L)) {
// 删除订单
hardOrderMapper.deleteById(order.getId());
log.info("删除过期的扫一扫订单,orderId|{}|", expiredValue);
}
}
}
@@ -0,0 +1,29 @@
package com.bsd.pjcloud.hard.service;
import com.bsd.pjcloud.hard.api.dto.panel.PanelCanteenDto;
import com.bsd.pjcloud.hard.api.vo.hard.PanelCanteenVo;
import java.util.List;
public interface PanelCanteenService {
/**
* 用餐数据统计(根据时间段和日期分类统计)
*/
PanelCanteenVo.HourTypeVo groupByTimeAndHourType(PanelCanteenDto dto);
/**
* 菜品分类统计(根据时间段和日期分类统计)
*/
PanelCanteenVo.HourTypeVo classifyGroupByTimeAndHourType(PanelCanteenDto dto);
/**
* 用餐数据统计(根据自定义时间段和日期分类统计)
*/
List<PanelCanteenVo> groupByTimeAndCustomHour(PanelCanteenDto dto);
/**
* 排行榜
*/
List<PanelCanteenVo> top(PanelCanteenDto dto);
}
@@ -0,0 +1,4 @@
package com.bsd.pjcloud.hard.service;
public interface PanelMchService {
}
@@ -0,0 +1,5 @@
package com.bsd.pjcloud.hard.service;
public interface PanelSupermarketService {
}
@@ -1,5 +1,7 @@
package com.bsd.pjcloud.hard.service.impl.order;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
@@ -1376,9 +1378,31 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
RequestContextHolder.setRequestAttributes(requestAttributes);
List<Long> userIds = list.stream().map(HardOrderVo::getUserId).filter(ObjectUtil::isNotEmpty).distinct().toList();
if (ObjectUtil.isNotEmpty(userIds)) {
List<UserVO> userList = userService.getUserDeptByIds(new ArrayList<>(userIds)).getData();
List<UserVO> userList = userService.getUserDeptByIds(userIds).getData();
if (ObjectUtil.isNotEmpty(userList)) {
DataUtil.convertUserDeptList(list, CollectionUtils.convertMap(userList, UserVO::getUserId));
Map<Long, UserVO> map = CollectionUtils.convertMap(userList, UserVO::getUserId);
for (HardOrderVo item : list) {
UserVO userVO = map.get(item.getUserId());
if (ObjectUtil.isEmpty(userVO)) continue;
item.setUsername(userVO.getName());
item.setUserMobile(userVO.getPhone());
item.setUserAvatar(userVO.getAvatar());
}
}
}
});
// 当前部门
CompletableFuture<Void> currentDeptFuture = CompletableFuture.runAsync(() -> {
RequestContextHolder.setRequestAttributes(requestAttributes);
List<Long> deptIds = list.stream().map(HardOrderVo::getUserDeptId).filter(ObjectUtil::isNotEmpty).distinct().toList();
if (ObjectUtil.isNotEmpty(deptIds)) {
Map<Long, SysDept> deptList = deptService.getDeptByDeptIds(deptIds).getData();
if (ObjectUtil.isNotEmpty(deptList)) {
for (HardOrderVo item : list) {
SysDept dept = deptList.get(item.getUserDeptId());
if (ObjectUtil.isEmpty(dept)) continue;
item.setUserDeptName(dept.getName());
}
}
}
});
@@ -1428,6 +1452,6 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
v.setCarList(carVoList);
}
}
CompletableFuture.allOf(deptFuture, mchFuture, deviceFuture, walletFuture).join();
CompletableFuture.allOf(deptFuture, mchFuture, deviceFuture, currentDeptFuture, walletFuture).join();
}
}
@@ -0,0 +1,118 @@
package com.bsd.pjcloud.hard.service.impl.panel;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import com.bsd.pjcloud.hard.api.constant.order.HardHourTypeEnum;
import com.bsd.pjcloud.hard.api.dto.panel.PanelCanteenDto;
import com.bsd.pjcloud.hard.api.vo.hard.PanelCanteenVo;
import com.bsd.pjcloud.hard.mapper.order.HardOrderMapper;
import com.bsd.pjcloud.hard.service.PanelCanteenService;
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.LocalDate;
import java.time.LocalDateTime;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Validated
@Slf4j
@RequiredArgsConstructor
@Service
public class PanelCanteenServiceImpl implements PanelCanteenService {
private final HardOrderMapper hardOrderMapper;
/**
* 用餐数据统计(根据时间段和日期分类统计)
*/
@Override
public PanelCanteenVo.HourTypeVo groupByTimeAndHourType(PanelCanteenDto dto) {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
List<PanelCanteenVo> dateList = generatePanelCanteenList(dto.getTotalTimeList());
PanelCanteenVo.HourTypeVo result = new PanelCanteenVo.HourTypeVo();
List<HardHourTypeEnum> hourTypeList = List.of(HardHourTypeEnum.MORNING, HardHourTypeEnum.NOONING, HardHourTypeEnum.NIGHT);
hourTypeList.stream().map(hourType -> CompletableFuture.runAsync(() -> {
RequestContextHolder.setRequestAttributes(requestAttributes);
PanelCanteenDto queryDto = BeanUtil.toBean(dto, PanelCanteenDto.class);
queryDto.setHourType(hourType.getType());
List<PanelCanteenVo> sqlList = hardOrderMapper.groupByTimeAndHourType(queryDto);
// 处理查询出来的数据
List<PanelCanteenVo> resultList = BeanUtil.copyToList(dateList, PanelCanteenVo.class);
for (PanelCanteenVo 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());
});
}
// 组装数据
PanelCanteenVo.HourTypeItemVo vo = PanelCanteenVo.HourTypeItemVo.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().forEach(CompletableFuture::join);
return result;
}
/**
* 菜品分类统计(根据时间段和日期分类统计)
*/
@Override
public PanelCanteenVo.HourTypeVo classifyGroupByTimeAndHourType(PanelCanteenDto dto) {
List<PanelCanteenVo> sqlList = hardOrderMapper.groupByTimeAndHourType(dto);
return null;
}
/**
* 用餐数据统计(根据时间段和日期分类统计)
*/
@Override
public List<PanelCanteenVo> groupByTimeAndCustomHour(PanelCanteenDto dto) {
return null;
}
/**
* 排行榜
*/
@Override
public List<PanelCanteenVo> top(PanelCanteenDto dto) {
return hardOrderMapper.top(dto);
}
private List<PanelCanteenVo> generatePanelCanteenList(LocalDateTime[] totalTimeList) {
List<PanelCanteenVo> dateList = new LinkedList<>();
LocalDate startTime = totalTimeList[0].toLocalDate();
LocalDate endTime = totalTimeList[1].toLocalDate();
LocalDate currentDate = startTime;
while (!currentDate.isAfter(endTime)) {
PanelCanteenVo entity = new PanelCanteenVo();
entity.setPersonCount(0L);
entity.setBuyCount(0L);
entity.setBuyProductCount(0L);
entity.setTime(currentDate);
entity.setWeekStr(LocalDateTimeUtil.dayOfWeek(currentDate).toChinese());
dateList.add(entity);
currentDate = currentDate.plusDays(1);
}
return dateList;
}
}
@@ -0,0 +1,15 @@
package com.bsd.pjcloud.hard.service.impl.panel;
import com.bsd.pjcloud.hard.service.PanelMchService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@Validated
@Slf4j
@RequiredArgsConstructor
@Service
public class PanelMchServiceImpl implements PanelMchService {
}
@@ -0,0 +1,15 @@
package com.bsd.pjcloud.hard.service.impl.panel;
import com.bsd.pjcloud.hard.service.PanelSupermarketService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@Validated
@Slf4j
@RequiredArgsConstructor
@Service
public class PanelSupermarketServiceImpl implements PanelSupermarketService {
}
@@ -549,4 +549,55 @@
</if>
</where>
</select>
<select id="groupByTimeAndHourType" resultType="com.bsd.pjcloud.hard.api.vo.hard.PanelCanteenVo">
select
date(o.create_time) as time,
o.hour_type as hourType,
SUM(a.product_count) as buyProductCount,
SUM(a.total_price) as totalPrice,
count(distinct o.id) as buyCount,
count(distinct o.user_id) as personCount
from hard_car a
inner join hard_parent_car p on a.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')
<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>
</where>
group by date(o.create_time), o.hour_type
<if test="dto.limit != null">
limit #{dto.limit}
</if>
</select>
<select id="top" resultType="com.bsd.pjcloud.hard.api.vo.hard.PanelCanteenVo">
select a.product_name as productName,
sum(a.product_count) as buyProductCount
from hard_car a
inner join hard_parent_car p on a.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')
<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>
</where>
group by a.product_id
order by sum(a.product_count) desc
<if test="dto.limit != null">
limit #{dto.limit}
</if>
</select>
</mapper>
@@ -258,7 +258,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
@Override
public IPage<UserVO> getUsersWithRolePage(Page page, UserDTO userDTO) {
DataScope dataScope = DataScope.of();
// dataScope.setScopeUserName(null);
dataScope.setScopeUserName(null);
IPage<UserVO> list = baseMapper.getUserVosPage(page, userDTO, dataScope);
if (ObjectUtil.isNotEmpty(list.getRecords())) {
List<Long> userIds = list.getRecords().stream().map(UserVO::getUserId).distinct().toList();
@@ -57,6 +57,12 @@ public class WalletRuleJoinEntity extends Model<WalletRuleJoinEntity> {
@Schema(description = "是否启用")
private String status;
/**
* 是否保留100元(用户跨单位支付)
*/
@Schema(description = "是否保留100元(用户跨单位支付)")
private String isReservePrice;
/**
* 创建人
*/
@@ -67,4 +67,9 @@ public class WalletRuleJoinUserConfigVo {
*/
private Integer balanceMultiple;
/**
* 是否保留100元用于钱包支付
*/
private String isReservePrice;
}
@@ -55,7 +55,7 @@ public class WalletRechargeApplyController {
@PostMapping("/save-topup")
@Operation(summary = "新增充值")
@Idempotent(expireTime = 3, info = "正在充值中,请勿重复操作")
@Idempotent(expireTime = 3, key = "'/wallet-recharge-apply/save-topup' + #dto.getInvoiceId()", info = "正在充值中,请勿重复操作")
public R comparePageJoin(@RequestBody WalletRechargeSaveTopupDto dto) {
walletRechargeApplyService.saveTopup(dto);
return R.ok();
@@ -12,7 +12,9 @@ import com.bsd.pjcloud.common.log.annotation.SysLog;
import com.bsd.pjcloud.common.security.annotation.Inner;
import com.bsd.pjcloud.common.security.service.PjcloudUser;
import com.bsd.pjcloud.common.security.util.SecurityUtils;
import com.bsd.pjcloud.flow.task.constant.TaskCheckStatusEnum;
import com.bsd.pjcloud.flow.task.dto.ProcessNodeRecordAssignUserParamDto;
import com.bsd.pjcloud.wallet.api.constant.WalletInvoiceStatusCheckEnum;
import com.bsd.pjcloud.wallet.api.dto.WalletManageBalanceDto;
import com.bsd.pjcloud.wallet.api.dto.recharge.WalletRechargeBindInvoiceDto;
import com.bsd.pjcloud.wallet.api.dto.recharge.WalletRechargeInvoiceApplyDto;
@@ -97,6 +99,7 @@ public class WalletRechargeInvoiceController {
@GetMapping("/select")
public R select(@ParameterObject Page page, @ParameterObject WalletRechargeBindInvoiceDto dto) {
DataScope dataScope = null;
dto.setProcessStatus(TaskCheckStatusEnum.RESULT.getCode());
return R.ok(walletRechargeInvoiceService.scopePageList(page, dto, dataScope));
}
@@ -117,7 +117,9 @@ public class WalletRechargeApplyServiceImpl extends ServiceImpl<WalletRechargeAp
WalletRechargeInvoiceEntity invoice = walletRechargeInvoiceService.getById(dto.getInvoiceId());
if (ObjectUtil.isEmpty(invoice)) throw new RuntimeException("发票记录不存在");
if (ObjectUtil.isNotEmpty(invoice.getApplyId())) throw new RuntimeException("该发票已被绑定");
if (ObjectUtil.notEqual(invoice.getProcessStatus(), TaskCheckStatusEnum.RESULT.getCode())) {
throw new RuntimeException("发票未审核通过");
}
WalletRechargeApplyEntity apply = new WalletRechargeApplyEntity();
apply.setInvoiceId(invoice.getId());
@@ -184,6 +184,7 @@ public class WalletRuleJoinServiceImpl extends ServiceImpl<WalletRuleJoinMapper,
throw new RuntimeException("该用户所属的部门<" + sysDept.getName() + ">未配置未打开");
}
configVo.setBalanceMultiple(walletRuleJoin.getBalanceMultiple());
configVo.setIsReservePrice(walletRuleJoin.getIsReservePrice());
// 计算最大可以转过去的金额
Long maxTransferBalance = BigDecimal.valueOf(sourceWallet.getTotalRecharge()).multiply(BigDecimal.valueOf(walletRuleJoin.getBalanceMultiple())).divide(BigDecimal.valueOf(100)).setScale(0, RoundingMode.HALF_UP).longValue();
configVo.setMaxTransferBalance(maxTransferBalance);
@@ -130,7 +130,10 @@ public class WalletRuleTransactionServiceImpl extends ServiceImpl<WalletRuleTran
// 查询源饭卡
if (ObjectUtil.equals(userConfig.getSourceWalletUniqueCode(), WalletTypeEnum.EAT.getCode())) {
if (price < 10000) {
throw new RuntimeException(WalletTypeEnum.EAT.getDesc() + "余额必须留100元用于公务餐");
// 是否开启用于100元跨单位吃饭
if (ObjectUtil.equals(userConfig.getIsReservePrice(), YesNoEnum.YES.getCode())) {
throw new RuntimeException(WalletTypeEnum.EAT.getDesc() + "余额必须留100元用于公务餐");
}
}
}
// 是否已经超过最大限制
@@ -24,6 +24,7 @@
a.target_dept_id,
a.balance_multiple,
a.status,
a.is_reserve_price,
a.create_by,
a.create_time,
a.update_by,
@@ -34,6 +35,12 @@
<sql id="whereA">
a.del_flag = 0
<if test="dto.targetDeptId != null">
and a.target_dept_id = #{dto.targetDeptId}
</if>
<if test="dto.status != null and dto.status != '' ">
and a.status = #{dto.status}
</if>
<if test="dto.sourceWalletTypeId != null">
and a.source_wallet_type_id = #{dto.sourceWalletTypeId}
</if>