From f4e85c870c82506e86b60f0f5338d713c9659f80 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Tue, 10 Feb 2026 08:45:00 +0100 Subject: [PATCH] implemented cloning of stock items. NEXT: update of GUI via message bus Signed-off-by: Stephan Richter --- .../umbrella/core/constants/Path.java | 4 ++- .../umbrella/documents/DocumentApi.java | 2 +- frontend/src/routes/stock/ItemProps.svelte | 35 +++++++++++-------- .../umbrella/stock/StockModule.java | 20 ++++++++++- web/src/main/resources/web/css/default.css | 10 ++++++ 5 files changed, 54 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/de/srsoftware/umbrella/core/constants/Path.java b/core/src/main/java/de/srsoftware/umbrella/core/constants/Path.java index decc82f2..853be141 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/constants/Path.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/constants/Path.java @@ -5,8 +5,10 @@ public class Path { private Path(){}; public static final String ADD = "add"; - public static final String AVAILABLE = "available"; + public static final String AVAILABLE = "available"; + public static final String CSS = "css"; + public static final String CLONE = "clone"; public static final String COMMON_TEMPLATES = "common_templates"; public static final String COMPANY = "company"; public static final String CONNECTED = "connected"; diff --git a/documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java b/documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java index 22e152da..2d1901b7 100644 --- a/documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java +++ b/documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java @@ -552,7 +552,7 @@ public class DocumentApi extends BaseHandler implements DocumentService { private boolean postToDocument(HttpExchange ex, de.srsoftware.tools.Path path, UmbrellaUser user, long docId) throws IOException, UmbrellaException { var head = path.pop(); return switch (head){ - case CLONE -> postCloneDoc(docId,ex,user); + case Path.CLONE -> postCloneDoc(docId,ex,user); case POSITION -> postDocumentPosition(docId,ex,user); case PATH_SEND -> sendDocument(ex,path,user,docId); case null, default -> super.doPost(path,ex); diff --git a/frontend/src/routes/stock/ItemProps.svelte b/frontend/src/routes/stock/ItemProps.svelte index a808eaf9..bc2077ba 100644 --- a/frontend/src/routes/stock/ItemProps.svelte +++ b/frontend/src/routes/stock/ItemProps.svelte @@ -1,7 +1,7 @@ {#if item} - patch('name',v)} /> -Code: patch('code',v)} /> + update('name',v)} /> +
{@html item.description.rendered}
+ + + + {#each item.properties.toSorted(byName) as prop}
{t('Code')}: + update('code',v)} /> +
diff --git a/stock/src/main/java/de/srsoftware/umbrella/stock/StockModule.java b/stock/src/main/java/de/srsoftware/umbrella/stock/StockModule.java index bd8d574d..2bf47ebe 100644 --- a/stock/src/main/java/de/srsoftware/umbrella/stock/StockModule.java +++ b/stock/src/main/java/de/srsoftware/umbrella/stock/StockModule.java @@ -27,6 +27,7 @@ import de.srsoftware.umbrella.core.api.Owner; import de.srsoftware.umbrella.core.api.StockService; import de.srsoftware.umbrella.core.constants.Field; import de.srsoftware.umbrella.core.constants.Path; +import de.srsoftware.umbrella.core.constants.Text; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.model.*; import de.srsoftware.umbrella.core.model.Location; @@ -190,6 +191,7 @@ public class StockModule extends BaseHandler implements StockService { if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head) { + case Path.CLONE -> postClone(user.get(),ex); case Path.ITEM -> postItem(user.get(), ex); case LIST -> postItemList(user.get(), path, ex); case Path.LOCATION -> postLocation(user.get(),ex); @@ -285,7 +287,7 @@ public class StockModule extends BaseHandler implements StockService { var json = json(ex); if (!(json.get(ID) instanceof Number id)) throw missingField(ID); json.remove(ID); - + LOG.log(WARNING,"Missing permission check in StockModule.patchItem()!"); var item = stockDb.loadItem(id.longValue()); item.patch(json); return sendContent(ex,stockDb.save(item)); @@ -336,6 +338,21 @@ public class StockModule extends BaseHandler implements StockService { return sendContent(ex,location); } + private boolean postClone(UmbrellaUser user, HttpExchange ex) throws IOException { + var json = json(ex); + if (!json.has(ID))throw missingField(ID); + if (!(json.get(ID) instanceof Number num)) throw invalidField(ID,Text.NUMBER); + long itemId = num.longValue(); + var item = stockDb.loadItem(itemId); + stockDb.loadProperties(item); + var location = item.location().resolve(); + var owner = location.owner().resolve(); + if (!assigned(owner,user)) throw forbidden("You are not allowed to add items to \"{location}\"!", Text.LOCATION,location.name()); + var newItem = new Item(0,owner,0,location,item.code(),item.name(),item.description()); + for (var property : item.properties()) newItem.properties().add(property); + return sendContent(ex,stockDb.save(newItem)); + } + private boolean postItem(UmbrellaUser user, HttpExchange ex) throws IOException { var json = json(ex); if (!json.has(NAME) || !(json.get(NAME) instanceof String name)) throw missingField(NAME); @@ -395,6 +412,7 @@ public class StockModule extends BaseHandler implements StockService { if (!(itemData.get(ID) instanceof Number itemId)) throw missingField(ID); if (!(json.get("add_prop") instanceof JSONObject propData)) throw missingField("add_prop"); if (!propData.has(VALUE)) throw missingField(VALUE); + LOG.log(WARNING,"Missing permission check in StockModule.postProperty()!"); var value = propData.get(VALUE); if (value == null) throw missingField(VALUE); diff --git a/web/src/main/resources/web/css/default.css b/web/src/main/resources/web/css/default.css index 5a402981..e4ca5d87 100644 --- a/web/src/main/resources/web/css/default.css +++ b/web/src/main/resources/web/css/default.css @@ -476,6 +476,16 @@ table{ bottom: 0; } +.properties{ + position: relative; +} + +.properties .clone{ + position: absolute; + right: 10px; + top: 40px; +} + .version > a{ padding: 5px; }