package com.vincent.rsf.server.api.controller; import com.vincent.rsf.framework.common.Cools; import com.vincent.rsf.framework.common.R; import com.vincent.rsf.server.api.entity.dto.InTaskMsgDto; import com.vincent.rsf.server.api.controller.erp.params.TaskInParam; import com.vincent.rsf.server.api.entity.params.ExMsgParams; import com.vincent.rsf.server.api.entity.params.WcsTaskParams; import com.vincent.rsf.server.common.annotation.OperationLog; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.vincent.rsf.server.common.domain.BaseParam; import com.vincent.rsf.server.common.domain.PageParam; import com.vincent.rsf.server.manager.controller.params.LocToTaskParams; import com.vincent.rsf.server.manager.entity.Loc; import com.vincent.rsf.server.manager.enums.LocStsType; import com.vincent.rsf.server.manager.enums.TaskType; import com.vincent.rsf.server.manager.service.LocItemService; import com.vincent.rsf.server.manager.service.LocService; import com.vincent.rsf.server.api.service.WcsService; import com.vincent.rsf.server.common.constant.Constants; import com.vincent.rsf.server.system.controller.BaseController; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; 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.util.Map; @RestController @RequestMapping("/wcs") @Api(tags = "wcs接口对接") public class WcsController extends BaseController { @Autowired private WcsService wcsService; @Autowired private LocItemService locItemService; @Autowired private LocService locService; @ApiOperation("空板库位列表(分页),仅返回 useStatus=D 的库位,用于空板出库页勾选") @PreAuthorize("hasAuthority('manager:emptyOutbound:list')") @PostMapping("/empty/locs/page") public R emptyLocsPage(@RequestBody Map map) { BaseParam baseParam = buildParam(map, BaseParam.class); PageParam pageParam = new PageParam<>(baseParam, Loc.class); LambdaQueryWrapper qw = new LambdaQueryWrapper() .eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_D.type) .orderByAsc(Loc::getId); return R.ok().add(locService.page(pageParam, qw)); } @ApiOperation(value = "wcs生成入库任务接口") @PostMapping("/create/in/task") public R createInTask(@RequestBody TaskInParam param) { if (Cools.isEmpty(param.getIoType())) { return R.error("入出库类型不能为空"); } if (Cools.isEmpty(param.getSourceStaNo())) { return R.error("源站编号不能为空"); } if (Cools.isEmpty(param.getBarcode()) && param.getIoType().equals(TaskType.TASK_TYPE_IN.type)) { return R.error("条码不能为空"); } if (Cools.isEmpty(param.getLocType1())){ return R.error("高低检测信号不能为空"); } InTaskMsgDto msgDto = wcsService.createInTask(param); return R.ok(msgDto); } @ApiOperation(value = "agv取货完成接口") @PostMapping("/agv/pickUp/complete") public R AgvTaskPickUpComplete(@RequestBody TaskInParam param) { if (Cools.isEmpty(param.getIoType())) { return R.error("入出库类型不能为空"); } if (Cools.isEmpty(param.getSourceStaNo())) { return R.error("源站编号不能为空"); } if (Cools.isEmpty(param.getBarcode())) { return R.error("条码不能为空"); } if (!param.getIoType().equals(TaskType.TASK_TYPE_IN.type)) { return R.error("入库类型有误"); } wcsService.agvTaskPickUpComplete(param); return R.ok(); } /** * 接收WCS调度,回传执行状态 * TODO 1. 拣料出库,再入库执行,修改状态为199.任务完成 并记录入库站点(源站点),添加任务号参数 * @param param * @return */ @ApiOperation("接收WCS调度,回传执行状态") @PostMapping("/exce/status") public R receiveTask(@RequestBody TaskInParam param) { if (Cools.isEmpty(param)) { return R.error("参数不能为空!!"); } return R.ok(); } /** * @author Ryan * @date 2025/8/27 * @description: RCS库位信息同步 * @version 1.0 */ @ApiOperation("RCS库位信息同步") @OperationLog("RCS库位信息同步") @PostMapping("/sync/locs") public R syncLocsToWms() { wcsService.syncLocsToWms(); return R.ok(); } /** * 下发任务至WCS,API中转 * @param * @return */ @ApiOperation("下发任务至WCS") @OperationLog("下发任务至WCS") @PostMapping("/pub/task/wcs") public R pubTaskToWcs(@RequestBody WcsTaskParams params) { return wcsService.pubWcsTask(params); } /** * @author Ryan * @date 2025/8/28 * @description: RCS上报异常信息 * @version 1.0 */ @ApiOperation("RCS上报异常执行信息") @OperationLog("RCS上报异常执行信息") @PostMapping("/receive/ex/msg") public R receiveExMsg(@RequestBody ExMsgParams params) { return wcsService.receiveExMsg(params); } /** * @author Ryan * @date 2026/2/6 * @description: 申请入库任务,分配库位 * @version 1.0 */ @ApiOperation("申请入库任务,分配库位") @PostMapping("/allocate/location") public R allocateLocation(@RequestBody Map params) { if (Cools.isEmpty(params)) { return R.error("参数不能为空!!"); } String barcode = (String) params.get("barcode"); String staNo = (String) params.get("staNo"); Integer type = params.get("type") != null ? Integer.valueOf(params.get("type").toString()) : null; Boolean full = null; if (params.get("full") != null) { if (params.get("full") instanceof Boolean) { full = (Boolean) params.get("full"); } else { full = Boolean.parseBoolean(params.get("full").toString()); } } if (Cools.isEmpty(barcode)) { return R.error("料箱码不能为空!!"); } if (Cools.isEmpty(staNo)) { return R.error("入库站点不能为空!!"); } if (type == null) { return R.error("入库类型不能为空!!"); } return wcsService.allocateLocation(barcode, staNo, type, full); } @ApiOperation("空板出库:从指定空板库位生成出库任务至目标站点") @PreAuthorize("hasAuthority('manager:emptyOutbound:list')") @PostMapping("/empty/outbound") public R emptyOutbound(@RequestBody Map params) { if (Cools.isEmpty(params)) { return R.error("参数不能为空!!"); } String staNo = (String) params.get("staNo"); String orgLoc = (String) params.get("orgLoc"); if (Cools.isEmpty(staNo)) { return R.error("目标站点 staNo 不能为空!!"); } if (Cools.isEmpty(orgLoc)) { return R.error("源库位 orgLoc 不能为空!!"); } LocToTaskParams map = new LocToTaskParams(); map.setSiteNo(staNo); map.setOrgLoc(orgLoc); map.setType(Constants.TASK_TYPE_OUT_STOCK_EMPTY); Long userId = getLoginUserId(); if (userId == null) { userId = 1L; } return R.ok("空板出库任务创建成功").add(locItemService.generateTaskEmpty(map, userId)); } }