diff --git a/servo/src/main/java/com/galaxis/rcs/common/entity/LccBasLocation.java b/servo/src/main/java/com/galaxis/rcs/common/entity/LccBasLocation.java index 000493c..fe6dbd3 100644 --- a/servo/src/main/java/com/galaxis/rcs/common/entity/LccBasLocation.java +++ b/servo/src/main/java/com/galaxis/rcs/common/entity/LccBasLocation.java @@ -19,6 +19,8 @@ public class LccBasLocation implements Serializable { private String wayPoint; /** 货位相对于路径方向 */ private String locDirection; + /** 楼层数据 */ + private String catalogCode; /** 位置编码 */ private String rack; /** 货架列 */ diff --git a/servo/src/main/java/com/galaxis/rcs/common/entity/LccInvLedger.java b/servo/src/main/java/com/galaxis/rcs/common/entity/LccInvLedger.java index 3a98dbc..fca6c22 100644 --- a/servo/src/main/java/com/galaxis/rcs/common/entity/LccInvLedger.java +++ b/servo/src/main/java/com/galaxis/rcs/common/entity/LccInvLedger.java @@ -21,16 +21,12 @@ public class LccInvLedger implements Serializable { private String ledgerRemark; /** 托盘条码 */ private String lpn; - /** 改变前库存位置 */ - private String locCodeBefore; - /** 改变前堆叠层号从0开始 */ - private Integer layerIndexBefore; - /** 改变前库存数量 */ - private Integer qtyBefore; - /** 改变前入库占用数量 */ - private Integer qtyInBefore; - /** 改变前出库占用数量 */ - private Integer qtyOutBefore; + /** 库存改变数量 */ + private Integer qtyChange; + /** 入库占用改变数量 */ + private Integer qtyInChange; + /** 出库占用改变数量 */ + private Integer qtyOutChange; /** 改变后堆叠层号从0开始 */ private Integer layerIndex; /** 改变前库存位置 */ diff --git a/servo/src/main/java/com/galaxis/rcs/common/query/QLccBasLocation.java b/servo/src/main/java/com/galaxis/rcs/common/query/QLccBasLocation.java index b673c9a..c4a5ce3 100644 --- a/servo/src/main/java/com/galaxis/rcs/common/query/QLccBasLocation.java +++ b/servo/src/main/java/com/galaxis/rcs/common/query/QLccBasLocation.java @@ -26,6 +26,8 @@ public class QLccBasLocation extends RelationalPathBase { public final StringPath wayPoint = createString("wayPoint"); /** 货位相对于路径方向 */ public final StringPath locDirection = createString("locDirection"); + /** 楼层数据 */ + public final StringPath catalogCode = createString("catalogCode"); /** 位置编码 */ public final StringPath rack = createString("rack"); /** 货架列 */ @@ -78,15 +80,16 @@ public class QLccBasLocation extends RelationalPathBase { addMetadata(locType, ColumnMetadata.named("loc_type").withIndex(3).ofType(Types.VARCHAR).withSize(20)); addMetadata(wayPoint, ColumnMetadata.named("way_point").withIndex(4).ofType(Types.VARCHAR).withSize(50)); addMetadata(locDirection, ColumnMetadata.named("loc_direction").withIndex(5).ofType(Types.VARCHAR).withSize(10)); - addMetadata(rack, ColumnMetadata.named("rack").withIndex(6).ofType(Types.VARCHAR).withSize(50)); - addMetadata(bay, ColumnMetadata.named("bay").withIndex(7).ofType(Types.INTEGER).withSize(10)); - addMetadata(level, ColumnMetadata.named("level").withIndex(8).ofType(Types.INTEGER).withSize(10)); - addMetadata(cell, ColumnMetadata.named("cell").withIndex(9).ofType(Types.INTEGER).withSize(10)); - addMetadata(isLock, ColumnMetadata.named("is_lock").withIndex(10).ofType(Types.TINYINT).withSize(3)); - addMetadata(isFrozen, ColumnMetadata.named("is_frozen").withIndex(11).ofType(Types.TINYINT).withSize(3)); - addMetadata(createAt, ColumnMetadata.named("create_at").withIndex(12).ofType(Types.TIMESTAMP)); - addMetadata(createBy, ColumnMetadata.named("create_by").withIndex(13).ofType(Types.VARCHAR).withSize(50)); - addMetadata(updateAt, ColumnMetadata.named("update_at").withIndex(14).ofType(Types.TIMESTAMP)); - addMetadata(updateBy, ColumnMetadata.named("update_by").withIndex(15).ofType(Types.VARCHAR).withSize(50)); + addMetadata(catalogCode, ColumnMetadata.named("catalog_code").withIndex(6).ofType(Types.VARCHAR).withSize(50)); + addMetadata(rack, ColumnMetadata.named("rack").withIndex(7).ofType(Types.VARCHAR).withSize(50)); + addMetadata(bay, ColumnMetadata.named("bay").withIndex(8).ofType(Types.INTEGER).withSize(10)); + addMetadata(level, ColumnMetadata.named("level").withIndex(9).ofType(Types.INTEGER).withSize(10)); + addMetadata(cell, ColumnMetadata.named("cell").withIndex(10).ofType(Types.INTEGER).withSize(10)); + addMetadata(isLock, ColumnMetadata.named("is_lock").withIndex(11).ofType(Types.TINYINT).withSize(3)); + addMetadata(isFrozen, ColumnMetadata.named("is_frozen").withIndex(12).ofType(Types.TINYINT).withSize(3)); + addMetadata(createAt, ColumnMetadata.named("create_at").withIndex(13).ofType(Types.TIMESTAMP)); + addMetadata(createBy, ColumnMetadata.named("create_by").withIndex(14).ofType(Types.VARCHAR).withSize(50)); + addMetadata(updateAt, ColumnMetadata.named("update_at").withIndex(15).ofType(Types.TIMESTAMP)); + addMetadata(updateBy, ColumnMetadata.named("update_by").withIndex(16).ofType(Types.VARCHAR).withSize(50)); } } diff --git a/servo/src/main/java/com/yvan/workbench/controller/LccModelManager.java b/servo/src/main/java/com/yvan/workbench/controller/LccModelManager.java index 6ed4349..3a5c1ab 100644 --- a/servo/src/main/java/com/yvan/workbench/controller/LccModelManager.java +++ b/servo/src/main/java/com/yvan/workbench/controller/LccModelManager.java @@ -1,11 +1,16 @@ package com.yvan.workbench.controller; +import com.galaxis.rcs.common.entity.LccBasLocation; +import com.galaxis.rcs.common.entity.StoreLocation; +import com.galaxis.rcs.ptr.JacksonUtils; import com.yvan.workbench.model.entity.LccModelFloor; import com.yvan.workbench.model.entity.LccModelWorld; import org.apache.commons.lang3.StringUtils; import org.clever.core.Assert; import org.clever.core.Conv; import org.clever.core.id.SnowFlake; +import org.clever.core.json.JsonArrayWrapper; +import org.clever.core.json.JsonWrapper; import org.clever.core.mapper.JacksonMapper; import org.clever.core.model.request.QueryByPage; import org.clever.core.model.request.page.Page; @@ -17,8 +22,12 @@ import org.clever.web.mvc.annotation.RequestBody; import org.clever.web.mvc.annotation.RequestParam; import org.clever.web.mvc.annotation.Transactional; +import java.util.Date; +import java.util.HashMap; +import java.util.List; import java.util.Map; +import static com.galaxis.rcs.common.query.QLccBasLocation.lccBasLocation; import static com.yvan.workbench.model.query.QLccModelFloor.lccModelFloor; import static com.yvan.workbench.model.query.QLccModelWorld.lccModelWorld; @@ -27,60 +36,60 @@ public class LccModelManager { private static String getOtherData(String projectUuid, String projectLabel) { return StringUtils.trim(String.format(""" - { - "project_uuid": "%s", - "project_label": "%s", - "project_version": 0, - "server": "demo", - "Tool": { - "Group": [], - "GlobalVariables": [], - "UserCommand": [], - "Dashboard": [], - "DataTable": [], - "Trigger": [ - { - "name": "OnOpen", - "fn": "" - }, - { - "name": "OnReset", - "fn": "" - }, - { - "name": "OnStart", - "fn": "" - }, - { - "name": "OnStop", - "fn": "" - } - ], - "gridHelper": { - "axesEnabled": true, - "axesSize": 5, - "axesColor": 14540253, - "axesWidth": 2, - "gridEnabled": true, - "gridSize": 1000, - "gridDivisions": 1000, - "gridColor": 14540253, - "gridOpacity": 1, - "backgroundColor": 16119285, - "snapEnabled": true, - "snapDistance": 0.25 - } + { + "project_uuid": "%s", + "project_label": "%s", + "project_version": 0, + "server": "demo", + "Tool": { + "Group": [], + "GlobalVariables": [], + "UserCommand": [], + "Dashboard": [], + "DataTable": [], + "Trigger": [ + { + "name": "OnOpen", + "fn": "" + }, + { + "name": "OnReset", + "fn": "" + }, + { + "name": "OnStart", + "fn": "" }, - "elevator": [], - "wall": [], - "pillar": [] - }""".stripIndent(), projectUuid, projectLabel)); + { + "name": "OnStop", + "fn": "" + } + ], + "gridHelper": { + "axesEnabled": true, + "axesSize": 5, + "axesColor": 14540253, + "axesWidth": 2, + "gridEnabled": true, + "gridSize": 1000, + "gridDivisions": 1000, + "gridColor": 14540253, + "gridOpacity": 1, + "backgroundColor": 16119285, + "snapEnabled": true, + "snapDistance": 0.25 + } + }, + "elevator": [], + "wall": [], + "pillar": [] + }""".stripIndent(), projectUuid, projectLabel)); } public static Page projectList() { return QueryDslUtils.queryByPage( - QUERY_DSL.selectFrom(lccModelWorld), - QueryByPage.getCurrent() + QUERY_DSL.selectFrom(lccModelWorld), + QueryByPage.getCurrent() ); } @@ -89,24 +98,24 @@ public class LccModelManager { Assert.isNotBlank(project.getProjectUuid(), "项目编号必填"); Assert.isNotBlank(project.getProjectLabel(), "项目标题必填"); Assert.isTrue( - QUERY_DSL.selectFrom(lccModelWorld).where(lccModelWorld.projectUuid.eq(project.getProjectUuid())).fetchCount() <= 0, - "项目编号重复" + QUERY_DSL.selectFrom(lccModelWorld).where(lccModelWorld.projectUuid.eq(project.getProjectUuid())).fetchCount() <= 0, + "项目编号重复" ); project.setProjectVersion(1L); project.setId(SnowFlake.SNOW_FLAKE.nextId()); project.setDirectoryData(""" - [ + [ + { + "label": "仓库楼层", + "items": [ { - "label": "仓库楼层", - "items": [ - { - "catalogCode": "f1", - "label": "一楼 (f1)" - } - ] + "catalogCode": "f1", + "label": "一楼 (f1)" } ] - """.stripIndent()); + } + ] + """.stripIndent()); project.setOtherData(getOtherData(project.getProjectUuid(), project.getProjectLabel())); QUERY_DSL.insert(lccModelWorld).populate(project).execute(); return QUERY_DSL.selectFrom(lccModelWorld).where(lccModelWorld.id.eq(project.getId())).fetchOne(); @@ -116,16 +125,16 @@ public class LccModelManager { public static R addOrUpdateWorld(@RequestBody LccModelWorld params) { Assert.isNotBlank(params.getProjectUuid(), "项目编号必填"); long count = QUERY_DSL.selectFrom(lccModelWorld) - .where(lccModelWorld.projectUuid.eq(params.getProjectUuid())) - .where(lccModelWorld.projectVersion.eq(1L)) - .fetchCount(); + .where(lccModelWorld.projectUuid.eq(params.getProjectUuid())) + .where(lccModelWorld.projectVersion.eq(1L)) + .fetchCount(); if (count >= 1) { QUERY_DSL.update(lccModelWorld) - .set(lccModelWorld.otherData, params.getOtherData()) - .set(lccModelWorld.directoryData, params.getDirectoryData()) - .where(lccModelWorld.projectUuid.eq(params.getProjectUuid())) - .where(lccModelWorld.projectVersion.eq(1L)) - .execute(); + .set(lccModelWorld.otherData, params.getOtherData()) + .set(lccModelWorld.directoryData, params.getDirectoryData()) + .where(lccModelWorld.projectUuid.eq(params.getProjectUuid())) + .where(lccModelWorld.projectVersion.eq(1L)) + .execute(); } else { //noinspection unchecked Map map = JacksonMapper.getInstance().fromJson(params.getOtherData(), Map.class); @@ -143,35 +152,232 @@ public class LccModelManager { String catalogCode = Conv.asString(params.get("catalogCode")); String project_uuid = Conv.asString(params.get("project_uuid")); return QUERY_DSL.selectFrom(lccModelFloor) - .where(lccModelFloor.projectUuid.eq(project_uuid)) - .where(lccModelFloor.catalogCode.eq(catalogCode)) - .orderBy(lccModelFloor.projectVersion.desc()) - .fetchFirst(); + .where(lccModelFloor.projectUuid.eq(project_uuid)) + .where(lccModelFloor.catalogCode.eq(catalogCode)) + .orderBy(lccModelFloor.projectVersion.desc()) + .fetchFirst(); } @Transactional public static R addOrUpdateFloor(@RequestBody LccModelFloor params) { Assert.isNotBlank(params.getProjectUuid(), "项目编号必填"); Assert.isNotBlank(params.getCatalogCode(), "楼层编号必填"); + Assert.notNull(params.getEnvId(), "环境编号必填"); Assert.isNotBlank(params.getItems(), "楼层数据必填"); + if (params.getEnvId() == null || params.getEnvId() <= 0) { + throw new RuntimeException("环境编号必填"); + } long count = QUERY_DSL.selectFrom(lccModelFloor) - .where(lccModelFloor.projectUuid.eq(params.getProjectUuid())) - .where(lccModelFloor.projectVersion.eq(1L)) - .where(lccModelFloor.catalogCode.eq(params.getCatalogCode())) - .fetchCount(); + .where(lccModelFloor.projectUuid.eq(params.getProjectUuid())) + .where(lccModelFloor.envId.eq(params.getEnvId())) + .where(lccModelFloor.catalogCode.eq(params.getCatalogCode())) + .fetchCount(); + if (count >= 1) { QUERY_DSL.update(lccModelFloor) - .set(lccModelFloor.items, params.getItems()) - .where(lccModelFloor.projectUuid.eq(params.getProjectUuid())) - .where(lccModelFloor.projectVersion.eq(1L)) - .where(lccModelFloor.catalogCode.eq(params.getCatalogCode())) - .execute(); + .set(lccModelFloor.items, params.getItems()) + .set(lccModelFloor.projectVersion, lccModelFloor.projectVersion.add(1L)) + .where(lccModelFloor.projectUuid.eq(params.getProjectUuid())) + .where(lccModelFloor.envId.eq(params.getEnvId())) + .where(lccModelFloor.catalogCode.eq(params.getCatalogCode())) + .execute(); } else { params.setId(SnowFlake.SNOW_FLAKE.nextId()); params.setProjectVersion(1L); // params.setCreateBy(); QUERY_DSL.insert(lccModelFloor).populate(params).execute(); } + + batchSaveBasLocation(params); + return R.success(); } + + /** + * 保存库存货位数据 + */ + private static void batchSaveBasLocation(LccModelFloor params) { + // 删除旧的楼层数据 + QUERY_DSL.delete(lccBasLocation) + .where(lccBasLocation.envId.eq(params.getEnvId())) + .where(lccBasLocation.catalogCode.eq(params.getCatalogCode())) + .execute(); + + // ================================== 从 params.items 中解析出货位数据 + var items = JacksonUtils.parseList(params.getItems(), HashMap.class); + var storeMap = new HashMap(); + for (Map item : items) { + String type = Conv.asString(item.get("t")); + String id = Conv.asString(item.get("id")); + if ("rack".equals(type)) { + // 循环 bays / levelHeight 生成存储位 + List> bays = (List>) (((Map) item.get("dt")).get("bays")); + int bayIndex = 0; + for (Map bay : bays) { + List levelHeight = (List) bay.get("levelHeight"); + for (int level = 0; level < levelHeight.size(); level++) { + // 生成存储位 + var storeLoc = new StoreLocation(id, bayIndex, level, 0); + LccBasLocation basLocation = new LccBasLocation(); + storeMap.put(storeLoc.toString(), basLocation); + basLocation.setLocCode(storeLoc.toString()); + basLocation.setLocType(type); + basLocation.setWayPoint("N/A"); + basLocation.setLocDirection("N/A"); + basLocation.setRack(id); + basLocation.setBay(bayIndex); + basLocation.setLevel(level); + } + bayIndex++; + } + + } else if ("gstore".equals(type)) { + // 地堆存储位只有一个格子 + var storeLoc = new StoreLocation(id, 0, 0, 0); + LccBasLocation basLocation = new LccBasLocation(); + storeMap.put(storeLoc.toString(), basLocation); + basLocation.setLocCode(storeLoc.toString()); + basLocation.setLocType(type); + basLocation.setWayPoint("N/A"); + basLocation.setLocDirection("N/A"); + basLocation.setRack(id); + basLocation.setBay(0); + basLocation.setLevel(0); + } + } + + // ================================== 从 params.items 中解析出地标连接数据 + for (Map item : items) { + String type = Conv.asString(item.get("t")); + String id = Conv.asString(item.get("id")); + if (!"way".equals(type)) { + continue; + } + + // 解析 linkStore 数据 + List> linkStore = (List>) (((Map) item.get("dt")).get("linkStore")); + if (linkStore != null) { + for (Map link : linkStore) { + String rackId = Conv.asString(link.get("item")); + int bay = Conv.asInteger(link.get("bay")); + int level = Conv.asInteger(link.get("level")); + int cell = Conv.asInteger(link.get("cell")); + String direction = Conv.asString(link.get("direction")); + + // 生成存储位 + var storeLoc = new StoreLocation(rackId, bay, level, cell); + LccBasLocation basLocation = storeMap.get(storeLoc.toString()); + if (basLocation != null) { + basLocation.setWayPoint(id); + basLocation.setLocDirection(direction); + } + } + } + } + + // 全部写进数据库 + var action = QUERY_DSL.insert(lccBasLocation); + for (LccBasLocation basLocation : storeMap.values()) { + basLocation.setEnvId(params.getEnvId()); + basLocation.setCatalogCode(params.getCatalogCode()); + basLocation.setCell(0); + basLocation.setIsLock(0); + basLocation.setIsFrozen(0); + basLocation.setUpdateAt(new Date()); + basLocation.setCreateAt(new Date()); + basLocation.setCreateBy("yvan"); + basLocation.setUpdateBy("yvan"); + action.populate(basLocation).addBatch(); + } + if (action.getBatchCount() > 0) { + action.execute(); + } + + // ================= JSON 结构 + /* +提取货架信息: +1. t=rack 的情况下,读取 bays 数组,并且枚举里面的 levelHeight 数组,按数量生成 loc_code + +{ + "id": "rack1", + "t": "rack", + "v": true, + "dt": { + "bays": [ + { "levelHeight": [ 0.001, 1.21 ], }, + { "levelHeight": [ 0.001, 1.21 ], } + ], + }, +} + +2. t=gstore 的情况下 +{ + "id": "105_105", + "t": "gstore", +} + +提取路标信息 +{ + "id": "1_2", + "t": "way", + "dt": { + "linkStore": [ + { + "item": "rack1", + "bay": 0, "level": 0, "cell": 0, "direction": "up" + }, + { + "item": "rack1", + "bay": 0, "level": 1, "cell": 0, "direction": "up" + } + ] + } +} +{ + "id": "1_2", + "t": "way", + "dt": { + "linkStore": [ + { + "item": "rack1", + "bay": 0, "level": 0, "cell": 0, "direction": "up" + }, + { + "item": "rack1", + "bay": 0, "level": 1, "cell": 0, "direction": "up" + } + ] + } +} +{ + "id": "4_2", + "t": "way", + "dt": { + "linkStore": [ + { + "item": "105_105", + "bay": 0, + "level": 0, + "cell": 0, + "direction": "down" + } + ] + } +} +生成实体 + LccBasLocation basLocation = new LccBasLocation(); + basLocation.setEnvId(params.getEnvId()); + basLocation.setCatalogCode(params.getCatalogCode()); + basLocation.setLocType("t"); + basLocation.setWayPoint("way.id"); + basLocation.setLocDirection("linkStore.direction"); + basLocation.setRack("rack.id"); + basLocation.setBay("rack.id"); + basLocation.setLevel("rack.id"); + basLocation.setCell("rack.id"); + basLocation.setIsLock(0); + basLocation.setIsFrozen(0); + */ + + } } diff --git a/servo/src/main/java/com/yvan/workbench/model/entity/LccModelFloor.java b/servo/src/main/java/com/yvan/workbench/model/entity/LccModelFloor.java index 0903212..715d090 100644 --- a/servo/src/main/java/com/yvan/workbench/model/entity/LccModelFloor.java +++ b/servo/src/main/java/com/yvan/workbench/model/entity/LccModelFloor.java @@ -15,6 +15,8 @@ public class LccModelFloor implements Serializable { private String projectUuid; /** 项目版本 */ private Long projectVersion; + /** 环境ID */ + private Long envId; /** 楼层编号 */ private String catalogCode; /** 楼层数据 */