feat:食堂统计

This commit is contained in:
dzc committed 2025-10-09 17:03:29 +08:00
1 parent d7b9c4293e
commit d3d38220eb
12 files changed
+111 -46

No files matched your search

@@ -1,6 +1,7 @@
package com.bsd.pjcloud.hard.api.dto.order;
import com.bsd.pjcloud.admin.api.vo.base.BaseIsIncludeTreeInterface;
import com.bsd.pjcloud.common.core.constant.enums.DateRangeTypeEnum;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import lombok.Data;
@@ -11,6 +12,8 @@ import java.util.List;
@Data
public class HardOrderDto extends HardOrderEntity implements BaseIsIncludeTreeInterface {
private DateRangeTypeEnum dateRangeType = DateRangeTypeEnum.YESTERDAY;
private List<Long> deptIds;
private Boolean isInclude = false;
@@ -19,6 +19,11 @@ public class PanelCanteenVo {
*/
private String productName;
/**
* 商家名称
*/
private String mchName;
/**
* 用餐时间段(早中晚)
*/
@@ -64,6 +69,11 @@ public class PanelCanteenVo {
*/
private String weekStr;
/**
* 排序
*/
private int order;
@Data
@Builder
@AllArgsConstructor
@@ -23,7 +23,6 @@ import com.bsd.pjcloud.hard.api.vo.order.HardCreateHardQrCodeScanOrderVo;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderVo;
import com.bsd.pjcloud.hard.service.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
@@ -105,7 +105,7 @@ public class HardAfterSaleController {
@PostMapping(value = "/admin-refund")
@Operation(summary = "后台退款")
@Idempotent(expireTime = 5, info = "正在退款中,请勿重复操作")
@Idempotent(expireTime = 5, key = "'/hard-after-sale/admin-refund' + #dto.getOrderId() ", info = "正在退款中,请勿重复操作")
@PreAuthorize("@pms.hasPermission('hard_hardAfterSale_adminRefund')")
public R<Boolean> adminRefund(@RequestBody HardAdminRefundDto dto) {
PjcloudUser user = SecurityUtils.getUser();
@@ -17,9 +17,11 @@ 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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.List;
@RestController
@@ -34,44 +36,57 @@ public class PanelCanteenController {
@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())) {
public R<PanelCanteenVo.HourTypeVo> groupByTimeAndHourType(@RequestBody PanelCanteenDto dto) {
if (ObjectUtil.isNotEmpty(dto.getDateRangeType()) && ObjectUtil.isEmpty(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())) {
public R<List<PanelCanteenVo>> groupByTimeAndCustomHour(@RequestBody PanelCanteenDto dto) {
if (ObjectUtil.isNotEmpty(dto.getDateRangeType()) && ObjectUtil.isEmpty(dto.getTotalTimeList())) {
dto.setTotalTimeList(DateRangeTool.transitionDateTypeToDateTimeList(dto.getDateRangeType()));
}
return R.ok(panelCanteenService.groupByTimeAndCustomHour(dto));
}
@PostMapping(value = "/top")
@PostMapping(value = "/mch-pay-person-count")
@Operation(summary = "各个食堂的用餐人数")
public R<List<PanelCanteenVo>> mchPayPersonCount(@RequestBody PanelCanteenDto dto) {
if (ObjectUtil.isNotEmpty(dto.getDateRangeType()) && ObjectUtil.isEmpty(dto.getTotalTimeList())) {
dto.setTotalTimeList(DateRangeTool.transitionDateTypeToDateTimeList(dto.getDateRangeType()));
}
return R.ok(panelCanteenService.mchPayPersonCount(dto));
}
@PostMapping(value = "/mch-pay-person-count-trend")
@Operation(summary = "各个食堂的用餐人数(趋势)")
public R<List<PanelCanteenVo>> mchPayPersonCountTrend(@RequestBody PanelCanteenDto dto) {
dto.setTotalTimeList(new LocalDateTime[]{
LocalDateTime.now().minusDays(6).withHour(0).withMinute(0).withSecond(0),
LocalDateTime.now().withHour(23).withMinute(59).withSecond(59)
});
return R.ok(panelCanteenService.mchPayPersonCount(dto));
}
@PostMapping(value = "/mch-pay-count-top")
@Operation(summary = "排行榜")
public R<List<PanelCanteenVo>> top(PanelCanteenDto dto) {
if (ObjectUtil.isNotEmpty(dto.getDateRangeType()) && ObjectUtil.isNotEmpty(dto.getTotalTimeList())) {
public R<List<PanelCanteenVo>> mchPayCountTop(@RequestBody PanelCanteenDto dto) {
if (ObjectUtil.isNotEmpty(dto.getDateRangeType()) && ObjectUtil.isEmpty(dto.getTotalTimeList())) {
dto.setTotalTimeList(DateRangeTool.transitionDateTypeToDateTimeList(dto.getDateRangeType()));
}
dto.setLimit(5L);
return R.ok(panelCanteenService.top(dto));
return R.ok(panelCanteenService.mchPayCountTop(dto));
}
@PostMapping(value = "/new-page")
@Operation(summary = "最新的吃饭数据")
public R<Page<HardOrderVo>> newPage(@ParameterObject Page page, HardOrderDto dto) {
if (ObjectUtil.isNotEmpty(dto.getDateRangeType()) && ObjectUtil.isEmpty(dto.getCreateTimeList())) {
dto.setCreateTimeList(DateRangeTool.transitionDateTypeToDateTimeList(dto.getDateRangeType()));
}
return R.ok(hardwareOrderService.scopePageList(page, dto, null));
}
}
@@ -142,7 +142,7 @@ public interface HardOrderMapper extends PjcloudBaseMapper<HardOrderEntity> {
List<PanelCanteenVo> groupByTimeAndHourType(@Param("dto") PanelCanteenDto dto);
/**
* 用餐数据统计(根据时间段和日期分类统计)
* 用餐数据统计(根据商户统计)
*/
List<PanelCanteenVo> top(@Param("dto") PanelCanteenDto dto);
List<PanelCanteenVo> groupByMch(@Param("dto") PanelCanteenDto dto);
}
@@ -11,6 +11,7 @@ import com.bsd.pjcloud.hard.api.entity.spu.HardSpuEntity;
import com.bsd.pjcloud.hard.api.vo.spu.HardSpuJoinVo;
import com.bsd.pjcloud.hard.api.vo.spu.HardSpuVo;
import com.bsd.pjcloud.thirdparty.dto.ks.KsSkuSubmitCallbackDto;
import com.bsd.pjcloud.thirdparty.vo.ks.KsSkuResultVo;
import java.util.ArrayList;
import java.util.List;
@@ -40,7 +41,7 @@ public interface HardSpuService extends IService<HardSpuEntity> {
/**
* 更新旷世商品审核进度
*/
void progress(Long id);
KsSkuResultVo progress(Long id);
/**
* 商品审核回调
@@ -13,9 +13,9 @@ public interface PanelCanteenService {
PanelCanteenVo.HourTypeVo groupByTimeAndHourType(PanelCanteenDto dto);
/**
* 菜品分类统计(根据时间段和日期分类统计)
* 各个食堂的用餐人数
*/
PanelCanteenVo.HourTypeVo classifyGroupByTimeAndHourType(PanelCanteenDto dto);
List<PanelCanteenVo> mchPayPersonCount(PanelCanteenDto dto);
/**
* 用餐数据统计(根据自定义时间段和日期分类统计)
@@ -25,5 +25,5 @@ public interface PanelCanteenService {
/**
* 排行榜
*/
List<PanelCanteenVo> top(PanelCanteenDto dto);
List<PanelCanteenVo> mchPayCountTop(PanelCanteenDto dto);
}
@@ -17,6 +17,8 @@ import org.springframework.web.context.request.RequestContextHolder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@@ -73,12 +75,11 @@ public class PanelCanteenServiceImpl implements PanelCanteenService {
}
/**
* 菜品分类统计(根据时间段和日期分类统计)
* 各个食堂的用餐人数
*/
@Override
public PanelCanteenVo.HourTypeVo classifyGroupByTimeAndHourType(PanelCanteenDto dto) {
List<PanelCanteenVo> sqlList = hardOrderMapper.groupByTimeAndHourType(dto);
return null;
public List<PanelCanteenVo> mchPayPersonCount(PanelCanteenDto dto) {
return hardOrderMapper.groupByMch(dto);
}
/**
@@ -86,15 +87,47 @@ public class PanelCanteenServiceImpl implements PanelCanteenService {
*/
@Override
public List<PanelCanteenVo> groupByTimeAndCustomHour(PanelCanteenDto dto) {
return null;
List<PanelCanteenVo> 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);
PanelCanteenDto queryDto = PanelCanteenDto
.builder()
.totalTimeList(new LocalDateTime[]{
now.withHour(targetHour).withMinute(0).withSecond(0),
now.withHour(targetHour).withMinute(59).withSecond(59)
})
.build();
List<PanelCanteenVo> sqlList = hardOrderMapper.groupByTimeAndHourType(queryDto);
PanelCanteenVo build = PanelCanteenVo.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(PanelCanteenVo::getOrder)).toList();
}
/**
* 排行榜
*/
@Override
public List<PanelCanteenVo> top(PanelCanteenDto dto) {
return hardOrderMapper.top(dto);
public List<PanelCanteenVo> mchPayCountTop(PanelCanteenDto dto) {
return hardOrderMapper.groupByMch(dto);
}
private List<PanelCanteenVo> generatePanelCanteenList(LocalDateTime[] totalTimeList) {
@@ -127,7 +127,7 @@ public class HardSpuServiceImpl extends ServiceImpl<HardSpuMapper, HardSpuEntity
* 更新旷世商品审核进度
*/
@Override
public void progress(Long id) {
public KsSkuResultVo progress(Long id) {
HardSpuEntity detail = baseMapper.selectById(id);
if (ObjectUtil.isEmpty(detail)) {
throw new RuntimeException("商品不存在");
@@ -149,6 +149,7 @@ public class HardSpuServiceImpl extends ServiceImpl<HardSpuMapper, HardSpuEntity
update.setKsComments(comments);
baseMapper.updateById(update);
}
return vo;
}
/**
@@ -577,9 +577,12 @@
</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
<select id="groupByMch" resultType="com.bsd.pjcloud.hard.api.vo.hard.PanelCanteenVo">
select o.merchant_id as mchName,
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
@@ -593,7 +596,7 @@
and o.hour_type = #{dto.hourType}
</if>
</where>
group by a.product_id
group by o.merchant_id
order by sum(a.product_count) desc
<if test="dto.limit != null">
limit #{dto.limit}
@@ -33,37 +33,37 @@ public class KsApi {
public static final KsApi.Api SKU_SUBMIT = KsApi.Api.builder().url("/openapi/sc/v1/sku").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT).method(HttpPost.METHOD_NAME).contentType("application/json").build();
// 集合SKU提交审核(未公开)
public static final KsApi.Api SKU_SUBMIT_COLLECTION = KsApi.Api.builder().url("/openapi/sc/v1/sku/collection").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT).method(HttpPost.METHOD_NAME).contentType("application/json").build();
public static final KsApi.Api SKU_SUBMIT_COLLECTION = KsApi.Api.builder().url("/openapi/sc/v1/sku/collection").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT_COLLECTION).method(HttpPost.METHOD_NAME).contentType("application/json").build();
// SKU审核结果主动获取
public static final KsApi.Api SKU_RESULT = KsApi.Api.builder().url("/openapi/sc/v1/sku/%s").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT).method(HttpGet.METHOD_NAME).contentType("application/json").build();
public static final KsApi.Api SKU_RESULT = KsApi.Api.builder().url("/openapi/sc/v1/sku/%s").bizType(ThirdDoorKsApiTypeEnum.RECOGNITION_RESULT).method(HttpGet.METHOD_NAME).contentType("application/json").build();
// 常规SKU修改
public static final KsApi.Api SKU_EDIT = KsApi.Api.builder().url("/openapi/sc/v1/sku/%s").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT).method(HttpPatch.METHOD_NAME).contentType("application/json").build();
public static final KsApi.Api SKU_EDIT = KsApi.Api.builder().url("/openapi/sc/v1/sku/%s").bizType(ThirdDoorKsApiTypeEnum.SKU_EDIT).method(HttpPatch.METHOD_NAME).contentType("application/json").build();
// SKU审核结果回调通知
public static final KsApi.Api SKU_SUBMIT_CALLBACK = KsApi.Api.builder().url("/callback").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT_CALLBACK).method(HttpPatch.METHOD_NAME).contentType("application/json").build();
// SKU删除
public static final KsApi.Api SKU_DELETE = KsApi.Api.builder().url("/openapi/sc/v1/sku/%s").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT).method(HttpDelete.METHOD_NAME).contentType("application/json").build();
public static final KsApi.Api SKU_DELETE = KsApi.Api.builder().url("/openapi/sc/v1/sku/%s").bizType(ThirdDoorKsApiTypeEnum.SKU_DELETE).method(HttpDelete.METHOD_NAME).contentType("application/json").build();
// 根据69码查询标准库和私有库商品信息
public static final KsApi.Api BARCODE_SKU = KsApi.Api.builder().url("/openapi/sc/v1/sku/all_sku/%s").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT).method(HttpGet.METHOD_NAME).contentType("application/json").build();
public static final KsApi.Api BARCODE_SKU = KsApi.Api.builder().url("/openapi/sc/v1/sku/all_sku/%s").bizType(ThirdDoorKsApiTypeEnum.BARCODE_SKU).method(HttpGet.METHOD_NAME).contentType("application/json").build();
// 根据ks_sku_id查询标准库和私有库商品信息
public static final KsApi.Api BARCODE_SKU_BY_ID = KsApi.Api.builder().url("/openapi/sc/v1/sku/skus/%s").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT).method(HttpGet.METHOD_NAME).contentType("application/json").build();
public static final KsApi.Api BARCODE_SKU_BY_ID = KsApi.Api.builder().url("/openapi/sc/v1/sku/skus/%s").bizType(ThirdDoorKsApiTypeEnum.BARCODE_SKU_BY_ID).method(HttpGet.METHOD_NAME).contentType("application/json").build();
// 模糊查询标准库和私有库商品信息
public static final KsApi.Api BARCODE_SKU_LIKE = KsApi.Api.builder().url("/openapi/sc/v1/sku/sku_list").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT).method(HttpGet.METHOD_NAME).contentType("application/json").build();
public static final KsApi.Api BARCODE_SKU_LIKE = KsApi.Api.builder().url("/openapi/sc/v1/sku/sku_list").bizType(ThirdDoorKsApiTypeEnum.BARCODE_SKU_LIKE).method(HttpGet.METHOD_NAME).contentType("application/json").build();
// SKU提交识别
public static final KsApi.Api RECOGNITION = KsApi.Api.builder().url("/openapi/sc/v1/recognition").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT).method(HttpPost.METHOD_NAME).contentType("application/json").build();
public static final KsApi.Api RECOGNITION = KsApi.Api.builder().url("/openapi/sc/v1/recognition").bizType(ThirdDoorKsApiTypeEnum.RECOGNITION).method(HttpPost.METHOD_NAME).contentType("application/json").build();
// SKU识别结果回调通知
public static final KsApi.Api RECOGNITION_CALLBACK = KsApi.Api.builder().url("/callback").bizType(ThirdDoorKsApiTypeEnum.RECOGNITION_CALLBACK).method(HttpPost.METHOD_NAME).contentType("application/json").build();
// SKU识别结果主动获取
public static final KsApi.Api RECOGNITION_RESULT = KsApi.Api.builder().url("/openapi/sc/v1/recognition/%s").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT).method(HttpPost.METHOD_NAME).contentType("application/json").build();
public static final KsApi.Api RECOGNITION_RESULT = KsApi.Api.builder().url("/openapi/sc/v1/recognition/%s").bizType(ThirdDoorKsApiTypeEnum.RECOGNITION_RESULT).method(HttpPost.METHOD_NAME).contentType("application/json").build();
@Data
@Builder