package cn.iocoder.yudao.module.mes.controller.admin.pro.batch;
|
|
import cn.hutool.core.collection.CollUtil;
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeRespVO;
|
import cn.iocoder.yudao.module.mes.controller.admin.pro.batch.vo.MesProBatchPageReqVO;
|
import cn.iocoder.yudao.module.mes.controller.admin.pro.batch.vo.MesProBatchRespVO;
|
import cn.iocoder.yudao.module.mes.controller.admin.pro.batch.vo.MesProBatchSaveReqVO;
|
import cn.iocoder.yudao.module.mes.controller.admin.pro.batch.vo.MesProBatchTraceRespVO;
|
import cn.iocoder.yudao.module.mes.controller.admin.pro.batch.vo.MesProBatchWorkerRespVO;
|
import cn.iocoder.yudao.module.mes.controller.admin.pro.pallet.vo.MesProPalletRespVO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.mdm.MesMdmItemDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.bagcode.MesProBagCodeDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.batch.MesProBatchDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.batch.MesProBatchWorkerDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.pallet.MesProPalletDO;
|
import cn.iocoder.yudao.module.mes.framework.qrcode.MesProQrLabelBuilder;
|
import cn.iocoder.yudao.module.mes.framework.qrcode.QrCodeImageUtils;
|
import cn.iocoder.yudao.module.mes.framework.qrcode.QrLabelInfo;
|
import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService;
|
import cn.iocoder.yudao.module.mes.service.pro.bagcode.MesProBagCodeService;
|
import cn.iocoder.yudao.module.mes.service.pro.batch.MesProBatchService;
|
import cn.iocoder.yudao.module.mes.service.pro.pallet.MesProPalletService;
|
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameters;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
import jakarta.annotation.Resource;
|
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.validation.Valid;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.validation.annotation.Validated;
|
import org.springframework.web.bind.annotation.*;
|
|
import java.io.IOException;
|
import java.util.ArrayList;
|
import java.util.Collections;
|
import java.util.HashSet;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Set;
|
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
|
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_BATCH_NOT_EXISTS;
|
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_QR_EXPORT_TOO_MANY;
|
|
@Tag(name = "管理后台 - MES 生产批次")
|
@RestController
|
@RequestMapping("/mes/pro/batch")
|
@Validated
|
public class MesProBatchController {
|
|
@Resource
|
private MesProBatchService batchService;
|
@Resource
|
private AdminUserApi adminUserApi;
|
@Resource
|
private MesMdmItemService mdmItemService;
|
@Resource
|
private MesProPalletService palletService;
|
@Resource
|
private MesProBagCodeService bagCodeService;
|
|
@PostMapping("/create")
|
@Operation(summary = "创建生产批次(自动生成批次号)")
|
@PreAuthorize("@ss.hasPermission('mes:pro-batch:create')")
|
public CommonResult<Long> createBatch(@Valid @RequestBody MesProBatchSaveReqVO createReqVO) {
|
return success(batchService.createBatch(createReqVO));
|
}
|
|
@PutMapping("/update")
|
@Operation(summary = "更新生产批次")
|
@PreAuthorize("@ss.hasPermission('mes:pro-batch:update')")
|
public CommonResult<Boolean> updateBatch(@Valid @RequestBody MesProBatchSaveReqVO updateReqVO) {
|
batchService.updateBatch(updateReqVO);
|
return success(true);
|
}
|
|
@DeleteMapping("/delete")
|
@Operation(summary = "删除生产批次")
|
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
@PreAuthorize("@ss.hasPermission('mes:pro-batch:delete')")
|
public CommonResult<Boolean> deleteBatch(@RequestParam("id") Long id) {
|
batchService.deleteBatch(id);
|
return success(true);
|
}
|
|
@PutMapping("/update-status")
|
@Operation(summary = "更新生产批次状态")
|
@Parameters({
|
@Parameter(name = "id", description = "编号", required = true, example = "1024"),
|
@Parameter(name = "status", description = "目标状态(字典 mes_pro_batch_status)", required = true, example = "20")
|
})
|
@PreAuthorize("@ss.hasPermission('mes:pro-batch:update')")
|
public CommonResult<Boolean> updateBatchStatus(@RequestParam("id") Long id,
|
@RequestParam("status") Integer status) {
|
batchService.updateBatchStatus(id, status);
|
return success(true);
|
}
|
|
@GetMapping("/get")
|
@Operation(summary = "获得生产批次详情(含人员配置)")
|
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
@PreAuthorize("@ss.hasPermission('mes:pro-batch:query')")
|
public CommonResult<MesProBatchRespVO> getBatch(@RequestParam("id") Long id) {
|
MesProBatchDO batch = batchService.getBatch(id);
|
if (batch == null) {
|
return success(null);
|
}
|
MesProBatchRespVO respVO = buildBatchRespVOList(Collections.singletonList(batch)).get(0);
|
// 填充人员配置
|
respVO.setWorkers(buildWorkerRespVOList(batchService.getBatchWorkerListByBatchId(id)));
|
return success(respVO);
|
}
|
|
@GetMapping("/page")
|
@Operation(summary = "获得生产批次分页")
|
@PreAuthorize("@ss.hasPermission('mes:pro-batch:query')")
|
public CommonResult<PageResult<MesProBatchRespVO>> getBatchPage(@Valid MesProBatchPageReqVO pageReqVO) {
|
PageResult<MesProBatchDO> pageResult = batchService.getBatchPage(pageReqVO);
|
return success(new PageResult<>(buildBatchRespVOList(pageResult.getList()), pageResult.getTotal()));
|
}
|
|
@GetMapping("/simple-list")
|
@Operation(summary = "获得生产批次精简列表(供下拉选择)")
|
@PreAuthorize("@ss.hasPermission('mes:pro-batch:query')")
|
public CommonResult<List<MesProBatchRespVO>> getBatchSimpleList() {
|
MesProBatchPageReqVO pageReqVO = new MesProBatchPageReqVO();
|
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
List<MesProBatchDO> list = batchService.getBatchPage(pageReqVO).getList();
|
return success(BeanUtils.toBean(list, MesProBatchRespVO.class));
|
}
|
|
@GetMapping("/export-excel")
|
@Operation(summary = "导出生产批次 Excel")
|
@PreAuthorize("@ss.hasPermission('mes:pro-batch:export')")
|
@ApiAccessLog(operateType = EXPORT)
|
public void exportBatchExcel(@Valid MesProBatchPageReqVO pageReqVO,
|
HttpServletResponse response) throws IOException {
|
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
List<MesProBatchDO> list = batchService.getBatchPage(pageReqVO).getList();
|
List<MesProBatchRespVO> voList = buildBatchRespVOList(list);
|
ExcelUtils.write(response, "生产批次.xls", "数据", MesProBatchRespVO.class, voList);
|
}
|
|
@GetMapping("/get-by-code")
|
@Operation(summary = "扫码追溯:根据批次号(二维码内容)反查批次、人员、托盘、袋码信息")
|
@Parameter(name = "code", description = "批次号(二维码内容)", required = true, example = "PC20260818L01001")
|
@PreAuthorize("@ss.hasPermission('mes:pro-batch:query')")
|
public CommonResult<MesProBatchTraceRespVO> getBatchByCode(@RequestParam("code") String code) {
|
MesProBatchDO batch = batchService.getBatchByCode(code);
|
if (batch == null) {
|
throw exception(PRO_BATCH_NOT_EXISTS);
|
}
|
return success(buildBatchTraceRespVO(batch));
|
}
|
|
@GetMapping("/export-qr")
|
@Operation(summary = "批量导出批次二维码图片 ZIP(批次图 + 该批次全部托盘图)")
|
@Parameter(name = "batchId", description = "生产批次编号", required = true, example = "1024")
|
@PreAuthorize("@ss.hasPermission('mes:pro-batch:export')")
|
@ApiAccessLog(operateType = EXPORT)
|
public void exportBatchQr(@RequestParam("batchId") Long batchId,
|
HttpServletResponse response) throws IOException {
|
MesProBatchDO batch = batchService.getBatch(batchId);
|
if (batch == null) {
|
throw exception(PRO_BATCH_NOT_EXISTS);
|
}
|
List<MesProPalletDO> pallets = palletService.getPalletListByBatchId(batchId);
|
if (pallets.size() + 1 > QrCodeImageUtils.MAX_QR_EXPORT) {
|
throw exception(PRO_QR_EXPORT_TOO_MANY);
|
}
|
QrCodeImageUtils.writeZip(response, "批次二维码-" + batch.getCode(), buildBatchQrLabels(batch, pallets));
|
}
|
|
// ==================== 拼接 VO ====================
|
|
private List<MesProBatchRespVO> buildBatchRespVOList(List<MesProBatchDO> list) {
|
if (CollUtil.isEmpty(list)) {
|
return Collections.emptyList();
|
}
|
// 1. 获得关联数据(责任人、品种物料)
|
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
|
convertSet(list, MesProBatchDO::getOwnerUserId));
|
Map<Long, MesMdmItemDO> itemMap = mdmItemService.getItemMap(
|
convertSet(list, MesProBatchDO::getItemId));
|
// 2. 构建结果
|
return BeanUtils.toBean(list, MesProBatchRespVO.class, vo -> {
|
MapUtils.findAndThen(userMap, vo.getOwnerUserId(), user ->
|
vo.setOwnerUserName(user.getNickname()));
|
MapUtils.findAndThen(itemMap, vo.getItemId(), item -> {
|
vo.setItemCode(item.getCode());
|
vo.setItemName(item.getName());
|
vo.setItemSpecification(item.getSpecification());
|
});
|
});
|
}
|
|
private List<MesProBatchWorkerRespVO> buildWorkerRespVOList(List<MesProBatchWorkerDO> workers) {
|
if (CollUtil.isEmpty(workers)) {
|
return Collections.emptyList();
|
}
|
Set<Long> userIds = new HashSet<>(convertList(workers, MesProBatchWorkerDO::getUserId));
|
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
|
return BeanUtils.toBean(workers, MesProBatchWorkerRespVO.class, vo ->
|
MapUtils.findAndThen(userMap, vo.getUserId(), user -> vo.setUserName(user.getNickname())));
|
}
|
|
private MesProBatchTraceRespVO buildBatchTraceRespVO(MesProBatchDO batch) {
|
MesProBatchTraceRespVO respVO = BeanUtils.toBean(batch, MesProBatchTraceRespVO.class);
|
// 品种信息
|
if (batch.getItemId() != null) {
|
MesMdmItemDO item = mdmItemService.getItem(batch.getItemId());
|
if (item != null) {
|
respVO.setItemCode(item.getCode())
|
.setItemName(item.getName())
|
.setItemSpecification(item.getSpecification());
|
}
|
}
|
// 责任人
|
if (batch.getOwnerUserId() != null) {
|
AdminUserRespDTO user = adminUserApi.getUser(batch.getOwnerUserId());
|
if (user != null) {
|
respVO.setOwnerUserName(user.getNickname());
|
}
|
}
|
// 人员配置
|
respVO.setWorkers(buildWorkerRespVOList(batchService.getBatchWorkerListByBatchId(batch.getId())));
|
// 托盘列表
|
respVO.setPallets(BeanUtils.toBean(palletService.getPalletListByBatchId(batch.getId()), MesProPalletRespVO.class));
|
// 袋码列表(封顶 2000,bagTotal 记录总数)
|
List<MesProBagCodeDO> bags = bagCodeService.getBagCodeListByBatchId(batch.getId());
|
respVO.setBagTotal(bags.size());
|
if (bags.size() > QrCodeImageUtils.MAX_QR_EXPORT) {
|
bags = bags.subList(0, QrCodeImageUtils.MAX_QR_EXPORT);
|
}
|
respVO.setBags(buildBagCodeRespVOList(bags));
|
return respVO;
|
}
|
|
private List<MesProBagCodeRespVO> buildBagCodeRespVOList(List<MesProBagCodeDO> list) {
|
if (CollUtil.isEmpty(list)) {
|
return Collections.emptyList();
|
}
|
// 获得批次的产线信息,拼接袋码的产线编码/名称
|
Map<Long, MesProBatchDO> batchMap = convertMap(
|
batchService.getBatchList(convertSet(list, MesProBagCodeDO::getBatchId)), MesProBatchDO::getId);
|
return BeanUtils.toBean(list, MesProBagCodeRespVO.class, vo ->
|
MapUtils.findAndThen(batchMap, vo.getBatchId(), batch ->
|
vo.setLineCode(batch.getLineCode()).setLineName(batch.getLineName())));
|
}
|
|
private List<QrLabelInfo> buildBatchQrLabels(MesProBatchDO batch, List<MesProPalletDO> pallets) {
|
// 获得关联数据(品种、责任人)——批次与托盘同属一批,共用同一份
|
Map<Long, MesMdmItemDO> itemMap = mdmItemService.getItemMap(
|
convertSet(Collections.singletonList(batch), MesProBatchDO::getItemId));
|
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
|
convertSet(Collections.singletonList(batch), MesProBatchDO::getOwnerUserId));
|
// 构建标签:批次图 + 全部托盘图
|
List<QrLabelInfo> labels = new ArrayList<>(pallets.size() + 1);
|
labels.add(MesProQrLabelBuilder.buildBatchLabel(batch, itemMap, userMap));
|
for (MesProPalletDO pallet : pallets) {
|
labels.add(MesProQrLabelBuilder.buildPalletLabel(pallet, batch, itemMap, userMap));
|
}
|
return labels;
|
}
|
|
}
|