diff --git a/servo/src/main/java/com/yvan/entity/InvUpdateVo.java b/servo/src/main/java/com/yvan/entity/InvUpdateVo.java new file mode 100644 index 0000000..965ac08 --- /dev/null +++ b/servo/src/main/java/com/yvan/entity/InvUpdateVo.java @@ -0,0 +1,9 @@ +package com.yvan.entity; + +public record InvUpdateVo( + String lpn, + BasLocationVo before, + BasLocationVo after, + int qty +) { +} diff --git a/servo/src/main/java/com/yvan/pusher/FrontendMessagePushService.java b/servo/src/main/java/com/yvan/pusher/FrontendMessagePushService.java index 0133420..be942ff 100644 --- a/servo/src/main/java/com/yvan/pusher/FrontendMessagePushService.java +++ b/servo/src/main/java/com/yvan/pusher/FrontendMessagePushService.java @@ -2,6 +2,7 @@ package com.yvan.pusher; import com.yvan.entity.AgvStatusVo; import com.yvan.entity.BasLocationVo; +import com.yvan.entity.InvUpdateVo; import com.yvan.entity.ServerStatusVo; import com.yvan.logisticsEnv.EnvConfig; import com.yvan.logisticsModel.LogisticsRuntime; @@ -174,17 +175,17 @@ public class FrontendMessagePushService implements MqttCallback { * @param lpn 容器号 * @param before 更新前库存 * @param after 更新后库存 + * @param qty 更新数量 */ public void pushInvUpdate(String lpn, BasLocationVo before, BasLocationVo after, int qty) { String topic = buildTopic("inv"); - Map data = new HashMap<>(); - data.put("lpn", lpn); - data.put("before", before); - data.put("after", after); - data.put("qty", qty); - - publishJson(topic, data); + publishJson(topic, new InvUpdateVo( + lpn, + before, + after, + qty + )); } /** diff --git a/servo/src/main/java/com/yvan/workbench/controller/InvController.java b/servo/src/main/java/com/yvan/workbench/controller/InvController.java new file mode 100644 index 0000000..e9d3994 --- /dev/null +++ b/servo/src/main/java/com/yvan/workbench/controller/InvController.java @@ -0,0 +1,286 @@ +package com.yvan.workbench.controller; + +import com.galaxis.rcs.common.entity.LccBasLocation; +import com.galaxis.rcs.common.entity.StoreLocation; +import com.galaxis.rcs.inv.InvManager; +import com.google.common.base.Strings; +import com.yvan.entity.BasLocationVo; +import com.yvan.logisticsModel.LogisticsRuntime; +import com.yvan.logisticsModel.LogisticsRuntimeService; +import org.clever.core.Conv; +import org.clever.core.model.response.R; +import org.clever.data.jdbc.DaoFactory; +import org.clever.data.jdbc.QueryDSL; +import org.clever.data.jdbc.querydsl.utils.QueryDslUtils; +import org.clever.web.mvc.annotation.RequestBody; + +import java.sql.Date; +import java.util.Map; + +import static com.galaxis.rcs.common.query.QLccBasContainer.lccBasContainer; +import static com.galaxis.rcs.common.query.QLccBasLocation.lccBasLocation; +import static com.galaxis.rcs.common.query.QLccInvLedger.lccInvLedger; +import static com.galaxis.rcs.common.query.QLccInvLpn.lccInvLpn; + +public class InvController { + static final QueryDSL queryDSL = DaoFactory.getQueryDSL(); + + public static R createInv(@RequestBody Map params) { + String projectUuid = Conv.asString(params.get("projectUUID")); + Long envId = Conv.asLong(params.get("envId")); + int qty = 1; + + if (Strings.isNullOrEmpty(projectUuid)) { + return R.fail("projectUUID must not be null"); + } + if (envId == null || envId <= 0) { + return R.fail("envId must not be null"); + } + + // =============== 校验目标存储位置 =============== + String targetStore = Conv.asString(params.get("targetStore")); + if (Strings.isNullOrEmpty(targetStore)) { + return R.fail("targetStore must not be null"); + } + + StoreLocation targetLocation = StoreLocation.of(targetStore, "/"); + LccBasLocation basLocation = queryDSL.selectFrom( + lccBasLocation + ) + .where(lccBasLocation.envId.eq(envId)) + .where(lccBasLocation.rack.eq(targetLocation.rackId())) + .where(lccBasLocation.bay.eq(targetLocation.bay())) + .where(lccBasLocation.level.eq(targetLocation.level())) + .where(lccBasLocation.cell.eq(targetLocation.cell())) + .fetchFirst(); + if (basLocation == null) { + return R.fail("targetStoreLoc location not found!"); + } + + // =============== 校验LPN =============== + String lpn = Conv.asString(params.get("lpn")); + if (Strings.isNullOrEmpty(lpn)) { + return R.fail("lpn must not be null"); + } + long lpnExists = queryDSL.selectFrom(lccBasContainer) + .where(lccBasContainer.lpn.eq(lpn)) + .where(lccBasContainer.envId.eq(envId)) + .fetchCount(); + if (lpnExists <= 0) { + // 插入容器表 + queryDSL.insert(lccBasContainer) + .set(lccBasContainer.envId, envId) + .set(lccBasContainer.lpn, lpn) + .set(lccBasContainer.containerType, "pallet") + .set(lccBasContainer.isActive, true) + .set(lccBasContainer.createAt, new Date(System.currentTimeMillis())) + .set(lccBasContainer.createBy, "api") + .set(lccBasContainer.updateAt, new Date(System.currentTimeMillis())) + .set(lccBasContainer.updateBy, "api") + .execute(); + } + + // =============== 查询是否重复 =============== + long invCount = queryDSL.selectFrom(lccInvLpn) + .where(lccInvLpn.lpn.eq(lpn)) + .where(lccInvLpn.envId.eq(envId)) + .fetchCount(); + if (invCount > 0) { + return R.fail("LPN already exists in inventory"); + } + + // =============== 创建库存 =============== + InvManager.invSave(envId, 0L, lpn, basLocation.getLocCode(), qty); + + // 推送前端更新 + LogisticsRuntime runtime = LogisticsRuntimeService.INSTANCE.getByProjectEnv(projectUuid, envId); + if (runtime != null) { + runtime.frontendMessagePushService.pushInvUpdate( + lpn, null, new BasLocationVo(basLocation), qty + ); + } + + return R.success("Inventory created successfully"); + } + + public static R deleteInv(@RequestBody Map params) { + String projectUuid = Conv.asString(params.get("projectUUID")); + Long envId = Conv.asLong(params.get("envId")); + + if (Strings.isNullOrEmpty(projectUuid)) { + return R.fail("projectUUID must not be null"); + } + if (envId == null || envId <= 0) { + return R.fail("envId must not be null"); + } + + // =============== 校验LPN =============== + String lpn = Conv.asString(params.get("lpn")); + if (Strings.isNullOrEmpty(lpn)) { + return R.fail("lpn must not be null"); + } + long lpnExists = queryDSL.selectFrom(lccBasContainer) + .where(lccBasContainer.lpn.eq(lpn)) + .where(lccBasContainer.envId.eq(envId)) + .fetchCount(); + if (lpnExists <= 0) { + return R.fail("LPN does not exist in BasContainer"); + } + + // =============== 校验库存 =============== + var inv = queryDSL.selectFrom(lccInvLpn) + .where(lccInvLpn.lpn.eq(lpn)) + .where(lccInvLpn.envId.eq(envId)) + .fetchFirst(); + if (inv == null) { + return R.fail("LPN does not exist in InvLpn"); + } + LccBasLocation basLocation = queryDSL.selectFrom( + lccBasLocation + ) + .where(lccBasLocation.envId.eq(envId)) + .where(lccBasLocation.locCode.eq(inv.getLocCode())) + .fetchFirst(); + if (basLocation == null) { + return R.fail("BasLocation not found:" + inv.getLocCode()); + } + + // 删除库存记录 + InvManager.invSave(envId, 0L, lpn, basLocation.getLocCode(), -inv.getQty()); + + // 推送前端更新 + LogisticsRuntime runtime = LogisticsRuntimeService.INSTANCE.getByProjectEnv(projectUuid, envId); + if (runtime != null) { + runtime.frontendMessagePushService.pushInvUpdate( + lpn, new BasLocationVo(basLocation), null, -inv.getQty() + ); + } + + return R.success("Inventory deleted successfully"); + } + + public static R moveInv(@RequestBody Map params) { + String projectUuid = Conv.asString(params.get("projectUUID")); + Long envId = Conv.asLong(params.get("envId")); + + if (Strings.isNullOrEmpty(projectUuid)) { + return R.fail("projectUUID must not be null"); + } + if (envId == null || envId <= 0) { + return R.fail("envId must not be null"); + } + + // =============== 校验LPN =============== + String lpn = Conv.asString(params.get("lpn")); + if (Strings.isNullOrEmpty(lpn)) { + return R.fail("lpn must not be null"); + } + long lpnExists = queryDSL.selectFrom(lccBasContainer) + .where(lccBasContainer.lpn.eq(lpn)) + .where(lccBasContainer.envId.eq(envId)) + .fetchCount(); + if (lpnExists <= 0) { + return R.fail("LPN does not exist in BasContainer"); + } + + // =============== 查询库存记录 =============== + var inv = queryDSL.selectFrom(lccInvLpn) + .where(lccInvLpn.lpn.eq(lpn)) + .where(lccInvLpn.envId.eq(envId)) + .fetchFirst(); + if (inv == null) { + return R.fail("LPN does not exist in InvLpn"); + } + + // =============== 校验源位置 =============== + LccBasLocation sourceLocation = queryDSL.selectFrom( + lccBasLocation + ) + .where(lccBasLocation.envId.eq(envId)) + .where(lccBasLocation.locCode.eq(inv.getLocCode())) + .fetchFirst(); + if (sourceLocation == null) { + return R.fail("BasLocation not found for locCode: " + inv.getLocCode()); + } + + // =============== 校验目标存储位置 =============== + String targetStore = Conv.asString(params.get("targetStore")); + if (Strings.isNullOrEmpty(targetStore)) { + return R.fail("targetStore must not be null"); + } + + StoreLocation targetLocation = StoreLocation.of(targetStore, "/"); + LccBasLocation basLocation = queryDSL.selectFrom( + lccBasLocation + ) + .where(lccBasLocation.envId.eq(envId)) + .where(lccBasLocation.rack.eq(targetLocation.rackId())) + .where(lccBasLocation.bay.eq(targetLocation.bay())) + .where(lccBasLocation.level.eq(targetLocation.level())) + .where(lccBasLocation.cell.eq(targetLocation.cell())) + .fetchFirst(); + if (basLocation == null) { + return R.fail("targetStoreLoc location not found!"); + } + + // 更新库存记录 + queryDSL.beginTX(status -> { + InvManager.invSave(envId, 0L, lpn, sourceLocation.getLocCode(), -inv.getQty()); + InvManager.invSave(envId, 0L, lpn, basLocation.getLocCode(), inv.getQty()); + }); + // 推送前端更新 + LogisticsRuntime runtime = LogisticsRuntimeService.INSTANCE.getByProjectEnv(projectUuid, envId); + if (runtime != null) { + runtime.frontendMessagePushService.pushInvUpdate( + lpn, new BasLocationVo(sourceLocation), new BasLocationVo(basLocation), inv.getQty() + ); + } + + return R.success("Inventory moved successfully"); + } + + public static R loadInv(@RequestBody Map params) { + String projectUuid = Conv.asString(params.get("projectUUID")); + Long envId = Conv.asLong(params.get("envId")); + + if (Strings.isNullOrEmpty(projectUuid)) { + return R.fail("projectUUID must not be null"); + } + if (envId == null || envId <= 0) { + return R.fail("envId must not be null"); + } + + String catalogCode = Conv.asString(params.get("catalogCode")); + + var selectAction = queryDSL.select(QueryDslUtils.linkedMap( + lccInvLpn.lpn, + lccBasContainer.containerType, + lccInvLpn.locCode, + lccBasLocation.rack, + lccBasLocation.bay, + lccBasLocation.level, + lccBasLocation.cell + )) + .from(lccInvLpn) + .innerJoin(lccBasLocation).on( + lccInvLpn.locCode.eq(lccBasLocation.locCode).and( + lccInvLpn.envId.eq(lccBasLocation.envId) + ) + ) + .innerJoin(lccBasContainer).on( + lccInvLpn.lpn.eq(lccBasContainer.lpn).and( + lccInvLpn.envId.eq(lccBasContainer.envId) + ) + ) + .where(lccInvLpn.envId.eq(envId)); + + if (!Strings.isNullOrEmpty(catalogCode)) { + selectAction.where(lccBasLocation.catalogCode.eq(catalogCode)); + } + + var list = selectAction.fetch(); + + return R.success(list); + } + +} diff --git a/servo/src/main/java/com/yvan/workbench/controller/LccController.java b/servo/src/main/java/com/yvan/workbench/controller/LccController.java index 546fb29..fa1d725 100644 --- a/servo/src/main/java/com/yvan/workbench/controller/LccController.java +++ b/servo/src/main/java/com/yvan/workbench/controller/LccController.java @@ -30,66 +30,6 @@ import static com.galaxis.rcs.common.query.QLccInvLpn.lccInvLpn; public class LccController { static final QueryDSL queryDSL = DaoFactory.getQueryDSL(); - public static R loadInv(@RequestBody Map params) { - String catalogCode = Conv.asString(params.get("catalogCode")); - Long envId = Conv.asLong(params.get("envId")); - - if (envId == null) { - return R.fail("envId must not be null"); - } - - var selectAction = queryDSL.select(QueryDslUtils.linkedMap( - lccInvLpn.lpn, - lccBasContainer.containerType, - lccInvLpn.locCode, - lccBasLocation.rack, - lccBasLocation.bay, - lccBasLocation.level, - lccBasLocation.cell - )) - .from(lccInvLpn) - .innerJoin(lccBasLocation).on( - lccInvLpn.locCode.eq(lccBasLocation.locCode).and( - lccInvLpn.envId.eq(lccBasLocation.envId) - ) - ) - .innerJoin(lccBasContainer).on( - lccInvLpn.lpn.eq(lccBasContainer.lpn).and( - lccInvLpn.envId.eq(lccBasContainer.envId) - ) - ) - .where(lccInvLpn.envId.eq(envId)); - - if (!Strings.isNullOrEmpty(catalogCode)) { - selectAction.where(lccBasLocation.catalogCode.eq(catalogCode)); - } - - var list = selectAction.fetch(); - - return R.success(list); - } - - // public static R loadExecutor(@RequestBody Map params) { - // Long envId = Conv.asLong(params.get("envId")); - // - // if (envId == null) { - // return R.fail("envId must not be null"); - // } - // - // var list = queryDSL.select(QueryDslUtils.linkedMap( - // lccBasExecutor.executorId, - // lccBasExecutor.virtualFloorCode, - // lccBasExecutor.virtualLocationAt, - // lccBasExecutor.virtualExecutorPayload - // )) - // .from(lccBasExecutor) - // .where(lccBasExecutor.envId.eq(envId)) - // .where(lccBasExecutor.isActive.eq(true)) - // .fetch(); - // - // return R.success(list); - // } - public static R queryDeviceInfoList(@RequestBody Map params) { String projectUuid = Conv.asString(params.get("projectUUID")); Long envId = Conv.asLong(params.get("envId"));