From 6e9a2b6acaf948a85ad7b048662ebe83315039a1 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Mon, 13 Oct 2025 21:57:50 +0200 Subject: [PATCH] working on loading items for location --- .../srsoftware/umbrella/core/Constants.java | 7 +++ .../srsoftware/umbrella/core/model/Item.java | 47 +++++++++++++++++-- .../umbrella/core/model/Location.java | 5 ++ .../umbrella/core/model/Property.java | 19 +++++++- frontend/src/routes/stock/Index.svelte | 23 ++++++++- frontend/src/routes/stock/Locations.svelte | 5 +- .../srsoftware/umbrella/stock/Constants.java | 2 + .../srsoftware/umbrella/stock/SqliteDb.java | 34 ++++++++++++++ .../srsoftware/umbrella/stock/StockApi.java | 15 +++++- .../de/srsoftware/umbrella/stock/StockDb.java | 2 + 10 files changed, 151 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/de/srsoftware/umbrella/core/Constants.java b/core/src/main/java/de/srsoftware/umbrella/core/Constants.java index 21b27b1..1410100 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/Constants.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/Constants.java @@ -9,6 +9,9 @@ public class Constants { private Constants(){} + + + public static final String ADDRESS = "address"; public static final String ALLOWED_STATES = "allowed_states"; public static final String ATTACHMENTS = "attachments"; @@ -117,6 +120,7 @@ public class Constants { public static final String LANGUAGE = "language"; public static final String LAST_CUSTOMER_NUMBER = "last_customer_number"; public static final String LIMIT = "limit"; + public static final String LOCATION = "location"; public static final String LOCATION_ID = "location_id"; public static final String LOGIN = "login"; @@ -144,7 +148,10 @@ public class Constants { public static final String PRIORITY = "priority"; public static final String PROJECT = "project"; public static final String PROJECT_ID = "project_id"; + public static final String PROPERTIES = "properties"; + public static final String QUANTITY = "quantity"; + public static final String RECEIVERS = "receivers"; public static final String REDIRECT = "redirect"; public static final String RENDERED = "rendered"; diff --git a/core/src/main/java/de/srsoftware/umbrella/core/model/Item.java b/core/src/main/java/de/srsoftware/umbrella/core/model/Item.java index 1cdc3a1..242e01c 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/model/Item.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/model/Item.java @@ -1,12 +1,53 @@ /* © SRSoftware 2025 */ package de.srsoftware.umbrella.core.model; +import de.srsoftware.tools.Mappable; + +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.Collection; +import java.util.HashSet; +import java.util.Map; + +import static de.srsoftware.umbrella.core.Constants.*; -public class Item { +public class Item implements Mappable { private long id; - private String code; - private boolean physical; + private Mappable owner; + private String code, name; private Location location; private Collection properties; + + private Item(Mappable owner, long id, Location location, String code, String name) { + this.owner = owner; + this.id = id; + this.location = location; + this.code = code; + this.name = name; + this.properties = new HashSet<>(); + } + + public static Item of(ResultSet rs, Mappable owner, Location location) throws SQLException { + var id = rs.getLong(ID); + var code = rs.getString(CODE); + var name = rs.getString(NAME); + return new Item(owner, id, location, code, name); + } + + @Override + public Map toMap() { + return Map.of( + OWNER, owner.toMap(), + ID, id, + LOCATION, location.toMap(), + CODE, code, + NAME, name, + PROPERTIES, properties.stream().map(Property::toMap).toList() + ); + } + + @Override + public String toString() { + return name; + } } diff --git a/core/src/main/java/de/srsoftware/umbrella/core/model/Location.java b/core/src/main/java/de/srsoftware/umbrella/core/model/Location.java index 0dab814..2a5ed7e 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/model/Location.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/model/Location.java @@ -64,4 +64,9 @@ public class Location implements Mappable { NAME,name, DESCRIPTION,description); } + + @Override + public String toString() { + return name; + } } diff --git a/core/src/main/java/de/srsoftware/umbrella/core/model/Property.java b/core/src/main/java/de/srsoftware/umbrella/core/model/Property.java index bede457..d592f48 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/model/Property.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/model/Property.java @@ -1,10 +1,27 @@ /* © SRSoftware 2025 */ package de.srsoftware.umbrella.core.model; -public class Property { +import de.srsoftware.tools.Mappable; + +import java.util.Map; + +import static de.srsoftware.umbrella.core.Constants.*; + +public class Property implements Mappable { long id; String name; Object value; String unit; String quantity; + + @Override + public Map toMap() { + return Map.of( + ID, id, + NAME, name, + VALUE, value, + UNIT, unit, + QUANTITY, quantity + ); + } } diff --git a/frontend/src/routes/stock/Index.svelte b/frontend/src/routes/stock/Index.svelte index 86214a8..8db3959 100644 --- a/frontend/src/routes/stock/Index.svelte +++ b/frontend/src/routes/stock/Index.svelte @@ -10,6 +10,21 @@ let top_level = $state(null); + let selected = $state(null); + let items = $derived(loadItems(selected)); + + async function loadItems(loc){ + if (!loc) return null; + const url = api(`stock/items_at/${loc.id}`) + const res = await fetch(url,{credentials:'include'}); + if (res.ok){ + yikes(); + return loc.name; + } else { + error(res); + return null; + } + } async function load(){ const url = api('stock/locations/of_user') @@ -32,12 +47,18 @@ {#each top_level as realm,idx}

{realm.name}

{#if realm.locations} - + {/if} {/each} {/if} + {#if selected} +

{selected.name}

+ {/if} + {#if items} +
{JSON.stringify(items)}
+ {/if} diff --git a/frontend/src/routes/stock/Locations.svelte b/frontend/src/routes/stock/Locations.svelte index 5a8567d..2dee340 100644 --- a/frontend/src/routes/stock/Locations.svelte +++ b/frontend/src/routes/stock/Locations.svelte @@ -3,11 +3,12 @@ import { error, yikes } from '../../warn.svelte'; import { t } from '../../translations.svelte'; - let { locations } = $props(); + let { locations, selected = $bindable(null) } = $props(); async function toggleChildren(ev, location){ ev.preventDefault(); ev.stopPropagation(); + selected = location; if (location.locations) { delete location.locations; } else { @@ -32,7 +33,7 @@
  • toggleChildren(e, location)} class={location.locations?'expanded':'collapsed'}> {location.name} {#if location.locations} - + {/if}
  • {/each} diff --git a/stock/src/main/java/de/srsoftware/umbrella/stock/Constants.java b/stock/src/main/java/de/srsoftware/umbrella/stock/Constants.java index d2e126c..035aca9 100644 --- a/stock/src/main/java/de/srsoftware/umbrella/stock/Constants.java +++ b/stock/src/main/java/de/srsoftware/umbrella/stock/Constants.java @@ -5,9 +5,11 @@ public class Constants { private Constants(){} + public static final String BELOW = "below"; public static final String CONFIG_DATABASE = "umbrella.modules.stock.database"; public static final String ITEM_ID = "item_id"; + public static final String ITEMS_AT = "items_at"; public static final String LOCATIONS = "locations"; public static final String OF_USER = "of_user"; public static final String PROPERTY_ID = "prop_id"; diff --git a/stock/src/main/java/de/srsoftware/umbrella/stock/SqliteDb.java b/stock/src/main/java/de/srsoftware/umbrella/stock/SqliteDb.java index f677f7b..29419a1 100644 --- a/stock/src/main/java/de/srsoftware/umbrella/stock/SqliteDb.java +++ b/stock/src/main/java/de/srsoftware/umbrella/stock/SqliteDb.java @@ -13,7 +13,9 @@ import static java.lang.System.Logger.Level.ERROR; import static java.lang.System.Logger.Level.WARNING; import static java.text.MessageFormat.format; +import de.srsoftware.tools.Mappable; import de.srsoftware.umbrella.core.BaseDb; +import de.srsoftware.umbrella.core.ModuleRegistry; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.model.Company; import de.srsoftware.umbrella.core.model.Item; @@ -139,6 +141,38 @@ public class SqliteDb extends BaseDb implements StockDb { return List.of(); } + @Override + public Collection listItemsAt(long locationId) { + try { + var rs = select(ALL).from(TABLE_ITEMS).where(LOCATION_ID,equal(locationId)).exec(db); + var list = new ArrayList(); + + while (rs.next()) { + var ownerId = rs.getLong(OWNER); + Mappable owner = ownerId < 0 ? ModuleRegistry.companyService().get(-ownerId) : ModuleRegistry.userService().loadUser(ownerId); + var location = loadLocation(rs.getLong(LOCATION_ID)); + list.add(Item.of(rs, owner, location)); + } + rs.close(); + return list; + } catch (SQLException e){ + throw databaseException("Failed to load items at {0}",locationId); + } + } + + private Location loadLocation(long locationId) { + try { + var rs = select(ALL).from(TABLE_LOCATIONS).where(ID,equal(locationId)).exec(db); + Location loc = null; + if (rs.next()) loc = Location.of(rs); + rs.close(); + if (loc != null) return loc; + throw databaseException("Failed to load location with id = {0}",locationId); + } catch (SQLException e){ + throw databaseException("Failed to load location with id = {0}",locationId); + } + } + @Override public Collection listLocations(long companyId) { return List.of(); diff --git a/stock/src/main/java/de/srsoftware/umbrella/stock/StockApi.java b/stock/src/main/java/de/srsoftware/umbrella/stock/StockApi.java index 5121d1f..ed25c70 100644 --- a/stock/src/main/java/de/srsoftware/umbrella/stock/StockApi.java +++ b/stock/src/main/java/de/srsoftware/umbrella/stock/StockApi.java @@ -19,6 +19,7 @@ import de.srsoftware.umbrella.core.BaseHandler; import de.srsoftware.umbrella.core.ModuleRegistry; import de.srsoftware.umbrella.core.api.StockService; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; +import de.srsoftware.umbrella.core.model.Item; import de.srsoftware.umbrella.core.model.Location; import de.srsoftware.umbrella.core.model.Token; import de.srsoftware.umbrella.core.model.UmbrellaUser; @@ -45,14 +46,26 @@ public class StockApi extends BaseHandler implements StockService { if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head) { + case ITEMS_AT -> { + try { + var id = Long.parseLong(path.pop()); + yield getItemsAt(user.get(),id,ex); + } catch (Exception e){ + yield super.doGet(path,ex); + } + } case LOCATIONS -> getLocations(path,user.get(),ex); - case null, default -> doGet(path,ex); + case null, default -> super.doGet(path,ex); }; } catch (UmbrellaException e){ return send(ex,e); } } + private boolean getItemsAt(UmbrellaUser user, long locationId, HttpExchange ex) throws IOException { + return sendContent(ex, stockDb.listItemsAt(locationId).stream().map(Item::toMap).toList()); + } + private boolean getLocations(Path path, UmbrellaUser user, HttpExchange ex) throws IOException { var head = path.pop(); return switch (head){ diff --git a/stock/src/main/java/de/srsoftware/umbrella/stock/StockDb.java b/stock/src/main/java/de/srsoftware/umbrella/stock/StockDb.java index e0f406d..2ff5a72 100644 --- a/stock/src/main/java/de/srsoftware/umbrella/stock/StockDb.java +++ b/stock/src/main/java/de/srsoftware/umbrella/stock/StockDb.java @@ -14,6 +14,8 @@ public interface StockDb { Collection listItems(long companyId) throws UmbrellaException; + Collection listItemsAt(long locationId); + Collection listLocations(long companyId); Collection listUserLocations(UmbrellaUser userId);