working on migration of items to stock db

Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
2025-11-30 23:24:02 +01:00
parent d6b5d243c1
commit fd536abe11
7 changed files with 168 additions and 57 deletions

View File

@@ -0,0 +1,63 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.stock;
import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL;
import static de.srsoftware.tools.jdbc.Query.select;
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.core.Field.COMPANY_ID;
import static de.srsoftware.umbrella.core.Field.UNIT_PRICE;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.databaseException;
import static de.srsoftware.umbrella.stock.Constants.TABLE_ITEMS;
import de.srsoftware.umbrella.core.ModuleRegistry;
import de.srsoftware.umbrella.core.model.DbLocation;
import de.srsoftware.umbrella.core.model.Item;
import de.srsoftware.umbrella.core.model.Location;
import de.srsoftware.umbrella.core.model.Property;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
public class ItemDb {
private final System.Logger LOG = System.getLogger(getClass().getSimpleName());
private final Connection db;
public ItemDb(String dbFilePath){
db = connect(dbFilePath);
}
public void migrateTo(StockDb stockDb) {
try {
var companyLocations = new HashMap<Long,Location>();
var rs = select(ALL).from(TABLE_ITEMS).exec(db);
while (rs.next()){
var id = rs.getLong(ID);
var companyId = rs.getLong(COMPANY_ID);
var code = rs.getString(CODE);
var name = rs.getString(NAME);
var description = rs.getString(DESCRIPTION);
var unit = rs.getString(UNIT);
var unitPrice = rs.getLong(UNIT_PRICE);
var tax = rs.getLong(TAX);
var company = ModuleRegistry.companyService().get(companyId);
var location = companyLocations.get(companyId);
if (location == null) { // TODO: ids currently do not get assigned
location = stockDb.save(new DbLocation(0,company,null,"virtual items",null));
companyLocations.put(companyId,location);
}
var stockItem = new Item(0,company,0,location,code,name,description);
var props = stockItem.properties(); // TODO: saving props currently does not work
props.add(new Property(0,UNIT_PRICE,unitPrice/100d,company.currency()));
props.add(new Property(0,UNIT,unit,null));
props.add(new Property(0,TAX,tax,"%"));
props.add(new Property(0,"legacy_id",id,null));
stockDb.save(stockItem);
}
rs.close();
} catch (SQLException e) {
throw databaseException("Failed to migrate items from itemDB to stockDB!");
}
LOG.log(System.Logger.Level.WARNING,"migrateTo({0}) not implemented", stockDb);
}
}

View File

@@ -11,8 +11,7 @@ import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.core.ModuleRegistry.noteService;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.databaseException;
import static de.srsoftware.umbrella.stock.Constants.*;
import static java.lang.System.Logger.Level.ERROR;
import static java.lang.System.Logger.Level.WARNING;
import static java.lang.System.Logger.Level.*;
import static java.text.MessageFormat.format;
import de.srsoftware.tools.jdbc.Query;
@@ -51,21 +50,21 @@ public class SqliteDb extends BaseDb implements StockDb {
Long propertyId = null;
if (rs.next()) propertyId = rs.getLong(1);
rs.close();
if (propertyId == null || propertyId == 0) throw databaseException("Failed to create new property {0} to DB",name);
if (propertyId == null || propertyId == 0) throw databaseException("Failed to create new property {0} in DB",name);
insertInto(TABLE_ITEM_PROPERTIES,ITEM_ID,PROPERTY_ID,VALUE).values(itemId,propertyId,value).execute(db);
return new Property(propertyId,name,value,unit);
} catch (SQLException e) {
throw databaseException("Failed to create new property {0} to DB",name);
throw databaseException("Failed to create new property {0} in DB",name);
}
}
@Override
public Location delete(DbLocation location) {
private void createDescriptionColumn(){
try {
Query.delete().from(TABLE_LOCATIONS).where(ID,equal(location.id())).execute(db);
return location;
} catch (SQLException e){
throw databaseException("Failed to delete \"{0}\"",location.name());
var sql = "ALTER TABLE {0} ADD COLUMN {1} TEXT";
sql = format(sql,TABLE_ITEMS,DESCRIPTION);
db.prepareStatement(sql).execute();
} catch (SQLException e) {
throw databaseException("failed to create {0} column in {1} table!",DESCRIPTION,TABLE_ITEMS);
}
}
@@ -165,8 +164,20 @@ public class SqliteDb extends BaseDb implements StockDb {
dropTokenTable();
case 2:
transformTables();
case 3:
createDescriptionColumn();
}
return setCurrentVersion(4);
}
@Override
public Location delete(DbLocation location) {
try {
Query.delete().from(TABLE_LOCATIONS).where(ID,equal(location.id())).execute(db);
return location;
} catch (SQLException e){
throw databaseException("Failed to delete \"{0}\"",location.name());
}
return setCurrentVersion(3);
}
private void dropTokenTable() {
@@ -400,7 +411,6 @@ public class SqliteDb extends BaseDb implements StockDb {
.execute(db).getGeneratedKeys();
if (rs.next()) item.id(rs.getLong(1));
rs.close();
return item;
} catch (SQLException e) {
throw databaseException("Failed to save new item to database!");
}
@@ -419,15 +429,43 @@ public class SqliteDb extends BaseDb implements StockDb {
} else {
pq.apply(item.code(),item.name(),item.location().id());
}
return item.clear();
item.clear();
} catch (SQLException e){
throw databaseException("Failed to update item {0}",item.name());
}
}
saveProperties(item);
return item;
}
private void saveProperties(Item item){
var saved = new ArrayList<Property>();
for (var property : item.properties()) {
saved.add(saveProperty(item, property));
}
item.properties().clear();
item.properties().addAll(saved);
}
private Property saveProperty(Item item, Property property) {
Long propId = property.id();
if (is0(propId)) {
LOG.log(DEBUG,"Saving new property {0}",property);
try {
var rs = select(ID).from(TABLE_PROPERTIES).where(NAME,equal(property.name())).where(UNIT,equal(property.unit())).exec(db);
if (rs.next()) {
propId = rs.getLong(1);
}
rs.close();
} catch (SQLException e) {
throw databaseException("Failed to load property \"{}\"!",property.name());
}
}
if (is0(propId)) return addNewProperty(item.id(), property.name(), property.value(), property.unit());
return setProperty(item.id(),propId,property.value());
}
@Override
public Property setProperty(long itemId, long existingPropId, Object value) {
try {
@@ -435,7 +473,7 @@ public class SqliteDb extends BaseDb implements StockDb {
var rs = select(ALL).from(TABLE_PROPERTIES).where(ID,equal(existingPropId)).exec(db);
if (rs.next()) prop = Property.of(rs);
rs.close();
if (prop == null) throw databaseException("Failed to add new property to item {0}",itemId);
if (prop == null) throw databaseException("Failed to load property {0} for item {1}",existingPropId,itemId);
if ("".equals(value)){
Query.delete().from(TABLE_ITEM_PROPERTIES).where(ITEM_ID,equal(itemId)).where(PROPERTY_ID,equal(existingPropId)).execute(db);
} else {

View File

@@ -12,12 +12,10 @@ import static de.srsoftware.umbrella.core.Paths.LIST;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
import static de.srsoftware.umbrella.stock.Constants.*;
import static java.lang.System.Logger.Level.WARNING;
import static java.text.MessageFormat.format;
import static java.util.Comparator.comparing;
import com.sun.net.httpserver.HttpExchange;
import de.srsoftware.configuration.Configuration;
import de.srsoftware.tools.Mappable;
import de.srsoftware.tools.Path;
import de.srsoftware.tools.SessionToken;
import de.srsoftware.umbrella.core.BaseHandler;
@@ -40,6 +38,8 @@ public class StockModule extends BaseHandler implements StockService {
super();
var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE));
stockDb = new SqliteDb(connect(dbFile));
Optional<String> itemDbConfig = config.get("umbrella.modules.items.database");
itemDbConfig.map(ItemDb::new).ifPresent(itemDb -> itemDb.migrateTo(stockDb));
ModuleRegistry.add(this);
}
@@ -309,13 +309,14 @@ public class StockModule extends BaseHandler implements StockService {
private boolean postItem(UmbrellaUser user, HttpExchange ex) throws IOException {
var json = json(ex);
if (!json.has(NAME) || !(json.get(NAME) instanceof String name)) throw missingFieldException(NAME);
var description = json.has(DESCRIPTION) && json.get(DESCRIPTION) instanceof String d ? d : null;
if (!json.has(CODE) || !(json.get(CODE) instanceof String code)) throw missingFieldException(CODE);
if (!json.has(LOCATION) || !(json.get(LOCATION) instanceof JSONObject locationData)) throw missingFieldException(LOCATION);
var location = stockDb.loadLocation(locationData.getLong(ID));
var owner = location.owner().resolve();
if (!assigned(owner,user)) throw forbidden("You are not allowed to add items to {0}!",location);
var number = stockDb.nextItemNumberFor(owner);
var newItem = new Item(0,owner,number,location,code,name);
var newItem = new Item(0,owner,number,location,code,name,description);
return sendContent(ex,stockDb.save(newItem));
}
@@ -380,32 +381,9 @@ 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);
String key = new ArrayList<>(keys).getFirst();
return switch (key) {
case COMPANY -> -owner.getLong(key);
case USER -> owner.getLong(key);
default -> throw invalidFieldException(format("Single child of {0}", OWNER), format("either {0} or {1}", COMPANY, USER));
};
}
@Override
public Collection<Object> redefineMe(long company_id) {
// TODO
return List.of();
}
}