Merge branch 'master' of https://gitea.zianxin.com/zax/biz-api-cloud-zax
This commit is contained in:
commit
23bb5fa2f9
29 files changed
+689
-55
No files matched your search
+30
@@ -0,0 +1,30 @@
|
||||
package com.bsd.pjcloud.canteen.api.feign;
|
||||
|
||||
import com.bsd.pjcloud.canteen.vo.erp.ProductTemplateVO;
|
||||
import com.bsd.pjcloud.common.core.constant.ServiceNameConstants;
|
||||
import com.bsd.pjcloud.common.core.util.R;
|
||||
import com.bsd.pjcloud.common.feign.annotation.NoToken;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 加工模版远程服务(用于线上订餐原料转换)
|
||||
*/
|
||||
@FeignClient(contextId = "remoteCanteenProductionTemplateService", value = ServiceNameConstants.CANTEEN_SERVICE)
|
||||
public interface RemoteCanteenProductionTemplateService {
|
||||
|
||||
/**
|
||||
* 根据菜品id列表获取加工模版详情
|
||||
*/
|
||||
@PostMapping("/canteenProductionTemplate/inner/getDetailsByDishIds")
|
||||
R<List<ProductTemplateVO>> getDetailsByDishIds(@RequestBody List<Long> dishIds);
|
||||
|
||||
/**
|
||||
* 根据菜品id列表获取线上加工模版详情(仅 template_type=2,用于线上订餐统计)
|
||||
*/
|
||||
@PostMapping("/canteenProductionTemplate/inner/getDetailsByDishIdsForOnline")
|
||||
R<List<ProductTemplateVO>> getDetailsByDishIdsForOnline(@RequestBody List<Long> dishIds);
|
||||
}
|
||||
+2
@@ -18,6 +18,8 @@ public class CanteenErpMaterialSaveDTO {
|
||||
@Schema(description="商品单位")
|
||||
private String unit;
|
||||
|
||||
@Schema(description="食材类型:1-线下,2-线上")
|
||||
private Integer materialType;
|
||||
|
||||
/**
|
||||
* 期初数量
|
||||
|
||||
+6
@@ -41,6 +41,12 @@ public class CanteenErpMaterialEntity extends Model<CanteenErpMaterialEntity> {
|
||||
@Schema(description="商品单位")
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 食材类型:1-线下,2-线上
|
||||
*/
|
||||
@Schema(description="食材类型:1-线下,2-线上")
|
||||
private Integer materialType;
|
||||
|
||||
/**
|
||||
* 部门id
|
||||
*/
|
||||
|
||||
+6
@@ -59,6 +59,12 @@ public class CanteenProductionTemplateDetailEntity extends Model<CanteenProducti
|
||||
@Schema(description="损耗率")
|
||||
private Double lossRate;
|
||||
|
||||
/**
|
||||
* 营养元素描述(用户自定义,如:每100g约120kcal、蛋白质5g等)
|
||||
*/
|
||||
@Schema(description="营养元素描述")
|
||||
private String nutritionDesc;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
|
||||
+14
@@ -44,6 +44,12 @@ public class CanteenProductionTemplateEntity extends Model<CanteenProductionTemp
|
||||
@Schema(description="菜品id")
|
||||
private Long dishId;
|
||||
|
||||
/**
|
||||
* 模版类型:1-线下,2-线上(用于数据隔离与统计区分)
|
||||
*/
|
||||
@Schema(description="模版类型:1-线下,2-线上")
|
||||
private Integer templateType;
|
||||
|
||||
/**
|
||||
* 部门id
|
||||
*/
|
||||
@@ -101,4 +107,12 @@ public class CanteenProductionTemplateEntity extends Model<CanteenProductionTemp
|
||||
@TableField(exist = false)
|
||||
@EntityMapping(thisField = "id", joinField = "templateId")
|
||||
private List<CanteenProductionTemplateDetailEntity> canteenProductionTemplateDetailList;
|
||||
|
||||
/**
|
||||
* 菜品名称(回显用,不落库;根据 templateType 从 CanteenSpu 或 CanteenOnlineSpu 解析)
|
||||
*/
|
||||
@ExcelIgnore
|
||||
@TableField(exist = false)
|
||||
@Schema(description = "菜品名称")
|
||||
private String dishName;
|
||||
}
|
||||
+6
@@ -122,6 +122,12 @@ public class CanteenOnlineSpuAppVO {
|
||||
@Schema(description="部门id")
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 关联线下菜品id(canteen_spu.id),用于原料转换
|
||||
*/
|
||||
@Schema(description="关联线下菜品id")
|
||||
private Long linkSpuId;
|
||||
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
|
||||
+2
@@ -20,6 +20,8 @@ public class CanteenErpMaterialVO {
|
||||
@Schema(description="商品单位")
|
||||
private String unit;
|
||||
|
||||
@Schema(description="食材类型:1-线下,2-线上")
|
||||
private Integer materialType;
|
||||
|
||||
/**
|
||||
* 期初数量
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.bsd.pjcloud.canteen.vo.erp;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Schema(description = "线上菜品简略VO,用于模板选择弹窗")
|
||||
public class CanteenOnlineSpuSimpleVO {
|
||||
|
||||
@Schema(description = "id")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "菜品名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "菜品封面图")
|
||||
private String picUrl;
|
||||
|
||||
@Schema(description = "关联线下菜品id")
|
||||
private Long linkSpuId;
|
||||
}
|
||||
+2
@@ -59,4 +59,6 @@ public class ProductionTemplateDetailVO{
|
||||
@Schema(description="单位")
|
||||
private String unit;
|
||||
|
||||
@Schema(description="营养元素描述")
|
||||
private String nutritionDesc;
|
||||
}
|
||||
+8
-6
@@ -49,7 +49,7 @@ public class CanteenErpMaterialController {
|
||||
* @param canteenErpMaterial 原料表
|
||||
* @return
|
||||
*/
|
||||
@Operation(summary = "分页查询" , description = "分页查询" )
|
||||
@Operation(summary = "分页查询" , description = "分页查询,支持按食材类型筛选" )
|
||||
@GetMapping("/page" )
|
||||
@PreAuthorize("@pms.hasPermission('canteen_canteenErpMaterial_view')" )
|
||||
public R getCanteenErpMaterialPage(@ParameterObject Page page, @ParameterObject CanteenErpMaterialEntity canteenErpMaterial) {
|
||||
@@ -127,13 +127,15 @@ public class CanteenErpMaterialController {
|
||||
|
||||
/**
|
||||
* erp选择食材分页数据
|
||||
* 分页查询
|
||||
* @param page 分页对象
|
||||
* @return
|
||||
* @param name 食材名称
|
||||
* @param materialType 食材类型:1-线下,2-线上,不传默认线下
|
||||
*/
|
||||
@Operation(summary = "选择食材分页数据" , description = "选择食材分页数据" )
|
||||
@Operation(summary = "选择食材分页数据" , description = "选择食材分页数据,materialType不传默认线下" )
|
||||
@GetMapping("/erpMaterialPage" )
|
||||
public R getErpMaterialPage(@ParameterObject Page page, @RequestParam(value = "name",required = false)String name) {
|
||||
return R.ok(canteenErpMaterialService.getErpMaterialPage(page, name));
|
||||
public R getErpMaterialPage(@ParameterObject Page page,
|
||||
@RequestParam(value = "name", required = false) String name,
|
||||
@RequestParam(value = "materialType", required = false) Integer materialType) {
|
||||
return R.ok(canteenErpMaterialService.getErpMaterialPage(page, name, materialType));
|
||||
}
|
||||
}
|
||||
+16
@@ -45,6 +45,22 @@ public class CanteenOnlineSpuController {
|
||||
|
||||
private final CanteenOnlineSpuService canteenOnlineSpuService;
|
||||
|
||||
/**
|
||||
* 模板选择线上菜品分页(用于加工模版选择菜品弹窗)
|
||||
* 类似 /canteen/canteenSpu/getCanteenSpuSimplePage
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param canteenOnlineSpu 查询条件(name、categoryId)
|
||||
* @return
|
||||
*/
|
||||
@Operation(summary = "模板选择线上菜品分页", description = "用于加工模版选择线上菜品弹窗,支持按名称、分类筛选")
|
||||
@GetMapping("/getCanteenOnlineSpuSimplePage")
|
||||
@PreAuthorize("@pms.hasPermission('canteen_canteenOnlineSpu_view')")
|
||||
public R<Page<com.bsd.pjcloud.canteen.vo.erp.CanteenOnlineSpuSimpleVO>> getCanteenOnlineSpuSimplePage(
|
||||
@ParameterObject Page page, @ParameterObject CanteenOnlineSpuEntity canteenOnlineSpu) {
|
||||
return R.ok(canteenOnlineSpuService.getCanteenOnlineSpuSimplePageScope(page, canteenOnlineSpu));
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
|
||||
+15
-1
@@ -10,6 +10,7 @@ import com.bsd.pjcloud.common.core.util.R;
|
||||
import com.bsd.pjcloud.common.log.annotation.SysLog;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenProductionTemplateEntity;
|
||||
import com.bsd.pjcloud.canteen.service.CanteenProductionTemplateService;
|
||||
import com.bsd.pjcloud.common.security.annotation.Inner;
|
||||
import com.bsd.pjcloud.common.security.util.SecurityUtils;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import com.bsd.pjcloud.common.excel.annotation.ResponseExcel;
|
||||
@@ -50,7 +51,8 @@ public class CanteenProductionTemplateController {
|
||||
@PreAuthorize("@pms.hasPermission('canteen_canteenProductionTemplate_view')" )
|
||||
public R getCanteenProductionTemplatePage(@ParameterObject Page page, @ParameterObject CanteenProductionTemplateEntity canteenProductionTemplate) {
|
||||
LambdaQueryWrapper<CanteenProductionTemplateEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(StrUtil.isNotBlank(canteenProductionTemplate.getTemplateName()),CanteenProductionTemplateEntity::getTemplateName,canteenProductionTemplate.getTemplateName());
|
||||
wrapper.eq(StrUtil.isNotBlank(canteenProductionTemplate.getTemplateName()),CanteenProductionTemplateEntity::getTemplateName,canteenProductionTemplate.getTemplateName())
|
||||
.eq(canteenProductionTemplate.getTemplateType() != null, CanteenProductionTemplateEntity::getTemplateType, canteenProductionTemplate.getTemplateType());
|
||||
return R.ok(canteenProductionTemplateService.pageScope(page, wrapper));
|
||||
}
|
||||
|
||||
@@ -129,4 +131,16 @@ public class CanteenProductionTemplateController {
|
||||
public R getSelectTemplatePage(@ParameterObject Page page, @RequestParam(value = "name",required = false)String name) {
|
||||
return R.ok(canteenProductionTemplateService.getSelectTemplatePageScope(page, name));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据菜品id列表获取模版详情(内部)")
|
||||
@PostMapping("/inner/getDetailsByDishIds")
|
||||
public R<List<com.bsd.pjcloud.canteen.vo.erp.ProductTemplateVO>> getDetailsByDishIds(@RequestBody List<Long> dishIds) {
|
||||
return R.ok(canteenProductionTemplateService.getDetailsByDishIds(dishIds));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据菜品id列表获取线上模版详情(内部)", description = "仅返回 template_type=2 的模版,用于线上订餐统计")
|
||||
@PostMapping("/inner/getDetailsByDishIdsForOnline")
|
||||
public R<List<com.bsd.pjcloud.canteen.vo.erp.ProductTemplateVO>> getDetailsByDishIdsForOnline(@RequestBody List<Long> dishIds) {
|
||||
return R.ok(canteenProductionTemplateService.getDetailsByDishIdsForOnline(dishIds));
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -7,6 +7,7 @@ import com.bsd.pjcloud.canteen.dto.erp.CanteenErpMaterialEditorDTO;
|
||||
import com.bsd.pjcloud.canteen.dto.erp.CanteenErpMaterialSaveDTO;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenErpMaterialEntity;
|
||||
import com.bsd.pjcloud.canteen.vo.erp.CanteenErpMaterialVO;
|
||||
import com.bsd.pjcloud.canteen.vo.erp.ErpMaterialPageVo;
|
||||
|
||||
public interface CanteenErpMaterialService extends IService<CanteenErpMaterialEntity> {
|
||||
|
||||
@@ -37,10 +38,11 @@ public interface CanteenErpMaterialService extends IService<CanteenErpMaterialEn
|
||||
|
||||
|
||||
/**
|
||||
* erp选择分页
|
||||
* erp选择食材分页,materialType不传默认线下(1)
|
||||
* @param page
|
||||
* @param name
|
||||
* @param materialType 食材类型:1-线下,2-线上
|
||||
* @return
|
||||
*/
|
||||
Object getErpMaterialPage(Page page, String name);
|
||||
Page<ErpMaterialPageVo> getErpMaterialPage(Page page, String name, Integer materialType);
|
||||
}
|
||||
+6
@@ -7,12 +7,18 @@ import com.bsd.pjcloud.canteen.dto.CanteenOnlineSpuUpdateStockReqDTO;
|
||||
import com.bsd.pjcloud.canteen.dto.canteenonline.CanteenOnlineSpuSaveDto;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenOnlineSpuEntity;
|
||||
import com.bsd.pjcloud.canteen.vo.APPOnlineSpuVO;
|
||||
import com.bsd.pjcloud.canteen.vo.erp.CanteenOnlineSpuSimpleVO;
|
||||
import com.bsd.pjcloud.common.core.util.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface CanteenOnlineSpuService extends IService<CanteenOnlineSpuEntity> {
|
||||
|
||||
/**
|
||||
* 模板选择线上菜品分页(简化数据,用于选择弹窗)
|
||||
*/
|
||||
Page<CanteenOnlineSpuSimpleVO> getCanteenOnlineSpuSimplePageScope(Page page, CanteenOnlineSpuEntity canteenOnlineSpu);
|
||||
|
||||
|
||||
/**
|
||||
* 根据分类id获取商品列表
|
||||
|
||||
+14
@@ -20,6 +20,20 @@ public interface CanteenProductionTemplateService extends MPJDeepService<Canteen
|
||||
|
||||
ProductTemplateVO getDetailById(Long id);
|
||||
|
||||
/**
|
||||
* 根据菜品id列表获取加工模版详情
|
||||
* @param dishIds 菜品id列表(canteen_spu.id 或 canteen_online_spu.link_spu_id)
|
||||
* @return 模版详情列表
|
||||
*/
|
||||
java.util.List<ProductTemplateVO> getDetailsByDishIds(java.util.List<Long> dishIds);
|
||||
|
||||
/**
|
||||
* 根据菜品id列表获取线上加工模版详情(仅 template_type=2)
|
||||
* @param dishIds 菜品id列表(canteen_online_spu.link_spu_id)
|
||||
* @return 模版详情列表
|
||||
*/
|
||||
java.util.List<ProductTemplateVO> getDetailsByDishIdsForOnline(java.util.List<Long> dishIds);
|
||||
|
||||
/**
|
||||
* 分页
|
||||
* @param page
|
||||
|
||||
+62
-38
@@ -20,6 +20,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -43,18 +44,23 @@ public class CanteenErpMaterialServiceImpl extends ServiceImpl<CanteenErpMateria
|
||||
CanteenErpMaterialEntity canteenErpMaterialEntity = new CanteenErpMaterialEntity();
|
||||
canteenErpMaterialEntity.setName(canteenErpMaterialSaveDTO.getName());
|
||||
canteenErpMaterialEntity.setUnit(canteenErpMaterialSaveDTO.getUnit());
|
||||
canteenErpMaterialEntity.setMaterialType(canteenErpMaterialSaveDTO.getMaterialType() != null ? canteenErpMaterialSaveDTO.getMaterialType() : 1);
|
||||
canteenErpMaterialEntity.setDeptId(deptId);
|
||||
canteenErpMaterialEntity.setPurchasePrice(canteenErpMaterialSaveDTO.getPurchasePrice());
|
||||
canteenErpMaterialEntity.setCategoryId(canteenErpMaterialSaveDTO.getCategoryId());
|
||||
int insert = baseMapper.insert(canteenErpMaterialEntity);
|
||||
CanteenStockEntity canteenStockEntity = new CanteenStockEntity();
|
||||
canteenStockEntity.setItemType("1");
|
||||
canteenStockEntity.setItemId(canteenErpMaterialEntity.getId());
|
||||
canteenStockEntity.setBaseStock(canteenErpMaterialSaveDTO.getBaseStock());
|
||||
canteenStockEntity.setCurrentStock(canteenErpMaterialSaveDTO.getBaseStock());
|
||||
canteenStockEntity.setInventoryUpperLimit(canteenErpMaterialSaveDTO.getInventoryUpperLimit());
|
||||
canteenStockEntity.setInventoryLowerLimit(canteenErpMaterialSaveDTO.getInventoryLowerLimit());
|
||||
canteenStockMapper.insert(canteenStockEntity);
|
||||
// 线上食材(materialType=2)仅作转换规则,不建库存
|
||||
int materialType = canteenErpMaterialEntity.getMaterialType() != null ? canteenErpMaterialEntity.getMaterialType() : 1;
|
||||
if (materialType == 1) {
|
||||
CanteenStockEntity canteenStockEntity = new CanteenStockEntity();
|
||||
canteenStockEntity.setItemType("1");
|
||||
canteenStockEntity.setItemId(canteenErpMaterialEntity.getId());
|
||||
canteenStockEntity.setBaseStock(canteenErpMaterialSaveDTO.getBaseStock());
|
||||
canteenStockEntity.setCurrentStock(canteenErpMaterialSaveDTO.getBaseStock());
|
||||
canteenStockEntity.setInventoryUpperLimit(canteenErpMaterialSaveDTO.getInventoryUpperLimit());
|
||||
canteenStockEntity.setInventoryLowerLimit(canteenErpMaterialSaveDTO.getInventoryLowerLimit());
|
||||
canteenStockMapper.insert(canteenStockEntity);
|
||||
}
|
||||
return insert;
|
||||
}
|
||||
|
||||
@@ -66,22 +72,28 @@ public class CanteenErpMaterialServiceImpl extends ServiceImpl<CanteenErpMateria
|
||||
canteenErpMaterialEntity.setId(id);
|
||||
canteenErpMaterialEntity.setName(canteenErpMaterialEditorDTO.getName());
|
||||
canteenErpMaterialEntity.setUnit(canteenErpMaterialEditorDTO.getUnit());
|
||||
canteenErpMaterialEntity.setMaterialType(canteenErpMaterialEditorDTO.getMaterialType() != null ? canteenErpMaterialEditorDTO.getMaterialType() : 1);
|
||||
canteenErpMaterialEntity.setPurchasePrice(canteenErpMaterialEditorDTO.getPurchasePrice());
|
||||
canteenErpMaterialEntity.setCategoryId(canteenErpMaterialEditorDTO.getCategoryId());
|
||||
|
||||
LambdaQueryWrapper<CanteenStockEntity> canteenStockEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
canteenStockEntityLambdaQueryWrapper.eq(CanteenStockEntity::getItemId, id);
|
||||
CanteenStockEntity sourceCanteenStockEntity = canteenStockMapper.selectOne(canteenStockEntityLambdaQueryWrapper);
|
||||
|
||||
CanteenStockEntity canteenStockEntity = new CanteenStockEntity();
|
||||
canteenStockEntity.setItemId(canteenErpMaterialEntity.getId());
|
||||
canteenStockEntity.setBaseStock(canteenErpMaterialEditorDTO.getBaseStock());
|
||||
canteenStockEntity.setCurrentStock(canteenErpMaterialEditorDTO.getBaseStock()+(sourceCanteenStockEntity.getCurrentStock()-sourceCanteenStockEntity.getBaseStock()));
|
||||
canteenStockEntity.setInventoryUpperLimit(canteenErpMaterialEditorDTO.getInventoryUpperLimit());
|
||||
canteenStockEntity.setInventoryLowerLimit(canteenErpMaterialEditorDTO.getInventoryLowerLimit());
|
||||
int i = baseMapper.updateById(canteenErpMaterialEntity);
|
||||
canteenStockMapper.update(canteenStockEntity,
|
||||
new LambdaQueryWrapper<CanteenStockEntity>().eq(CanteenStockEntity::getItemId, id));
|
||||
// 线上食材(materialType=2)无库存,不更新
|
||||
int materialType = canteenErpMaterialEditorDTO.getMaterialType() != null ? canteenErpMaterialEditorDTO.getMaterialType() : 1;
|
||||
if (materialType == 1) {
|
||||
LambdaQueryWrapper<CanteenStockEntity> canteenStockEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
canteenStockEntityLambdaQueryWrapper.eq(CanteenStockEntity::getItemId, id);
|
||||
CanteenStockEntity sourceCanteenStockEntity = canteenStockMapper.selectOne(canteenStockEntityLambdaQueryWrapper);
|
||||
if (sourceCanteenStockEntity != null) {
|
||||
CanteenStockEntity canteenStockEntity = new CanteenStockEntity();
|
||||
canteenStockEntity.setItemId(canteenErpMaterialEntity.getId());
|
||||
canteenStockEntity.setBaseStock(canteenErpMaterialEditorDTO.getBaseStock());
|
||||
canteenStockEntity.setCurrentStock(canteenErpMaterialEditorDTO.getBaseStock() + (sourceCanteenStockEntity.getCurrentStock() - sourceCanteenStockEntity.getBaseStock()));
|
||||
canteenStockEntity.setInventoryUpperLimit(canteenErpMaterialEditorDTO.getInventoryUpperLimit());
|
||||
canteenStockEntity.setInventoryLowerLimit(canteenErpMaterialEditorDTO.getInventoryLowerLimit());
|
||||
canteenStockMapper.update(canteenStockEntity,
|
||||
new LambdaQueryWrapper<CanteenStockEntity>().eq(CanteenStockEntity::getItemId, id));
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -94,27 +106,39 @@ public class CanteenErpMaterialServiceImpl extends ServiceImpl<CanteenErpMateria
|
||||
@Override
|
||||
public CanteenErpMaterialVO getCanteenErpMaterialVOById(Long id) {
|
||||
CanteenErpMaterialEntity canteenErpMaterialEntity = baseMapper.selectById(id);
|
||||
LambdaQueryWrapper<CanteenStockEntity> canteenStockEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
canteenStockEntityLambdaQueryWrapper.eq(CanteenStockEntity::getItemId, id);
|
||||
CanteenStockEntity sourceCanteenStockEntity = canteenStockMapper.selectOne(canteenStockEntityLambdaQueryWrapper);
|
||||
|
||||
CanteenErpMaterialVO canteenErpMaterialVO = new CanteenErpMaterialVO();
|
||||
canteenErpMaterialVO.setId(canteenErpMaterialEntity.getId());
|
||||
canteenErpMaterialVO.setName(canteenErpMaterialEntity.getName());
|
||||
canteenErpMaterialVO.setUnit(canteenErpMaterialEntity.getUnit());
|
||||
canteenErpMaterialVO.setBaseStock(sourceCanteenStockEntity.getBaseStock());
|
||||
canteenErpMaterialVO.setInventoryUpperLimit(sourceCanteenStockEntity.getInventoryUpperLimit());
|
||||
canteenErpMaterialVO.setInventoryLowerLimit(sourceCanteenStockEntity.getInventoryLowerLimit());
|
||||
canteenErpMaterialVO.setCurrentStock(sourceCanteenStockEntity.getCurrentStock());
|
||||
canteenErpMaterialVO.setPurchasePrice(canteenErpMaterialEntity.getPurchasePrice());
|
||||
canteenErpMaterialVO.setCategoryId(canteenErpMaterialEntity.getCategoryId());
|
||||
canteenErpMaterialVO.setMaterialType(canteenErpMaterialEntity.getMaterialType());
|
||||
// 线上食材无库存,仅线下查询库存
|
||||
int materialType = canteenErpMaterialEntity.getMaterialType() != null ? canteenErpMaterialEntity.getMaterialType() : 1;
|
||||
if (materialType == 1) {
|
||||
LambdaQueryWrapper<CanteenStockEntity> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CanteenStockEntity::getItemId, id);
|
||||
CanteenStockEntity stock = canteenStockMapper.selectOne(wrapper);
|
||||
if (stock != null) {
|
||||
canteenErpMaterialVO.setBaseStock(stock.getBaseStock());
|
||||
canteenErpMaterialVO.setInventoryUpperLimit(stock.getInventoryUpperLimit());
|
||||
canteenErpMaterialVO.setInventoryLowerLimit(stock.getInventoryLowerLimit());
|
||||
canteenErpMaterialVO.setCurrentStock(stock.getCurrentStock());
|
||||
}
|
||||
} else {
|
||||
canteenErpMaterialVO.setBaseStock(0D);
|
||||
canteenErpMaterialVO.setCurrentStock(0D);
|
||||
canteenErpMaterialVO.setInventoryUpperLimit(0);
|
||||
canteenErpMaterialVO.setInventoryLowerLimit(0);
|
||||
}
|
||||
return canteenErpMaterialVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ErpMaterialPageVo> getErpMaterialPage(Page page, String name) {
|
||||
public Page<ErpMaterialPageVo> getErpMaterialPage(Page page, String name, Integer materialType) {
|
||||
LambdaQueryWrapper<CanteenErpMaterialEntity> smErpUnitEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
smErpUnitEntityLambdaQueryWrapper.like(StringUtils.isNotBlank(name), CanteenErpMaterialEntity::getName, name);
|
||||
smErpUnitEntityLambdaQueryWrapper.like(StringUtils.isNotBlank(name), CanteenErpMaterialEntity::getName, name)
|
||||
.eq(CanteenErpMaterialEntity::getMaterialType, materialType != null ? materialType : 1);
|
||||
Page<CanteenErpMaterialEntity> spuPage = baseMapper.selectPageByScope(page, smErpUnitEntityLambdaQueryWrapper, DataScope.of());
|
||||
|
||||
// 将 SmErpSpuEntity 转换为 SmErpPageScopeVo
|
||||
@@ -122,22 +146,22 @@ public class CanteenErpMaterialServiceImpl extends ServiceImpl<CanteenErpMateria
|
||||
.map(entity -> BeanUtils.toBean(entity, ErpMaterialPageVo.class))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<Long> materialIds = voList.stream().map(vo -> vo.getId()).collect(Collectors.toList());
|
||||
List<Long> materialIds = voList.stream().map(ErpMaterialPageVo::getId).collect(Collectors.toList());
|
||||
|
||||
// 批量查询库存信息
|
||||
List<CanteenStockEntity> stocks = canteenStockMapper.selectList(
|
||||
// 批量查询库存信息(materialIds 为空时跳过,避免 IN () 语法错误)
|
||||
List<CanteenStockEntity> stocks = materialIds.isEmpty() ? Collections.emptyList() : canteenStockMapper.selectList(
|
||||
new LambdaQueryWrapper<CanteenStockEntity>()
|
||||
.in(CanteenStockEntity::getItemId, materialIds));
|
||||
.in(CanteenStockEntity::getItemId, materialIds));
|
||||
|
||||
// 建立SPU ID与库存的映射关系
|
||||
Map<Long,CanteenStockEntity> stockMap = stocks.stream()
|
||||
Map<Long, CanteenStockEntity> stockMap = stocks.stream()
|
||||
.collect(Collectors.toMap(CanteenStockEntity::getItemId, smErpStockEntity -> smErpStockEntity));
|
||||
|
||||
|
||||
voList.stream().forEach(vo -> {
|
||||
//库存
|
||||
CanteenStockEntity smErpStockEntity = stockMap.get(vo.getId());
|
||||
vo.setStock(smErpStockEntity != null ? smErpStockEntity.getCurrentStock() : 0);
|
||||
CanteenStockEntity stock = stockMap.get(vo.getId());
|
||||
Double currentStock = (stock != null && stock.getCurrentStock() != null) ? stock.getCurrentStock() : 0D;
|
||||
vo.setStock(currentStock);
|
||||
});
|
||||
|
||||
// 创建新的 Page 对象并设置数据
|
||||
|
||||
+19
@@ -16,6 +16,7 @@ import com.bsd.pjcloud.canteen.mapper.CanteenOnlineCategoryMapper;
|
||||
import com.bsd.pjcloud.canteen.mapper.CanteenOnlineSpuMapper;
|
||||
import com.bsd.pjcloud.canteen.service.CanteenOnlineSpuService;
|
||||
import com.bsd.pjcloud.canteen.vo.APPOnlineSpuVO;
|
||||
import com.bsd.pjcloud.canteen.vo.erp.CanteenOnlineSpuSimpleVO;
|
||||
import com.bsd.pjcloud.common.core.util.BeanUtils;
|
||||
import com.bsd.pjcloud.common.core.util.R;
|
||||
import com.bsd.pjcloud.common.data.datascope.DataScope;
|
||||
@@ -33,6 +34,7 @@ import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.Objects;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
/**
|
||||
* 在线点餐spu
|
||||
@@ -166,6 +168,23 @@ public class CanteenOnlineSpuServiceImpl extends ServiceImpl<CanteenOnlineSpuMap
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<CanteenOnlineSpuSimpleVO> getCanteenOnlineSpuSimplePageScope(Page page, CanteenOnlineSpuEntity canteenOnlineSpu) {
|
||||
LambdaQueryWrapper<CanteenOnlineSpuEntity> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.like(StrUtil.isNotBlank(canteenOnlineSpu.getName()), CanteenOnlineSpuEntity::getName, canteenOnlineSpu.getName())
|
||||
.eq(Objects.nonNull(canteenOnlineSpu.getCategoryId()), CanteenOnlineSpuEntity::getCategoryId, canteenOnlineSpu.getCategoryId())
|
||||
.orderByAsc(CanteenOnlineSpuEntity::getSort).orderByDesc(CanteenOnlineSpuEntity::getId);
|
||||
Page<CanteenOnlineSpuEntity> pageData = baseMapper.selectPageByScope(page, wrapper, DataScope.of());
|
||||
List<CanteenOnlineSpuSimpleVO> voList = BeanUtils.toBean(pageData.getRecords(), CanteenOnlineSpuSimpleVO.class);
|
||||
Page<CanteenOnlineSpuSimpleVO> resultPage = new Page<>();
|
||||
resultPage.setRecords(voList);
|
||||
resultPage.setCurrent(pageData.getCurrent());
|
||||
resultPage.setPages(pageData.getPages());
|
||||
resultPage.setSize(pageData.getSize());
|
||||
resultPage.setTotal(pageData.getTotal());
|
||||
return resultPage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object pageScope(Page page, LambdaQueryWrapper<CanteenOnlineSpuEntity> wrapper) {
|
||||
Page pageData = baseMapper.selectPageByScope(page, wrapper, DataScope.of());
|
||||
|
||||
+85
-8
@@ -6,8 +6,10 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenErpMaterialEntity;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenProductionTemplateEntity;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenOnlineSpuEntity;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenSpuEntity;
|
||||
import com.bsd.pjcloud.canteen.mapper.CanteenErpMaterialMapper;
|
||||
import com.bsd.pjcloud.canteen.mapper.CanteenOnlineSpuMapper;
|
||||
import com.bsd.pjcloud.canteen.mapper.CanteenProductionTemplateMapper;
|
||||
import com.bsd.pjcloud.canteen.mapper.CanteenSpuMapper;
|
||||
import com.bsd.pjcloud.canteen.service.CanteenProductionTemplateService;
|
||||
@@ -38,8 +40,11 @@ import java.util.stream.Collectors;
|
||||
public class CanteenProductionTemplateServiceImpl extends ServiceImpl<CanteenProductionTemplateMapper, CanteenProductionTemplateEntity> implements CanteenProductionTemplateService {
|
||||
private final CanteenProductionTemplateDetailMapper canteenProductionTemplateDetailMapper;
|
||||
private final CanteenSpuMapper canteenSpuMapper;
|
||||
private final CanteenOnlineSpuMapper canteenOnlineSpuMapper;
|
||||
private final CanteenErpMaterialMapper canteenErpMaterialMapper;
|
||||
|
||||
private static final int TEMPLATE_TYPE_ONLINE = 2;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean saveDeep(CanteenProductionTemplateEntity canteenProductionTemplate) {
|
||||
@@ -85,29 +90,101 @@ public class CanteenProductionTemplateServiceImpl extends ServiceImpl<CanteenPro
|
||||
@Override
|
||||
public ProductTemplateVO getDetailById(Long id) {
|
||||
CanteenProductionTemplateEntity canteenProductionTemplateEntity = baseMapper.selectById(id);
|
||||
if (canteenProductionTemplateEntity == null) return null;
|
||||
Long dishId = canteenProductionTemplateEntity.getDishId();
|
||||
CanteenSpuEntity canteenSpuEntity = canteenSpuMapper.selectById(dishId);
|
||||
String dishName = resolveDishName(canteenProductionTemplateEntity.getTemplateType(), dishId);
|
||||
LambdaQueryWrapper<CanteenProductionTemplateDetailEntity> canteenProductionTemplateDetailEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
canteenProductionTemplateDetailEntityLambdaQueryWrapper.eq(CanteenProductionTemplateDetailEntity::getTemplateId, id);
|
||||
List<CanteenProductionTemplateDetailEntity> canteenProductionTemplateDetailEntities = canteenProductionTemplateDetailMapper.selectList(canteenProductionTemplateDetailEntityLambdaQueryWrapper);
|
||||
ProductTemplateVO bean = BeanUtils.toBean(canteenProductionTemplateEntity, ProductTemplateVO.class);
|
||||
bean.setDishName(canteenSpuEntity.getName());
|
||||
bean.setDishName(dishName);
|
||||
List<ProductionTemplateDetailVO> productionTemplateDetailVOList= BeanUtils.toBean(canteenProductionTemplateDetailEntities, ProductionTemplateDetailVO.class);
|
||||
for (ProductionTemplateDetailVO productionTemplateDetailVO : productionTemplateDetailVOList) {
|
||||
Long materialId = productionTemplateDetailVO.getMaterialId();
|
||||
CanteenErpMaterialEntity canteenErpMaterialEntity = canteenErpMaterialMapper.selectById(materialId);
|
||||
productionTemplateDetailVO.setMaterialName(canteenErpMaterialEntity.getName());
|
||||
productionTemplateDetailVO.setUnit(canteenErpMaterialEntity.getUnit());
|
||||
CanteenErpMaterialEntity material = canteenErpMaterialMapper.selectById(materialId);
|
||||
if (material != null) {
|
||||
productionTemplateDetailVO.setMaterialName(material.getName());
|
||||
productionTemplateDetailVO.setUnit(material.getUnit());
|
||||
}
|
||||
}
|
||||
bean.setCanteenProductionTemplateDetailList(productionTemplateDetailVOList);
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProductTemplateVO> getDetailsByDishIds(List<Long> dishIds) {
|
||||
if (CollUtil.isEmpty(dishIds)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<CanteenProductionTemplateEntity> templates = baseMapper.selectList(
|
||||
Wrappers.<CanteenProductionTemplateEntity>lambdaQuery().in(CanteenProductionTemplateEntity::getDishId, dishIds));
|
||||
if (CollUtil.isEmpty(templates)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return buildTemplateDetailList(templates);
|
||||
}
|
||||
|
||||
/** 根据模板类型解析菜品名称:线上查 CanteenOnlineSpu,线下查 CanteenSpu */
|
||||
private String resolveDishName(Integer templateType, Long dishId) {
|
||||
if (dishId == null) return "";
|
||||
if (TEMPLATE_TYPE_ONLINE == templateType) {
|
||||
CanteenOnlineSpuEntity onlineSpu = canteenOnlineSpuMapper.selectById(dishId);
|
||||
if (onlineSpu != null) return onlineSpu.getName();
|
||||
// 兼容:线上模板可能存的是 linkSpuId,回退查线下
|
||||
}
|
||||
CanteenSpuEntity spu = canteenSpuMapper.selectById(dishId);
|
||||
return spu != null ? spu.getName() : "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProductTemplateVO> getDetailsByDishIdsForOnline(List<Long> dishIds) {
|
||||
if (CollUtil.isEmpty(dishIds)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<CanteenProductionTemplateEntity> templates = baseMapper.selectList(
|
||||
Wrappers.<CanteenProductionTemplateEntity>lambdaQuery()
|
||||
.in(CanteenProductionTemplateEntity::getDishId, dishIds)
|
||||
.eq(CanteenProductionTemplateEntity::getTemplateType, TEMPLATE_TYPE_ONLINE));
|
||||
if (CollUtil.isEmpty(templates)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return buildTemplateDetailList(templates);
|
||||
}
|
||||
|
||||
private List<ProductTemplateVO> buildTemplateDetailList(List<CanteenProductionTemplateEntity> templates) {
|
||||
List<Long> templateIds = templates.stream().map(CanteenProductionTemplateEntity::getId).collect(Collectors.toList());
|
||||
List<CanteenProductionTemplateDetailEntity> details = canteenProductionTemplateDetailMapper.selectList(
|
||||
Wrappers.<CanteenProductionTemplateDetailEntity>lambdaQuery().in(CanteenProductionTemplateDetailEntity::getTemplateId, templateIds));
|
||||
Set<Long> dishIdSet = templates.stream().map(CanteenProductionTemplateEntity::getDishId).collect(Collectors.toSet());
|
||||
Set<Long> materialIds = details.stream().map(CanteenProductionTemplateDetailEntity::getMaterialId).collect(Collectors.toSet());
|
||||
Map<Long, CanteenSpuEntity> dishMap = CollUtil.isEmpty(dishIdSet) ? Collections.emptyMap()
|
||||
: canteenSpuMapper.selectByIds(dishIdSet).stream().collect(Collectors.toMap(CanteenSpuEntity::getId, e -> e));
|
||||
Map<Long, CanteenErpMaterialEntity> materialMap = CollUtil.isEmpty(materialIds) ? Collections.emptyMap()
|
||||
: canteenErpMaterialMapper.selectByIds(materialIds).stream().collect(Collectors.toMap(CanteenErpMaterialEntity::getId, e -> e));
|
||||
Map<Long, List<CanteenProductionTemplateDetailEntity>> detailMap = details.stream().collect(Collectors.groupingBy(CanteenProductionTemplateDetailEntity::getTemplateId));
|
||||
List<ProductTemplateVO> result = new ArrayList<>();
|
||||
for (CanteenProductionTemplateEntity t : templates) {
|
||||
ProductTemplateVO vo = BeanUtils.toBean(t, ProductTemplateVO.class);
|
||||
vo.setDishName(dishMap.getOrDefault(t.getDishId(), new CanteenSpuEntity()).getName());
|
||||
List<ProductionTemplateDetailVO> detailVOList = BeanUtils.toBean(detailMap.getOrDefault(t.getId(), Collections.emptyList()), ProductionTemplateDetailVO.class);
|
||||
for (ProductionTemplateDetailVO d : detailVOList) {
|
||||
CanteenErpMaterialEntity m = materialMap.get(d.getMaterialId());
|
||||
if (m != null) {
|
||||
d.setMaterialName(m.getName());
|
||||
d.setUnit(m.getUnit());
|
||||
}
|
||||
}
|
||||
vo.setCanteenProductionTemplateDetailList(detailVOList);
|
||||
result.add(vo);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object pageScope(Page page, LambdaQueryWrapper<CanteenProductionTemplateEntity> wrapper) {
|
||||
Page pageData = baseMapper.selectPageByScope(page, wrapper, DataScope.of());
|
||||
// pageData.getRecords().forEach(item->{
|
||||
// });
|
||||
Page<CanteenProductionTemplateEntity> pageData = baseMapper.selectPageByScope(page, wrapper, DataScope.of());
|
||||
pageData.getRecords().forEach(item ->
|
||||
item.setDishName(resolveDishName(item.getTemplateType(), item.getDishId())));
|
||||
return pageData;
|
||||
}
|
||||
|
||||
|
||||
+5
@@ -7,6 +7,7 @@
|
||||
<id property="id" column="id"/>
|
||||
<result property="name" column="name"/>
|
||||
<result property="unit" column="unit"/>
|
||||
<result property="materialType" column="material_type"/>
|
||||
<result property="deptId" column="dept_id"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
@@ -22,6 +23,7 @@
|
||||
m.id,
|
||||
m.name,
|
||||
m.unit,
|
||||
m.material_type AS materialType,
|
||||
m.category_id,
|
||||
m.purchase_price,
|
||||
s.base_stock AS baseStock,
|
||||
@@ -36,6 +38,9 @@
|
||||
<if test="canteenErpMaterial.name != null">
|
||||
and m.name like concat('%',#{canteenErpMaterial.name},'%')
|
||||
</if>
|
||||
<if test="canteenErpMaterial.materialType != null">
|
||||
and m.material_type = #{canteenErpMaterial.materialType}
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
</mapper>
|
||||
+1
@@ -10,6 +10,7 @@
|
||||
<result property="deptId" column="dept_id"/>
|
||||
<result property="baseUsage" column="base_usage"/>
|
||||
<result property="lossRate" column="loss_rate"/>
|
||||
<result property="nutritionDesc" column="nutrition_desc"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
|
||||
+1
@@ -7,6 +7,7 @@
|
||||
<id property="id" column="id"/>
|
||||
<result property="templateName" column="template_name"/>
|
||||
<result property="dishId" column="dish_id"/>
|
||||
<result property="templateType" column="template_type"/>
|
||||
<result property="deptId" column="dept_id"/>
|
||||
<result property="baseOutput" column="base_output"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.bsd.pjcloud.hard.api.dto.order;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 线上订餐统计查询参数
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "线上订餐统计查询")
|
||||
public class HardOnlineCanteenStatsQueryDto {
|
||||
|
||||
@Schema(description = "支付时间范围")
|
||||
private LocalDateTime[] payTimeList;
|
||||
|
||||
@Schema(description = "商户(食堂)id列表")
|
||||
private List<Long> mchIds;
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.bsd.pjcloud.hard.api.vo.order;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 原料用量明细
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "原料用量明细")
|
||||
public class HardOnlineCanteenMaterialUsageVo {
|
||||
|
||||
@Schema(description = "原料id")
|
||||
private Long materialId;
|
||||
|
||||
@Schema(description = "原料名称")
|
||||
private String materialName;
|
||||
|
||||
@Schema(description = "用量")
|
||||
private Double usage;
|
||||
|
||||
@Schema(description = "单位")
|
||||
private String unit;
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.bsd.pjcloud.hard.api.vo.order;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 营养元素汇总(原料营养描述合集)
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "营养元素汇总")
|
||||
public class HardOnlineCanteenNutritionVo {
|
||||
|
||||
@Schema(description = "营养描述(各原料营养描述的汇总,用户自定义文案)")
|
||||
private String nutritionDesc;
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package com.bsd.pjcloud.hard.api.vo.order;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 线上订餐统计结果(按食堂汇总)
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "线上订餐统计-按食堂")
|
||||
public class HardOnlineCanteenStatsVo {
|
||||
|
||||
@Schema(description = "食堂(商户)id")
|
||||
private Long merchantId;
|
||||
|
||||
@Schema(description = "食堂名称")
|
||||
private String merchantName;
|
||||
|
||||
@Schema(description = "订单数")
|
||||
private Long orderCount = 0L;
|
||||
|
||||
@Schema(description = "菜品份数合计")
|
||||
private Long totalDishCount = 0L;
|
||||
|
||||
@Schema(description = "原料用量明细")
|
||||
private List<HardOnlineCanteenMaterialUsageVo> materialUsages;
|
||||
|
||||
@Schema(description = "营养元素汇总")
|
||||
private HardOnlineCanteenNutritionVo nutritionSummary;
|
||||
}
|
||||
+25
@@ -30,6 +30,7 @@ import com.bsd.pjcloud.hard.api.constant.order.HardPayTypeEnum;
|
||||
import com.bsd.pjcloud.hard.api.dto.app.HardAppCreateOrderScancode;
|
||||
import com.bsd.pjcloud.hard.api.dto.hard.CurrentUserHardTypeInfoDto;
|
||||
import com.bsd.pjcloud.hard.api.dto.hard.HardOfflinePayDto;
|
||||
import com.bsd.pjcloud.hard.api.dto.order.HardOnlineCanteenStatsQueryDto;
|
||||
import com.bsd.pjcloud.hard.api.dto.order.HardOrderDto;
|
||||
import com.bsd.pjcloud.hard.api.dto.order.HardOrderPreferencesDto;
|
||||
import com.bsd.pjcloud.hard.api.dto.order.act.HardCreateActOrderDto;
|
||||
@@ -39,7 +40,9 @@ import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
|
||||
import com.bsd.pjcloud.hard.api.vo.order.HardOrderVo;
|
||||
import com.bsd.pjcloud.hard.api.vo.order.excel.HardOrderExcelVo;
|
||||
import com.bsd.pjcloud.hard.mapper.order.HardOrderMapper;
|
||||
import com.bsd.pjcloud.hard.api.vo.order.HardOnlineCanteenStatsVo;
|
||||
import com.bsd.pjcloud.hard.service.HardManagerService;
|
||||
import com.bsd.pjcloud.hard.service.HardOnlineCanteenStatsService;
|
||||
import com.bsd.pjcloud.hard.service.HardOrderService;
|
||||
import com.bsd.pjcloud.hard.service.HardOrderSyncService;
|
||||
import com.bsd.pjcloud.wallet.api.constant.WalletTypeEnum;
|
||||
@@ -78,6 +81,7 @@ public class HardOrderController {
|
||||
|
||||
private final HardOrderService hardwareOrderService;
|
||||
private final HardManagerService hardManagerService;
|
||||
private final HardOnlineCanteenStatsService hardOnlineCanteenStatsService;
|
||||
private final HardOrderSyncService hardOrderSyncService;
|
||||
|
||||
private final HardOrderMapper hardOrderMapper;
|
||||
@@ -262,6 +266,27 @@ public class HardOrderController {
|
||||
return R.ok(hardwareOrderService.page(page, wrapper));
|
||||
}
|
||||
|
||||
@Operation(summary = "线上订餐统计", description = "按食堂统计线上订餐订单的菜品份数仅用 template_type=2 的线上模板,排除退款")
|
||||
@PostMapping("/online-canteen-stats")
|
||||
@PreAuthorize("@pms.hasPermission('hard_hardwareOrder_view')")
|
||||
public R<List<HardOnlineCanteenStatsVo>> onlineCanteenStats(@RequestBody HardOnlineCanteenStatsQueryDto query) {
|
||||
if (query.getMchIds() == null || query.getMchIds().isEmpty()) {
|
||||
query.setMchIds(null);
|
||||
}
|
||||
List<Long> mchDtoIds = query.getMchIds();
|
||||
if (ObjectUtil.isNotEmpty(mchDtoIds) && mchDtoIds.size() == 1) {
|
||||
Long mchId = mchDtoIds.get(0);
|
||||
List<MchManageVo> mchList = mchService.getByParentId(mchId).getData();
|
||||
if (ObjectUtil.isNotEmpty(mchList)) {
|
||||
List<Long> mchIds = mchList.stream().map(MchManageVo::getId).toList();
|
||||
mchDtoIds = new java.util.ArrayList<>(List.of(mchId));
|
||||
mchDtoIds.addAll(mchIds);
|
||||
query.setMchIds(mchDtoIds);
|
||||
}
|
||||
}
|
||||
return R.ok(hardOnlineCanteenStatsService.stats(query));
|
||||
}
|
||||
|
||||
@Operation(summary = "分页复杂查询", description = "分页复杂查询")
|
||||
@PostMapping("/page-join")
|
||||
@PreAuthorize("@pms.hasPermission('hard_hardwareOrder_view')")
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package com.bsd.pjcloud.hard.service;
|
||||
|
||||
import com.bsd.pjcloud.hard.api.dto.order.HardOnlineCanteenStatsQueryDto;
|
||||
import com.bsd.pjcloud.hard.api.vo.order.HardOnlineCanteenStatsVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 线上订餐统计服务(按食堂汇总:菜品、原料、营养)
|
||||
*/
|
||||
public interface HardOnlineCanteenStatsService {
|
||||
|
||||
/**
|
||||
* 统计各食堂线上订餐数据:订单数、菜品份数、原料用量、营养元素(排除退款)
|
||||
*/
|
||||
List<HardOnlineCanteenStatsVo> stats(HardOnlineCanteenStatsQueryDto query);
|
||||
}
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
package com.bsd.pjcloud.hard.service.impl.order;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.bsd.pjcloud.canteen.api.feign.RemoteCanteenProductionTemplateService;
|
||||
import com.bsd.pjcloud.canteen.api.feign.RemoteOnlineCanteenSpuService;
|
||||
import com.bsd.pjcloud.canteen.vo.app.CanteenOnlineSpuAppVO;
|
||||
import com.bsd.pjcloud.canteen.vo.erp.ProductTemplateVO;
|
||||
import com.bsd.pjcloud.canteen.vo.erp.ProductionTemplateDetailVO;
|
||||
import com.bsd.pjcloud.common.core.constant.enums.MerchantTypeEnum;
|
||||
import com.bsd.pjcloud.common.core.util.R;
|
||||
import com.bsd.pjcloud.common.data.datascope.DataScope;
|
||||
import com.bsd.pjcloud.common.data.datascope.DataScopeFuncEnum;
|
||||
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.refund.HardRefundStatusEnum;
|
||||
import com.bsd.pjcloud.hard.api.dto.order.HardOnlineCanteenStatsQueryDto;
|
||||
import com.bsd.pjcloud.hard.api.dto.order.HardOrderDto;
|
||||
import com.bsd.pjcloud.hard.api.entity.order.HardCarEntity;
|
||||
import com.bsd.pjcloud.hard.api.vo.order.*;
|
||||
import com.bsd.pjcloud.hard.service.HardOrderService;
|
||||
import com.bsd.pjcloud.hard.service.HardOnlineCanteenStatsService;
|
||||
import com.bsd.pjcloud.wallet.api.feign.RemoteMchService;
|
||||
import com.bsd.pjcloud.wallet.api.vo.MchManageVo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 线上订餐统计实现
|
||||
* 仅统计线上订餐订单,排除退款,按食堂汇总:菜品份数、原料用量、营养元素
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class HardOnlineCanteenStatsServiceImpl implements HardOnlineCanteenStatsService {
|
||||
|
||||
private final HardOrderService hardOrderService;
|
||||
private final RemoteOnlineCanteenSpuService onlineCanteenSpuService;
|
||||
private final RemoteCanteenProductionTemplateService productionTemplateService;
|
||||
private final RemoteMchService mchService;
|
||||
|
||||
@Override
|
||||
public List<HardOnlineCanteenStatsVo> stats(HardOnlineCanteenStatsQueryDto query) {
|
||||
HardOrderDto dto = buildQueryDto(query);
|
||||
DataScope dataScope = DataScope.of().func(DataScopeFuncEnum.ALL);
|
||||
dataScope.setScopeDeptName("merchant_dept_id");
|
||||
List<HardOrderVo> ordersWithCar = hardOrderService.scopeList(dto, dataScope);
|
||||
if (ObjectUtil.isEmpty(ordersWithCar)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Set<Long> onlineSpuIds = new HashSet<>();
|
||||
Map<Long, List<OrderItem>> merchantItems = new HashMap<>();
|
||||
Map<Long, String> merchantNameMap = new HashMap<>();
|
||||
for (HardOrderVo o : ordersWithCar) {
|
||||
if (ObjectUtil.isEmpty(o.getCarList())) continue;
|
||||
Long mchId = o.getMerchantId();
|
||||
if (mchId == null) continue;
|
||||
merchantNameMap.put(mchId, o.getMerchantName());
|
||||
for (HardCarVo car : o.getCarList()) {
|
||||
if (car.getProductId() == null || car.getProductCount() == null || car.getProductCount() <= 0) continue;
|
||||
onlineSpuIds.add(car.getProductId());
|
||||
merchantItems.computeIfAbsent(mchId, k -> new ArrayList<>())
|
||||
.add(new OrderItem(car.getProductId(), car.getProductCount()));
|
||||
}
|
||||
}
|
||||
if (onlineSpuIds.isEmpty()) {
|
||||
return buildResult(merchantNameMap, Collections.emptyMap(), Collections.emptyMap());
|
||||
}
|
||||
|
||||
R<List<CanteenOnlineSpuAppVO>> spuRes = onlineCanteenSpuService.getSpuListByIds(new ArrayList<>(onlineSpuIds));
|
||||
List<CanteenOnlineSpuAppVO> onlineSpus = (spuRes != null && spuRes.getData() != null) ? spuRes.getData() : Collections.emptyList();
|
||||
Map<Long, Long> onlineSpuToLinkSpu = onlineSpus.stream()
|
||||
.filter(s -> s.getLinkSpuId() != null)
|
||||
.collect(Collectors.toMap(CanteenOnlineSpuAppVO::getId, CanteenOnlineSpuAppVO::getLinkSpuId, (a, b) -> a));
|
||||
|
||||
// 模板查找:每日菜品用 linkSpuId,常驻菜品用 onlineSpuId
|
||||
// 优先查 template_type=2 的线上模板;若无则回退查全部(兼容未设置类型的模板)
|
||||
Set<Long> dishIdsForTemplate = new HashSet<>(onlineSpuToLinkSpu.values());
|
||||
onlineSpus.stream().filter(s -> s.getLinkSpuId() == null).forEach(s -> dishIdsForTemplate.add(s.getId()));
|
||||
Map<Long, ProductTemplateVO> dishIdToTemplate = new HashMap<>();
|
||||
if (!dishIdsForTemplate.isEmpty()) {
|
||||
List<ProductTemplateVO> templates = fetchTemplatesWithFallback(new ArrayList<>(dishIdsForTemplate));
|
||||
for (ProductTemplateVO t : templates) {
|
||||
if (t.getDishId() != null) {
|
||||
dishIdToTemplate.put(t.getDishId(), t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map<Long, Map<Long, MaterialAccumulator>> merchantMaterialMap = new HashMap<>();
|
||||
Map<Long, NutritionAccumulator> merchantNutritionMap = new HashMap<>();
|
||||
Map<Long, long[]> merchantCounts = new HashMap<>();
|
||||
|
||||
for (Map.Entry<Long, List<OrderItem>> e : merchantItems.entrySet()) {
|
||||
Long mchId = e.getKey();
|
||||
merchantMaterialMap.put(mchId, new HashMap<>());
|
||||
merchantNutritionMap.put(mchId, new NutritionAccumulator());
|
||||
long orderCount = ordersWithCar.stream().filter(o -> Objects.equals(o.getMerchantId(), mchId)).count();
|
||||
long dishCount = 0;
|
||||
for (OrderItem item : e.getValue()) {
|
||||
Long templateKey = onlineSpuToLinkSpu.getOrDefault(item.productId, item.productId);
|
||||
ProductTemplateVO template = dishIdToTemplate.get(templateKey);
|
||||
if (template == null || ObjectUtil.isEmpty(template.getCanteenProductionTemplateDetailList())) continue;
|
||||
double baseOutput = ObjectUtil.defaultIfNull(template.getBaseOutput(), 1.0);
|
||||
if (baseOutput <= 0) baseOutput = 1.0;
|
||||
double ratio = item.count / baseOutput;
|
||||
dishCount += item.count;
|
||||
|
||||
for (ProductionTemplateDetailVO d : template.getCanteenProductionTemplateDetailList()) {
|
||||
double baseUsage = ObjectUtil.defaultIfNull(d.getBaseUsage(), 0.0);
|
||||
double lossRate = ObjectUtil.defaultIfNull(d.getLossRate(), 0.0);
|
||||
double usage = ratio * baseUsage * (1 + lossRate);
|
||||
merchantMaterialMap.get(mchId).computeIfAbsent(d.getMaterialId(), k -> new MaterialAccumulator(d.getMaterialId(), d.getMaterialName(), d.getUnit()))
|
||||
.add(usage);
|
||||
if (d.getNutritionDesc() != null && !d.getNutritionDesc().isBlank()) {
|
||||
merchantNutritionMap.get(mchId).addDesc(d.getMaterialName(), d.getNutritionDesc());
|
||||
}
|
||||
}
|
||||
}
|
||||
merchantCounts.put(mchId, new long[]{orderCount, dishCount});
|
||||
}
|
||||
|
||||
return buildResult(merchantNameMap, merchantMaterialMap, merchantNutritionMap, merchantCounts);
|
||||
}
|
||||
|
||||
/** 优先查线上模板(type=2),无则回退查全部,兼容未设置 templateType 的模板 */
|
||||
private List<ProductTemplateVO> fetchTemplatesWithFallback(List<Long> dishIds) {
|
||||
R<List<ProductTemplateVO>> res = productionTemplateService.getDetailsByDishIdsForOnline(dishIds);
|
||||
List<ProductTemplateVO> list = (res != null && res.getData() != null) ? res.getData() : Collections.emptyList();
|
||||
if (!list.isEmpty()) return list;
|
||||
R<List<ProductTemplateVO>> fallback = productionTemplateService.getDetailsByDishIds(dishIds);
|
||||
return (fallback != null && fallback.getData() != null) ? fallback.getData() : Collections.emptyList();
|
||||
}
|
||||
|
||||
private HardOrderDto buildQueryDto(HardOnlineCanteenStatsQueryDto query) {
|
||||
HardOrderDto dto = new HardOrderDto();
|
||||
dto.setOrderTypeCodes(List.of(HardOrderTypeEnum.RESERVE.getType()));
|
||||
dto.setMchTypeCodes(List.of(MerchantTypeEnum.CANTEEN.getType()));
|
||||
dto.setOrderStatusCodes(HardOrderStatusEnum.getPaySuccessCodes());
|
||||
dto.setRefundStatusCodes(List.of(HardRefundStatusEnum.NONE.getStatus(), HardRefundStatusEnum.APPLY.getStatus(), HardRefundStatusEnum.REJECT.getStatus()));
|
||||
dto.setPayTimeList(query.getPayTimeList());
|
||||
dto.setMchIds(query.getMchIds());
|
||||
dto.setIsFindCarList(true);
|
||||
return dto;
|
||||
}
|
||||
|
||||
private List<HardOnlineCanteenStatsVo> buildResult(Map<Long, String> merchantNameMap,
|
||||
Map<Long, Map<Long, MaterialAccumulator>> materialMap,
|
||||
Map<Long, NutritionAccumulator> nutritionMap) {
|
||||
return buildResult(merchantNameMap, materialMap, nutritionMap, new HashMap<>());
|
||||
}
|
||||
|
||||
private List<HardOnlineCanteenStatsVo> buildResult(Map<Long, String> merchantNameMap,
|
||||
Map<Long, Map<Long, MaterialAccumulator>> materialMap,
|
||||
Map<Long, NutritionAccumulator> nutritionMap,
|
||||
Map<Long, long[]> countsMap) {
|
||||
Set<Long> mchIds = new HashSet<>(merchantNameMap.keySet());
|
||||
mchIds.addAll(materialMap.keySet());
|
||||
mchIds.addAll(nutritionMap.keySet());
|
||||
mchIds.addAll(countsMap.keySet());
|
||||
List<HardOnlineCanteenStatsVo> result = new ArrayList<>();
|
||||
for (Long mchId : mchIds) {
|
||||
HardOnlineCanteenStatsVo vo = new HardOnlineCanteenStatsVo();
|
||||
vo.setMerchantId(mchId);
|
||||
vo.setMerchantName(merchantNameMap.getOrDefault(mchId, ""));
|
||||
long[] c = countsMap.getOrDefault(mchId, new long[]{0, 0});
|
||||
vo.setOrderCount(c[0]);
|
||||
vo.setTotalDishCount(c[1]);
|
||||
Map<Long, MaterialAccumulator> mat = materialMap.getOrDefault(mchId, Collections.emptyMap());
|
||||
vo.setMaterialUsages(mat.values().stream().map(MaterialAccumulator::toVo).collect(Collectors.toList()));
|
||||
vo.setNutritionSummary(nutritionMap.getOrDefault(mchId, new NutritionAccumulator()).toVo());
|
||||
result.add(vo);
|
||||
}
|
||||
result.sort(Comparator.comparing(HardOnlineCanteenStatsVo::getTotalDishCount).reversed());
|
||||
return result;
|
||||
}
|
||||
|
||||
private record OrderItem(Long productId, int count) {}
|
||||
|
||||
private static class MaterialAccumulator {
|
||||
Long materialId;
|
||||
String materialName;
|
||||
String unit;
|
||||
double usage;
|
||||
|
||||
MaterialAccumulator(Long materialId, String materialName, String unit) {
|
||||
this.materialId = materialId;
|
||||
this.materialName = materialName;
|
||||
this.unit = unit;
|
||||
}
|
||||
void add(double u) { usage += u; }
|
||||
HardOnlineCanteenMaterialUsageVo toVo() {
|
||||
HardOnlineCanteenMaterialUsageVo vo = new HardOnlineCanteenMaterialUsageVo();
|
||||
vo.setMaterialId(materialId);
|
||||
vo.setMaterialName(materialName);
|
||||
vo.setUnit(unit);
|
||||
vo.setUsage(usage);
|
||||
return vo;
|
||||
}
|
||||
}
|
||||
|
||||
private static class NutritionAccumulator {
|
||||
private final Set<String> descSet = new LinkedHashSet<>();
|
||||
void addDesc(String materialName, String nutritionDesc) {
|
||||
descSet.add(materialName + ":" + nutritionDesc);
|
||||
}
|
||||
HardOnlineCanteenNutritionVo toVo() {
|
||||
HardOnlineCanteenNutritionVo vo = new HardOnlineCanteenNutritionVo();
|
||||
vo.setNutritionDesc(String.join(";", descSet));
|
||||
return vo;
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -97,6 +97,12 @@
|
||||
<if test="dto.orderType != null and dto.orderType != '' ">
|
||||
and a.order_type = #{dto.orderType}
|
||||
</if>
|
||||
<if test="dto.orderTypeCodes != null and dto.orderTypeCodes.size() != 0">
|
||||
and a.order_type in
|
||||
<foreach collection="dto.orderTypeCodes" item="v" open="(" close=")" separator=",">
|
||||
#{v}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="dto.hourType != null and dto.hourType != '' ">
|
||||
and a.hour_type = #{dto.hourType}
|
||||
</if>
|
||||
@@ -195,6 +201,13 @@
|
||||
<if test="dto.payTimeList != null and dto.payTimeList.length == 2">
|
||||
and a.pay_time between #{dto.payTimeList[0]} and #{dto.payTimeList[1]}
|
||||
</if>
|
||||
<if test="dto.refundStatusCodes != null and dto.refundStatusCodes.size() != 0">
|
||||
and (a.refund_status in
|
||||
<foreach collection="dto.refundStatusCodes" item="v" open="(" close=")" separator=",">
|
||||
#{v}
|
||||
</foreach>
|
||||
or a.refund_status is null)
|
||||
</if>
|
||||
</sql>
|
||||
|
||||
<sql id="pageList">
|
||||
|
||||
Reference in new issue
Block a user