diff --git a/core/src/main/java/de/srsoftware/umbrella/core/ModuleRegistry.java b/core/src/main/java/de/srsoftware/umbrella/core/ModuleRegistry.java index 594a7ae..ea02c2c 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/ModuleRegistry.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/ModuleRegistry.java @@ -89,6 +89,8 @@ public class ModuleRegistry { return singleton.projectService; } + public static StockService stockService() { return singleton.stockService; } + public static TagService tagService(){ return singleton.tagService; } diff --git a/core/src/main/java/de/srsoftware/umbrella/core/api/LocationRef.java b/core/src/main/java/de/srsoftware/umbrella/core/api/LocationRef.java deleted file mode 100644 index 2611fdc..0000000 --- a/core/src/main/java/de/srsoftware/umbrella/core/api/LocationRef.java +++ /dev/null @@ -1,10 +0,0 @@ -/* © SRSoftware 2025 */ -package de.srsoftware.umbrella.core.api; - -import de.srsoftware.tools.Mappable; -import de.srsoftware.umbrella.core.model.Location; - -public interface LocationRef extends Mappable { - Location resolve(StockService stockService); - long id(); -} diff --git a/core/src/main/java/de/srsoftware/umbrella/core/api/Owner.java b/core/src/main/java/de/srsoftware/umbrella/core/api/Owner.java index e1929e5..ee7bce8 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/api/Owner.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/api/Owner.java @@ -1,6 +1,16 @@ /* © SRSoftware 2025 */ package de.srsoftware.umbrella.core.api; -public interface Owner { - long signum(); +import static de.srsoftware.umbrella.core.Constants.*; + +import de.srsoftware.tools.Mappable; + +public interface Owner extends Mappable { + public static final String SEPARATOR = ":"; + default String dbCode(){ + return type()+SEPARATOR+id(); + } + long id(); + String type(); + public Owner resolve(); } diff --git a/core/src/main/java/de/srsoftware/umbrella/core/api/OwnerRef.java b/core/src/main/java/de/srsoftware/umbrella/core/api/OwnerRef.java deleted file mode 100644 index c16fc06..0000000 --- a/core/src/main/java/de/srsoftware/umbrella/core/api/OwnerRef.java +++ /dev/null @@ -1,10 +0,0 @@ -/* © SRSoftware 2025 */ -package de.srsoftware.umbrella.core.api; - -import de.srsoftware.tools.Mappable; -import de.srsoftware.umbrella.core.ModuleRegistry; - -public interface OwnerRef extends Mappable { - long id(); - Owner resolve(ModuleRegistry registry); -} diff --git a/core/src/main/java/de/srsoftware/umbrella/core/api/StockService.java b/core/src/main/java/de/srsoftware/umbrella/core/api/StockService.java index 061bf72..bd3c448 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/api/StockService.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/api/StockService.java @@ -2,6 +2,7 @@ package de.srsoftware.umbrella.core.api; +import de.srsoftware.umbrella.core.model.DbLocation; import java.util.Collection; public interface StockService { @@ -12,4 +13,6 @@ public interface StockService { * @return */ Collection redefineMe(long company_id); + + DbLocation loadLocation(long locationId); } diff --git a/core/src/main/java/de/srsoftware/umbrella/core/model/Company.java b/core/src/main/java/de/srsoftware/umbrella/core/model/Company.java index 3d71d94..978baae 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/model/Company.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/model/Company.java @@ -6,6 +6,7 @@ import static de.srsoftware.umbrella.core.Constants.*; import static java.util.Map.entry; import de.srsoftware.tools.Mappable; +import de.srsoftware.umbrella.core.api.Owner; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import java.sql.ResultSet; import java.sql.SQLException; @@ -13,7 +14,7 @@ import java.util.*; import org.json.JSONException; import org.json.JSONObject; -public class Company implements Mappable { +public class Company implements Mappable, Owner { private final long id; private String name, address, court, taxId, phone, decimalSeparator, thousandsSeparator, customerNumberPrefix, currency, email, bankAccount;; private long lastCustomerNumber; @@ -80,7 +81,8 @@ public class Company implements Mappable { return email; } - public long id(){ + @Override + public long id() { return id; } @@ -162,6 +164,11 @@ public class Company implements Mappable { return phone; } + @Override + public Owner resolve() { + return this; + } + public String taxId() { return taxId; } @@ -182,7 +189,6 @@ public class Company implements Mappable { memberMap.put(entry.getKey(),entry.getValue().toMap()); } return Map.ofEntries( - entry(ID,id), entry(NAME,name), entry(ADDRESS,emptyIfNull(address)), entry(FIELD_COURT,emptyIfNull(court)), @@ -196,8 +202,14 @@ public class Company implements Mappable { entry(FIELD_CURRENCY,emptyIfNull(currency)), entry(EMAIL,emptyIfNull(email)), entry(FIELD_BANK_ACCOUNT,emptyIfNull(bankAccount)), - entry(MEMBERS,memberMap) - ); + entry(MEMBERS,memberMap), + entry(TYPE,type()), + entry(ID,id) + ); } + @Override + public String type() { + return COMPANY; + } } diff --git a/core/src/main/java/de/srsoftware/umbrella/core/model/DbLocation.java b/core/src/main/java/de/srsoftware/umbrella/core/model/DbLocation.java new file mode 100644 index 0000000..24d4d51 --- /dev/null +++ b/core/src/main/java/de/srsoftware/umbrella/core/model/DbLocation.java @@ -0,0 +1,61 @@ +/* © SRSoftware 2025 */ +package de.srsoftware.umbrella.core.model; + +import static de.srsoftware.umbrella.core.Constants.*; + +import de.srsoftware.umbrella.core.api.Owner; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Map; + +public class DbLocation extends Location { + private Owner owner; + private Long parentLocationId; + private String name; + private String description; + private String relation; // when added to an item, this field describes the type of the relation + + private DbLocation(long id, Owner owner, Long parentLocationId, String name, String description){ + super(id); + this.owner = owner; + this.parentLocationId = parentLocationId; + this.name = name; + this.description = description; + } + + public String description() { + return description; + } + + public String name() { + return name; + } + + public static DbLocation of(ResultSet rs) throws SQLException { + + return new DbLocation(rs.getLong(ID), OwnerRef.of(rs), rs.getLong(PARENT_LOCATION_ID), rs.getString(NAME),rs.getString(DESCRIPTION)); + } + + public Long parent(){ + return parentLocationId; + } + + @Override + public DbLocation resolve() { + return this; + } + + @Override + public Map toMap() { + return Map.of( + OWNER,owner.toMap(), + ID,id(), + NAME,name, + DESCRIPTION,description); + } + + @Override + public String toString() { + return name; + } +} 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 10a090a..d71ea97 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 @@ -4,8 +4,7 @@ package de.srsoftware.umbrella.core.model; import static de.srsoftware.umbrella.core.Constants.*; import de.srsoftware.tools.Mappable; -import de.srsoftware.umbrella.core.api.LocationRef; -import de.srsoftware.umbrella.core.api.OwnerRef; +import de.srsoftware.umbrella.core.api.Owner; import java.sql.ResultSet; import java.sql.SQLException; import java.util.*; @@ -13,17 +12,17 @@ import org.json.JSONObject; public class Item implements Mappable { private long id, number; // id is the database key, number the owner-relative id - private OwnerRef ownerRef; + private Owner owner; private String code, name; - private LocationRef locationRef; + private Location location; private Collection properties; private Set dirtyFields = new HashSet<>(); - private Item(long id, OwnerRef ownerRef, long number, LocationRef locationRef, String code, String name) { + private Item(long id, Owner owner, long number, Location location, String code, String name) { this.id = id; - this.ownerRef = ownerRef; + this.owner = owner; this.number = number; - this.locationRef = locationRef; + this.location = location; this.code = code; this.name = name; this.properties = new HashSet<>(); @@ -41,23 +40,26 @@ public class Item implements Mappable { return id; } - public LocationRef location(){ - return locationRef; + public Location location(){ + return location; } public String name(){ return name; } - public static Item of(ResultSet rs, OwnerRef ownerRef, long number, LocationRef locationRef) throws SQLException { + public static Item of(ResultSet rs) throws SQLException { var id = rs.getLong(ID); var code = rs.getString(CODE); var name = rs.getString(NAME); - return new Item(id, ownerRef, number, locationRef, code, name); + var owner = OwnerRef.of(rs); + var number = rs.getLong(NUMBER); + var location = Location.of(rs); + return new Item(id, owner, number, location, code, name); } - public OwnerRef ownerRef(){ - return ownerRef; + public Owner owner(){ + return owner; } public Collection properties() { @@ -67,9 +69,9 @@ public class Item implements Mappable { @Override public Map toMap() { var map = new HashMap(); - map.put(OWNER,ownerRef.toMap()); + map.put(OWNER,owner.toMap()); map.put(ID,id); - map.put(LOCATION,locationRef.toMap()); + map.put(LOCATION,location.toMap()); map.put(CODE,code); map.put(NAME,name); if (properties != null) map.put(PROPERTIES,properties.stream().map(Property::toMap).toList()); 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 2a5ed7e..e11e33d 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 @@ -1,72 +1,48 @@ /* © SRSoftware 2025 */ package de.srsoftware.umbrella.core.model; -import static de.srsoftware.umbrella.core.Constants.*; +import static de.srsoftware.umbrella.core.Constants.ID; +import static de.srsoftware.umbrella.core.Constants.LOCATION_ID; +import static de.srsoftware.umbrella.core.ModuleRegistry.stockService; +import static java.text.MessageFormat.format; import de.srsoftware.tools.Mappable; + import java.sql.ResultSet; import java.sql.SQLException; import java.util.Map; public class Location implements Mappable { - private long owner; - private boolean ownerIsCompany = false; - private long id; - private Long parentLocationId; - private String name; - private String description; - private String relation; // when added to an item, this field describes the type of the relation - - private Location(long owner, boolean ownerIsCompany, long id, Long parentLocationId, String name, String description){ - this.owner = owner; - this.ownerIsCompany = ownerIsCompany; - this.id = id; - this.parentLocationId = parentLocationId; - this.name = name; - this.description = description; - } - - public final long id(){ - return id; - } - public String description() { - return description; - } + private final long id; - public String name() { - return name; + public Location(long id){ + this.id = id; } public static Location of(ResultSet rs) throws SQLException { - var owner = rs.getLong(OWNER); - var id = rs.getLong(ID); - var isCompany = owner < 0; - if (isCompany) owner = -owner; - return new Location(owner,isCompany,id, rs.getLong(PARENT_LOCATION_ID), rs.getString(NAME),rs.getString(DESCRIPTION)); + return new Location(rs.getLong(LOCATION_ID)); } + public static Location of(long locationId) { + return new Location(locationId); + } - - public long ownerCoded(){ - return ownerIsCompany ? -owner : owner; + public DbLocation resolve(){ + return stockService().loadLocation(id()); } - public Long parent(){ - return parentLocationId; + public long id(){ + return id; } @Override public Map toMap() { - return Map.of( - ownerIsCompany ? COMPANY : USER,owner, - ID,id, - NAME,name, - DESCRIPTION,description); + return Map.of(ID,id); } @Override public String toString() { - return name; + return format("Location({0})",id); } } diff --git a/core/src/main/java/de/srsoftware/umbrella/core/model/OwnerRef.java b/core/src/main/java/de/srsoftware/umbrella/core/model/OwnerRef.java new file mode 100644 index 0000000..1a64888 --- /dev/null +++ b/core/src/main/java/de/srsoftware/umbrella/core/model/OwnerRef.java @@ -0,0 +1,73 @@ +/* © SRSoftware 2025 */ +package de.srsoftware.umbrella.core.model; + +import static de.srsoftware.umbrella.core.Constants.*; +import static de.srsoftware.umbrella.core.Constants.ID; +import static de.srsoftware.umbrella.core.ModuleRegistry.companyService; +import static de.srsoftware.umbrella.core.ModuleRegistry.userService; +import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.unprocessable; + +import de.srsoftware.umbrella.core.api.Owner; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + +public class OwnerRef implements Owner { + + private final String type; + private final long id; + + public OwnerRef(String dbCode){ + var parts = dbCode.split(":"); + if (parts.length != 2) throw unprocessable("Encountered invalid dbCode: {0}",dbCode); + type = parts[0]; + try { + id = Long.parseLong(parts[1]); + } catch (NumberFormatException e) { + throw unprocessable("Encountered invalid dbCode: {0}",dbCode); + } + } + + public OwnerRef(String type, long id){ + this.type = type; + this.id = id; + } + + public static Owner of(ResultSet rs) throws SQLException { + return new OwnerRef(rs.getString(OWNER)); + } + + public String dbCode(){ + return type+SEPARATOR+id; + } + + public long id(){ + return id; + } + + public String type(){ + // TODO: is this needed? + return type; + } + + /** + * returns the actual owner object + * @return the actual owner object + */ + public Owner resolve(){ + return switch (type){ + case COMPANY -> companyService().get(id()); + case USER -> userService().loadUser(id()); + case null, default -> throw unprocessable("Encountered invalid owner type: {0}",type); + }; + } + + @Override + public Map toMap() { + var map = new HashMap(); + map.put(TYPE,type); + map.put(ID, id); + return map; + } +} diff --git a/core/src/main/java/de/srsoftware/umbrella/core/model/UmbrellaUser.java b/core/src/main/java/de/srsoftware/umbrella/core/model/UmbrellaUser.java index 7aae12c..8ee8997 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/model/UmbrellaUser.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/model/UmbrellaUser.java @@ -5,12 +5,13 @@ package de.srsoftware.umbrella.core.model; import static de.srsoftware.umbrella.core.Constants.*; import de.srsoftware.tools.Mappable; +import de.srsoftware.umbrella.core.api.Owner; import java.util.HashMap; import java.util.Map; import java.util.Objects; /* © SRSoftware 2025 */ -public class UmbrellaUser extends User implements Mappable { +public class UmbrellaUser extends User implements Mappable, Owner { private final long id; private final String theme; @@ -21,7 +22,6 @@ public class UmbrellaUser extends User implements Mappable { this.theme = theme; } - @Override public boolean equals(Object o) { if (!(o instanceof UmbrellaUser user)) return false; @@ -40,6 +40,11 @@ public class UmbrellaUser extends User implements Mappable { return id; } + @Override + public Owner resolve() { + return this; + } + public String theme(){ return theme; } @@ -55,4 +60,9 @@ public class UmbrellaUser extends User implements Mappable { map.put(LANGUAGE,language()); return map; } + + @Override + public String type() { + return USER; + } } 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 0ab04b3..a2bd2ad 100644 --- a/stock/src/main/java/de/srsoftware/umbrella/stock/SqliteDb.java +++ b/stock/src/main/java/de/srsoftware/umbrella/stock/SqliteDb.java @@ -7,8 +7,6 @@ import static de.srsoftware.tools.jdbc.Condition.isNull; import static de.srsoftware.tools.jdbc.Query.*; import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL; import static de.srsoftware.umbrella.core.Constants.*; -import static de.srsoftware.umbrella.core.ModuleRegistry.companyService; -import static de.srsoftware.umbrella.core.ModuleRegistry.userService; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.databaseException; import static de.srsoftware.umbrella.stock.Constants.*; import static java.lang.System.Logger.Level.ERROR; @@ -17,6 +15,7 @@ import static java.text.MessageFormat.format; import de.srsoftware.tools.Mappable; import de.srsoftware.umbrella.core.BaseDb; +import de.srsoftware.umbrella.core.model.Location; import de.srsoftware.umbrella.core.model.*; import java.sql.Connection; import java.sql.ResultSet; @@ -195,11 +194,11 @@ public class SqliteDb extends BaseDb implements StockDb { } @Override - public Collection listChildLocations(long parentId) { + public Collection listChildLocations(long parentId) { try { var rs = select(ALL).from(TABLE_LOCATIONS).where(PARENT_LOCATION_ID,equal(parentId)).exec(db); - var list = new ArrayList(); - while (rs.next()) list.add(Location.of(rs)); + var list = new ArrayList(); + while (rs.next()) list.add(DbLocation.of(rs)); rs.close(); return list; } catch (SQLException e){ @@ -208,11 +207,11 @@ public class SqliteDb extends BaseDb implements StockDb { } @Override - public Collection listCompanyLocations(Company company) { + public Collection listCompanyLocations(Company company) { try { var rs = select(ALL).from(TABLE_LOCATIONS).where(OWNER,equal(-company.id())).where(PARENT_LOCATION_ID,isNull()).exec(db); - var list = new ArrayList(); - while (rs.next()) list.add(Location.of(rs)); + var list = new ArrayList(); + while (rs.next()) list.add(DbLocation.of(rs)); rs.close(); return list; } catch (SQLException e){ @@ -221,41 +220,32 @@ public class SqliteDb extends BaseDb implements StockDb { } @Override - public Collection listItemsAt(long locationId) { + public Collection listItemsAt(Location location) { try { - var location = loadLocation(locationId); - var rs = select(ALL).from(TABLE_ITEMS).where(LOCATION_ID,equal(locationId)).exec(db); + var rs = select(ALL).from(TABLE_ITEMS).where(LOCATION_ID,equal(location.id())).exec(db); var list = new ArrayList(); var ownerMap = new HashMap(); - while (rs.next()) { - var ownerId = rs.getLong(OWNER); - var owner = ownerMap.get(ownerId); - if (owner == null) { - owner = ownerId < 0 ? companyService().get(-ownerId) : userService().loadUser(ownerId); - ownerMap.put(ownerId,owner); - } - list.add(Item.of(rs, owner, location)); - } + while (rs.next()) list.add(Item.of(rs)); rs.close(); for (var item : list){ - var ownerId = item.ownerId(); + var ownerId = item.owner(); rs = select(ALL).from(TABLE_ITEM_PROPERTIES).leftJoin(PROPERTY_ID,TABLE_PROPERTIES,ID).where(OWNER,equal(ownerId)).where(ITEM_ID,equal(item.id())).exec(db); while (rs.next()) item.properties().add(Property.of(rs)); rs.close(); } return list; } catch (SQLException e){ - throw databaseException("Failed to load items at {0}",locationId); + throw databaseException("Failed to load items at {0}",location); } } @Override - public Item loadItem(Mappable owner, long itemId) { + public Item loadItem(long id) { try { - var rs = select(ALL).from(TABLE_ITEMS).where(OWNER,equal(Item.ownerId(owner))).where(ID,equal(itemId)).exec(db); + var rs = select(ALL).from(TABLE_ITEMS).where(ID,equal(id)).exec(db); Item result = null; - if (rs.next()) result = Item.of(rs,owner,null); + if (rs.next()) result = Item.of(rs); rs.close(); if (result != null) return result; } catch (SQLException ignored) { @@ -263,11 +253,11 @@ public class SqliteDb extends BaseDb implements StockDb { throw databaseException("Failed to load item"); } - private Location loadLocation(long locationId) { + public DbLocation 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); + DbLocation loc = null; + if (rs.next()) loc = DbLocation.of(rs); rs.close(); if (loc != null) return loc; throw databaseException("Failed to load location with id = {0}",locationId); @@ -290,11 +280,11 @@ public class SqliteDb extends BaseDb implements StockDb { } @Override - public Collection listUserLocations(UmbrellaUser user) { + public Collection listUserLocations(UmbrellaUser user) { try { var rs = select(ALL).from(TABLE_LOCATIONS).where(OWNER,equal(user.id())).where(PARENT_LOCATION_ID,isNull()).exec(db); - var list = new ArrayList(); - while (rs.next()) list.add(Location.of(rs)); + var list = new ArrayList(); + while (rs.next()) list.add(DbLocation.of(rs)); rs.close(); return list; } catch (SQLException e){ @@ -324,7 +314,7 @@ public class SqliteDb extends BaseDb implements StockDb { } else if (item.isDirty()) { try { var location = item.location(); - var query = update(TABLE_ITEMS).where(OWNER, equal(item.ownerId())).where(ID, equal(item.id())); + var query = update(TABLE_ITEMS).where(ID, equal(item.id())); if (location == null) { query.set(CODE,NAME); } else { 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 6a60915..95081e2 100644 --- a/stock/src/main/java/de/srsoftware/umbrella/stock/StockDb.java +++ b/stock/src/main/java/de/srsoftware/umbrella/stock/StockDb.java @@ -1,18 +1,19 @@ /* © SRSoftware 2025 */ package de.srsoftware.umbrella.stock; -import de.srsoftware.tools.Mappable; +import de.srsoftware.umbrella.core.model.Location; import de.srsoftware.umbrella.core.model.*; import java.util.Collection; public interface StockDb { Property addNewProperty(long ownerId, long itemId, String name, Object value, String unit); - Collection listChildLocations(long parentId); - Collection listCompanyLocations(Company company); - Collection listItemsAt(long locationId); + Collection listChildLocations(long parentId); + Collection listCompanyLocations(Company company); + Collection listItemsAt(Location location); Collection listProperties(); - Collection listUserLocations(UmbrellaUser userId); - Item loadItem(Mappable owner, long itemId); + Collection listUserLocations(UmbrellaUser userId); + Item loadItem(long id); + DbLocation loadLocation(long locationId); Item save(Item item); Property setProperty(long ownerId, long itemId, long existingPropId, Object value); } 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 3dca260..26a1413 100644 --- a/stock/src/main/java/de/srsoftware/umbrella/stock/StockModule.java +++ b/stock/src/main/java/de/srsoftware/umbrella/stock/StockModule.java @@ -19,6 +19,7 @@ import de.srsoftware.tools.Path; import de.srsoftware.tools.SessionToken; import de.srsoftware.umbrella.core.BaseHandler; import de.srsoftware.umbrella.core.ModuleRegistry; +import de.srsoftware.umbrella.core.model.Location; import de.srsoftware.umbrella.core.api.StockService; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.model.*; @@ -49,7 +50,7 @@ public class StockModule extends BaseHandler implements StockService { case LOCATION -> { try { var id = Long.parseLong(path.pop()); - yield getLocation(user.get(),id,ex); + yield getLocation(user.get(), Location.of(id),ex); } catch (Exception e){ yield super.doGet(path,ex); } @@ -95,12 +96,12 @@ public class StockModule extends BaseHandler implements StockService { private boolean getChildLocations(UmbrellaUser user, long parentId, HttpExchange ex) throws IOException { LOG.log(WARNING,"No security check implemented for {0}.getChildLocations(user, parentId, ex)!",getClass().getSimpleName()); // TODO check, that user is allowed to request that location - return sendContent(ex, stockDb.listChildLocations(parentId).stream().sorted(comparing(l -> l.name().toLowerCase())).map(Location::toMap)); + return sendContent(ex, stockDb.listChildLocations(parentId).stream().sorted(comparing(l -> l.name().toLowerCase())).map(DbLocation::toMap)); } - private boolean getLocation(UmbrellaUser user, long locationId, HttpExchange ex) throws IOException { - return sendContent(ex, stockDb.listItemsAt(locationId).stream().map(Item::toMap).toList()); + private boolean getLocation(UmbrellaUser user, Location location, HttpExchange ex) throws IOException { + return sendContent(ex, stockDb.listItemsAt(location).stream().map(Item::toMap).toList()); } private boolean getLocations(Path path, UmbrellaUser user, HttpExchange ex) throws IOException { @@ -130,7 +131,7 @@ public class StockModule extends BaseHandler implements StockService { result.add(Map.of( ID, user.id(), NAME,user.name(), - LOCATIONS,userLocations.stream().map(Location::toMap).toList())); + LOCATIONS,userLocations.stream().map(DbLocation::toMap).toList())); var companies = companyService().listCompaniesOf(user); companies.values().stream().sorted(comparing(a -> a.name().toLowerCase())).forEach(company -> { @@ -138,37 +139,27 @@ public class StockModule extends BaseHandler implements StockService { result.add(Map.of( ID, company.id(), NAME,company.name(), - LOCATIONS,locations.stream().sorted(comparing(a -> a.name().toLowerCase())).map(Location::toMap).toList())); + LOCATIONS,locations.stream().sorted(comparing(a -> a.name().toLowerCase())).map(DbLocation::toMap).toList())); }); return sendContent(ex, result); } + @Override + public DbLocation loadLocation(long locationId) { + return stockDb.loadLocation(locationId); + } + private boolean patchItem(UmbrellaUser user, HttpExchange ex) throws IOException { var json = json(ex); if (!(json.get(ID) instanceof Number id)) throw missingFieldException(ID); - if (!(json.get(OWNER) instanceof JSONObject ownerRef)) throw missingFieldException(OWNER); json.remove(ID); - json.remove(OWNER); - var owner = toOwner(ownerRef); - var item = stockDb.loadItem(owner,id.longValue()); + var item = stockDb.loadItem(id.longValue()); item.patch(json); return sendContent(ex,stockDb.save(item)); } - private Mappable toOwner(JSONObject owner) { - var keys = owner.keySet(); - if (keys.size() != 1) throw unprocessable("{0} expected to have only one child!",OWNER); - String key = new ArrayList<>(keys).getFirst(); - return switch (key) { - case COMPANY -> companyService().get(owner.getLong(key)); - case USER -> userService().loadUser(owner.getLong(key)); - default -> throw invalidFieldException(format("Single child of {0}", OWNER), format("either {0} or {1}", COMPANY, USER)); - }; - - } - private boolean postProperty(UmbrellaUser user, HttpExchange ex) throws IOException { var json = json(ex); if (!(json.get(FIELD_ITEM) instanceof JSONObject itemData)) throw missingFieldException(FIELD_ITEM); @@ -192,6 +183,18 @@ public class StockModule extends BaseHandler implements StockService { return sendContent(ex,property); } + private Mappable toOwner(JSONObject owner) { + var keys = owner.keySet(); + if (keys.size() != 1) throw unprocessable("{0} expected to have only one child!",OWNER); + String key = new ArrayList<>(keys).getFirst(); + return switch (key) { + case COMPANY -> companyService().get(owner.getLong(key)); + case USER -> userService().loadUser(owner.getLong(key)); + default -> throw invalidFieldException(format("Single child of {0}", OWNER), format("either {0} or {1}", COMPANY, USER)); + }; + + } + private long toOwnerId(JSONObject owner) { var keys = owner.keySet(); if (keys.size() != 1) throw unprocessable("{0} expected to have only one child!",OWNER);