| New file |
| | |
| | | package com.zy.api.controller; |
| | | |
| | | |
| | | import com.zy.api.controller.params.PageRequestParams; |
| | | import com.zy.api.entity.PubOrderParams; |
| | | import com.zy.api.entity.ReportOrderParam; |
| | | import com.zy.api.entity.StockAdjustParams; |
| | | import com.zy.api.entity.StockUpOrderParams; |
| | | import com.zy.api.entity.SyncMatParmas; |
| | | import com.zy.api.entity.dto.XSR; |
| | | import com.zy.api.service.HWmsApiService; |
| | | import com.zy.common.web.BaseController; |
| | | |
| | | import io.swagger.annotations.ApiOperation; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | 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.List; |
| | | import java.util.Objects; |
| | | |
| | | |
| | | |
| | | @Slf4j |
| | | @RestController |
| | | @RequestMapping("/kopen") |
| | | public class HWmsApiController extends BaseController{ |
| | | |
| | | @Autowired |
| | | private HWmsApiService kopenApiService; |
| | | |
| | | /** |
| | | * 上游下发派工单 |
| | | * |
| | | * @author Ryan |
| | | * @date 2025/11/24 15:18 |
| | | * @param params |
| | | * @return com.core.common.R |
| | | */ |
| | | @ApiOperation("入库单下发") |
| | | @PostMapping("/sendInDispatch") |
| | | public XSR receiveOrders(@RequestBody List<PubOrderParams> params) { |
| | | if (Objects.isNull(params)) { |
| | | return XSR.error("参数不能为空!!"); |
| | | } |
| | | // if (Objects.isNull(params.getType())) { |
| | | // return XSR.error("单据类型不能为空!"); |
| | | // } |
| | | |
| | | return kopenApiService.receiveOrders(params); |
| | | } |
| | | |
| | | /** |
| | | * 上游下发零件数据变更 |
| | | * |
| | | * @author Ryan |
| | | * @date 2025/11/24 15:19 |
| | | * @param params |
| | | * @return com.core.common.R |
| | | */ |
| | | @ApiOperation("零件信息数据更新") |
| | | @PostMapping("/sendPartsMaster") |
| | | public XSR basMatUpdate(@RequestBody List<SyncMatParmas> params) { |
| | | if (Objects.isNull(params) || params.isEmpty()) { |
| | | return XSR.error("参数不能为空!!"); |
| | | } |
| | | return kopenApiService.basMatupdate(params); |
| | | } |
| | | |
| | | /** |
| | | * 上架派工单反馈 |
| | | * @author Ryan |
| | | * @date 2025/11/24 15:20 |
| | | * @param params |
| | | * @return com.core.common.R |
| | | */ |
| | | @ApiOperation("上架派工单反馈") |
| | | @PostMapping("/getInDispatchResult") |
| | | public XSR getInDispatchResult(@RequestBody List<ReportOrderParam> params) { |
| | | if (Objects.isNull(params)) { |
| | | return XSR.error("参数不能为空!!"); |
| | | } |
| | | // if (Objects.isNull(params.getKopen_id()) && Objects.isNull(params.getInv_no()) && Objects.isNull(params.getDispatch_no())) { |
| | | // return XSR.error("取消条件不能为空!!"); |
| | | // } |
| | | return kopenApiService.getInDispatchResult(params, null); |
| | | } |
| | | |
| | | /** |
| | | * 备货指示派工单下发 |
| | | * @author Ryan |
| | | * @date 2025/11/24 15:21 |
| | | * @param params |
| | | * @return com.core.common.R |
| | | */ |
| | | @ApiOperation("备货指示派工单下发") |
| | | @PostMapping("/sendOutDispatch") |
| | | public XSR sendStockPrepareDispatch(@RequestBody List<PubOrderParams> params) { |
| | | if (Objects.isNull(params)) { |
| | | return XSR.error("参数不能为空!!"); |
| | | } |
| | | // if (Objects.isNull(params.getDetails()) || params.getDetails().isEmpty()) { |
| | | // return XSR.error("上报订单列表不能为空!!"); |
| | | // } |
| | | return kopenApiService.sendOutDispatch(params); |
| | | } |
| | | |
| | | |
| | | // /** |
| | | // * 备货指示派工单反馈 |
| | | // * @author Ryan |
| | | // * @date 2025/11/24 15:22 |
| | | // * @param params |
| | | // * @return com.core.common.R |
| | | // */ |
| | | // @ApiOperation("备货指示派工单反馈") |
| | | // @PostMapping("/getOutDispatchResult") |
| | | // public R getOutDispatchResult(@RequestBody ReportOrderParam params) { |
| | | // if (Objects.isNull(params)) { |
| | | // return R.error("参数不能为空!!"); |
| | | // } |
| | | // if (Objects.isNull(params.getKopen_id()) && Objects.isNull(params.getInv_no()) && Objects.isNull(params.getDispatch_no())) { |
| | | // return R.error("取消条件不能为空!!"); |
| | | // } |
| | | // return kopenApiService.getOutDispatchResult(params); |
| | | // } |
| | | |
| | | |
| | | /** |
| | | * 备货单下发 |
| | | * @author Ryan |
| | | * @date 2025/11/24 15:21 |
| | | * @param params |
| | | * @return com.core.common.R |
| | | */ |
| | | @ApiOperation("备货单下发") |
| | | @PostMapping("/getOutDetails") |
| | | public XSR getOutDetails(@RequestBody List<StockUpOrderParams> params) { |
| | | if (Objects.isNull(params)) { |
| | | return XSR.error("参数不能为空!!"); |
| | | } |
| | | return kopenApiService.getOutDetails(params); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 查询WMS库存信息 |
| | | * @author Ryan |
| | | * @date 2025/11/24 15:22 |
| | | * @param params |
| | | * @return com.core.common.R |
| | | */ |
| | | @ApiOperation("查询WMS库存信息") |
| | | @PostMapping("/getStockInfo") |
| | | public XSR getStockInfo(@RequestBody PageRequestParams params) { |
| | | return kopenApiService.getStockInfo(params); |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.api.controller; |
| | | |
| | | import io.swagger.annotations.Api; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | |
| | | @Api(value = "HMES对接") |
| | | @RestController |
| | | @RequestMapping("/api") |
| | | public class HmesApiController { |
| | | |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.api.controller; |
| | | |
| | | |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.core.annotations.ManagerAuth; |
| | | import com.core.common.R; |
| | | import com.zy.api.controller.params.ReceviceTaskParams; |
| | | import com.zy.api.controller.params.WorkTaskParams; |
| | | import com.zy.api.service.WcsApiService; |
| | | import com.zy.asrs.entity.WaitPakin; |
| | | import com.zy.asrs.service.WaitPakinService; |
| | | import com.zy.asrs.utils.Utils; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | |
| | | @Api("WCS交互接口") |
| | | @RequestMapping("/wcs") |
| | | @RestController |
| | | public class WcsApiController { |
| | | |
| | | @Autowired |
| | | private WcsApiService wcsApiService; |
| | | @Autowired |
| | | private WaitPakinService waitPakinService; |
| | | |
| | | /** |
| | | * 下发任务至WCS |
| | | * @author Ryan |
| | | * @date 2026/1/10 13:57 |
| | | * @param params |
| | | * @return com.core.common.R |
| | | */ |
| | | @ManagerAuth |
| | | @ApiOperation("下发任务至WCS") |
| | | @PostMapping("/pub/wrks") |
| | | public R pubWrkToWcs(@RequestBody WorkTaskParams params) { |
| | | if (Objects.isNull(params)) { |
| | | return R.error("参数不能为空!!"); |
| | | } |
| | | return wcsApiService.pubWrkToWcs(params); |
| | | } |
| | | |
| | | // @ManagerAuth |
| | | @ApiOperation("设备执行状态回写-wcs任务完成回写") |
| | | @PostMapping("/openapi/report") |
| | | public R receviceTaskFromWcs(@RequestBody ReceviceTaskParams params) { |
| | | if (Objects.isNull(params)) { |
| | | return R.error("参数不能为空!!"); |
| | | } |
| | | return wcsApiService.receviceTaskFromWcs(params); |
| | | |
| | | } |
| | | |
| | | @ManagerAuth |
| | | @ApiOperation("获取组托入库托盘信息") |
| | | @PostMapping("/openapi/waitPakins") |
| | | public R waitPakins() { |
| | | List<WaitPakin> waitPakins = waitPakinService.selectList(new EntityWrapper<WaitPakin>().eq("io_status", "N")); |
| | | return R.ok().add(waitPakins); |
| | | |
| | | } |
| | | } |
| New file |
| | |
| | | package com.zy.api.controller.params; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import lombok.Data; |
| | | import lombok.experimental.Accessors; |
| | | |
| | | @Data |
| | | @Accessors(chain = true) |
| | | @ApiModel("分页请求参数") |
| | | public class PageRequestParams { |
| | | |
| | | private Integer curr = 1; |
| | | |
| | | private Integer limit = 50; |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.api.controller.params; |
| | | |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.experimental.Accessors; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | @Data |
| | | @Accessors(chain = true) |
| | | @ApiModel(value = "ReceviceTaskParams", description = "穿线墙参数") |
| | | public class ReceviceTaskParams implements Serializable { |
| | | |
| | | @ApiModelProperty("机台号") |
| | | private String devNo; |
| | | |
| | | @ApiModelProperty("流水号") |
| | | private Long id; |
| | | |
| | | @ApiModelProperty("通知类型:task") |
| | | private String notifyType; |
| | | |
| | | @ApiModelProperty("堆垛机号") |
| | | private Integer device; |
| | | |
| | | @ApiModelProperty("WMS任务号") |
| | | private String superTaskNo; |
| | | |
| | | @ApiModelProperty("消息类型:task_complete、task_cancel") |
| | | private String msgType; |
| | | |
| | | @ApiModelProperty("消息描述") |
| | | private String msgDesc; |
| | | |
| | | @ApiModelProperty("消息数据") |
| | | private String data; |
| | | |
| | | @ApiModelProperty("重量") |
| | | private Double weight; |
| | | |
| | | @ApiModelProperty("Y:冻结 N:解冻") |
| | | private String freeze; |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.api.controller.params; |
| | | |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.experimental.Accessors; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | @Data |
| | | @Accessors(chain = true) |
| | | @ApiModel(value = "WorkTaskParams", description = "执行任务参数") |
| | | public class WorkTaskParams implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @ApiModelProperty("协议任务编号(对应出库任务号)") |
| | | private String taskNo; |
| | | |
| | | @ApiModelProperty("工作档任务号") |
| | | private String wrkNo; |
| | | |
| | | @ApiModelProperty("库位编码") |
| | | private String locNo; |
| | | |
| | | //源库位 |
| | | private String sourceLocNo; |
| | | |
| | | //源站点 |
| | | private String sourceStaNo; |
| | | |
| | | @ApiModelProperty("条码") |
| | | private String barcode; |
| | | |
| | | @ApiModelProperty("优先级") |
| | | private Integer taskPri; |
| | | |
| | | @ApiModelProperty("出库站点") |
| | | private String staNo; |
| | | |
| | | @ApiModelProperty("作业类型,in: 入库, out:出库") |
| | | private String type; |
| | | |
| | | @ApiModelProperty("是否余料") |
| | | private Integer isSuplus; |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.api.entity; |
| | | |
| | | import java.util.Map; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import lombok.Data; |
| | | import lombok.experimental.Accessors; |
| | | |
| | | @Data |
| | | @ApiModel("基础请求参数") |
| | | @Accessors(chain = true) |
| | | public class BaseRequstParam { |
| | | |
| | | private Map<String, Object> root; |
| | | } |
| New file |
| | |
| | | package com.zy.api.entity; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.experimental.Accessors; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | @Data |
| | | @Accessors(chain = true) |
| | | @ApiModel(value = "CallAgvParams", description = "AGV搬运参数") |
| | | public class CallAgvParams implements Serializable { |
| | | |
| | | @ApiModelProperty("呼叫类型:出库:out, 入库:in") |
| | | private String type; |
| | | |
| | | @ApiModelProperty("原库位") |
| | | private String orgLoc; |
| | | |
| | | @ApiModelProperty("目标站点") |
| | | private String tarSite; |
| | | |
| | | @ApiModelProperty("原站点") |
| | | private String orgSite; |
| | | |
| | | @ApiModelProperty("目标库位") |
| | | private String tarLoc; |
| | | |
| | | @ApiModelProperty("搬运状态") |
| | | private String status; |
| | | |
| | | @ApiModelProperty("任务号") |
| | | private String wrkNo; |
| | | } |
| New file |
| | |
| | | package com.zy.api.entity; |
| | | |
| | | import lombok.Data; |
| | | import java.util.Map; |
| | | |
| | | @Data |
| | | public class CrnProtocol { |
| | | private Integer crnNo; |
| | | private Integer mode; // 1=Manual, 2=Auto, 3=Computer |
| | | private Object modeType; // Enum: CrnModeType |
| | | private Integer alarm; // Error code |
| | | private Integer taskNo; // Task number |
| | | private Integer status; // Current status code |
| | | private Object statusType; // Enum: CrnStatusType |
| | | private Integer bay; // Current bay |
| | | private Integer level; // Current level |
| | | private Integer forkPos; // Fork position code |
| | | private Object forkPosType; // Enum: CrnForkPosType |
| | | private Integer liftPos; // Lift position code |
| | | private Object liftPosType; // Enum: CrnLiftPosType |
| | | private Integer walkPos; // 0=In Position, 1=Not in Position |
| | | private Integer loaded; // 1=Loaded, 0=Empty |
| | | |
| | | // Speed and Distance |
| | | private Double xSpeed; |
| | | private Double ySpeed; |
| | | private Double zSpeed; |
| | | private Double xDistance; |
| | | private Double yDistance; |
| | | private Double xDuration; |
| | | private Double yDuration; |
| | | |
| | | // Other Info |
| | | private String lastIo; // "I"=Inbound, "O"=Outbound |
| | | private Integer crnLane; // Lane number |
| | | private float weight; |
| | | private String barcode; |
| | | private Long deviceDataLog; |
| | | private Long lastCommandTime; |
| | | |
| | | // Reserved/Temp |
| | | private Integer temp1; |
| | | private Integer temp2; |
| | | private Integer temp3; |
| | | private Integer temp4; |
| | | |
| | | private Map<String, Object> extend; |
| | | } |
| New file |
| | |
| | | package com.zy.api.entity; |
| | | |
| | | import lombok.Data; |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | |
| | | @Data |
| | | public class DeviceConfig implements Serializable { |
| | | private Integer id; |
| | | private String ip; |
| | | private Integer port; |
| | | private String threadImpl; |
| | | private Date createTime; |
| | | private String deviceType; |
| | | private Integer deviceNo; |
| | | private Integer fake; |
| | | private String fakeInitStatus; |
| | | } |
| New file |
| | |
| | | package com.zy.api.entity; |
| | | |
| | | import lombok.Data; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * Device Status Response Object |
| | | * Corresponds to the map returned by OpenController.getDeviceStatus |
| | | */ |
| | | @Data |
| | | public class DeviceStatusVo { |
| | | /** |
| | | * Stacker Crane (CRN) Data List |
| | | */ |
| | | private List<CrnProtocol> crnList; |
| | | |
| | | /** |
| | | * RGV Device Config List |
| | | * Note: The controller returns the DeviceConfig list for RGV, not the protocol status list. |
| | | */ |
| | | private List<DeviceConfig> rgvList; |
| | | |
| | | /** |
| | | * Dual-Station Stacker Crane Data List |
| | | */ |
| | | private List<DualCrnProtocol> dualCrnList; |
| | | |
| | | /** |
| | | * Conveyor Station Data List |
| | | */ |
| | | private List<StationProtocol> stationList; |
| | | } |
| New file |
| | |
| | | package com.zy.api.entity; |
| | | import lombok.Data; |
| | | import java.util.Map; |
| | | |
| | | @Data |
| | | public class DualCrnProtocol { |
| | | private Integer crnNo; |
| | | private Integer mode; |
| | | private Object modeType; // Enum: DualCrnModeType |
| | | private Integer alarm; |
| | | |
| | | // Station 1 Data |
| | | private Integer taskNo; |
| | | private Integer status; |
| | | private Object statusType; // Enum: DualCrnStatusType |
| | | private Integer bay; |
| | | private Integer level; |
| | | private Integer forkPos; |
| | | private Object forkPosType; // Enum: DualCrnForkPosType |
| | | private Integer liftPos; |
| | | private Object liftPosType; // Enum: DualCrnLiftPosType |
| | | private Integer walkPos; |
| | | private Integer loaded; |
| | | private Integer taskReceive; |
| | | |
| | | // Station 2 Data |
| | | private Integer taskNoTwo; |
| | | private Integer statusTwo; |
| | | private Object statusTypeTwo; |
| | | private Integer bayTwo; |
| | | private Integer levelTwo; |
| | | private Integer forkPosTwo; |
| | | private Object forkPosTypeTwo; |
| | | private Integer liftPosTwo; |
| | | private Object liftPosTypeTwo; |
| | | private Integer walkPosTwo; |
| | | private Integer loadedTwo; |
| | | private Integer taskReceiveTwo; |
| | | |
| | | // Movement Data (Integer type in DualCrnProtocol) |
| | | private Integer xSpeed; |
| | | private Integer ySpeed; |
| | | private Integer zSpeed; |
| | | private Integer xDistance; |
| | | private Integer yDistance; |
| | | private Integer xDuration; |
| | | private Integer yDuration; |
| | | |
| | | // Other Info |
| | | private Integer goodsType; |
| | | private String barcode; |
| | | private String lastIo; |
| | | private Integer crnLane; |
| | | private Long deviceDataLog; |
| | | private Long lastCommandTime; |
| | | |
| | | // Reserved/Temp |
| | | private Integer temp1; |
| | | private Integer temp2; |
| | | private Integer temp3; |
| | | private Integer temp4; |
| | | |
| | | private Map<String, Object> extend; |
| | | } |
| New file |
| | |
| | | package com.zy.api.entity; |
| | | |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.experimental.Accessors; |
| | | |
| | | |
| | | @Data |
| | | @Accessors(chain = true) |
| | | @ApiModel(value = "MatnrsParams", description = "物料信息") |
| | | public class MatnrsParams { |
| | | |
| | | @ApiModelProperty("单据类型") |
| | | private String pro_komcode; |
| | | |
| | | @ApiModelProperty("工单类型") |
| | | private String pro_id; |
| | | |
| | | @ApiModelProperty("订单号") |
| | | private String company_id; |
| | | |
| | | @ApiModelProperty("订单数量") |
| | | private Double pro_name; |
| | | |
| | | @ApiModelProperty("操作人") |
| | | private String pro_size; |
| | | |
| | | @ApiModelProperty("重量") |
| | | private String pro_wet; |
| | | |
| | | @ApiModelProperty("零件类型") |
| | | private String pro_type; |
| | | |
| | | @ApiModelProperty("更新时间") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private String update_time; |
| | | } |
| New file |
| | |
| | | package com.zy.api.entity; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.experimental.Accessors; |
| | | import java.io.Serializable; |
| | | |
| | | @Data |
| | | @Accessors(chain = true) |
| | | @ApiModel(value = "OrderItemsParam", description = "订单明细参数") |
| | | public class OrderItemsParam implements Serializable { |
| | | |
| | | @ApiModelProperty("BS Code") |
| | | private String total_serial; |
| | | |
| | | @ApiModelProperty("目标库区") |
| | | private String target_location; |
| | | |
| | | @ApiModelProperty("零件类型") |
| | | private String pro_type; |
| | | |
| | | @ApiModelProperty("零件代码") |
| | | private String pro_komcode; |
| | | |
| | | @ApiModelProperty("供应商编码") |
| | | private String pro_id; |
| | | |
| | | @ApiModelProperty("入库通知数量") |
| | | private Double inv_qty; |
| | | |
| | | @ApiModelProperty("指示拣货订单数量") |
| | | private Integer order_qty; |
| | | |
| | | @ApiModelProperty("原上架派工数量") |
| | | private Integer old_qty; |
| | | |
| | | @ApiModelProperty("变更数量") |
| | | private Integer new_qty; |
| | | |
| | | @ApiModelProperty("捆绑/叫料/数量数量") |
| | | private Integer pick_qty; |
| | | |
| | | @ApiModelProperty("损溢数量") |
| | | private Integer bsby_qty; |
| | | |
| | | @ApiModelProperty("托盘编号") |
| | | private String location_no; |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.api.entity; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.experimental.Accessors; |
| | | |
| | | @Data |
| | | @Accessors(chain = true) |
| | | @ApiModel(value = "OrderParams", description = "单据信息") |
| | | public class OrderParams implements Serializable { |
| | | |
| | | @ApiModelProperty("流水号(唯一)") |
| | | private String kopen_id; |
| | | |
| | | @ApiModelProperty("派工单号") |
| | | private String dispatch_no; |
| | | |
| | | @ApiModelProperty("公司ID") |
| | | private String company_id; |
| | | |
| | | @ApiModelProperty("入库类型 1: 采购入库,2: 调拨入库,3: 销售退货入库,4: 套包入库, 5:SO, 6:EO, 7:出库") |
| | | private String type; |
| | | |
| | | @ApiModelProperty("箱号") |
| | | private String pm_tktid; |
| | | |
| | | @ApiModelProperty("入库通知单号") |
| | | private String inv_no; |
| | | |
| | | @ApiModelProperty("目标库区") |
| | | private String target_location; |
| | | |
| | | @ApiModelProperty("源库区") |
| | | private String source_location; |
| | | |
| | | |
| | | @ApiModelProperty("拣货单号") |
| | | private String pick_no; |
| | | |
| | | @ApiModelProperty("订单号") |
| | | private String order_no; |
| | | |
| | | |
| | | @ApiModelProperty("客户ID") |
| | | private String cus_id; |
| | | |
| | | |
| | | @ApiModelProperty("客户地址") |
| | | private String cus_address; |
| | | |
| | | |
| | | @ApiModelProperty("WMS ID") |
| | | private String wms_id; |
| | | |
| | | |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private String update_time; |
| | | } |
| New file |
| | |
| | | package com.zy.api.entity; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.experimental.Accessors; |
| | | import java.io.Serializable; |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | @Accessors(chain = true) |
| | | @ApiModel(value = "OutOrderParams", description = "备货订单参数") |
| | | public class OutOrderParams implements Serializable { |
| | | |
| | | @ApiModelProperty("明细备货单号") |
| | | private String pick_no; |
| | | |
| | | @ApiModelProperty("订单号") |
| | | private String order_no; |
| | | |
| | | @ApiModelProperty("客户") |
| | | private String cus_id; |
| | | |
| | | @ApiModelProperty("客户地址") |
| | | private String cus_address; |
| | | |
| | | @ApiModelProperty("业务类型") |
| | | private String type; |
| | | |
| | | @ApiModelProperty("订单明细") |
| | | private List<OrderItemsParam> partList; |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.api.entity; |
| | | |
| | | import java.util.List; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.experimental.Accessors; |
| | | |
| | | @Data |
| | | @Accessors(chain = true) |
| | | @ApiModel(value = "PubOrderParams", description = "发布订单信息") |
| | | public class PubOrderParams extends OrderParams { |
| | | |
| | | @ApiModelProperty("入库物料列表") |
| | | List<OrderItemsParam> details; |
| | | } |
| New file |
| | |
| | | package com.zy.api.entity; |
| | | |
| | | import java.util.List; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.experimental.Accessors; |
| | | |
| | | @Data |
| | | @Accessors(chain = true) |
| | | @ApiModel(value = "ReportOrderParam", description = "上报订单信息") |
| | | public class ReportOrderParam extends OrderParams{ |
| | | |
| | | @ApiModelProperty("上报订单列表") |
| | | List<ReportOrderParams> details; |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.api.entity; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.experimental.Accessors; |
| | | |
| | | @Data |
| | | @Accessors(chain = true) |
| | | @ApiModel("上报订单参数") |
| | | public class ReportOrderParams implements Serializable { |
| | | |
| | | @ApiModelProperty("BS Code") |
| | | private String total_serial; |
| | | |
| | | @ApiModelProperty("产品类型") |
| | | private String pro_type; |
| | | |
| | | @ApiModelProperty("零件代码") |
| | | private String pro_komcode; |
| | | |
| | | @ApiModelProperty("供应商ID") |
| | | private String pro_id; |
| | | |
| | | @ApiModelProperty("容器编码") |
| | | private String location_no; |
| | | |
| | | @ApiModelProperty("货位类型") |
| | | private String location_type; |
| | | |
| | | @ApiModelProperty("上架日期") |
| | | private String sj_date; |
| | | |
| | | @ApiModelProperty("上架人") |
| | | private String sj_emp; |
| | | |
| | | @ApiModelProperty("上架数量") |
| | | private Integer pick_qty; |
| | | |
| | | @ApiModelProperty("破损数量") |
| | | private Integer damage_qty; |
| | | |
| | | @ApiModelProperty("差异数量") |
| | | private Integer diff_qty; |
| | | |
| | | @ApiModelProperty("原上架派工数量") |
| | | private Integer old_qty; |
| | | |
| | | @ApiModelProperty("变更数量") |
| | | private Integer new_qty; |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.api.entity; |
| | | import lombok.Data; |
| | | import java.util.Map; |
| | | |
| | | @Data |
| | | public class StationProtocol { |
| | | private Integer stationId; // Station ID |
| | | private Integer taskNo; // Task number |
| | | private Integer targetStaNo; // Target Station ID |
| | | |
| | | // Status Flags |
| | | private boolean autoing; // Auto mode |
| | | private boolean loading; // Has goods |
| | | private boolean inEnable; // Inbound enabled |
| | | private boolean outEnable; // Outbound enabled |
| | | private boolean emptyMk; // Empty pallet mark |
| | | private boolean fullPlt; // Full pallet |
| | | private boolean runBlock; // Running blocked |
| | | private boolean enableIn; // Start inbound |
| | | |
| | | private Integer palletHeight; |
| | | private Integer error; // Error code |
| | | private String errorMsg; // Error message |
| | | private String barcode; |
| | | private Double weight; |
| | | |
| | | private Map<String, Object> extend; |
| | | } |
| New file |
| | |
| | | package com.zy.api.entity; |
| | | |
| | | import java.util.List; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.experimental.Accessors; |
| | | |
| | | @Data |
| | | @Accessors(chain = true) |
| | | @ApiModel(value = "StockAdjustParams", description = "零件损溢单参数") |
| | | public class StockAdjustParams extends OrderParams { |
| | | |
| | | @ApiModelProperty("调整原因") |
| | | private String reason; |
| | | |
| | | @ApiModelProperty("调整原因名称") |
| | | private String reason_name; |
| | | |
| | | @ApiModelProperty("调整单编号") |
| | | private String bsby_no; |
| | | |
| | | @ApiModelProperty("调整单明细列表") |
| | | List<OrderItemsParam> details; |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.api.entity; |
| | | |
| | | import java.util.List; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.experimental.Accessors; |
| | | |
| | | @Data |
| | | @Accessors(chain = true) |
| | | @ApiModel(value = "StockUpOrderParams", description = "备货订单参数") |
| | | public class StockUpOrderParams extends OrderParams{ |
| | | |
| | | |
| | | @ApiModelProperty("订单明细") |
| | | private List<OutOrderParams> details; |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.api.entity; |
| | | |
| | | |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.experimental.Accessors; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | @Data |
| | | @Accessors(chain = true) |
| | | @ApiModel(value = "SyncMatParmas", description = "物料同步参数") |
| | | public class SyncMatParmas implements Serializable { |
| | | |
| | | |
| | | @ApiModelProperty("零件类型") |
| | | private String pro_type; |
| | | |
| | | @ApiModelProperty("零件代码") |
| | | private String pro_komcode; |
| | | |
| | | @ApiModelProperty("供应商编码") |
| | | private String pro_id; |
| | | |
| | | @ApiModelProperty("入库通知数量") |
| | | private Double inv_qty; |
| | | |
| | | @ApiModelProperty("公司ID") |
| | | private String company_id; |
| | | |
| | | @ApiModelProperty("零件名称") |
| | | private String pro_name; |
| | | |
| | | @ApiModelProperty("尺寸") |
| | | private String pro_size; |
| | | |
| | | @ApiModelProperty("重量") |
| | | private String pro_wet; |
| | | |
| | | @ApiModelProperty("更新时间") |
| | | private String update_time; |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.api.entity.dto; |
| | | |
| | | import java.sql.Date; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | import io.swagger.annotations.ApiModel; |
| | | import lombok.Data; |
| | | import lombok.experimental.Accessors; |
| | | |
| | | @Data |
| | | @Accessors(chain = true) |
| | | @ApiModel(value = "XSR", description = "基础响应") |
| | | public class XSR<T> { |
| | | private static final String SUCCESS_CODE = "200"; |
| | | private static final String FAIL_CODE = "500"; |
| | | |
| | | private String code; |
| | | |
| | | private String message; |
| | | |
| | | private Boolean success; |
| | | |
| | | private String returnMessage; |
| | | |
| | | private T result; |
| | | |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") |
| | | private Date timestamp; |
| | | |
| | | public XSR() { |
| | | this.timestamp = new Date(System.currentTimeMillis()); |
| | | } |
| | | |
| | | public static <T> XSR<T> ok() { |
| | | return new XSR<T>() |
| | | .setCode(SUCCESS_CODE) |
| | | .setSuccess(true) |
| | | .setMessage("操作成功") |
| | | .setReturnMessage("操作成功"); |
| | | } |
| | | |
| | | public static <T> XSR<T> ok(T data) { |
| | | return new XSR<T>() |
| | | .setCode(SUCCESS_CODE) |
| | | .setSuccess(true) |
| | | .setMessage("操作成功") |
| | | .setReturnMessage("操作成功") |
| | | .setResult(data); |
| | | } |
| | | |
| | | public static <T> XSR<T> ok(T data, String message) { |
| | | return new XSR<T>() |
| | | .setCode(SUCCESS_CODE) |
| | | .setSuccess(true) |
| | | .setMessage(message) |
| | | .setReturnMessage(message) |
| | | .setResult(data); |
| | | } |
| | | |
| | | public static <T> XSR<T> error(String message) { |
| | | return new XSR<T>() |
| | | .setCode(FAIL_CODE) |
| | | .setSuccess(false) |
| | | .setMessage(message) |
| | | .setReturnMessage(message); |
| | | } |
| | | |
| | | public static <T> XSR<T> error(String code, String message) { |
| | | return new XSR<T>() |
| | | .setCode(code) |
| | | .setSuccess(false) |
| | | .setMessage(message) |
| | | .setReturnMessage(message); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.zy.api.enums; |
| | | /** |
| | | * 库区类型 |
| | | */ |
| | | public enum LocAreaType { |
| | | |
| | | |
| | | /** 大库区 */ |
| | | AUTOMATED("1", "立库"), |
| | | /** 中库区 */ |
| | | SO_HOLDING("2", "SO等待区"), |
| | | /** 小件库区 */ |
| | | EO_HOLDING("3", "EO等待区"); |
| | | |
| | | public String type; |
| | | |
| | | public String desc; |
| | | |
| | | LocAreaType(String type, String desc) { |
| | | this.type = type; |
| | | this.desc = desc; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.api.enums; |
| | | |
| | | /** |
| | | * 物料所属库位类型 |
| | | * @author Ryan |
| | | * @date 2025/12/6 10:41 |
| | | * @return null |
| | | */ |
| | | public enum MatLocType { |
| | | |
| | | /** 小件 */ |
| | | AUTOMATED("12", "小件"), |
| | | /** 中件 */ |
| | | SO_HOLDING("13", "中件"), |
| | | /** 大件 */ |
| | | EO_HOLDING("14", "滤芯"); |
| | | |
| | | public String type; |
| | | |
| | | public String desc; |
| | | |
| | | MatLocType(String type, String desc) { |
| | | this.type = type; |
| | | this.desc = desc; |
| | | } |
| | | |
| | | public static String getTagName(String type) { |
| | | if (type.equals(MatLocType.AUTOMATED.type)) { |
| | | return MatLocType.AUTOMATED.desc; |
| | | } else if (type.equals(MatLocType.SO_HOLDING.type)) { |
| | | return MatLocType.SO_HOLDING.desc; |
| | | } else if (type.equals(MatLocType.EO_HOLDING.type)) { |
| | | return MatLocType.EO_HOLDING.desc; |
| | | } else { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | |
| | | public static Long getTag(String type) { |
| | | if (type.equals(MatType.LARGE.type)) { |
| | | return Long.parseLong(MatLocType.AUTOMATED.type); |
| | | } else if (type.equals(MatType.MIDDEL.type)) { |
| | | return Long.parseLong(MatLocType.SO_HOLDING.type); |
| | | } else if (type.equals(MatType.SMALL.type)) { |
| | | return Long.parseLong(MatLocType.EO_HOLDING.type); |
| | | } else { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | public static String getMatTag(String type) { |
| | | if (type.equals(MatLocType.AUTOMATED.type)) { |
| | | return MatType.LARGE.type; |
| | | } else if (type.equals(MatLocType.SO_HOLDING.type)) { |
| | | return MatType.MIDDEL.type; |
| | | } else if (type.equals(MatLocType.EO_HOLDING.type)) { |
| | | return MatType.SMALL.type; |
| | | } else { |
| | | return null; |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | package com.zy.api.enums; |
| | | |
| | | /** |
| | | * 物料类型 |
| | | */ |
| | | public enum MatType { |
| | | |
| | | /** 滤芯 */ |
| | | LARGE("1", "滤芯"), |
| | | /** 中件 */ |
| | | MIDDEL("2", "中件"), |
| | | /** 小件 */ |
| | | SMALL("3", "小件"); |
| | | |
| | | public String type; |
| | | |
| | | public String desc; |
| | | |
| | | MatType(String type, String desc) { |
| | | this.type = type; |
| | | this.desc = desc; |
| | | } |
| | | |
| | | public static Long getTag(String type) { |
| | | if (type.equals(MatType.LARGE.type)) { |
| | | return Long.parseLong(MatLocType.AUTOMATED.type); |
| | | } else if (type.equals(MatType.MIDDEL.type)) { |
| | | return Long.parseLong(MatLocType.SO_HOLDING.type); |
| | | } else if (type.equals(MatType.SMALL.type)) { |
| | | return Long.parseLong(MatLocType.EO_HOLDING.type); |
| | | } else { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.api.enums; |
| | | |
| | | /** |
| | | * @author Ryan |
| | | * @version 1.0 |
| | | * @title PurchaseType |
| | | * @description |
| | | * @create 2025/3/5 15:54 |
| | | */ |
| | | public enum OrderType { |
| | | //订单类型 |
| | | ORDER_OUT("out", "出库单"), |
| | | ORDER_IN("in", "入库单"), |
| | | ORDER_TRANSFER("transfer", "调拔单"), |
| | | ORDER_REVISE("revise", "库存调整"), |
| | | ORDER_CHECK("check", "盘点单"); |
| | | |
| | | |
| | | OrderType(String type, String desc) { |
| | | this.type = type; |
| | | this.desc = desc; |
| | | } |
| | | |
| | | public String type; |
| | | public String desc; |
| | | |
| | | public static String getTypeVal(String desc) { |
| | | if (desc.equals(OrderType.ORDER_IN.desc)) { |
| | | return OrderType.ORDER_IN.type; |
| | | } else if (desc.equals(OrderType.ORDER_OUT.desc)) { |
| | | return OrderType.ORDER_OUT.type; |
| | | } else if (desc.equals(OrderType.ORDER_CHECK.desc)) { |
| | | return OrderType.ORDER_CHECK.type; |
| | | } else if (desc.equals(OrderType.ORDER_TRANSFER.desc)) { |
| | | return OrderType.ORDER_TRANSFER.type; |
| | | } else if (desc.equals(OrderType.ORDER_REVISE.desc)) { |
| | | return OrderType.ORDER_REVISE.type; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | public static String getValType(String type) { |
| | | if (type.equals(OrderType.ORDER_IN.type)) { |
| | | return OrderType.ORDER_IN.desc; |
| | | } else if (type.equals(OrderType.ORDER_OUT.type)) { |
| | | return OrderType.ORDER_OUT.desc; |
| | | } else if (type.equals(OrderType.ORDER_CHECK.type)) { |
| | | return OrderType.ORDER_CHECK.desc; |
| | | } else if (type.equals(OrderType.ORDER_TRANSFER.type)) { |
| | | return OrderType.ORDER_TRANSFER.desc; |
| | | } else if (type.equals(OrderType.ORDER_REVISE.type)) { |
| | | return OrderType.ORDER_REVISE.desc; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.api.enums; |
| | | |
| | | |
| | | public enum OrderWkType { |
| | | |
| | | // 订单类型 |
| | | ORDER_WK_PUR_IN("0", "采购入库"), |
| | | ORDER_WK_TRANSFER_IN("1", "调拔入库"), |
| | | ORDER_WK_SALE_IN("2", "客户退货"), |
| | | ORDER_WK_BAG_IN("5", "索赔入库"), |
| | | ORDER_WK_SUPLUS_IN("7", "报溢入库"), |
| | | ORDER_WK_PRO_UPDATE_IN("8", "件号变更入库"), |
| | | ORDER_WK_MEGER_IN("K", "组合拆零入库"), |
| | | ORDER_WK_ORDER_OUT_EO("11", "备货指示派工单(EO)"), |
| | | ORDER_WK_ORDER_OUT_SO("12", "备货指示派工单(SO)"), |
| | | ORDER_WK_ORDER_OUT("13", "备货单"); |
| | | |
| | | OrderWkType(String val, String desc) { |
| | | this.val = val; |
| | | this.desc = desc; |
| | | } |
| | | |
| | | public String val; |
| | | public String desc; |
| | | |
| | | public static String getTypeVal(String val) { |
| | | if (val.equals(OrderWkType.ORDER_WK_PUR_IN.val) |
| | | || val.equals(OrderWkType.ORDER_WK_SUPLUS_IN.val) |
| | | || val.equals(OrderWkType.ORDER_WK_MEGER_IN.val) |
| | | || val.equals(OrderWkType.ORDER_WK_PRO_UPDATE_IN.val)) { |
| | | return OrderType.ORDER_IN.type; |
| | | } else if (val.equals(OrderWkType.ORDER_WK_TRANSFER_IN.val)) { |
| | | return OrderType.ORDER_IN.type; |
| | | } else if (val.equals(OrderWkType.ORDER_WK_SALE_IN.val)) { |
| | | return OrderType.ORDER_IN.type; |
| | | } else if (val.equals(OrderWkType.ORDER_WK_BAG_IN.val)) { |
| | | return OrderType.ORDER_IN.type; |
| | | } else if (val.equals(OrderWkType.ORDER_WK_ORDER_OUT_EO.val) || val.equals(OrderWkType.ORDER_WK_ORDER_OUT_SO.val) || val.equals(OrderWkType.ORDER_WK_ORDER_OUT.val)) { |
| | | return OrderType.ORDER_OUT.type; |
| | | } else { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.api.service; |
| | | |
| | | import java.util.List; |
| | | |
| | | import com.zy.api.controller.params.PageRequestParams; |
| | | import com.zy.api.entity.PubOrderParams; |
| | | import com.zy.api.entity.ReportOrderParam; |
| | | import com.zy.api.entity.StockAdjustParams; |
| | | import com.zy.api.entity.StockUpOrderParams; |
| | | import com.zy.api.entity.SyncMatParmas; |
| | | import com.zy.api.entity.dto.XSR; |
| | | import com.zy.asrs.entity.Order; |
| | | |
| | | public interface HWmsApiService { |
| | | |
| | | |
| | | /** |
| | | * 上架派工单下发 |
| | | * @author Ryan |
| | | * @date 2025/11/24 14:42 |
| | | * @param params |
| | | * @return com.core.common.R |
| | | */ |
| | | XSR receiveOrders(List<PubOrderParams> params); |
| | | |
| | | /** |
| | | * 基础零件变更 |
| | | * @author Ryan |
| | | * @date 2025/11/24 15:04 |
| | | * @param matnrs |
| | | * @return com.core.common.R |
| | | */ |
| | | XSR basMatupdate(List<SyncMatParmas> matnrs); |
| | | |
| | | |
| | | /** |
| | | * 新增或修改单据信息 |
| | | * @author Ryan |
| | | * @date 2025/11/24 15:33 |
| | | */ |
| | | void addOrUpdateOrders(PubOrderParams params, String type) ; |
| | | |
| | | /** |
| | | * 上架派工单反馈 |
| | | * |
| | | * @param params |
| | | * @param order |
| | | * @return |
| | | */ |
| | | XSR getInDispatchResult(List<ReportOrderParam> params, Order order); |
| | | |
| | | /** |
| | | * 备货指示派工单下发 |
| | | * @param params |
| | | * @return |
| | | */ |
| | | XSR sendOutDispatch(List<PubOrderParams> params); |
| | | |
| | | /** |
| | | * 备货单下发 |
| | | * @author Ryan |
| | | * @date 2025/11/24 15:40 |
| | | * @param params |
| | | * @return com.core.common.R |
| | | */ |
| | | XSR getOutDetails(List<StockUpOrderParams> params); |
| | | |
| | | /** |
| | | * 查询WMS库存信息 |
| | | * @author Ryan |
| | | * @date 2025/11/24 15:22 |
| | | * @param params |
| | | * @return com.core.common.R |
| | | */ |
| | | XSR getStockInfo(PageRequestParams params); |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.api.service; |
| | | |
| | | import com.core.common.R; |
| | | import com.zy.api.controller.params.ReceviceTaskParams; |
| | | import com.zy.asrs.entity.param.OpenOrderPakoutParam; |
| | | |
| | | public interface HmesApiService { |
| | | |
| | | R pubWorkTask(OpenOrderPakoutParam params); |
| | | |
| | | R releaseLock(ReceviceTaskParams params); |
| | | } |
| New file |
| | |
| | | package com.zy.api.service; |
| | | |
| | | import com.core.common.R; |
| | | import com.zy.api.controller.params.ReceviceTaskParams; |
| | | import com.zy.api.controller.params.StopOutTaskParams; |
| | | import com.zy.api.controller.params.WorkTaskParams; |
| | | |
| | | import java.util.Set; |
| | | |
| | | public interface WcsApiService { |
| | | |
| | | /** |
| | | * 下发任务至WCS |
| | | * @author Ryan |
| | | * @date 2026/1/10 13:57 |
| | | * @param params |
| | | * @return com.core.common.R |
| | | */ |
| | | R pubWrkToWcs(WorkTaskParams params); |
| | | |
| | | /** |
| | | * 堆垛机任务完成状态上报 |
| | | * @author Ryan |
| | | * @date 2026/1/10 16:29 |
| | | * @param params |
| | | * @return com.core.common.R |
| | | */ |
| | | R receviceTaskFromWcs(ReceviceTaskParams params); |
| | | |
| | | /** |
| | | * batch pause out tasks |
| | | * @param params |
| | | * @return |
| | | */ |
| | | R pauseOutTasks(StopOutTaskParams params); |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.api.service.impl; |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.baomidou.mybatisplus.plugins.Page; |
| | | import com.core.common.SnowflakeIdWorker; |
| | | import com.core.exception.CoolException; |
| | | import com.zy.api.controller.params.PageRequestParams; |
| | | import com.zy.api.entity.OrderItemsParam; |
| | | import com.zy.api.entity.OrderParams; |
| | | import com.zy.api.entity.OutOrderParams; |
| | | import com.zy.api.entity.PubOrderParams; |
| | | import com.zy.api.entity.ReportOrderParam; |
| | | import com.zy.api.entity.StockUpOrderParams; |
| | | import com.zy.api.entity.SyncMatParmas; |
| | | import com.zy.api.entity.dto.XSR; |
| | | import com.zy.api.enums.MatLocType; |
| | | import com.zy.api.enums.OrderType; |
| | | import com.zy.api.enums.OrderWkType; |
| | | import com.zy.api.service.HWmsApiService; |
| | | import com.zy.asrs.entity.LocDetl; |
| | | import com.zy.asrs.entity.Mat; |
| | | import com.zy.asrs.entity.Order; |
| | | import com.zy.asrs.entity.OrderDetl; |
| | | import com.zy.asrs.enums.CommonEnum; |
| | | import com.zy.asrs.service.LocDetlService; |
| | | import com.zy.asrs.service.MatService; |
| | | import com.zy.asrs.service.OrderDetlService; |
| | | import com.zy.asrs.service.OrderService; |
| | | |
| | | import com.zy.asrs.utils.Utils; |
| | | import com.zy.common.utils.HttpHandler; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.util.*; |
| | | |
| | | @Slf4j |
| | | @Service("kopenApiServiceImpl") |
| | | public class HWmsApiServiceImpl implements HWmsApiService { |
| | | |
| | | @Autowired |
| | | private OrderService orderService; |
| | | @Autowired |
| | | private OrderDetlService orderDetlService; |
| | | @Autowired |
| | | private MatService matService; |
| | | @Autowired |
| | | private LocDetlService locDetlService; |
| | | @Autowired |
| | | private SnowflakeIdWorker snowflakeIdWorker; |
| | | // @Value("${kopen.url}") |
| | | private String url; |
| | | // @Value("${kopen.port}") |
| | | private String port; |
| | | // @Value("${kopen.prefix}") |
| | | private String prefix; |
| | | |
| | | |
| | | /** |
| | | * 接收下发订单信息 |
| | | * |
| | | * @param orderParams |
| | | * @return com.core.common.R |
| | | * @author Ryan |
| | | * @date 2025/11/24 14:49 |
| | | */ |
| | | @Override |
| | | public XSR receiveOrders(List<PubOrderParams> orderParams) { |
| | | orderParams.forEach(params -> { |
| | | if (params.getType().equals(OrderWkType.getTypeVal(params.getType()))) { |
| | | throw new CoolException("当前类型不是上架派工单!!"); |
| | | } |
| | | addOrUpdateOrders(params, "add"); |
| | | }); |
| | | |
| | | return XSR.ok("单据下发成功!!"); |
| | | } |
| | | |
| | | /** |
| | | * 上架派工单反馈 |
| | | * |
| | | * @author Ryan |
| | | * @date 2025/11/24 15:33 |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public XSR getInDispatchResult(List<ReportOrderParam> params, Order order) { |
| | | if (Objects.isNull(params)) { |
| | | return XSR.error("参数不能为空!!"); |
| | | } |
| | | String response = null; |
| | | |
| | | try { |
| | | response = new HttpHandler.Builder() |
| | | .setUri(url + ":" + port) |
| | | .setPath(prefix + "/getInDispatchResult") |
| | | .setJson(JSONObject.toJSONString(params)) |
| | | .build() |
| | | .doPost(); |
| | | if (Objects.isNull(response) || response.trim().isEmpty()) { |
| | | return XSR.error("外网接口无响应!!"); |
| | | } |
| | | JSONObject jsonObject = JSONObject.parseObject(response); |
| | | Integer code = jsonObject.getInteger("code"); |
| | | if (!Objects.isNull(code) && code.equals(200)) { |
| | | if (!Objects.isNull(order)) { |
| | | // order.setReportOnce(5); |
| | | orderService.updateById(order); |
| | | } |
| | | return XSR.ok("入库单上报完成!!"); |
| | | } else { |
| | | if (!Objects.isNull(order)) { |
| | | // int reportOnce = order.getReportOnce(); |
| | | // reportOnce ++; |
| | | // order.setReportOnce(reportOnce); |
| | | orderService.updateById(order); |
| | | } |
| | | String msg = jsonObject.getString("message"); |
| | | return XSR.error(Objects.isNull(msg) ? "上报失败!!" : msg); |
| | | } |
| | | } catch (Exception e) { |
| | | if (!Objects.isNull(order)) { |
| | | // int reportOnce = order.getReportOnce(); |
| | | // reportOnce ++; |
| | | // order.setReportOnce(reportOnce); |
| | | orderService.updateById(order); |
| | | } |
| | | log.error(e.getMessage(), e); |
| | | return XSR.error(e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 获取自定义请求头 |
| | | * @author Ryan |
| | | * @date 2025/12/29 9:11 |
| | | * @return java.util.Map<java.lang.String,java.lang.Object> |
| | | */ |
| | | private Map<String, Object> getHeaderParam() { |
| | | Map<String, Object> headerParam = new HashMap<>(); |
| | | // headerParam.put("accept", "*/*"); |
| | | // headerParam.put("connection", "Keep-Alive"); |
| | | //设置请求连接的Token |
| | | headerParam.put("api_key", "WMS"); |
| | | headerParam.put("charset", "UTF-8"); |
| | | headerParam.put("timestamp", new Date()); |
| | | headerParam.put("format", "xml"); |
| | | headerParam.put("signature", "c56ced444ed772098ffeb59537bbfa59"); |
| | | |
| | | return headerParam; |
| | | } |
| | | |
| | | /* */ |
| | | |
| | | /** |
| | | * 备货指示派工单下发 |
| | | * |
| | | * @param pubOrderParams |
| | | * @return com.core.common.R |
| | | * @author Ryan |
| | | * @date 2025/11/24 15:21 |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public XSR sendOutDispatch(List<PubOrderParams> pubOrderParams) { |
| | | if (Objects.isNull(pubOrderParams) || pubOrderParams.isEmpty()) { |
| | | return XSR.error("参数不能为空!!"); |
| | | } |
| | | pubOrderParams.forEach(params -> { |
| | | // 校验参数 |
| | | if (Objects.isNull(params.getDispatch_no())) { |
| | | throw new CoolException("派工单编号不能为空!!"); |
| | | } |
| | | if (Objects.isNull(params.getKopen_id())) { |
| | | throw new CoolException("流水号不能为空!!"); |
| | | } |
| | | if (Objects.isNull(params.getCompany_id())) { |
| | | throw new CoolException("公司ID不能为空!!"); |
| | | } |
| | | |
| | | addOrUpdateOrders(params, "add"); |
| | | }); |
| | | |
| | | return XSR.ok("备货指示派工单下发成功!!"); |
| | | } |
| | | |
| | | // /** |
| | | // * 备货指示派工单 |
| | | // * |
| | | // * @author Ryan |
| | | // * @date 2025/12/16 9:15 |
| | | // * @param params |
| | | // */ |
| | | // private void outOrderAddAndUpdate(PubOrderParams params, String type) { |
| | | // if (Objects.isNull(params)) { |
| | | // throw new CoolException("参数不能为空!!"); |
| | | // } |
| | | // if (Objects.isNull(params.getType())) { |
| | | // throw new CoolException("订单类型不能为空!!"); |
| | | // } |
| | | |
| | | // OrderParams orderParams = |
| | | // JSONObject.parseObject(JSONObject.toJSONString(params), OrderParams.class); |
| | | // Order order = orderService.selectOne(new |
| | | // EntityWrapper<Order>().eq("order_no", orderParams.getInv_no())); |
| | | // if (type.equals("add") && !Objects.isNull(order)) { |
| | | // throw new CoolException("单据已存在, 不可重复添加!!"); |
| | | // } |
| | | // // 判断订单是否存在 |
| | | // if (Objects.isNull(order)) { |
| | | // /** 不存在,新增订单 */ |
| | | // generateOrders(params); |
| | | // } else { |
| | | // /** 存在,删除老订单,更新插入新订单 */ |
| | | // // 删除旧订单明细 |
| | | // if (!orderDetlService.delete(new EntityWrapper<OrderDetl>().eq("order_id", |
| | | // order.getId()))) { |
| | | // throw new CoolException("订单明细删除失败!!"); |
| | | // } |
| | | // ; |
| | | // if (!orderService.deleteById(order.getId())) { |
| | | // throw new CoolException("原单据删除失败!!"); |
| | | // } |
| | | // generateOrders(params); |
| | | // } |
| | | |
| | | // } |
| | | |
| | | /** |
| | | * 基础零件变更 |
| | | * |
| | | * @param params |
| | | * @return com.core.common.R |
| | | * @author Ryan |
| | | * @date 2025/11/24 15:05 |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public synchronized XSR basMatupdate(List<SyncMatParmas> params) { |
| | | if (Objects.isNull(params) || params.isEmpty()) { |
| | | return XSR.error("参数不能为空!!"); |
| | | } |
| | | params.forEach(mats -> { |
| | | if (Objects.isNull(mats)) { |
| | | throw new CoolException("物料编码不能为空!!"); |
| | | } |
| | | if (Objects.isNull(mats.getPro_type())) { |
| | | throw new CoolException("零件类型不能为空!!"); |
| | | } |
| | | Mat matnr = matService.selectOne(new EntityWrapper<Mat>().eq("matnr", mats.getPro_komcode())); |
| | | if (!Objects.isNull(matnr)) { |
| | | // // 订单时间 |
| | | // if (Utils.isValidFormat(mats.getUpdate_time(), "yyyy-MM-dd HH:mm:ss")) { |
| | | // Date date1 = Utils.getFormateDate(mats.getUpdate_time()); |
| | | // matnr.setUpdateTime(date1); |
| | | // } |
| | | // matnr.setMaktx(mats.getPro_name()); |
| | | // matnr.setSpecs(mats.getPro_size()); |
| | | // matnr.setWeight(Objects.isNull(mats.getPro_wet()) ? 0.0 : Double.parseDouble(mats.getPro_wet())); |
| | | // matnr.setSuppCode(mats.getPro_id()); |
| | | // matnr.setTagId(MatLocType.getTag(mats.getPro_type())); |
| | | // matnr.setLocType(MatLocType.getTag(mats.getPro_type())); |
| | | // matnr.setManu(mats.getCompany_id()); |
| | | // if (!matService.updateById(matnr)) { |
| | | // throw new CoolException("物料更新失败或无需更新!!"); |
| | | // } |
| | | } else { |
| | | if (Objects.isNull(matnr)) { |
| | | matnr = new Mat(); |
| | | } |
| | | // // 订单时间 |
| | | // if (Utils.isValidFormat(mats.getUpdate_time(), "yyyy-MM-dd HH:mm:ss")) { |
| | | // Date date1 = Utils.getFormateDate(mats.getUpdate_time()); |
| | | // matnr.setUpdateTime(date1); |
| | | // } |
| | | // matnr.setMaktx(mats.getPro_name()); |
| | | // matnr.setMatnr(mats.getPro_komcode()); |
| | | // matnr.setSpecs(mats.getPro_size()); |
| | | // matnr.setWeight(Double.parseDouble(mats.getPro_wet())); |
| | | // matnr.setSuppCode(mats.getPro_id()); |
| | | // matnr.setTagId(MatLocType.getTag(mats.getPro_type())); |
| | | // matnr.setLocType(MatLocType.getTag(mats.getPro_type())); |
| | | // matnr.setManu(mats.getCompany_id()); |
| | | // if (!matService.insert(matnr)) { |
| | | // throw new CoolException("物料更新失败!!"); |
| | | // } |
| | | } |
| | | }); |
| | | |
| | | return XSR.ok("保存成功!!"); |
| | | } |
| | | |
| | | /** |
| | | * 新增或修改订单信息 |
| | | * |
| | | * @author Ryan |
| | | * @date 2025/11/24 15:32 |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void addOrUpdateOrders(PubOrderParams params, String type) { |
| | | if (Objects.isNull(params)) { |
| | | throw new CoolException("参数不能为空!!"); |
| | | } |
| | | if (Objects.isNull(params.getType())) { |
| | | throw new CoolException("订单类型不能为空!!"); |
| | | } |
| | | OrderParams orderParams = JSONObject.parseObject(JSONObject.toJSONString(params), OrderParams.class); |
| | | // Order order = orderService.selectOne(new |
| | | // EntityWrapper<Order>().eq("order_no", orderParams.getDispatch_no())); |
| | | Order order = null; |
| | | if (OrderType.ORDER_IN.type.equals(OrderWkType.getTypeVal(params.getType()))) { |
| | | // 入库 |
| | | order = orderService.selectOne(new EntityWrapper<Order>().eq("order_no", |
| | | orderParams.getDispatch_no())); |
| | | } else if (OrderType.ORDER_OUT.type.equals(OrderWkType.getTypeVal(params.getType()))) { |
| | | // 出库 |
| | | if (OrderWkType.ORDER_WK_ORDER_OUT.val.equals(params.getType())) { |
| | | // 备货单出库 |
| | | order = orderService.selectOne(new EntityWrapper<Order>().eq("order_no", |
| | | orderParams.getPick_no())); |
| | | } else if (OrderWkType.ORDER_WK_ORDER_OUT_EO.val.equals(params.getType()) |
| | | || OrderWkType.ORDER_WK_ORDER_OUT_SO.val.equals(params.getType())) { |
| | | // 备货指示派工单(EO/SO)出库 |
| | | order = orderService.selectOne(new EntityWrapper<Order>().eq("order_no", |
| | | orderParams.getDispatch_no())); |
| | | } else { |
| | | throw new CoolException("单据类型不存在,不支持添加!!"); |
| | | } |
| | | } else { |
| | | throw new CoolException("单据类型不存在,不支持添加!!"); |
| | | } |
| | | // 出库 |
| | | if (type.equals("add") && !Objects.isNull(order)) { |
| | | throw new CoolException("单据已存在, 不可重复添加!!"); |
| | | } |
| | | // 判断订单是否存在 |
| | | if (Objects.isNull(order)) { |
| | | /** 不存在,新增订单 */ |
| | | generateOrders(params); |
| | | } else { |
| | | /** 存在,删除老订单,更新插入新订单 */ |
| | | // 删除旧订单明细 |
| | | if (!orderDetlService.delete(new EntityWrapper<OrderDetl>().eq("order_id", order.getId()))) { |
| | | throw new CoolException("订单明细删除失败!!"); |
| | | } |
| | | |
| | | if (!orderService.deleteById(order.getId())) { |
| | | throw new CoolException("原单据删除失败!!"); |
| | | } |
| | | generateOrders(params); |
| | | } |
| | | } |
| | | |
| | | public static String generateUUID(OrderParams params) { |
| | | return UUID.randomUUID().toString(); |
| | | } |
| | | |
| | | /** |
| | | * 生成订单信息 |
| | | * |
| | | * @param params |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void generateOrders(PubOrderParams params) { |
| | | // 将数据当新订单插入 |
| | | Order newOrder = new Order(); |
| | | // 派工单号 |
| | | newOrder.setOrderNo(params.getDispatch_no()); |
| | | if (OrderType.ORDER_IN.type.equals(OrderWkType.getTypeVal(params.getType()))) { |
| | | // 入库 |
| | | newOrder.setPakinPakoutStatus(1); |
| | | // Integer docType = OrderWkType.getDocType(params.getType()); |
| | | // newOrder.setDocType(Long.parseLong(docType + "")); |
| | | newOrder.setNumber(params.getInv_no()); |
| | | } else if (OrderType.ORDER_OUT.type.equals(OrderWkType.getTypeVal(params.getType()))) { |
| | | // 出库 |
| | | if (OrderWkType.ORDER_WK_ORDER_OUT.val.equals(params.getType())) { |
| | | // 备货单出库 |
| | | newOrder.setOrderNo(params.getPick_no()); |
| | | newOrder.setNumber(params.getDispatch_no()); |
| | | newOrder.setShipCode(params.getOrder_no()); |
| | | newOrder.setCstmrName(params.getCus_id()); |
| | | newOrder.setTel(params.getCus_address()); |
| | | // newOrder.setDocType(Long.parseLong(OrderTypeEnum.STOCK.type + "")); |
| | | } else if (OrderWkType.ORDER_WK_ORDER_OUT_EO.val.equals(params.getType()) |
| | | || OrderWkType.ORDER_WK_ORDER_OUT_SO.val.equals(params.getType())) { |
| | | // 备货指示派工单(EO/SO)出库 |
| | | // newOrder.setDocType(Long.parseLong(OrderTypeEnum.TRANSFER.type + "")); |
| | | } |
| | | newOrder.setPakinPakoutStatus(2); |
| | | } |
| | | |
| | | newOrder.setUuid(generateUUID(params)); |
| | | // 流水号(唯一) |
| | | newOrder.setDefNumber(params.getKopen_id()); |
| | | // newOrder.setTargetLocation(params.getTarget_location()); |
| | | // 箱号 |
| | | newOrder.setItemName(params.getPm_tktid()); |
| | | // newOrder.setSettle(OrderSettle.ORDER_SETTLE_HOLDING.type); |
| | | newOrder.setStatus(CommonEnum.COMMON_ENUM_Y.type); |
| | | // 订单时间 |
| | | // if (Utils.isValidFormat(params.getUpdate_time(), "yyyy-MM-dd HH:mm:ss")) { |
| | | // newOrder.setOrderTime(params.getUpdate_time()); |
| | | // } |
| | | // 公司ID |
| | | newOrder.setCstmrName(params.getCompany_id()); |
| | | newOrder.setCreateTime(new Date()); |
| | | newOrder.setUpdateTime(new Date()); |
| | | if (!orderService.insert(newOrder)) { |
| | | throw new RuntimeException("新增订单失败!!"); |
| | | } |
| | | if (!Objects.isNull(params.getDetails()) && !params.getDetails().isEmpty()) { |
| | | params.getDetails().forEach(item -> { |
| | | Mat matnr = matService.selectOne(new EntityWrapper<Mat>().eq("matnr", item.getPro_komcode())); |
| | | if (Objects.isNull(matnr)) { |
| | | throw new CoolException("物料编码不存在!!"); |
| | | } |
| | | OrderDetl orderItem = new OrderDetl(); |
| | | BeanUtils.copyProperties(matnr, orderItem); |
| | | orderItem.setOrderId(newOrder.getId()); |
| | | orderItem.setOrderNo(newOrder.getOrderNo()); |
| | | |
| | | if (OrderType.ORDER_IN.type.equals(OrderWkType.getTypeVal(params.getType()))) { |
| | | // 入库 |
| | | orderItem.setAnfme(Math.round(item.getInv_qty() * 10000) / 10000.0); |
| | | } else if (OrderType.ORDER_OUT.type.equals(OrderWkType.getTypeVal(params.getType()))) { |
| | | // 出库 |
| | | if (OrderWkType.ORDER_WK_ORDER_OUT.val.equals(params.getType())) { |
| | | // 备货单出库 |
| | | orderItem.setAnfme(Math.round(item.getPick_qty() * 10000) / 10000.0); |
| | | } else if (OrderWkType.ORDER_WK_ORDER_OUT_EO.val.equals(params.getType()) |
| | | || OrderWkType.ORDER_WK_ORDER_OUT_SO.val.equals(params.getType())) { |
| | | // 备货指示派工单(EO/SO)出库 |
| | | orderItem.setAnfme(Math.round(item.getOrder_qty() * 10000) / 10000.0); |
| | | } |
| | | } |
| | | orderItem.setMatnr(matnr.getMatnr()); |
| | | orderItem.setMaktx(matnr.getMaktx()); |
| | | orderItem.setBrand(matnr.getBrand()); |
| | | orderItem.setBatch(""); |
| | | orderItem.setStandby1(item.getPro_id()); |
| | | // 关联上加派工单号+零件代码+供应商代码 |
| | | orderItem.setThreeCode(item.getTotal_serial()); |
| | | // 供应商代码 |
| | | orderItem.setSuppCode(item.getPro_id()); |
| | | orderItem.setCreateTime(new Date()); |
| | | orderItem.setUpdateTime(new Date()); |
| | | if (!orderDetlService.insert(orderItem)) { |
| | | throw new CoolException("订单明细新增失败!!"); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 备货单下发 |
| | | * |
| | | * @param stockUpParams |
| | | * @return com.core.common.R |
| | | * @author Ryan |
| | | * @date 2025/11/24 15:40 |
| | | */ |
| | | @Override |
| | | public XSR getOutDetails(List<StockUpOrderParams> stockUpParams) { |
| | | if (Objects.isNull(stockUpParams)) { |
| | | return XSR.error("参数不能为空!!"); |
| | | } |
| | | stockUpParams.forEach(params -> { |
| | | if (Objects.isNull(params.getDispatch_no())) { |
| | | throw new CoolException("派工单编号不能为空!!"); |
| | | } |
| | | if (Objects.isNull(params.getKopen_id())) { |
| | | throw new CoolException("流水号不能为空!!"); |
| | | } |
| | | if (Objects.isNull(params.getCompany_id())) { |
| | | throw new CoolException("公司ID不能为空!!"); |
| | | } |
| | | if (Objects.isNull(params.getDetails()) || params.getDetails().isEmpty()) { |
| | | throw new CoolException("订单明细不能为空!!"); |
| | | } |
| | | List<OrderItemsParam> items = new ArrayList<>(); |
| | | if (params.getDetails() != null) { |
| | | for (OutOrderParams detail : params.getDetails()) { |
| | | if (detail.getPartList() != null) { |
| | | items.addAll(detail.getPartList()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | params.getDetails().forEach(item -> { |
| | | PubOrderParams pubOrderParams = new PubOrderParams(); |
| | | BeanUtils.copyProperties(params, pubOrderParams); |
| | | pubOrderParams.setType(item.getType()) |
| | | .setPick_no(item.getPick_no()) |
| | | .setCus_address(item.getCus_address()) |
| | | .setOrder_no(item.getOrder_no()) |
| | | .setUpdate_time(params.getUpdate_time()) |
| | | .setCus_id(item.getCus_id()); |
| | | pubOrderParams.setDetails(item.getPartList()); |
| | | addOrUpdateOrders(pubOrderParams, "add"); |
| | | }); |
| | | }); |
| | | |
| | | return XSR.ok("备货单下发成功!!"); |
| | | } |
| | | |
| | | /** |
| | | * 查询WMS库存信息 |
| | | * |
| | | * @param params |
| | | * @return com.core.common.R |
| | | */ |
| | | @Override |
| | | public XSR getStockInfo(PageRequestParams params) { |
| | | EntityWrapper<LocDetl> wrapper = new EntityWrapper<>(); |
| | | // if (!Objects.isNull(params.getPro_id())) { |
| | | // wrapper.eq("supp_code", params.getPro_id()); |
| | | // } |
| | | // if (!Objects.isNull(params.getPro_komcode())) { |
| | | // wrapper.eq("matnr", params.getPro_komcode()); |
| | | // } |
| | | |
| | | Page<LocDetl> locDetls = locDetlService.selectPage(new Page<>(params.getCurr(), params.getLimit()), wrapper); |
| | | |
| | | return XSR.ok(locDetls.getRecords()); |
| | | } |
| | | |
| | | |
| | | private String kopen() { |
| | | return url + ":" + port + prefix; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.api.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.core.common.Cools; |
| | | import com.core.common.DateUtils; |
| | | import com.core.common.R; |
| | | import com.core.common.SnowflakeIdWorker; |
| | | import com.core.exception.CoolException; |
| | | import com.zy.api.controller.params.ReceviceTaskParams; |
| | | import com.zy.api.service.HmesApiService; |
| | | import com.zy.api.service.WcsApiService; |
| | | import com.zy.asrs.entity.*; |
| | | import com.zy.asrs.entity.param.OpenOrderPakoutParam; |
| | | import com.zy.asrs.enums.LocStsType; |
| | | import com.zy.asrs.service.*; |
| | | import com.zy.asrs.service.impl.LocDetlServiceImpl; |
| | | import com.zy.asrs.service.impl.OrderDetlPakoutServiceImpl; |
| | | import com.zy.asrs.service.impl.OrderPakoutServiceImpl; |
| | | import com.zy.common.model.DetlDto; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @Service |
| | | public class HmesApiServiceImpl implements HmesApiService { |
| | | |
| | | |
| | | @Autowired |
| | | private LocMastService locMastService; |
| | | |
| | | @Autowired |
| | | private WcsApiService wcsApiService; |
| | | |
| | | @Autowired |
| | | private OrderService orderService; |
| | | |
| | | @Autowired |
| | | private DocTypeService docTypeService; |
| | | |
| | | @Autowired |
| | | private SnowflakeIdWorker snowflakeIdWorker; |
| | | |
| | | @Autowired |
| | | private MatService matService; |
| | | |
| | | @Autowired |
| | | private OrderDetlService orderDetlService; |
| | | @Autowired |
| | | private OrderPakoutServiceImpl orderPakoutService; |
| | | @Autowired |
| | | private OrderDetlPakoutServiceImpl orderDetlPakoutService; |
| | | @Autowired |
| | | private LocDetlServiceImpl locDetlService; |
| | | |
| | | |
| | | @Override |
| | | public R pubWorkTask(OpenOrderPakoutParam params) { |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public R releaseLock(ReceviceTaskParams params) { |
| | | return null; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.zy.api.service.impl; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.core.common.Cools; |
| | | import com.core.common.R; |
| | | import com.core.exception.CoolException; |
| | | import com.zy.api.controller.params.ReceviceTaskParams; |
| | | import com.zy.api.controller.params.StopOutTaskParams; |
| | | import com.zy.api.controller.params.WorkTaskParams; |
| | | import com.zy.api.service.WcsApiService; |
| | | import com.zy.asrs.entity.*; |
| | | import com.zy.asrs.service.*; |
| | | import com.zy.asrs.utils.Utils; |
| | | import com.zy.common.constant.MesConstant; |
| | | import com.zy.common.service.CommonService; |
| | | import com.zy.common.utils.HttpHandler; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.io.IOException; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | import java.util.Set; |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @Slf4j |
| | | @Service |
| | | public class WcsApiServiceImpl implements WcsApiService { |
| | | |
| | | @Autowired |
| | | private LocMastService locMastService; |
| | | @Autowired |
| | | private WrkMastService wrkMastService; |
| | | @Autowired |
| | | private WorkService workService; |
| | | @Autowired |
| | | private WrkDetlService wrkDetlService; |
| | | @Autowired |
| | | private MatService matService; |
| | | @Autowired |
| | | private LocDetlService locDetlService; |
| | | @Value("${wcs.switch}") |
| | | private String switchValue; |
| | | |
| | | @Value("${wcs.address.URL}") |
| | | private String wcs_address; |
| | | |
| | | @Value("${wcs.address.createOutTask}") |
| | | private String getWcs_address; |
| | | |
| | | @Value("${wcs.address.createInTask}") |
| | | private String createInTask; |
| | | |
| | | @Value("${wcs.address.createLocMoveTask}") |
| | | private String createLocMoveTask; |
| | | |
| | | @Value("${wcs.address.stopOutTask}") |
| | | private String stopOutTask; |
| | | @Autowired |
| | | private CommonService commonService; |
| | | |
| | | |
| | | /** |
| | | * 下发任务至WCS |
| | | * |
| | | * @param params |
| | | * @return com.core.common.R |
| | | * @author Ryan |
| | | * @date 2026/1/10 13:58 |
| | | */ |
| | | @Override |
| | | public R pubWrkToWcs(WorkTaskParams params) { |
| | | if (Objects.isNull(params.getTaskNo())) { |
| | | return R.error("任务号不能为空!!"); |
| | | } |
| | | if (Objects.isNull(params.getBarcode())) { |
| | | return R.error("托盘码不能为空!!"); |
| | | } |
| | | if (Objects.isNull(params.getLocNo())) { |
| | | return R.error("目标库位不能为空!!"); |
| | | } |
| | | String url = createInTask; |
| | | if (!Objects.isNull(params.getType()) && params.getType().equals("out")) { |
| | | url = getWcs_address; |
| | | }else if (!Objects.isNull(params.getType()) && params.getType().equals("move")) { |
| | | url = createLocMoveTask; |
| | | } |
| | | String response; |
| | | R r = R.ok(); |
| | | WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", params.getTaskNo())); |
| | | if (!Objects.isNull(wrkMast) && "out".equalsIgnoreCase(params.getType()) && "Y".equalsIgnoreCase(wrkMast.getPauseMk())) { |
| | | return R.error("task paused"); |
| | | } |
| | | try { |
| | | log.info("下发搬运任务给wcs="+JSON.toJSONString(params)); |
| | | response = new HttpHandler.Builder() |
| | | .setUri(wcs_address) |
| | | .setPath(url) |
| | | .setJson(JSON.toJSONString(params)) |
| | | .build() |
| | | .doPost(); |
| | | JSONObject jsonObject = JSON.parseObject(response); |
| | | log.info("下发任务给wcs的返回值="+response); |
| | | Integer code = jsonObject.getInteger("code"); |
| | | |
| | | if (code==200) { |
| | | if (!Objects.isNull(wrkMast)) { |
| | | if (wrkMast.getIoType()==1 || wrkMast.getIoType()==10) { |
| | | wrkMast.setWrkSts(2L); |
| | | wrkMast.setModiTime(new Date()); |
| | | wrkMastService.updateById(wrkMast); |
| | | }else if(wrkMast.getIoType()==2){ |
| | | wrkMast.setWrkSts(2L); |
| | | wrkMast.setModiTime(new Date()); |
| | | wrkMastService.updateById(wrkMast); |
| | | }else if (wrkMast.getIoType()==101 || wrkMast.getIoType()==110) { |
| | | wrkMast.setWrkSts(12L); |
| | | wrkMast.setModiTime(new Date()); |
| | | wrkMastService.updateById(wrkMast); |
| | | } |
| | | } |
| | | //TODO 上报是否成功 |
| | | }else { |
| | | r =R.error(); |
| | | } |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | return r; |
| | | } |
| | | |
| | | /** |
| | | * 堆垛机执行状态上报 |
| | | * |
| | | * @param params |
| | | * @return com.core.common.R |
| | | * @author Ryan |
| | | * @date 2026/1/10 16:30 |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public R receviceTaskFromWcs(ReceviceTaskParams params) { |
| | | log.info("wcs任务反馈="+JSON.toJSONString(params)); |
| | | if (Objects.isNull(params.getSuperTaskNo())) { |
| | | throw new CoolException("WMS任务号不能为空!!"); |
| | | } |
| | | if (Objects.isNull(params.getNotifyType())) { |
| | | throw new CoolException("动作类型不能为空!!"); |
| | | } |
| | | WrkMast mast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", params.getSuperTaskNo())); |
| | | if (Objects.isNull(mast)) { |
| | | throw new CoolException("任务档不存在!!"); |
| | | } |
| | | |
| | | |
| | | if (params.getNotifyType().equals("task")) { |
| | | //任务 |
| | | if (params.getMsgType().equals("task_complete")) { |
| | | |
| | | if (mast.getIoType() == 1 || mast.getIoType() == 2 ||mast.getIoType() == 10) { |
| | | mast.setWrkSts(4L); |
| | | } else if ((mast.getIoType() == 101||mast.getIoType()==110) && mast.getWrkSts()<14) { |
| | | mast.setWrkSts(14L); |
| | | if(Cools.isEmpty(mast.getStaNo())){ |
| | | mast.setOveMk("Y"); |
| | | } |
| | | } |
| | | if (!wrkMastService.updateById(mast)) { |
| | | throw new CoolException("任务状态修改失败!!"); |
| | | } |
| | | } else if (params.getMsgType().equals("task_cancel")) { |
| | | if (mast.getIoType() != null && mast.getIoType() > 100 && mast.getWrkSts() < 14) { |
| | | mast.setPauseMk("Y"); |
| | | mast.setUpdMk("WCS_CANCELLED"); |
| | | mast.setManuType("WCS_CANCELLED"); |
| | | mast.setModiTime(new Date()); |
| | | if (!wrkMastService.updateById(mast)) { |
| | | throw new CoolException("task cancel update fail"); |
| | | } |
| | | } |
| | | }else if (params.getMsgType().equals("task_arrive")) { |
| | | //到达目的地 |
| | | //如果出库任务是跨区则需要生成新的入库任务入库 |
| | | if(!Cools.isEmpty(mast.getLocNo())){ |
| | | mast.setOnlineYn("N");//等待生成跨区入库任务 |
| | | } |
| | | mast.setWrkSts(14L); |
| | | if(Cools.isEmpty(mast.getStaNo())){ |
| | | mast.setOveMk("Y"); |
| | | } |
| | | mast.setModiTime(new Date()); |
| | | if (!wrkMastService.updateById(mast)) { |
| | | throw new CoolException("任务状态修改失败!!"); |
| | | } |
| | | } |
| | | } else if (params.getNotifyType().equals("weight")) { |
| | | |
| | | } |
| | | return R.ok(); |
| | | } |
| | | @Override |
| | | public R pauseOutTasks(StopOutTaskParams params) { |
| | | if (params == null || params.getTasks() == null || params.getTasks().isEmpty()) { |
| | | return R.ok("no tasks to stop"); |
| | | } |
| | | if (!Boolean.parseBoolean(String.valueOf(switchValue))) { |
| | | return R.ok("wcs switch off"); |
| | | } |
| | | String response; |
| | | try { |
| | | response = new HttpHandler.Builder() |
| | | .setUri(wcs_address) |
| | | .setPath(stopOutTask) |
| | | .setHttps(wcs_address != null && wcs_address.startsWith("https://")) |
| | | .setTimeout(10, TimeUnit.SECONDS) |
| | | .setJson(JSON.toJSONString(params)) |
| | | .build() |
| | | .doPost(); |
| | | JSONObject jsonObject = JSON.parseObject(response == null ? "{}" : response); |
| | | Integer code = jsonObject.getInteger("code"); |
| | | if (code == null || !Objects.equals(code, 200)) { |
| | | String msg = jsonObject.getString("msg"); |
| | | throw new CoolException(Cools.isEmpty(msg) ? "WCS stop out task failed" : msg); |
| | | } |
| | | } catch (IOException e) { |
| | | throw new CoolException("call WCS stop out task fail: " + e.getMessage()); |
| | | } |
| | | return R.ok(); |
| | | } |
| | | |
| | | } |
| | |
| | | String[] dates = val.split(RANGE_TIME_LINK); |
| | | wrapper.ge(entry.getKey(), DateUtils.convert(dates[0])); |
| | | wrapper.le(entry.getKey(), DateUtils.convert(dates[1])); |
| | | } else if (entry.getKey().equals("binding_tags")){ |
| | | long aLong = Long.parseLong(val); |
| | | wrapper.ge(entry.getKey(), aLong); |
| | | } else { |
| | | wrapper.like(entry.getKey(), val); |
| | | } |
| | |
| | | String[] dates = val.split(RANGE_TIME_LINK); |
| | | wrapper.ge(entry.getKey(), DateUtils.convert(dates[0])); |
| | | wrapper.le(entry.getKey(), DateUtils.convert(dates[1])); |
| | | } else if (entry.getKey().equals("binding_tags")){ |
| | | long aLong = Long.parseLong(val); |
| | | wrapper.ge(entry.getKey(), aLong); |
| | | } else { |
| | | wrapper.like(entry.getKey(), val); |
| | | } |
| | |
| | | String[] dates = val.split(RANGE_TIME_LINK); |
| | | wrapper.ge(entry.getKey(), DateUtils.convert(dates[0])); |
| | | wrapper.le(entry.getKey(), DateUtils.convert(dates[1])); |
| | | } else if (entry.getKey().equals("create_time")){ |
| | | long aLong = Long.parseLong(val); |
| | | wrapper.ge(entry.getKey(), aLong); |
| | | } else { |
| | | wrapper.like(entry.getKey(), val); |
| | | } |
| | |
| | | wrapper.le(entry.getKey(), DateUtils.convert(dates[1])); |
| | | } else { |
| | | if (entry.getKey().equals("locNo")) { |
| | | wrapper.eq("loc_no", String.valueOf(entry.getValue())); |
| | | wrapper.like("loc_no", String.valueOf(entry.getValue())); |
| | | } else { |
| | | wrapper.like(entry.getKey(), String.valueOf(entry.getValue())); |
| | | } |
| | |
| | | String[] dates = val.split(RANGE_TIME_LINK); |
| | | wrapper.ge(entry.getKey(), DateUtils.convert(dates[0])); |
| | | wrapper.le(entry.getKey(), DateUtils.convert(dates[1])); |
| | | } else if (entry.getKey().equals("loc_no")){ |
| | | wrapper.like(entry.getKey(), val); |
| | | } else { |
| | | if (entry.getKey().equals("loc_type1")){ |
| | | sign=true; |
| | | } |
| | | wrapper.eq(entry.getKey(), val); |
| | | wrapper.like(entry.getKey(), val); |
| | | } |
| | | } |
| | | if (sign){ |
| | |
| | | wrapper.le(entry.getKey(), DateUtils.convert(dates[1])); |
| | | } else { |
| | | if (entry.getKey().equals("locNo")) { |
| | | wrapper.eq("loc_no", String.valueOf(entry.getValue())); |
| | | wrapper.like("loc_no", String.valueOf(entry.getValue())); |
| | | } else { |
| | | wrapper.like(entry.getKey(), String.valueOf(entry.getValue())); |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * pause out order |
| | | */ |
| | | @PostMapping("/order/pakout/pause/default/v1") |
| | | @AppAuth(memo = "pause out order") |
| | | public synchronized R pakoutOrderPause(@RequestHeader(required = false) String appkey, |
| | | @RequestBody OpenOrderPakoutPauseParam param, |
| | | HttpServletRequest request) { |
| | | auth(appkey, param, request); |
| | | if (Cools.isEmpty(param) || Cools.isEmpty(param.getOrderNo())) { |
| | | return R.error("orderNo is empty"); |
| | | } |
| | | return openService.pakoutOrderPause(param); |
| | | } |
| | | |
| | | /** |
| | | * 出库单回写 |
| | | */ |
| | | // @PostMapping("/order/pakout/complete/default/v1") |
| | |
| | | // 判断是否有相同条码的数据 |
| | | if (waitPakinService.selectCount(new EntityWrapper<WaitPakin>(). |
| | | eq("zpallet", mesToCombParam.getPalletId()).eq("io_status", "N")) > 0) { |
| | | return R.error(mesToCombParam.getPalletId()+"-该托盘码已经存在组托档中"); |
| | | waitPakinService.delete(new EntityWrapper<WaitPakin>().eq("zpallet", mesToCombParam.getPalletId())); |
| | | } |
| | | |
| | | if (mesToCombParam.getPalletId().length() != 8) { |
| | |
| | | } |
| | | return R.ok(); |
| | | } |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.baomidou.mybatisplus.mapper.Wrapper; |
| | | import com.baomidou.mybatisplus.plugins.Page; |
| | | import com.zy.asrs.entity.StaDesc; |
| | | import com.zy.asrs.entity.param.StaDescInitParam; |
| | | import com.zy.asrs.mapper.StaDescMapper; |
| | | import com.zy.asrs.service.StaDescService; |
| | | import com.zy.common.web.BaseController; |
| | | import com.core.annotations.ManagerAuth; |
| | | import com.core.common.BaseRes; |
| | | import com.core.common.Cools; |
| | | import com.core.common.DateUtils; |
| | | import com.core.common.R; |
| | | import org.apache.ibatis.session.ExecutorType; |
| | | import org.apache.ibatis.session.SqlSession; |
| | | import org.apache.ibatis.session.SqlSessionFactory; |
| | | import com.zy.asrs.entity.StaDesc; |
| | | import com.zy.asrs.entity.param.StaDescInitParam; |
| | | import com.zy.asrs.service.StaDescService; |
| | | import com.zy.common.web.BaseController; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.bind.annotation.PathVariable; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.*; |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | |
| | | @RestController |
| | | public class StaDescController extends BaseController { |
| | | |
| | | private static final Logger log = LoggerFactory.getLogger(StaDescController.class); |
| | | |
| | | @Autowired |
| | | private StaDescService staDescService; |
| | | @Autowired |
| | | private SqlSessionFactory sqlSessionFactory; |
| | | |
| | | @RequestMapping(value = "/staDesc/init/auth") |
| | | @ManagerAuth(memo = "初始化站点路径") |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public R init(StaDescInitParam param) { |
| | | try{ |
| | | if (param.getTypeDesc()==1){ |
| | |
| | | } |
| | | String[] startStaList = param.getStartStaList().split(";"); |
| | | String[] endStaList = param.getEndStaList().split(";"); |
| | | List<StaDesc> staDescList = new ArrayList<>(); |
| | | SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH,false); |
| | | StaDescMapper sqlSessionMapper = sqlSession.getMapper(StaDescMapper.class); |
| | | Set<String> requestKeys = new HashSet<>(); |
| | | for (String startSta : startStaList){ |
| | | for (String endSta : endStaList){ |
| | | for (Integer type:param.getType()){ |
| | | String uniqueKey = type + "_" + startSta + "_" + param.getCrnNo() + "_" + endSta; |
| | | if (!requestKeys.add(uniqueKey)) { |
| | | continue; |
| | | } |
| | | int sameRes = staDescService.selectCount(new EntityWrapper<StaDesc>() |
| | | .eq("type_no", type) |
| | | .eq("stn_no", Integer.parseInt(startSta)) |
| | |
| | | staDesc.setModiTime(new Date()); |
| | | staDesc.setAppeUser(getUserId()); |
| | | staDesc.setAppeTime(new Date()); |
| | | // staDescList.add(staDesc); |
| | | sqlSessionMapper.insert(staDesc); |
| | | |
| | | staDescService.insert(staDesc); |
| | | } |
| | | } |
| | | } |
| | | try{ |
| | | sqlSession.commit(); |
| | | sqlSession.close(); |
| | | }catch (Exception e){ |
| | | log.error("初始化站点路径异常===>sql异常:{}",e.getMessage()); |
| | | } |
| | | // staDescService.insertBatch(staDescList); |
| | | }catch (Exception e){ |
| | | log.error("初始化站点路径异常:{}",e.getMessage()); |
| | | log.error("初始化站点路径异常:{}", e.getMessage(), e); |
| | | return R.error("初始化站点路径异常:"+e.getMessage()); |
| | | } |
| | | |
| | |
| | | excludeTrash(param); |
| | | EntityWrapper<StaDesc> wrapper = new EntityWrapper<>(); |
| | | convert(param, wrapper); |
| | | if (!Cools.isEmpty(orderByField)){wrapper.orderBy(humpToLine(orderByField), "asc".equals(orderByType));} |
| | | if (!Cools.isEmpty(orderByField)) { |
| | | wrapper.orderBy(humpToLine(orderByField), "asc".equals(orderByType)); |
| | | } |
| | | return R.ok(staDescService.selectPage(new Page<>(curr, limit), wrapper)); |
| | | } |
| | | |
| | |
| | | } |
| | | return R.ok(); |
| | | } |
| | | |
| | | } |
| | |
| | | wrapper.ge(entry.getKey(), DateUtils.convert(dates[0])); |
| | | wrapper.le(entry.getKey(), DateUtils.convert(dates[1])); |
| | | } else { |
| | | wrapper.eq(entry.getKey(), val); |
| | | wrapper.like(entry.getKey(), val); |
| | | } |
| | | } |
| | | } |
| | |
| | | wrapper.ge(entry.getKey(), DateUtils.convert(dates[0])); |
| | | wrapper.le(entry.getKey(), DateUtils.convert(dates[1])); |
| | | } else { |
| | | if (entry.getKey().equals("manu_type")) { |
| | | wrapper.like(entry.getKey(), val); |
| | | } else { |
| | | wrapper.eq(entry.getKey(), val); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | private Integer operateType; |
| | | //唯一码 |
| | | private String BizNo; |
| | | //是否散货,0 非散货;1 散货;为了管控出货速率,散货可以出慢点。 |
| | | private Integer package1; |
| | | } |
| New file |
| | |
| | | package com.zy.asrs.enums; |
| | | |
| | | /** |
| | | * @author Ryan |
| | | * @date 2025/9/25 |
| | | * @description: 通用类型枚举 |
| | | * @version 1.0 |
| | | */ |
| | | public enum CommonEnum { |
| | | |
| | | //通用类型 |
| | | COMMON_ENUM_Y(1, "是"), |
| | | //通用 |
| | | COMMON_ENUM_N(0, "否"); |
| | | |
| | | public Integer type; |
| | | |
| | | public String desc; |
| | | |
| | | CommonEnum(Integer type, String desc) { |
| | | this.type = type; |
| | | this.desc = desc; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.asrs.enums; |
| | | |
| | | public enum ContainerType { |
| | | |
| | | //料箱 |
| | | CONTAINER_TYPE_BOX("12", "料箱"), |
| | | //托盘 |
| | | CONTAINER_TYPE_SALVER("14", "托盘"), |
| | | |
| | | CONTAINER_TYPE_CAGE("13", "笼框"), |
| | | |
| | | CONTAINER_TYPE_CAR("3", "台车"), |
| | | ; |
| | | |
| | | public Long type; |
| | | |
| | | public String desc; |
| | | |
| | | ContainerType(String type, String desc) { |
| | | this.type = Long.valueOf(type); |
| | | this.desc = desc; |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.asrs.enums; |
| | | |
| | | public enum LocStsType { |
| | | |
| | | //空板 |
| | | LOC_STS_TYPE_D("D", "空板"), |
| | | //在库 |
| | | LOC_STS_TYPE_F("F", "在库"), |
| | | //空库 |
| | | LOC_STS_TYPE_O("O", "空库"), |
| | | //禁用 |
| | | LOC_STS_TYPE_X("X", "禁用"), |
| | | //入库预约 |
| | | LOC_STS_TYPE_S("S", "入库预约"), |
| | | //出库预约 |
| | | LOC_STS_TYPE_R("R", "出库预约"), |
| | | ; |
| | | |
| | | public String type; |
| | | |
| | | public String desc; |
| | | |
| | | LocStsType(String type, String desc) { |
| | | this.type = type; |
| | | this.desc = desc; |
| | | } |
| | | |
| | | |
| | | public static LocStsType get(String el) { |
| | | for (LocStsType value : LocStsType.values()) { |
| | | if (el.equals(value.toString())) { |
| | | return value; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | // /** |
| | | // * @author Ryan |
| | | // * @date 2025/8/28 |
| | | // * @description: RCS库位状态转换 |
| | | // * @version 1.0 |
| | | // */ |
| | | // public static String getLocSts(String val) { |
| | | // if (val.equals(RcsLocStsType.LOC_STS_TYPE_D.type)) { |
| | | // return LocStsType.LOC_STS_TYPE_O.type; |
| | | // } else if (val.equals(RcsLocStsType.LOC_STS_TYPE_F.type)) { |
| | | // return LocStsType.LOC_STS_TYPE_F.type; |
| | | // } else if (val.equals(RcsLocStsType.LOC_STS_TYPE_S.type)) { |
| | | // return LocStsType.LOC_STS_TYPE_S.type; |
| | | // } else if (val.equals(RcsLocStsType.LOC_STS_TYPE_R.type)) { |
| | | // return LocStsType.LOC_STS_TYPE_R.type; |
| | | // } else if (val.equals(RcsLocStsType.LOC_STS_TYPE_X.type)) { |
| | | // return LocStsType.LOC_STS_TYPE_X.type; |
| | | // } |
| | | // return null; |
| | | // } |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.asrs.enums; |
| | | |
| | | public enum MatTagType { |
| | | //中件 |
| | | MAT_TAGT_YPE_MIDDLE("13", "中件"), |
| | | //小件 |
| | | MAT_TAGT_YPE_SMALL("12", "小件"), |
| | | //滤芯 |
| | | MAT_TAGT_YPE_XIN("14", "滤芯") |
| | | ; |
| | | |
| | | public String id; |
| | | |
| | | public String type; |
| | | |
| | | MatTagType(String id, String type) { |
| | | this.type = type; |
| | | this.id = id; |
| | | } |
| | | } |
| | |
| | | void pakoutOrderCreate(OpenOrderPakoutParam param); |
| | | |
| | | /** |
| | | * pause out order |
| | | */ |
| | | R pakoutOrderPause(OpenOrderPakoutPauseParam param); |
| | | |
| | | /** |
| | | * 入库单回写 |
| | | */ |
| | | List<OpenOrderCompeteResult> pakoutOrderComplete(OpenOrderCompleteParam param); |
| | |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.zy.api.controller.params.StopOutTaskParams; |
| | | import com.zy.api.service.WcsApiService; |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.core.common.*; |
| | | import com.core.exception.CoolException; |
| | |
| | | |
| | | import javax.rmi.CORBA.Util; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * Created by vincent on 2022/4/9 |
| | |
| | | private WaitPakinService waitPakinService; |
| | | @Autowired |
| | | private WrkMastService wrkMastService; |
| | | @Autowired |
| | | private WcsApiService wcsApiService; |
| | | |
| | | @Override |
| | | @Transactional |
| | |
| | | throw new CoolException("生成单据明细失败,请联系管理员"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | public R pakoutOrderPause(OpenOrderPakoutPauseParam param) { |
| | | if (param == null || Cools.isEmpty(param.getOrderNo())) { |
| | | throw new CoolException("orderNo is empty"); |
| | | } |
| | | Order order = orderService.selectByNo(param.getOrderNo()); |
| | | if (order == null) { |
| | | order = OrderInAndOutUtil.selectByNo(Boolean.FALSE, param.getOrderNo()); |
| | | } |
| | | if (order == null) { |
| | | throw new CoolException("order not found: " + param.getOrderNo()); |
| | | } |
| | | |
| | | List<WrkMast> activeTasks = findActiveOutboundTasks(param.getOrderNo()); |
| | | if (activeTasks.isEmpty()) { |
| | | return R.ok("no active out tasks"); |
| | | } |
| | | |
| | | Date now = new Date(); |
| | | int pausedCount = 0; |
| | | List<WrkMast> issuedTasks = new ArrayList<>(); |
| | | for (WrkMast wrkMast : activeTasks) { |
| | | if (wrkMast == null || "Y".equalsIgnoreCase(wrkMast.getPauseMk())) { |
| | | continue; |
| | | } |
| | | wrkMast.setPauseMk("Y"); |
| | | wrkMast.setUpdMk(needNotifyWcsStop(wrkMast) ? "WCS_STOP_REQUESTED" : "WMS_PAUSED"); |
| | | wrkMast.setManuType("ERP_PAUSE"); |
| | | wrkMast.setModiTime(now); |
| | | wrkMast.setModiUser(9527L); |
| | | if (!wrkMastService.updateById(wrkMast)) { |
| | | throw new CoolException("pause out task failed: " + wrkMast.getWrkNo()); |
| | | } |
| | | pausedCount++; |
| | | if (needNotifyWcsStop(wrkMast)) { |
| | | issuedTasks.add(wrkMast); |
| | | } |
| | | } |
| | | |
| | | if (pausedCount == 0) { |
| | | return R.ok("tasks already paused"); |
| | | } |
| | | |
| | | if (!issuedTasks.isEmpty()) { |
| | | wcsApiService.pauseOutTasks(buildStopOutTaskParams(param, issuedTasks)); |
| | | } |
| | | |
| | | Map<String, Object> result = new HashMap<>(); |
| | | result.put("orderNo", param.getOrderNo()); |
| | | result.put("pausedCount", pausedCount); |
| | | result.put("wcsStopCount", issuedTasks.size()); |
| | | return R.ok("pause out success").add(result); |
| | | } |
| | | |
| | | private List<WrkMast> findActiveOutboundTasks(String orderNo) { |
| | | List<WrkDetl> wrkDetls = wrkDetlService.selectList(new EntityWrapper<WrkDetl>().eq("order_no", orderNo)); |
| | | if (wrkDetls == null || wrkDetls.isEmpty()) { |
| | | return Collections.emptyList(); |
| | | } |
| | | Set<Integer> wrkNos = wrkDetls.stream() |
| | | .map(WrkDetl::getWrkNo) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toCollection(LinkedHashSet::new)); |
| | | if (wrkNos.isEmpty()) { |
| | | return Collections.emptyList(); |
| | | } |
| | | List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>() |
| | | .in("wrk_no", wrkNos) |
| | | .in("io_type", Arrays.asList(101, 108, 110)) |
| | | .lt("wrk_sts", 14L)); |
| | | if (wrkMasts == null || wrkMasts.isEmpty()) { |
| | | return Collections.emptyList(); |
| | | } |
| | | wrkMasts.sort(Comparator.comparing(WrkMast::getWrkNo)); |
| | | return wrkMasts; |
| | | } |
| | | |
| | | private boolean needNotifyWcsStop(WrkMast wrkMast) { |
| | | return wrkMast != null |
| | | && wrkMast.getWrkSts() != null |
| | | && wrkMast.getWrkSts() >= 12L |
| | | && wrkMast.getWrkSts() < 14L; |
| | | } |
| | | |
| | | private StopOutTaskParams buildStopOutTaskParams(OpenOrderPakoutPauseParam param, List<WrkMast> wrkMasts) { |
| | | StopOutTaskParams stopParams = new StopOutTaskParams(); |
| | | stopParams.setOrderNo(param.getOrderNo()); |
| | | stopParams.setReason(param.getReason()); |
| | | for (WrkMast wrkMast : wrkMasts) { |
| | | StopOutTaskParams.TaskItem item = new StopOutTaskParams.TaskItem(); |
| | | item.setTaskNo(String.valueOf(wrkMast.getWrkNo())); |
| | | if (wrkMast.getStaNo() != null) { |
| | | item.setStaNo(String.valueOf(wrkMast.getStaNo())); |
| | | } |
| | | item.setLocNo(wrkMast.getSourceLocNo()); |
| | | stopParams.getTasks().add(item); |
| | | } |
| | | return stopParams; |
| | | } |
| | | |
| | | @Override |
| | |
| | | |
| | | Mat mat = matService.selectByMatnr(param.getMatnr()); |
| | | if (Cools.isEmpty(mat)) { |
| | | if (Cools.isEmpty(param.getFull())) { |
| | | if (param.getAnfme() == 0) { |
| | | //空托盘 |
| | | mat = matService.selectByMatnr("0"); |
| | | } else { |
| | | //满托盘 |
| | | mat = matService.selectByMatnr("1"); |
| | | } |
| | | } else { |
| | | |
| | | if (param.getFull()==1){ |
| | | //满托盘 |
| | | mat = matService.selectByMatnr("1"); |
| | | mat = matService.selectByMatnr(param.getMatnr()); |
| | | }else if (param.getFull()==0){ |
| | | //空托盘 |
| | | mat = matService.selectByMatnr("0"); |
| | | mat = matService.selectByMatnr("emptyPallet"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | WaitPakin waitPakin = new WaitPakin(); |
| | | waitPakin.sync(mat); |
| | | waitPakin.setBatch(String.valueOf(param.getBatchId())); |
| | | waitPakin.setZpallet(param.getPalletId()); // 托盘码 |
| | | |
| | | waitPakin.setIoStatus("N"); // 入出状态 |
| | | waitPakin.setAnfme(param.getAnfme()); // 数量 |
| | | waitPakin.setStatus("Y"); // 状态 |
| | |
| | | waitPakin.setOrigin(String.valueOf(param.getStorageArea()));//建议入库区域 |
| | | waitPakin.setManu(String.valueOf(param.getLocId()));//mes具体库位编号 |
| | | waitPakin.setThreeCode(param.getBizNo()); |
| | | waitPakin.setBeBatch(param.getPackage1());//是否散货,0 非散货;1 散货;为了管控出货速率,散货可以出慢点。 |
| | | if (!waitPakinService.insert(waitPakin)) { |
| | | throw new CoolException("保存入库通知档失败"); |
| | | } |
| | |
| | | } |
| | | LocTypeDto locTypeDto = new LocTypeDto(); |
| | | locTypeDto.setLocType1((short) 1); |
| | | return wcsController.startupFullPutStore(301, list.get(0).getZpallet(), locTypeDto, list); |
| | | return wcsController.startupFullPutStore(301, list.get(0).getZpallet(), locTypeDto, list, null); |
| | | } |
| | | |
| | | @Override |
| | |
| | | List<WrkMast> wrkMasts = wrkMastService.selectList( |
| | | new com.baomidou.mybatisplus.mapper.EntityWrapper<WrkMast>() |
| | | .eq("wrk_sts", 11) |
| | | .last(" and (pause_mk is null or pause_mk <> 'Y')") |
| | | ); |
| | | if (wrkMasts.isEmpty()) { |
| | | return; |
| | |
| | | @Autowired |
| | | private WorkMastHandler workMastHandler; |
| | | |
| | | /** |
| | | * wcs上报任务完成后,将任务上报给erp |
| | | * 2.入库上报 |
| | | * 13.出库上报 |
| | | */ |
| | | @Scheduled(cron = "0/3 * * * * ? ") |
| | | private void execute1(){ |
| | | List<WrkMast> wrkMasts = wrkMastService.selectList( |
| | | new com.baomidou.mybatisplus.mapper.EntityWrapper<WrkMast>() |
| | | .in("wrk_sts", 2, 13) |
| | | ); |
| | | if (wrkMasts.isEmpty()) { |
| | | return; |
| | | } |
| | | for (WrkMast wrkMast : wrkMasts) { |
| | | ReturnT<String> returnT = workMastHandler.start1(wrkMast); |
| | | if (!returnT.isSuccess()) { |
| | | wrkMast.setUpdMk("X"); |
| | | wrkMast.setErrorMemo(returnT.getMsg()); |
| | | wrkMast.setErrorTime(new Date()); |
| | | if (!wrkMastService.updateById(wrkMast)) { |
| | | log.error("工作档[workNo={}]标记待处理失败", wrkMast.getWrkNo()); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Scheduled(cron = "0/3 * * * * ? ") |
| | | private void execute(){ |
| | | List<WrkMast> wrkMasts = wrkMastService.selectToBeCompleteData(); |
| | |
| | | for (WrkMast m : wrkMast) { |
| | | if (m == null) { continue; } |
| | | if (Objects.equals(m.getWrkSts(), 11L)) { |
| | | if ("Y".equalsIgnoreCase(m.getPauseMk())) { |
| | | continue; |
| | | } |
| | | if (m.getUpdMk() != null && "WCS_SENT".equalsIgnoreCase(m.getUpdMk())) { |
| | | continue; |
| | | } |
| | |
| | | package com.zy.asrs.task.handler; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.core.common.Cools; |
| | | import com.core.exception.CoolException; |
| | | import com.zy.asrs.entity.*; |
| | | import com.zy.asrs.enums.LocStsType; |
| | | import com.zy.asrs.service.*; |
| | | import com.zy.asrs.service.impl.*; |
| | | import com.zy.asrs.task.AbstractHandler; |
| | | import com.zy.asrs.task.core.ReturnT; |
| | | import com.zy.common.entity.Parameter; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.transaction.interceptor.TransactionAspectSupport; |
| | | import springfox.documentation.spring.web.json.Json; |
| | | |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * Created by vincent on 2020/7/4 |
| | |
| | | @Service |
| | | @Transactional |
| | | public class WorkMastHandler extends AbstractHandler<String> { |
| | | |
| | | @Value("${erp.address.URL}") |
| | | private String erpBaseUrl; |
| | | |
| | | @Value("${erp.address.Inaddress}") |
| | | private String erpInAddress; |
| | | |
| | | @Value("${erp.address.Outaddress}") |
| | | private String erpOutAddress; |
| | | |
| | | @Autowired |
| | | private WrkMastService wrkMastService; |
| | |
| | | private OrderDetlPakinService orderDetlPakinService; |
| | | @Autowired |
| | | private OrderDetlPakoutService orderDetlPakoutService; |
| | | @Autowired |
| | | private OrderPakinService orderPakinService; |
| | | @Autowired |
| | | private WorkService workService; |
| | | |
| | | @Value("${erp.switch.ErpReportOld}") |
| | | private boolean erpReportOld; |
| | | |
| | | public ReturnT<String> start(WrkMast wrkMast) { |
| | | // 4.入库完成 |
| | |
| | | return SUCCESS; |
| | | } |
| | | |
| | | private ReturnT<String> doIn(WrkMast wrkMast){ |
| | | |
| | | private boolean needInboundErpReport(WrkMast wrkMast) { |
| | | if (!erpReportOld) { |
| | | return false; |
| | | } |
| | | String erpReport = Parameter.get().getErpReport(); |
| | | if (!Cools.isEmpty(erpReport) && !"true".equalsIgnoreCase(erpReport)) { |
| | | return false; |
| | | } |
| | | if (wrkMast == null || Cools.isEmpty(wrkMast.getBarcode())) { |
| | | return false; |
| | | } |
| | | Integer ioType = wrkMast.getIoType(); |
| | | return ioType != null && (ioType == 1 || ioType == 8 || ioType == 53 || ioType == 54 || ioType == 57); |
| | | } |
| | | |
| | | private boolean needOutboundErpReport(WrkMast wrkMast) { |
| | | if (!erpReportOld) { |
| | | return false; |
| | | } |
| | | String erpReport = Parameter.get().getErpReport(); |
| | | if (!Cools.isEmpty(erpReport) && !"true".equalsIgnoreCase(erpReport)) { |
| | | return false; |
| | | } |
| | | if (wrkMast == null || Cools.isEmpty(wrkMast.getBarcode())) { |
| | | return false; |
| | | } |
| | | Integer ioType = wrkMast.getIoType(); |
| | | return ioType != null && (ioType == 101 || ioType == 108 || ioType == 110); |
| | | } |
| | | |
| | | public ReturnT<String> doIn(WrkMast wrkMast) { |
| | | Date now = new Date(); |
| | | LocMast locMast = locMastService.selectById(wrkMast.getLocNo()); |
| | | try { |
| | |
| | | } |
| | | // 遍历工作明细,更新库存明细和入库通知档 |
| | | for (WrkDetl wrkDetl : wrkDetls) { |
| | | |
| | | LocDetl locDetl = locDetlService.selectItem(locMast.getLocNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(),wrkDetl.getBrand() |
| | | ,wrkDetl.getStandby1(),wrkDetl.getStandby2(),wrkDetl.getStandby3(),wrkDetl.getBoxType1(),wrkDetl.getBoxType2(),wrkDetl.getBoxType3()); |
| | | if (null != locDetl) { |
| | |
| | | locDetl.setZpallet(wrkDetl.getZpallet()); // 托盘条码 |
| | | locDetl.setModiTime(now); |
| | | locDetl.setAppeTime(now); |
| | | locDetl.setOrigin("在库"); |
| | | if (!locDetlService.insert(locDetl)) { |
| | | // exceptionHandle("全板入库 ===>> 添加库存明细失败;[workNo={0}],[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("全板入库 ===>> 添加库存明细失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } |
| | | |
| | | if (!Cools.isEmpty(wrkDetl.getOrderNo())){ |
| | | log.info("进入入库任务完成,带订单:"+ JSON.toJSONString(wrkDetl)); |
| | | // 更新订单完成数量 |
| | | OrderDetlPakin orderDetlPakin = orderDetlPakinService.selectItem |
| | | (wrkDetl.getOrderNo(), wrkDetl.getMatnr(), |
| | | wrkDetl.getBatch(), wrkDetl.getBrand(), |
| | | wrkDetl.getStandby1(), wrkDetl.getStandby2(),wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(),wrkDetl.getBoxType2(), wrkDetl.getBoxType3()); |
| | | if (orderDetlPakin==null){ |
| | | log.info("进入入库任务完成,查询订单失败:"+ JSON.toJSONString(wrkDetl)); |
| | | |
| | | orderDetlPakin = orderDetlPakinService.selectItem |
| | | (wrkDetl.getOrderNo(), wrkDetl.getMatnr(), |
| | | wrkDetl.getBatch(), wrkDetl.getBrand(), |
| | | wrkDetl.getStandby1(),wrkDetl.getStandby2(),wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(),wrkDetl.getBoxType2(),wrkDetl.getBoxType3()); |
| | | } |
| | | try { |
| | | if(!Cools.isEmpty(orderDetlPakin)){ |
| | | if(!orderDetlPakinService.increaseQtyByOrderNo(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), |
| | | orderDetlPakin.getBatch(),wrkDetl.getBrand(),wrkDetl.getStandby1(),wrkDetl.getStandby2(),wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(),wrkDetl.getBoxType2(),wrkDetl.getBoxType3(),wrkDetl.getAnfme())){ |
| | | // exceptionHandle("全板入库 ===>> 更新订单完成数量失败;[workNo={0}],[locNo={1}]", |
| | | // wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("全板入库 ===>> 更新订单完成数量失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } |
| | | } catch (Exception ignore){} |
| | | } |
| | | |
| | | } |
| | | // 修改库位状态 S ====>> F |
| | | if (locMast.getLocSts().equals("S")) { |
| | |
| | | } |
| | | // 遍历工作明细,更新库存明细和入库通知档 |
| | | for (WrkDetl wrkDetl : wrkDetls8) { |
| | | |
| | | LocDetl locDetl = locDetlService.selectItem(locMast.getLocNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand() |
| | | , wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3()); |
| | | if (null != locDetl) { |
| | |
| | | } |
| | | } |
| | | |
| | | if (!Cools.isEmpty(wrkDetl.getOrderNo())){ |
| | | // 更新订单完成数量 |
| | | OrderDetlPakout orderDetlPakout = orderDetlPakoutService.selectItem |
| | | OrderDetlPakin orderDetlPakin = orderDetlPakinService.selectItem |
| | | (wrkDetl.getOrderNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand(), |
| | | wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3()); |
| | | if (orderDetlPakout==null){ |
| | | orderDetlPakout = orderDetlPakoutService.selectItem |
| | | if (orderDetlPakin == null) { |
| | | orderDetlPakin = orderDetlPakinService.selectItem |
| | | (wrkDetl.getOrderNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(),wrkDetl.getBrand(),wrkDetl.getStandby1(),wrkDetl.getStandby2(),wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(),wrkDetl.getBoxType2(),wrkDetl.getBoxType3()); |
| | | } |
| | | try { |
| | | if(!Cools.isEmpty(orderDetlPakout)){ |
| | | if(!orderDetlPakoutService.increaseQtyByOrderNo(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), |
| | | orderDetlPakout.getBatch(),wrkDetl.getBrand(),wrkDetl.getStandby1(),wrkDetl.getStandby2(),wrkDetl.getStandby3(), |
| | | if (!Cools.isEmpty(orderDetlPakin)) { |
| | | if (!orderDetlPakinService.increaseQtyByOrderNo(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), |
| | | orderDetlPakin.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(),wrkDetl.getBoxType2(),wrkDetl.getBoxType3(),wrkDetl.getAnfme())){ |
| | | // exceptionHandle("拣料入库 ===>> 更新订单完成数量失败;[workNo={0}],[locNo={1}]", |
| | | // wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | |
| | | return FAIL.setMsg("拣料入库 ===>> 更新订单完成数量失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } |
| | | } catch (Exception ignore){} |
| | | } catch (Exception ignore) { |
| | | } |
| | | |
| | | } |
| | |
| | | break; |
| | | } |
| | | // 修改工作主档状态 |
| | | if (needInboundErpReport(wrkMast)) { |
| | | wrkMast.setWrkSts(WorkErpReportHandler.ERP_REPORT_PENDING_WRK_STS); |
| | | wrkMast.setLogMk(WorkErpReportHandler.ERP_REPORT_PENDING_FLAG); |
| | | wrkMast.setExpTime(0D); |
| | | wrkMast.setLogErrMemo(null); |
| | | wrkMast.setLogErrTime(null); |
| | | } else { |
| | | wrkMast.setWrkSts(5L); |
| | | } |
| | | wrkMast.setModiTime(now); |
| | | if (!wrkMastService.updateById(wrkMast)) { |
| | | // exceptionHandle("更新入库完成状态失败;[workNo={0}]", wrkMast.getWrkNo()); |
| | |
| | | return SUCCESS; |
| | | } |
| | | |
| | | private ReturnT<String> doOut(WrkMast wrkMast){ |
| | | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public ReturnT<String> doOut(WrkMast wrkMast) { |
| | | Date now = new Date(); |
| | | LocMast locMast = locMastService.selectById(wrkMast.getSourceLocNo()); |
| | | try { |
| | | if (null == locMast && wrkMast.getIoType() !=12) { |
| | | if (null == locMast) { |
| | | // exceptionHandle("工作档[workNo={0}]库位号错误[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("工作档库位号错误; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | |
| | | switch (wrkMast.getIoType()) { |
| | | // 全板出库 |
| | | case 101: |
| | | //如果wrkCode不为空,表示是工作台叫货,如果不为空走移库逻辑 |
| | | //todo 判断如果库位所属不是同一个堆垛机号,需再生成一个新的入库任务 |
| | | |
| | | // // 出库确认信号位 |
| | | // if (Cools.isEmpty(wrkMast.getInvWh()) || wrkMast.getInvWh().equals("N")) { |
| | | // return SUCCESS; |
| | |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("全板出库 ===>> 工作明细档为空; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getSourceLocNo() + "]"); |
| | | } |
| | | |
| | | for (WrkDetl wrkDetl : wrkDetls101) { |
| | | if (!Cools.isEmpty(wrkDetl.getOrderNo())){ |
| | | // 更新订单完成数量 |
| | | OrderDetlPakout orderDetlPakout = orderDetlPakoutService.selectItem(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(),wrkDetl.getBrand(),wrkDetl.getStandby1(),wrkDetl.getStandby2(),wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(),wrkDetl.getBoxType2(),wrkDetl.getBoxType3()); |
| | |
| | | if(!orderDetlPakoutService.increaseQtyByOrderNo(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), |
| | | orderDetlPakout.getBatch(),wrkDetl.getBrand(),wrkDetl.getStandby1(),wrkDetl.getStandby2(),wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(),wrkDetl.getBoxType2(),wrkDetl.getBoxType3(),wrkDetl.getAnfme())){ |
| | | // exceptionHandle("全板出库 ===>> 更新订单完成数量失败;[workNo={0}],[locNo={1}]", |
| | | // wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("全板出库 ===>> 更新订单完成数量失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getSourceLocNo() + "]"); |
| | | } |
| | | } |
| | | } catch (Exception ignore){} |
| | | } catch (Exception ignore) { |
| | | |
| | | } |
| | | } |
| | | // 删除工作档源库位的库存明细 |
| | | if (!locDetlService.delete(new EntityWrapper<LocDetl>().eq("loc_no", wrkMast.getSourceLocNo()))) { |
| | | // exceptionHandle("全板出库 ===>> 删除库存明细失败;[workNo={0}],[sourceLocNo={1}]", wrkMast.getWrkNo(), wrkMast.getSourceLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("全板出库 ===>> 删除库存明细失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getSourceLocNo() + "]"); |
| | | } |
| | |
| | | locMast.setModiTime(now); |
| | | locMast.setIoTime(now); |
| | | if (!locMastService.updateById(locMast)) { |
| | | // exceptionHandle("全板出库 ===>> 修改源库位状态失败;[workNo={0}],[sourceLocNo={1}]", wrkMast.getWrkNo(), wrkMast.getSourceLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("全板出库 ===>> 修改源库位状态失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getSourceLocNo() + "]"); |
| | | } |
| | | } |
| | | |
| | | break; |
| | | // 并板途中捡料 |
| | | case 108: |
| | |
| | | return FAIL.setMsg("并板途中捡料 ===>> 更新订单完成数量失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getSourceLocNo() + "]"); |
| | | } |
| | | } |
| | | } catch (Exception ignore){} |
| | | } catch (Exception ignore) { |
| | | } |
| | | } |
| | | break; |
| | | // 空板出库 |
| | |
| | | } |
| | | } |
| | | break; |
| | | //3号堆垛机衔接 |
| | | case 12: |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | // 修改工作主档状态 |
| | | if (needOutboundErpReport(wrkMast)) { |
| | | wrkMast.setWrkSts(WorkOutErpReportHandler.ERP_REPORT_PENDING_WRK_STS); |
| | | wrkMast.setLogMk(WorkOutErpReportHandler.ERP_REPORT_PENDING_FLAG); |
| | | wrkMast.setExpTime(0D); |
| | | wrkMast.setLogErrMemo(null); |
| | | wrkMast.setLogErrTime(null); |
| | | } else { |
| | | wrkMast.setWrkSts(15L); |
| | | } |
| | | // if (!Objects.isNull(wrkMast.getWrkCode())) { |
| | | // //领料出库任务,不修改 |
| | | // } else { |
| | | // } |
| | | wrkMast.setModiTime(now); |
| | | if (!wrkMastService.updateById(wrkMast)) { |
| | | // exceptionHandle("更新出库完成状态失败;[workNo={0}]", wrkMast.getWrkNo()); |
| | |
| | | } |
| | | return SUCCESS; |
| | | } |
| | | |
| | | /** |
| | | * wcs上报任务完成后,将任务上报给erp |
| | | * 2.入库上报 |
| | | * 13.出库上报 |
| | | */ |
| | | public ReturnT<String> start1(WrkMast wrkMast) { |
| | | // 2.入库上报 |
| | | if (wrkMast.getWrkSts() == 2) { |
| | | return ErpdoIn(wrkMast); |
| | | // 13.出库上报 |
| | | } else if (wrkMast.getWrkSts() == 13) { |
| | | return ErpdoOut(wrkMast); |
| | | } |
| | | return SUCCESS; |
| | | } |
| | | |
| | | private ReturnT<String> ErpdoOut(WrkMast wrkMast){ |
| | | try { |
| | | com.zy.common.utils.HttpHandler.Builder builder = new com.zy.common.utils.HttpHandler.Builder(); |
| | | if (Cools.isEmpty(erpBaseUrl) || Cools.isEmpty(erpOutAddress)) { |
| | | return FAIL.setMsg("ERP出库上报地址未配置[erp.address.URL / erp.address.Outaddress]"); |
| | | } |
| | | java.util.List<WrkDetl> wrkDetls = wrkDetlService.selectList( |
| | | new com.baomidou.mybatisplus.mapper.EntityWrapper<WrkDetl>().eq("wrk_no", wrkMast.getWrkNo()) |
| | | ); |
| | | if (wrkDetls == null || wrkDetls.isEmpty()) { |
| | | return FAIL.setMsg("ERP出库上报失败, 未找到工作明细[workNo=" + wrkMast.getWrkNo() + "]"); |
| | | } |
| | | |
| | | java.util.Map<String, Object> payload = new java.util.HashMap<>(); |
| | | payload.put("palletId", wrkMast.getBarcode()); |
| | | payload.put("anfme", wrkDetls.get(0).getAnfme()); |
| | | payload.put("locId", wrkMast.getSourceLocNo()); |
| | | payload.put("weight", wrkMast.getScWeight()); |
| | | payload.put("photos", new java.util.ArrayList<String>()); |
| | | if (wrkMast.getModiTime() != null) { |
| | | payload.put("createTime", new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(wrkMast.getModiTime())); |
| | | } else { |
| | | payload.put("createTime", new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date())); |
| | | } |
| | | payload.put("BizNo", String.valueOf(wrkDetls.get(0).getThreeCode())); |
| | | |
| | | String uri = erpBaseUrl; |
| | | String response = builder |
| | | .setUri(uri) |
| | | .setPath(erpOutAddress) |
| | | .setHttps(uri != null && uri.startsWith("https://")) |
| | | .setTimeout(10, java.util.concurrent.TimeUnit.SECONDS) |
| | | .setJson(com.alibaba.fastjson.JSON.toJSONString(payload)) |
| | | .build() |
| | | .doPost(); |
| | | |
| | | com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSON.parseObject(response == null ? "{}" : response); |
| | | Integer code = jsonObject.getInteger("code"); |
| | | if (code == null || code != 0) { |
| | | String msg = jsonObject.getString("msg"); |
| | | return FAIL.setMsg(Cools.isEmpty(msg) ? "ERP出库上报失败" : msg); |
| | | } |
| | | wrkMast.setWrkSts(wrkMast.getWrkSts() + 1); |
| | | wrkMast.setModiTime(new java.util.Date()); |
| | | if (!wrkMastService.updateById(wrkMast)) { |
| | | return FAIL.setMsg("ERP出库上报成功但更新工作状态失败; [workNo=" + wrkMast.getWrkNo() + "]"); |
| | | } |
| | | } catch (Exception e) { |
| | | return FAIL.setMsg(e.getMessage()); |
| | | } |
| | | return SUCCESS; |
| | | } |
| | | |
| | | private ReturnT<String> ErpdoIn(WrkMast wrkMast){ |
| | | try { |
| | | com.zy.common.utils.HttpHandler.Builder builder = new com.zy.common.utils.HttpHandler.Builder(); |
| | | if (Cools.isEmpty(erpBaseUrl) || Cools.isEmpty(erpInAddress)) { |
| | | return FAIL.setMsg("ERP入库上报地址未配置[erp.address.URL / erp.address.Inaddress]"); |
| | | } |
| | | |
| | | java.util.Map<String, Object> payload = new java.util.HashMap<>(); |
| | | payload.put("palletId", wrkMast.getBarcode()); |
| | | java.util.List<WrkDetl> wrkDetls = wrkDetlService.selectList( |
| | | new com.baomidou.mybatisplus.mapper.EntityWrapper<WrkDetl>().eq("wrk_no", wrkMast.getWrkNo()) |
| | | ); |
| | | if (wrkDetls == null || wrkDetls.isEmpty()) { |
| | | return FAIL.setMsg("ERP入库上报失败, 未找到工作明细[workNo=" + wrkMast.getWrkNo() + "]"); |
| | | } |
| | | double anfme = 0D; |
| | | for (WrkDetl d : wrkDetls) { |
| | | if (d != null && d.getAnfme() != null) { |
| | | anfme += d.getAnfme(); |
| | | } |
| | | } |
| | | payload.put("anfme", anfme); |
| | | payload.put("locId", wrkMast.getLocNo()); |
| | | payload.put("weight", wrkMast.getScWeight()); |
| | | payload.put("photos", new java.util.ArrayList<String>()); |
| | | if (wrkMast.getModiTime() != null) { |
| | | payload.put("createTime", new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(wrkMast.getModiTime())); |
| | | } else { |
| | | payload.put("createTime", new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date())); |
| | | } |
| | | payload.put("BizNo", String.valueOf(wrkDetls.get(0).getThreeCode())); |
| | | |
| | | String uri = erpBaseUrl; |
| | | |
| | | String response = builder |
| | | .setUri(uri) |
| | | .setPath(erpInAddress) |
| | | .setHttps(uri != null && uri.startsWith("https://")) |
| | | .setTimeout(10, java.util.concurrent.TimeUnit.SECONDS) |
| | | .setJson(com.alibaba.fastjson.JSON.toJSONString(payload)) |
| | | .build() |
| | | .doPost(); |
| | | |
| | | com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSON.parseObject(response == null ? "{}" : response); |
| | | Integer code = jsonObject.getInteger("code"); |
| | | if (code == null || code != 0) { |
| | | String msg = jsonObject.getString("msg"); |
| | | return FAIL.setMsg(Cools.isEmpty(msg) ? "ERP入库上报失败" : msg); |
| | | } |
| | | wrkMast.setWrkSts(wrkMast.getWrkSts() + 1); |
| | | wrkMast.setModiTime(new java.util.Date()); |
| | | if (!wrkMastService.updateById(wrkMast)) { |
| | | return FAIL.setMsg("ERP入库上报成功但更新工作状态失败; [workNo=" + wrkMast.getWrkNo() + "]"); |
| | | } |
| | | } catch (Exception e) { |
| | | return FAIL.setMsg(e.getMessage()); |
| | | } |
| | | return SUCCESS; |
| | | } |
| | | |
| | | } |
| | |
| | | return result; |
| | | } |
| | | |
| | | //将wms库位号转换成wcs库位号 |
| | | public static String WMSLocToWCSLoc(String locNo) { |
| | | String row = locNo.substring(0, 2); |
| | | int i = 0; |
| | | for (char c : row.toCharArray()) { |
| | | if (c == '0') { |
| | | i++; |
| | | }else { |
| | | break; |
| | | } |
| | | } |
| | | row = row.substring(i); |
| | | int j = 0; |
| | | String boy = locNo.substring(2, 5); |
| | | for (char c : boy.toCharArray()) { |
| | | if (c == '0') { |
| | | j++; |
| | | }else { |
| | | break; |
| | | } |
| | | } |
| | | boy = boy.substring(j); |
| | | int k = 0; |
| | | String lev = locNo.substring(5); |
| | | for (char c : lev.toCharArray()) { |
| | | if (c == '0') { |
| | | k++; |
| | | }else { |
| | | break; |
| | | } |
| | | } |
| | | lev = lev.substring(k); |
| | | return row + "-" + boy + "-" + lev; |
| | | } |
| | | } |
| | |
| | | |
| | | private Integer workNo; |
| | | |
| | | private String barcode; |
| | | |
| | | private String taskNo; |
| | | |
| | | } |
| | |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.time.temporal.ChronoUnit; |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Optional; |
| | | |
| | | /** |
| | |
| | | @Slf4j |
| | | @Service |
| | | public class CommonService { |
| | | private static final int MIN_SPARE_LOC_COUNT = 2; |
| | | |
| | | @Autowired |
| | | private WrkMastService wrkMastService; |
| | |
| | | */ |
| | | @Transactional |
| | | public StartupDto getLocNo(Integer staDescId, Integer sourceStaNo, FindLocNoAttributeVo findLocNoAttributeVo, LocTypeDto locTypeDto) { |
| | | return getLocNo(staDescId, sourceStaNo, findLocNoAttributeVo, locTypeDto, null); |
| | | } |
| | | |
| | | @Transactional |
| | | public StartupDto getLocNo(Integer staDescId, Integer sourceStaNo, FindLocNoAttributeVo findLocNoAttributeVo, LocTypeDto locTypeDto, List<Integer> recommendRows) { |
| | | try { |
| | | Integer whsType = Utils.GetWhsType(sourceStaNo); |
| | | RowLastno rowLastno = rowLastnoService.selectById(whsType); |
| | | RowLastnoType rowLastnoType = rowLastnoTypeService.selectById(rowLastno.getTypeId()); |
| | | if (rowLastnoType.getType() == 2) { |
| | | return getLocNoRun2(whsType, staDescId, sourceStaNo, findLocNoAttributeVo, 0, locTypeDto, 0); |
| | | } |
| | | /** |
| | | * 库型 1: 标准堆垛机库 2: 平库 3: 穿梭板 4: 四向车 5: AGV 0: 未知 |
| | | */ |
| | |
| | | case 4: |
| | | return getLocNoRun4(whsType, staDescId, sourceStaNo, findLocNoAttributeVo, 4, locTypeDto, 0); |
| | | case 5: |
| | | return getLocNoRun5(whsType, staDescId, sourceStaNo, findLocNoAttributeVo, 0, locTypeDto, 0); |
| | | return getLocNoRun5(whsType, staDescId, sourceStaNo, findLocNoAttributeVo, 0, locTypeDto, recommendRows, 0); |
| | | default: |
| | | log.error("站点={} 未查询到对应的规则", sourceStaNo); |
| | | break; |
| | |
| | | int availableLocCount = locMastService.selectCount(new EntityWrapper<LocMast>() |
| | | .eq("row1", nearRow) |
| | | .eq("loc_sts", "O") |
| | | .eq("whs_type", rowLastnoType.getType().longValue())); |
| | | .eq("whs_type", 1)); |
| | | int crnCountO = wrkMastService.selectCount(new EntityWrapper<WrkMast>() |
| | | .eq("crn_no", crnNo).le("io_type", 100)); |
| | | if (availableLocCount - crnCountO <= 2) { // 可以提成常量,比如 MIN_SPARE_SLOTS = 2 |
| | |
| | | return Optional.of(new CrnRowInfo(crnNo, nearRow, curRow, rowCount, attempt)); |
| | | } |
| | | return Optional.empty(); |
| | | } |
| | | |
| | | private Optional<CrnRowInfo> findBalancedCrnAndNearRow(RowLastno rowLastno, int curRow, int crnNumber, int times, |
| | | FindLocNoAttributeVo findLocNoAttributeVo, LocTypeDto locTypeDto, |
| | | RowLastnoType rowLastnoType) { |
| | | int maxScanTimes = Math.max(crnNumber * 2, 1); |
| | | int scanCurRow = curRow; |
| | | Map<Integer, Integer> availableLocCountCache = new HashMap<>(); |
| | | Map<Integer, Integer> crnTaskCountCache = new HashMap<>(); |
| | | |
| | | CrnRowInfo bestInfo = null; |
| | | int bestTaskCount = Integer.MAX_VALUE; |
| | | int bestSpareLocCount = Integer.MIN_VALUE; |
| | | int bestOffset = Integer.MAX_VALUE; |
| | | CrnRowInfo fallbackInfo = null; |
| | | int fallbackTaskCount = Integer.MAX_VALUE; |
| | | int fallbackAvailableLocCount = Integer.MIN_VALUE; |
| | | int fallbackOffset = Integer.MAX_VALUE; |
| | | |
| | | for (int attempt = 0; attempt < maxScanTimes; attempt++) { |
| | | int[] params = Utils.LocNecessaryParameters(rowLastno, scanCurRow, crnNumber); |
| | | scanCurRow = params[1]; |
| | | int rowCount = params[0]; |
| | | int crnNo = params[2]; |
| | | int nearRow = params[3]; |
| | | |
| | | if (attempt < times) { |
| | | continue; |
| | | } |
| | | |
| | | int availableLocCount = availableLocCountCache.computeIfAbsent(crnNo, key -> |
| | | countAvailableLocForCrn(rowLastno, rowLastnoType, key, nearRow)); |
| | | int crnTaskCount = crnTaskCountCache.computeIfAbsent(crnNo, key -> |
| | | wrkMastService.selectCount(new EntityWrapper<WrkMast>() |
| | | .eq("crn_no", key) |
| | | .le("io_type", 100))); |
| | | int spareLocCount = availableLocCount - crnTaskCount; |
| | | int offset = attempt - times; |
| | | |
| | | if (availableLocCount > 0 && isBetterCrnCandidate(crnTaskCount, availableLocCount, offset, |
| | | fallbackTaskCount, fallbackAvailableLocCount, fallbackOffset)) { |
| | | fallbackInfo = new CrnRowInfo(crnNo, nearRow, scanCurRow, rowCount, attempt); |
| | | fallbackTaskCount = crnTaskCount; |
| | | fallbackAvailableLocCount = availableLocCount; |
| | | fallbackOffset = offset; |
| | | } |
| | | |
| | | if (spareLocCount <= MIN_SPARE_LOC_COUNT) { |
| | | log.warn("{}号堆垛机可用空库位余量不足,降级候选继续保留。尺寸规格:{},轮询次数:{}", crnNo, JSON.toJSONString(locTypeDto), attempt); |
| | | continue; |
| | | } |
| | | |
| | | if (isBetterCrnCandidate(crnTaskCount, spareLocCount, offset, bestTaskCount, bestSpareLocCount, bestOffset)) { |
| | | bestInfo = new CrnRowInfo(crnNo, nearRow, scanCurRow, rowCount, attempt); |
| | | bestTaskCount = crnTaskCount; |
| | | bestSpareLocCount = spareLocCount; |
| | | bestOffset = offset; |
| | | } |
| | | } |
| | | if (bestInfo != null) { |
| | | return Optional.of(bestInfo); |
| | | } |
| | | if (fallbackInfo != null) { |
| | | log.warn("堆垛机均衡分配未找到满足余量阈值的候选,降级使用仍有空位的堆垛机: crnNo={}", fallbackInfo.getCrnNo()); |
| | | } |
| | | return Optional.ofNullable(fallbackInfo); |
| | | } |
| | | |
| | | private boolean isBetterCrnCandidate(int taskCount, int spareLocCount, int offset, |
| | | int bestTaskCount, int bestSpareLocCount, int bestOffset) { |
| | | if (taskCount != bestTaskCount) { |
| | | return taskCount < bestTaskCount; |
| | | } |
| | | if (spareLocCount != bestSpareLocCount) { |
| | | return spareLocCount > bestSpareLocCount; |
| | | } |
| | | return offset < bestOffset; |
| | | } |
| | | |
| | | private int countAvailableLocForCrn(RowLastno rowLastno, RowLastnoType rowLastnoType, int crnNo, int preferredNearRow) { |
| | | List<Integer> searchRows = getCrnSearchRows(rowLastno, crnNo, preferredNearRow); |
| | | if (searchRows.isEmpty()) { |
| | | return 0; |
| | | } |
| | | return locMastService.selectCount(new EntityWrapper<LocMast>() |
| | | .in("row1", searchRows) |
| | | .eq("loc_sts", "O") |
| | | .eq("whs_type", rowLastnoType.getType().longValue())); |
| | | } |
| | | |
| | | private int countAvailableSingleExtensionLocForCrn(RowLastno rowLastno, RowLastnoType rowLastnoType, int crnNo, int preferredNearRow, LocTypeDto locTypeDto) { |
| | | List<Integer> searchRows = getCrnSearchRows(rowLastno, crnNo, preferredNearRow); |
| | | if (searchRows.isEmpty()) { |
| | | return 0; |
| | | } |
| | | Wrapper<LocMast> wrapper = new EntityWrapper<LocMast>() |
| | | .in("row1", searchRows) |
| | | .eq("loc_sts", "O") |
| | | .eq("whs_type", rowLastnoType.getType().longValue()); |
| | | if (locTypeDto != null && locTypeDto.getLocType1() != null) { |
| | | wrapper.eq("loc_type1", locTypeDto.getLocType1()); |
| | | } |
| | | return locMastService.selectCount(wrapper); |
| | | } |
| | | |
| | | private Optional<CrnRowInfo> findBalancedSingleExtensionCrnAndNearRow(RowLastno rowLastno, int curRow, int crnNumber, int times, |
| | | LocTypeDto locTypeDto, RowLastnoType rowLastnoType) { |
| | | int maxScanTimes = Math.max(crnNumber * 2, 1); |
| | | int scanCurRow = curRow; |
| | | Map<Integer, Integer> availableLocCountCache = new HashMap<>(); |
| | | Map<Integer, Integer> crnTaskCountCache = new HashMap<>(); |
| | | |
| | | CrnRowInfo bestInfo = null; |
| | | int bestTaskCount = Integer.MAX_VALUE; |
| | | int bestSpareLocCount = Integer.MIN_VALUE; |
| | | int bestOffset = Integer.MAX_VALUE; |
| | | CrnRowInfo fallbackInfo = null; |
| | | int fallbackTaskCount = Integer.MAX_VALUE; |
| | | int fallbackAvailableLocCount = Integer.MIN_VALUE; |
| | | int fallbackOffset = Integer.MAX_VALUE; |
| | | |
| | | for (int attempt = 0; attempt < maxScanTimes; attempt++) { |
| | | int[] params = Utils.LocNecessaryParameters(rowLastno, scanCurRow, crnNumber); |
| | | scanCurRow = params[1]; |
| | | int rowCount = params[0]; |
| | | int crnNo = params[2]; |
| | | int nearRow = params[3]; |
| | | |
| | | if (attempt < times) { |
| | | continue; |
| | | } |
| | | |
| | | int availableLocCount = availableLocCountCache.computeIfAbsent(crnNo, key -> |
| | | countAvailableSingleExtensionLocForCrn(rowLastno, rowLastnoType, key, nearRow, locTypeDto)); |
| | | int crnTaskCount = crnTaskCountCache.computeIfAbsent(crnNo, key -> |
| | | wrkMastService.selectCount(new EntityWrapper<WrkMast>() |
| | | .eq("crn_no", key) |
| | | .le("io_type", 100))); |
| | | int spareLocCount = availableLocCount - crnTaskCount; |
| | | int offset = attempt - times; |
| | | |
| | | if (availableLocCount > 0 && isBetterCrnCandidate(crnTaskCount, availableLocCount, offset, |
| | | fallbackTaskCount, fallbackAvailableLocCount, fallbackOffset)) { |
| | | fallbackInfo = new CrnRowInfo(crnNo, nearRow, scanCurRow, rowCount, attempt); |
| | | fallbackTaskCount = crnTaskCount; |
| | | fallbackAvailableLocCount = availableLocCount; |
| | | fallbackOffset = offset; |
| | | } |
| | | |
| | | if (spareLocCount <= MIN_SPARE_LOC_COUNT) { |
| | | continue; |
| | | } |
| | | |
| | | if (isBetterCrnCandidate(crnTaskCount, spareLocCount, offset, bestTaskCount, bestSpareLocCount, bestOffset)) { |
| | | bestInfo = new CrnRowInfo(crnNo, nearRow, scanCurRow, rowCount, attempt); |
| | | bestTaskCount = crnTaskCount; |
| | | bestSpareLocCount = spareLocCount; |
| | | bestOffset = offset; |
| | | } |
| | | } |
| | | if (bestInfo != null) { |
| | | return Optional.of(bestInfo); |
| | | } |
| | | return Optional.ofNullable(fallbackInfo); |
| | | } |
| | | |
| | | private List<Integer> getCrnSearchRows(RowLastno rowLastno, int crnNo, int preferredNearRow) { |
| | | List<Integer> searchRows = new ArrayList<>(); |
| | | addSearchRow(searchRows, preferredNearRow, rowLastno); |
| | | |
| | | Integer rowSpan = getCrnRowSpan(rowLastno.getTypeId()); |
| | | if (rowSpan == null) { |
| | | return searchRows; |
| | | } |
| | | |
| | | int crnOffset = crnNo - rowLastno.getsCrnNo(); |
| | | if (crnOffset < 0) { |
| | | return searchRows; |
| | | } |
| | | int startRow = rowLastno.getsRow() + crnOffset * rowSpan; |
| | | switch (rowLastno.getTypeId()) { |
| | | case 1: |
| | | addSearchRow(searchRows, startRow + 1, rowLastno); |
| | | addSearchRow(searchRows, startRow + 2, rowLastno); |
| | | break; |
| | | case 2: |
| | | addSearchRow(searchRows, startRow, rowLastno); |
| | | addSearchRow(searchRows, startRow + 1, rowLastno); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | return searchRows; |
| | | } |
| | | |
| | | private Integer getCrnRowSpan(Integer typeId) { |
| | | if (typeId == null) { |
| | | return null; |
| | | } |
| | | switch (typeId) { |
| | | case 1: |
| | | return 4; |
| | | case 2: |
| | | return 2; |
| | | default: |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | private void addSearchRow(List<Integer> searchRows, Integer row, RowLastno rowLastno) { |
| | | if (row == null) { |
| | | return; |
| | | } |
| | | if (row < rowLastno.getsRow() || row > rowLastno.geteRow()) { |
| | | return; |
| | | } |
| | | if (!searchRows.contains(row)) { |
| | | searchRows.add(row); |
| | | } |
| | | } |
| | | |
| | | private LocMast findStandardEmptyLoc(RowLastno rowLastno, RowLastnoType rowLastnoType, int crnNo, int nearRow, LocTypeDto locTypeDto) { |
| | | for (Integer searchRow : getCrnSearchRows(rowLastno, crnNo, nearRow)) { |
| | | List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>() |
| | | .eq("row1", searchRow) |
| | | .eq("loc_sts", "O") |
| | | .eq("whs_type", rowLastnoType.getType().longValue()) |
| | | .orderBy("lev1", true) |
| | | .orderBy("bay1", true)); |
| | | for (LocMast locMast1 : locMasts) { |
| | | if (!VersionUtils.locMoveCheckLocTypeComplete(locMast1, locTypeDto)) { |
| | | continue; |
| | | } |
| | | if (Utils.BooleanWhsTypeStaIoType(rowLastno)) { |
| | | String shallowLoc = Utils.getDeepLoc(slaveProperties, locMast1.getLocNo()); |
| | | LocMast locMast2 = locMastService.selectOne(new EntityWrapper<LocMast>() |
| | | .eq("loc_no", shallowLoc) |
| | | .eq("loc_sts", "O") |
| | | .eq("whs_type", rowLastnoType.getType().longValue())); |
| | | if (!Cools.isEmpty(locMast2)) { |
| | | return locMast2; |
| | | } |
| | | } else if (!Cools.isEmpty(locMast1)) { |
| | | return locMast1; |
| | | } |
| | | } |
| | | |
| | | if (!Utils.BooleanWhsTypeStaIoType(rowLastno)) { |
| | | continue; |
| | | } |
| | | |
| | | for (LocMast locMast1 : locMasts) { |
| | | if (!VersionUtils.locMoveCheckLocTypeComplete(locMast1, locTypeDto)) { |
| | | continue; |
| | | } |
| | | String shallowLoc = Utils.getDeepLoc(slaveProperties, locMast1.getLocNo()); |
| | | LocMast locMast2 = locMastService.selectOne(new EntityWrapper<LocMast>() |
| | | .eq("loc_no", shallowLoc) |
| | | .eq("loc_sts", "O") |
| | | .eq("whs_type", rowLastnoType.getType().longValue())); |
| | | if (!Cools.isEmpty(locMast2)) { |
| | | return locMast2; |
| | | } |
| | | locMast2 = locMastService.selectOne(new EntityWrapper<LocMast>() |
| | | .eq("loc_no", shallowLoc) |
| | | .eq("loc_sts", "F") |
| | | .eq("whs_type", rowLastnoType.getType().longValue())); |
| | | if (!Cools.isEmpty(locMast2)) { |
| | | return locMast1; |
| | | } |
| | | locMast2 = locMastService.selectOne(new EntityWrapper<LocMast>() |
| | | .eq("loc_no", shallowLoc) |
| | | .eq("loc_sts", "D") |
| | | .eq("whs_type", rowLastnoType.getType().longValue())); |
| | | if (!Cools.isEmpty(locMast2)) { |
| | | return locMast1; |
| | | } |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | private LocTypeDto buildUpwardCompatibleLocTypeDto(LocTypeDto locTypeDto) { |
| | | if (locTypeDto == null || locTypeDto.getLocType1() == null || locTypeDto.getLocType1() >= 2) { |
| | | return null; |
| | | } |
| | | LocTypeDto compatibleLocTypeDto = new LocTypeDto(); |
| | | compatibleLocTypeDto.setLocType1((short) (locTypeDto.getLocType1() + 1)); |
| | | compatibleLocTypeDto.setLocType2(locTypeDto.getLocType2()); |
| | | compatibleLocTypeDto.setLocType3(locTypeDto.getLocType3()); |
| | | compatibleLocTypeDto.setSiteId(locTypeDto.getSiteId()); |
| | | return compatibleLocTypeDto; |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | |
| | | //此程序用于优化堆垛机异常时的运行时间 |
| | | Optional<CrnRowInfo> infoOpt = findAvailableCrnAndNearRow(rowLastno, curRow, crnNumber, times, findLocNoAttributeVo, locTypeDto, rowLastnoType); |
| | | Optional<CrnRowInfo> infoOpt = findBalancedCrnAndNearRow(rowLastno, curRow, crnNumber, times, findLocNoAttributeVo, locTypeDto, rowLastnoType); |
| | | if (!infoOpt.isPresent()) { |
| | | infoOpt = findAvailableCrnAndNearRow(rowLastno, curRow, crnNumber, times, findLocNoAttributeVo, locTypeDto, rowLastnoType); |
| | | } |
| | | if (!infoOpt.isPresent()) { |
| | | throw new CoolException("无可用堆垛机"); |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | // 开始查找库位 ==============================>> |
| | | // Search empty location ==============================>> |
| | | if (staDescId == 10 && Cools.isEmpty(locMast) && crnNo != 0) { |
| | | List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>() |
| | | .eq("row1", nearRow) |
| | | .eq("loc_sts", "O").eq("whs_type", rowLastnoType.getType().longValue()) |
| | | .orderBy("lev1", true).orderBy("bay1", false)); |
| | | for (LocMast locMast1 : locMasts) { |
| | | if (!VersionUtils.locMoveCheckLocTypeComplete(locMast1, locTypeDto)) { |
| | | continue; |
| | | } |
| | | if (Utils.BooleanWhsTypeStaIoType(rowLastno)) { |
| | | String shallowLoc = Utils.getDeepLoc(slaveProperties, locMast1.getLocNo()); |
| | | LocMast locMast2 = locMastService.selectOne(new EntityWrapper<LocMast>() |
| | | .eq("loc_no", shallowLoc).eq("loc_sts", "O").eq("whs_type", rowLastnoType.getType().longValue())); |
| | | if (!Cools.isEmpty(locMast2)) { |
| | | locMast = locMast2; |
| | | break; |
| | | } |
| | | } else { |
| | | if (!Cools.isEmpty(locMast1)) { |
| | | locMast = locMast1; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (Cools.isEmpty(locMast) && Utils.BooleanWhsTypeStaIoType(rowLastno)) { |
| | | for (LocMast locMast1 : locMasts) { |
| | | if (!VersionUtils.locMoveCheckLocTypeComplete(locMast1, locTypeDto)) { |
| | | continue; |
| | | } |
| | | if (Utils.BooleanWhsTypeStaIoType(rowLastno)) { |
| | | String shallowLoc = Utils.getDeepLoc(slaveProperties, locMast1.getLocNo()); |
| | | LocMast locMast2 = locMastService.selectOne(new EntityWrapper<LocMast>() |
| | | .eq("loc_no", shallowLoc).eq("loc_sts", "O").eq("whs_type", rowLastnoType.getType().longValue())); |
| | | if (!Cools.isEmpty(locMast2)) { |
| | | locMast = locMast2; |
| | | break; |
| | | } else { |
| | | locMast2 = locMastService.selectOne(new EntityWrapper<LocMast>() |
| | | .eq("loc_no", shallowLoc).eq("loc_sts", "F").eq("whs_type", rowLastnoType.getType().longValue())); |
| | | if (!Cools.isEmpty(locMast2)) { |
| | | locMast = locMast1; |
| | | break; |
| | | } else { |
| | | locMast2 = locMastService.selectOne(new EntityWrapper<LocMast>() |
| | | .eq("loc_no", shallowLoc).eq("loc_sts", "D").eq("whs_type", rowLastnoType.getType().longValue())); |
| | | if (!Cools.isEmpty(locMast2)) { |
| | | locMast = locMast1; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } else { |
| | | if (!Cools.isEmpty(locMast1)) { |
| | | locMast = locMast1; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | locMast = findStandardEmptyLoc(rowLastno, rowLastnoType, crnNo, nearRow, locTypeDto); |
| | | } |
| | | |
| | | |
| | | |
| | | // 1.按规则查找库位 |
| | | if (Cools.isEmpty(locMast) && crnNo != 0) { |
| | | List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>() |
| | | .eq("row1", nearRow) |
| | | .eq("loc_sts", "O").eq("whs_type", rowLastnoType.getType().longValue()) |
| | | .orderBy("lev1", true).orderBy("bay1", false)); |
| | | for (LocMast locMast1 : locMasts) { |
| | | if (!VersionUtils.locMoveCheckLocTypeComplete(locMast1, locTypeDto)) { |
| | | continue; |
| | | } |
| | | if (Utils.BooleanWhsTypeStaIoType(rowLastno)) { |
| | | String shallowLoc = Utils.getDeepLoc(slaveProperties, locMast1.getLocNo()); |
| | | LocMast locMast2 = locMastService.selectOne(new EntityWrapper<LocMast>() |
| | | .eq("loc_no", shallowLoc).eq("loc_sts", "O").eq("whs_type", rowLastnoType.getType().longValue())); |
| | | if (!Cools.isEmpty(locMast2)) { |
| | | locMast = locMast2; |
| | | break; |
| | | } |
| | | } else { |
| | | if (!Cools.isEmpty(locMast1)) { |
| | | locMast = locMast1; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (Cools.isEmpty(locMast) && Utils.BooleanWhsTypeStaIoType(rowLastno)) { |
| | | for (LocMast locMast1 : locMasts) { |
| | | if (!VersionUtils.locMoveCheckLocTypeComplete(locMast1, locTypeDto)) { |
| | | continue; |
| | | } |
| | | if (Utils.BooleanWhsTypeStaIoType(rowLastno)) { |
| | | String shallowLoc = Utils.getDeepLoc(slaveProperties, locMast1.getLocNo()); |
| | | LocMast locMast2 = locMastService.selectOne(new EntityWrapper<LocMast>() |
| | | .eq("loc_no", shallowLoc).eq("loc_sts", "O").eq("whs_type", rowLastnoType.getType().longValue())); |
| | | if (!Cools.isEmpty(locMast2)) { |
| | | locMast = locMast2; |
| | | break; |
| | | } else { |
| | | locMast2 = locMastService.selectOne(new EntityWrapper<LocMast>() |
| | | .eq("loc_no", shallowLoc).eq("loc_sts", "F").eq("whs_type", rowLastnoType.getType().longValue())); |
| | | if (!Cools.isEmpty(locMast2)) { |
| | | locMast = locMast1; |
| | | break; |
| | | } else { |
| | | locMast2 = locMastService.selectOne(new EntityWrapper<LocMast>() |
| | | .eq("loc_no", shallowLoc).eq("loc_sts", "D").eq("whs_type", rowLastnoType.getType().longValue())); |
| | | if (!Cools.isEmpty(locMast2)) { |
| | | locMast = locMast1; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } else { |
| | | if (!Cools.isEmpty(locMast1)) { |
| | | locMast = locMast1; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | locMast = findStandardEmptyLoc(rowLastno, rowLastnoType, crnNo, nearRow, locTypeDto); |
| | | } |
| | | |
| | | if (!Cools.isEmpty(locMast) && !basCrnpService.checkSiteError(crnNo, true)) { |
| | | locMast = null; |
| | | } |
| | | |
| | | // 递归查询 |
| | | // Retry search |
| | | if (Cools.isEmpty(locMast) || !locMast.getLocSts().equals("O")) { |
| | | // 当前巷道无空库位时,递归调整至下一巷道,检索全部巷道无果后,跳出递归 |
| | | // Scan next aisle first, then retry with upward-compatible locType1. |
| | | if (times < rowCount * 2) { |
| | | times = times + 1; |
| | | return getLocNoRun(whsType, staDescId, sourceStaNo, findLocNoAttributeVo, moveCrnNo, locTypeDto, times); |
| | | } |
| | | // // 2.库位当前所属尺寸无空库位时,调整尺寸参数,向上兼容检索库位 |
| | | // if (locTypeDto.getLocType1() < 2) { |
| | | // int i = locTypeDto.getLocType1() + 1; |
| | | // locTypeDto.setLocType1((short)i); |
| | | // return getLocNo(1, staDescId, sourceStaNo, matnr,batch,grade, locTypeDto, 0); |
| | | // } |
| | | log.error("系统没有空库位!!! 尺寸规格: {}, 轮询次数:{}", JSON.toJSONString(locTypeDto), times); |
| | | throw new CoolException("没有空库位"); |
| | | LocTypeDto compatibleLocTypeDto = buildUpwardCompatibleLocTypeDto(locTypeDto); |
| | | if (compatibleLocTypeDto != null) { |
| | | log.warn("locType1 upward compatibility retry. source={}, target={}", JSON.toJSONString(locTypeDto), JSON.toJSONString(compatibleLocTypeDto)); |
| | | return getLocNoRun(whsType, staDescId, sourceStaNo, findLocNoAttributeVo, moveCrnNo, compatibleLocTypeDto, 0); |
| | | } |
| | | log.error("No empty location found. spec={}, times={}", JSON.toJSONString(locTypeDto), times); |
| | | throw new CoolException("\u6ca1\u6709\u7a7a\u5e93\u4f4d"); |
| | | } |
| | | String locNo = locMast.getLocNo(); |
| | | |
| | |
| | | startupDto.setSourceStaNo(sourceStaNo); |
| | | startupDto.setLocNo(locNo); |
| | | return startupDto; |
| | | } |
| | | |
| | | public StartupDto getLocNoRun2(Integer whsType, Integer staDescId, Integer sourceStaNo, FindLocNoAttributeVo findLocNoAttributeVo, Integer moveCrnNo, LocTypeDto locTypeDto, int times) { |
| | | |
| | | int crnNo = 0; |
| | | int nearRow = 0; |
| | | int curRow = 0; |
| | | int rowCount = 0; |
| | | LocMast locMast = null; |
| | | |
| | | StartupDto startupDto = new StartupDto(); |
| | | RowLastno rowLastno = rowLastnoService.selectById(whsType); |
| | | |
| | | if (Cools.isEmpty(rowLastno)) { |
| | | throw new CoolException("数据异常,请联系管理员===>库位规则未知"); |
| | | } |
| | | crnNo = rowLastno.getCurrentRow()/2+1; |
| | | RowLastnoType rowLastnoType = rowLastnoTypeService.selectById(rowLastno.getTypeId()); |
| | | if (Cools.isEmpty(rowLastnoType)) { |
| | | throw new CoolException("数据异常,请联系管理员===》库位规则类型未知"); |
| | | } |
| | | int crnNumber = rowLastno.getCrnQty(); |
| | | |
| | | curRow = rowLastno.getCurrentRow(); |
| | | |
| | | Wrapper<StaDesc> wrapper = null; |
| | | StaDesc staDesc = null; |
| | | BasDevp staNo = null; |
| | | |
| | | if (Utils.BooleanWhsTypeSta(rowLastno, staDescId)) { |
| | | wrapper = new EntityWrapper<StaDesc>() |
| | | .eq("type_no", staDescId) |
| | | .eq("stn_no", sourceStaNo) |
| | | .eq("crn_no", crnNo); |
| | | staDesc = staDescService.selectOne(wrapper); |
| | | if (Cools.isEmpty(staDesc)) { |
| | | log.error("type_no={},stn_no={},crn_no={}", staDescId, sourceStaNo, crnNo); |
| | | crnNo = 0; |
| | | } else { |
| | | staNo = basDevpService.selectById(staDesc.getCrnStn()); |
| | | if (!staNo.getAutoing().equals("Y")) { |
| | | log.error("目标站{}不可用", staDesc.getCrnStn()); |
| | | crnNo = 0; |
| | | } |
| | | startupDto.setStaNo(staNo.getDevNo()); |
| | | } |
| | | } |
| | | |
| | | LocMast locMast1 = locMastService.selectOne(new EntityWrapper<LocMast>() |
| | | .eq("crn_no", crnNo) |
| | | .eq("loc_sts", "O") |
| | | .orderBy("lev1") |
| | | .orderBy("bay1") |
| | | .eq("loc_type1",locTypeDto.getLocType1())); |
| | | if (!Cools.isEmpty(locMast1)) { |
| | | locMast=locMast1; |
| | | } |
| | | if (curRow==rowLastno.geteRow()-1) { |
| | | curRow = 1; |
| | | }else{ |
| | | curRow = curRow + 2; |
| | | } |
| | | rowLastno.setCurrentRow(curRow); |
| | | rowLastnoService.updateById(rowLastno); |
| | | |
| | | if (!Cools.isEmpty(locMast) && !basCrnpService.checkSiteError(crnNo, true)) { |
| | | locMast = null; |
| | | } |
| | | |
| | | if (Cools.isEmpty(locMast) || !locMast.getLocSts().equals("O")) { |
| | | if (times < rowCount * 2) { |
| | | times = times + 1; |
| | | return getLocNoRun2(whsType, staDescId, sourceStaNo, findLocNoAttributeVo, moveCrnNo, locTypeDto, times); |
| | | } |
| | | LocTypeDto compatibleLocTypeDto = buildUpwardCompatibleLocTypeDto(locTypeDto); |
| | | if (compatibleLocTypeDto != null) { |
| | | log.warn("locType1 upward compatibility retry. source={}, target={}", JSON.toJSONString(locTypeDto), JSON.toJSONString(compatibleLocTypeDto)); |
| | | return getLocNoRun2(whsType, staDescId, sourceStaNo, findLocNoAttributeVo, moveCrnNo, compatibleLocTypeDto, 0); |
| | | } |
| | | log.error("No empty location found. spec={}, times={}", JSON.toJSONString(locTypeDto), times); |
| | | throw new CoolException("\u6ca1\u6709\u7a7a\u5e93\u4f4d"); |
| | | } |
| | | |
| | | int workNo = getWorkNo(0); |
| | | startupDto.setWorkNo(workNo); |
| | | startupDto.setCrnNo(crnNo); |
| | | startupDto.setSourceStaNo(sourceStaNo); |
| | | startupDto.setLocNo(locMast.getLocNo()); |
| | | return startupDto; |
| | | } |
| | | |
| | | private LocMast findSingleExtensionEmptyLoc(RowLastno rowLastno, int crnNo, int nearRow, RowLastnoType rowLastnoType, LocTypeDto locTypeDto) { |
| | | for (Integer searchRow : getCrnSearchRows(rowLastno, crnNo, nearRow)) { |
| | | List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>() |
| | | .eq("row1", searchRow) |
| | | .eq("loc_sts", "O") |
| | | .eq("whs_type", rowLastnoType.getType().longValue()) |
| | | .orderBy("bay1", true) |
| | | .orderBy("lev1", true)); |
| | | for (LocMast locMast : locMasts) { |
| | | if (VersionUtils.locMoveCheckLocTypeComplete(locMast, locTypeDto)) { |
| | | return locMast; |
| | | } |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | public StartupDto getLocNoRun4(Integer whsType, Integer staDescId, Integer sourceStaNo, FindLocNoAttributeVo findLocNoAttributeVo, Integer moveCrnNo, LocTypeDto locTypeDto, int times) { |
| | |
| | | continue; |
| | | } |
| | | if (Utils.BooleanWhsTypeStaIoType(rowLastno)) { |
| | | //获取目标库位所在巷道并排序 |
| | | // ????????????? |
| | | // List<String> groupOutsideLocCrn = Utils.getGroupOutLocCrn(curRow,nearRow,locMast1.getLocNo(), curRow>nearRow); |
| | | |
| | | //获取目标库位所在巷道最浅非空库位 |
| | | // ???????????????? |
| | | LocMast locMast2 = locMastService.selectLocByLocStsPakInF(curRow, nearRow, locMast1, rowLastnoType.getType().longValue()); |
| | | if (Cools.isEmpty(locMast2)) { |
| | | LocMast locMast3 = locMastService.selectLocByLocStsPakInO(curRow, nearRow, locMast1, rowLastnoType.getType().longValue()); |
| | |
| | | } |
| | | } |
| | | |
| | | // 递归查询 |
| | | // Retry search |
| | | if (Cools.isEmpty(locMast) || !locMast.getLocSts().equals("O")) { |
| | | // 当前巷道无空库位时,递归调整至下一巷道,检索全部巷道无果后,跳出递归 |
| | | // Scan next aisle first, then retry with upward-compatible locType1. |
| | | if (times < rowCount * 2) { |
| | | times = times + 1; |
| | | return getLocNoRun4(whsType, staDescId, sourceStaNo, findLocNoAttributeVo, moveCrnNo, locTypeDto, times); |
| | | } |
| | | log.error("系统没有空库位!!! 尺寸规格: {}, 轮询次数:{}", JSON.toJSONString(locTypeDto), times); |
| | | throw new CoolException("没有空库位"); |
| | | LocTypeDto compatibleLocTypeDto = buildUpwardCompatibleLocTypeDto(locTypeDto); |
| | | if (compatibleLocTypeDto != null) { |
| | | log.warn("locType1 upward compatibility retry. source={}, target={}", JSON.toJSONString(locTypeDto), JSON.toJSONString(compatibleLocTypeDto)); |
| | | return getLocNoRun4(whsType, staDescId, sourceStaNo, findLocNoAttributeVo, moveCrnNo, compatibleLocTypeDto, 0); |
| | | } |
| | | log.error("No empty location found. spec={}, times={}", JSON.toJSONString(locTypeDto), times); |
| | | throw new CoolException("\u6ca1\u6709\u7a7a\u5e93\u4f4d"); |
| | | } |
| | | String locNo = locMast.getLocNo(); |
| | | |
| | |
| | | return startupDto; |
| | | } |
| | | |
| | | public StartupDto getLocNoRun5(Integer whsType, Integer staDescId, Integer sourceStaNo, FindLocNoAttributeVo findLocNoAttributeVo, Integer moveCrnNo, LocTypeDto locTypeDto, int times) { |
| | | public StartupDto getLocNoRun5(Integer whsType, Integer staDescId, Integer sourceStaNo, FindLocNoAttributeVo findLocNoAttributeVo, Integer moveCrnNo, LocTypeDto locTypeDto, List<Integer> recommendRows, int times) { |
| | | |
| | | // 初始化参数 |
| | | int crnNo = 0; //堆垛机号 |
| | |
| | | } |
| | | |
| | | // 开始查找库位 ==============================>> |
| | | |
| | | if (Cools.isEmpty(locMast) && !Cools.isEmpty(recommendRows)) { |
| | | for (Integer recommendRow : recommendRows) { |
| | | if (Cools.isEmpty(recommendRow)) { |
| | | continue; |
| | | } |
| | | LocMast recommendLoc = locMastService.queryFreeLocMast(recommendRow, locTypeDto.getLocType1(), rowLastnoType.getType().longValue()); |
| | | if (!Cools.isEmpty(recommendLoc) && VersionUtils.locMoveCheckLocTypeComplete(recommendLoc, locTypeDto)) { |
| | | locMast = recommendLoc; |
| | | crnNo = recommendLoc.getCrnNo(); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (Cools.isEmpty(locMast) && sourceStaNo != 4006) {//si'lou'p四楼盘点选择区域 |
| | | List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>() |
| | |
| | | continue; |
| | | } |
| | | if (Utils.BooleanWhsTypeStaIoType(rowLastno)) { |
| | | // 获取目标库位所在巷道最深空库位 |
| | | // ??????????????? |
| | | LocMast locMast2 = locMastService.selectLocByLocStsPakInO(curRow, nearRow, locMast1, rowLastnoType.getType().longValue()); |
| | | if (!Cools.isEmpty(locMast2) && locMast2.getRow1() == curRow) { |
| | | locMast = locMast2; |
| | |
| | | } |
| | | |
| | | if (found) { |
| | | break; // 找到目标库位后跳出循环 |
| | | break; // ??????????? |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | // 递归查询 |
| | | // Retry search |
| | | if (Cools.isEmpty(locMast) || !locMast.getLocSts().equals("O")) { |
| | | // 当前巷道无空库位时,递归调整至下一巷道,检索全部巷道无果后,跳出递归 |
| | | // Scan next aisle first, then retry with upward-compatible locType1. |
| | | if (times < rowCount * 2) { |
| | | times = times + 1; |
| | | return getLocNoRun5(whsType, staDescId, sourceStaNo, findLocNoAttributeVo, moveCrnNo, locTypeDto, times); |
| | | return getLocNoRun5(whsType, staDescId, sourceStaNo, findLocNoAttributeVo, moveCrnNo, locTypeDto, recommendRows, times); |
| | | } |
| | | log.error("系统没有空库位!!! 尺寸规格: {}, 轮询次数:{}", JSON.toJSONString(locTypeDto), times); |
| | | throw new CoolException("没有空库位"); |
| | | LocTypeDto compatibleLocTypeDto = buildUpwardCompatibleLocTypeDto(locTypeDto); |
| | | if (compatibleLocTypeDto != null) { |
| | | log.warn("locType1 upward compatibility retry. source={}, target={}", JSON.toJSONString(locTypeDto), JSON.toJSONString(compatibleLocTypeDto)); |
| | | return getLocNoRun5(whsType, staDescId, sourceStaNo, findLocNoAttributeVo, moveCrnNo, compatibleLocTypeDto, recommendRows, 0); |
| | | } |
| | | log.error("No empty location found. spec={}, times={}", JSON.toJSONString(locTypeDto), times); |
| | | throw new CoolException("\u6ca1\u6709\u7a7a\u5e93\u4f4d"); |
| | | } |
| | | String locNo = locMast.getLocNo(); |
| | | |
| | |
| | | import com.zy.asrs.entity.param.EmptyPlateOutParam; |
| | | import com.zy.asrs.entity.result.FindLocNoAttributeVo; |
| | | import com.zy.asrs.service.*; |
| | | import com.zy.asrs.utils.Utils; |
| | | import com.zy.common.CodeRes; |
| | | import com.zy.common.model.LocTypeDto; |
| | | import com.zy.common.model.StartupDto; |
| | |
| | | if (Cools.isEmpty(param.getBarcode())) { |
| | | return R.error("条码不能为空"); |
| | | } |
| | | WrkMast wrkMast1 = wrkMastService.selectByBarcode(param.getBarcode()); |
| | | if (!Cools.isEmpty(wrkMast1)&&wrkMast1.getWrkSts()==2) { |
| | | StartupDto dto1 =new StartupDto(); |
| | | dto1.setBarcode(param.getBarcode()); |
| | | dto1.setStaNo(Integer.valueOf(wrkMast1.getStaNo())); |
| | | String wcsLoc = Utils.WMSLocToWCSLoc(wrkMast1.getLocNo()); |
| | | dto1.setLocNo(wcsLoc); |
| | | dto1.setCrnNo(wrkMast1.getCrnNo()); |
| | | dto1.setWorkNo(wrkMast1.getWrkNo()); |
| | | dto1.setTaskNo(wrkMast1.getWrkNo()+""); |
| | | // dto1.setTaskPri((int) Math.round(wrkMast1.getIoPri())); |
| | | return R.ok(dto1); |
| | | } |
| | | List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>().eq("io_type", 1)); |
| | | if (!Cools.isEmpty(wrkMasts)&&wrkMasts.size()>30) { |
| | | return R.error("限行"); |
| | | } |
| | | waitPakins = waitPakinService.selectList(new EntityWrapper<WaitPakin>().eq("zpallet", param.getBarcode())); |
| | | if (Cools.isEmpty(waitPakins)) { |
| | | WrkMast wrkMast = wrkMastService.selectByBarcode(param.getBarcode()); |
| | |
| | | sourceStaNo.setLocType1(param.getLocType1()); |
| | | LocTypeDto locTypeDto = new LocTypeDto(sourceStaNo); |
| | | |
| | | StartupDto dto = null; |
| | | switch (param.getIoType()) { |
| | | case 1://满托盘入库 |
| | | assert waitPakins != null; |
| | | dto = startupFullPutStore(param.getSourceStaNo(), param.getBarcode(), locTypeDto, waitPakins); |
| | | break; |
| | | case 10://空托盘入库 |
| | | dto = emptyPlateIn(param.getSourceStaNo(), locTypeDto, param.getBarcode()); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | StartupDto dto = startupFullPutStore(param.getSourceStaNo(), param.getBarcode(), locTypeDto, waitPakins, param.getRow()); |
| | | log.info("WCS入库接口返参:{},托盘码:{}", dto, param.getBarcode()); |
| | | return R.ok().add(dto); |
| | | } |
| | |
| | | * 全板入库 |
| | | */ |
| | | @Transactional |
| | | public StartupDto startupFullPutStore(Integer devpNo, String barcode, LocTypeDto locTypeDto, List<WaitPakin> waitPakins) { |
| | | public StartupDto startupFullPutStore(Integer devpNo, String barcode, LocTypeDto locTypeDto, List<WaitPakin> waitPakins, List<Integer> recommendRows) { |
| | | // 源站点状态检测 |
| | | BasDevp sourceStaNo = basDevpService.checkSiteStatus(devpNo, true); |
| | | // 检索库位 |
| | |
| | | List<String> batchs = waitPakins.stream().map(WaitPakin::getBatch).distinct().collect(Collectors.toList()); |
| | | FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo(matnrs.get(0), batchs.get(0)); |
| | | // FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo(waitPakins.get(0)); |
| | | StartupDto dto = commonService.getLocNo( 1, devpNo,findLocNoAttributeVo, locTypeDto); |
| | | StartupDto dto = commonService.getLocNo(1, devpNo, findLocNoAttributeVo, locTypeDto, recommendRows); |
| | | int workNo = dto.getWorkNo(); |
| | | Date now = new Date(); |
| | | // 生成工作档 |
| | |
| | | if (!waitPakinService.update(setParam, wrapper)) { |
| | | throw new CoolException("更新通知档失败"); |
| | | } |
| | | // 更新源站点信息 |
| | | sourceStaNo.setWrkNo(workNo); |
| | | sourceStaNo.setModiTime(now); |
| | | if (!basDevpService.updateById(sourceStaNo)){ |
| | | throw new CoolException("更新源站失败"); |
| | | } |
| | | // // 更新源站点信息 |
| | | // sourceStaNo.setWrkNo(workNo); |
| | | // sourceStaNo.setModiTime(now); |
| | | // if (!basDevpService.updateById(sourceStaNo)){ |
| | | // throw new CoolException("更新源站失败"); |
| | | // } |
| | | // 更新目标库位状态 |
| | | LocMast locMast = locMastService.selectById(dto.getLocNo()); |
| | | if (locMast.getLocSts().equals("O")){ |
| | |
| | | } else { |
| | | throw new CoolException(dto.getLocNo()+"目标库位已被占用"); |
| | | } |
| | | String wcsLoc = Utils.WMSLocToWCSLoc(dto.getLocNo()); |
| | | dto.setLocNo(wcsLoc); |
| | | dto.setTaskNo(workNo+""); |
| | | return dto; |
| | | } |
| | | |
| | |
| | | public class SearchLocParam { |
| | | private String barcode; |
| | | private Integer sourceStaNo; |
| | | private List<Integer> rowList; |
| | | private List<Integer> row; |
| | | |
| | | // 库位规格( 0:未知, 1:低库位, 2:高库位) |
| | | private Short locType1; |
| | | |
| | | private Integer ioType; |
| | | private Integer outArea; |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | createOutTask: /openapi/createOutTask |
| | | #移库任务下发地址 |
| | | createLocMoveTask: /openapi/createLocMoveTask |
| | | #pause out task |
| | | stopOutTask: /openapi/stopOutTask |