21 changed files with 209 additions and 189 deletions
@ -1,10 +0,0 @@
@@ -1,10 +0,0 @@
|
||||
/* © SRSoftware 2025 */ |
||||
package de.srsoftware.umbrella.core.api; |
||||
|
||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException; |
||||
import de.srsoftware.umbrella.core.model.Item; |
||||
import java.util.Collection; |
||||
|
||||
public interface ItemService { |
||||
Collection<Item> list(long companyId) throws UmbrellaException; |
||||
} |
||||
@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
|
||||
/* © SRSoftware 2025 */ |
||||
package de.srsoftware.umbrella.core.api; |
||||
|
||||
|
||||
import java.util.Collection; |
||||
|
||||
public interface StockService { |
||||
/** |
||||
* Das war mal die methode um zu checken, ob einer Firma noch Items zugewiesen sind. |
||||
* Diese Methode muss neu definiert werden, sobald der Stock-Service neu implementiert ist. |
||||
* @param company_id |
||||
* @return |
||||
*/ |
||||
Collection<Object> redefineMe(long company_id); |
||||
} |
||||
@ -1,38 +1,12 @@
@@ -1,38 +1,12 @@
|
||||
/* © SRSoftware 2025 */ |
||||
package de.srsoftware.umbrella.core.model; |
||||
|
||||
import static de.srsoftware.umbrella.core.Constants.*; |
||||
import static de.srsoftware.umbrella.core.Constants.CODE; |
||||
import static de.srsoftware.umbrella.core.Util.mapMarkdown; |
||||
|
||||
import de.srsoftware.tools.Mappable; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
import java.util.Map; |
||||
|
||||
public record Item(long id, long companyId, String code, String name, String description, String unit, long unitPrice, long tax) implements Mappable { |
||||
public static Item of(ResultSet rs) throws SQLException { |
||||
var id = rs.getLong(ID); |
||||
var companyId = rs.getLong(COMPANY_ID); |
||||
var code = rs.getString(CODE); |
||||
var name = rs.getString(NAME); |
||||
var desc = rs.getString(DESCRIPTION); |
||||
var unit = rs.getString(UNIT); |
||||
var unitPrice = rs.getLong(UNIT_PRICE); |
||||
var tax = rs.getInt(TAX); |
||||
|
||||
return new Item(id,companyId,code,name,desc,unit,unitPrice,tax); |
||||
} |
||||
|
||||
@Override |
||||
public Map<String, Object> toMap() { |
||||
return Map.of( |
||||
ID,id, |
||||
COMPANY_ID,companyId, |
||||
CODE,code,NAME,name, |
||||
DESCRIPTION,mapMarkdown(description), |
||||
UNIT,unit, |
||||
UNIT_PRICE,unitPrice, |
||||
TAX,tax); |
||||
} |
||||
import java.util.Collection; |
||||
|
||||
public class Item { |
||||
private long id; |
||||
private String code; |
||||
private boolean physical; |
||||
private Location location; |
||||
private Collection<Property> properties; |
||||
} |
||||
|
||||
@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
|
||||
/* © SRSoftware 2025 */ |
||||
package de.srsoftware.umbrella.core.model; |
||||
|
||||
public class Location { |
||||
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
|
||||
} |
||||
@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
|
||||
/* © SRSoftware 2025 */ |
||||
package de.srsoftware.umbrella.core.model; |
||||
|
||||
public class Property { |
||||
long id; |
||||
String name; |
||||
Object value; |
||||
String unit; |
||||
String quantity; |
||||
} |
||||
@ -1,8 +0,0 @@
@@ -1,8 +0,0 @@
|
||||
/* © SRSoftware 2025 */ |
||||
package de.srsoftware.umbrella.items; |
||||
|
||||
public class Constants { |
||||
private Constants(){} |
||||
public static final String CONFIG_DATABASE = "umbrella.modules.items.database"; |
||||
public static final String TABLE_ITEMS = "items"; |
||||
} |
||||
@ -1,75 +0,0 @@
@@ -1,75 +0,0 @@
|
||||
/* © SRSoftware 2025 */ |
||||
package de.srsoftware.umbrella.items; |
||||
|
||||
import static de.srsoftware.umbrella.core.ConnectionProvider.connect; |
||||
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.Paths.LIST; |
||||
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.forbidden; |
||||
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException; |
||||
import static de.srsoftware.umbrella.items.Constants.CONFIG_DATABASE; |
||||
|
||||
import com.sun.net.httpserver.HttpExchange; |
||||
import de.srsoftware.configuration.Configuration; |
||||
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.api.ItemService; |
||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException; |
||||
import de.srsoftware.umbrella.core.model.Item; |
||||
import de.srsoftware.umbrella.core.model.Token; |
||||
import de.srsoftware.umbrella.core.model.UmbrellaUser; |
||||
import java.io.IOException; |
||||
import java.util.Collection; |
||||
import java.util.HashMap; |
||||
import java.util.Optional; |
||||
|
||||
public class ItemApi extends BaseHandler implements ItemService { |
||||
|
||||
private final ItemDb itemDb; |
||||
|
||||
public ItemApi(Configuration config) throws UmbrellaException { |
||||
super(); |
||||
var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE)); |
||||
itemDb = new SqliteDb(connect(dbFile)); |
||||
ModuleRegistry.add(this); |
||||
} |
||||
|
||||
@Override |
||||
public boolean doPost(Path path, HttpExchange ex) throws IOException { |
||||
addCors(ex); |
||||
try { |
||||
Optional<Token> token = SessionToken.from(ex).map(Token::of); |
||||
var user = userService().loadUser(token); |
||||
if (user.isEmpty()) return unauthorized(ex); |
||||
var head = path.pop(); |
||||
return switch (head) { |
||||
case LIST -> listItems(ex,user.get()); |
||||
default -> super.doGet(path,ex); |
||||
}; |
||||
} catch (UmbrellaException e){ |
||||
return send(ex,e); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public Collection<Item> list(long companyId) throws UmbrellaException { |
||||
return itemDb.list(companyId); |
||||
} |
||||
|
||||
private boolean listItems(HttpExchange ex, UmbrellaUser user) throws IOException, UmbrellaException { |
||||
var json = json(ex); |
||||
if (!(json.has(COMPANY_ID) && json.get(COMPANY_ID) instanceof Number cid)) throw missingFieldException(COMPANY_ID); |
||||
var companyId = cid.longValue(); |
||||
var company = companyService().get(companyId); |
||||
if (!companyService().membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name()); |
||||
var items = list(companyId) |
||||
.stream() |
||||
.map(Item::toMap) |
||||
.map(HashMap::new) |
||||
.peek(map -> map.put(FIELD_CURRENCY,company.currency())); |
||||
return sendContent(ex,items); |
||||
} |
||||
} |
||||
@ -1,10 +0,0 @@
@@ -1,10 +0,0 @@
|
||||
/* © SRSoftware 2025 */ |
||||
package de.srsoftware.umbrella.items; |
||||
|
||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException; |
||||
import de.srsoftware.umbrella.core.model.Item; |
||||
import java.util.Collection; |
||||
|
||||
public interface ItemDb { |
||||
Collection<Item> list(long companyId) throws UmbrellaException; |
||||
} |
||||
@ -1,37 +0,0 @@
@@ -1,37 +0,0 @@
|
||||
/* © SRSoftware 2025 */ |
||||
package de.srsoftware.umbrella.items; |
||||
|
||||
import static de.srsoftware.tools.jdbc.Condition.equal; |
||||
import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL; |
||||
import static de.srsoftware.tools.jdbc.Query.select; |
||||
import static de.srsoftware.umbrella.core.Constants.COMPANY_ID; |
||||
import static de.srsoftware.umbrella.items.Constants.TABLE_ITEMS; |
||||
|
||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException; |
||||
import de.srsoftware.umbrella.core.model.Item; |
||||
import java.sql.Connection; |
||||
import java.sql.SQLException; |
||||
import java.util.Collection; |
||||
import java.util.HashSet; |
||||
|
||||
public class SqliteDb implements ItemDb{ |
||||
|
||||
private final Connection db; |
||||
|
||||
public SqliteDb(Connection connection) { |
||||
db = connection; |
||||
} |
||||
|
||||
@Override |
||||
public Collection<Item> list(long companyId) throws UmbrellaException { |
||||
try { |
||||
var items = new HashSet<Item>(); |
||||
var rs = select(ALL).from(TABLE_ITEMS).where(COMPANY_ID, equal(companyId)).exec(db); |
||||
while (rs.next()) items.add(Item.of(rs)); |
||||
rs.close(); |
||||
return items; |
||||
} catch (SQLException e) { |
||||
throw new UmbrellaException("Failed to load items from database"); |
||||
} |
||||
} |
||||
} |
||||
@ -1,4 +1,4 @@
@@ -1,4 +1,4 @@
|
||||
description = "Umbrella : Items" |
||||
description = "Umbrella : Stock" |
||||
|
||||
dependencies{ |
||||
implementation(project(":core")) |
||||
@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
|
||||
/* © SRSoftware 2025 */ |
||||
package de.srsoftware.umbrella.stock; |
||||
|
||||
public class Constants { |
||||
private Constants(){} |
||||
|
||||
|
||||
public static final String CONFIG_DATABASE = "umbrella.modules.stock.database"; |
||||
public static final String ITEM_ID = "item_id"; public static final String LOCATION_ID = "location_id"; |
||||
public static final String PROPERTY_ID = "prop_id"; |
||||
public static final String TABLE_ITEMS = "items"; |
||||
public static final String TABLE_ITEM_PROPERTIES = "item_props"; |
||||
public static final String TABLE_LOCATIONS = "locations"; |
||||
public static final String TABLE_PROPERTIES = "properties"; |
||||
} |
||||
@ -0,0 +1,87 @@
@@ -0,0 +1,87 @@
|
||||
/* © SRSoftware 2025 */ |
||||
package de.srsoftware.umbrella.stock; |
||||
|
||||
import static de.srsoftware.umbrella.core.Constants.*; |
||||
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.databaseException; |
||||
import static de.srsoftware.umbrella.stock.Constants.*; |
||||
import static java.text.MessageFormat.format; |
||||
|
||||
import de.srsoftware.umbrella.core.BaseDb; |
||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException; |
||||
import de.srsoftware.umbrella.core.model.Item; |
||||
import de.srsoftware.umbrella.core.model.Location; |
||||
import java.sql.Connection; |
||||
import java.sql.SQLException; |
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
|
||||
public class SqliteDb extends BaseDb implements StockDb { |
||||
public SqliteDb(Connection connection) { |
||||
super(connection); |
||||
} |
||||
|
||||
@Override |
||||
protected int createTables() { |
||||
int currentVersion = createSettingsTable(); |
||||
switch (currentVersion){ |
||||
case 0: |
||||
createLocationsTable(); |
||||
createItemsTable(); |
||||
createPropertiesTable(); |
||||
createItemPropsTable(); |
||||
} |
||||
return setCurrentVersion(1); |
||||
} |
||||
|
||||
private void createItemsTable() { |
||||
try { |
||||
var sql = "CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) PRIMARY KEY, {2} VARCHAR(255) NOT NULL, {3} TEXT, {4} VARCHAR(255))"; |
||||
sql = format(sql, TABLE_ITEMS, ID, CODE, NAME, LOCATION_ID); |
||||
db.prepareStatement(sql).execute(); |
||||
} catch (SQLException e) { |
||||
throw databaseException(ERROR_FAILED_CREATE_TABLE,TABLE_ITEMS); |
||||
} |
||||
} |
||||
|
||||
private void createItemPropsTable() { |
||||
try { |
||||
var sql = "CREATE TABLE IF NOT EXISTS {0} ( {1} INT NOT NULL, {2} INT NOT NULL, {3} VARCHAR(255) NOT NULL, PRIMARY KEY({1}, {2}))"; |
||||
sql = format(sql, TABLE_ITEM_PROPERTIES, ITEM_ID, PROPERTY_ID,VALUE); |
||||
db.prepareStatement(sql).execute(); |
||||
} catch (SQLException e) { |
||||
throw databaseException(ERROR_FAILED_CREATE_TABLE,TABLE_ITEM_PROPERTIES); |
||||
} |
||||
} |
||||
|
||||
private void createLocationsTable() { |
||||
try { |
||||
var sql = "CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) PRIMARY KEY, {2} VARCHAR(255) DEFAULT NULL, {3} VARCHAR(255) NOT NULL, {4} TEXT)"; |
||||
sql = format(sql, TABLE_LOCATIONS, ID, LOCATION_ID, NAME, DESCRIPTION); |
||||
db.prepareStatement(sql).execute(); |
||||
} catch (SQLException e) { |
||||
throw databaseException(ERROR_FAILED_CREATE_TABLE,TABLE_LOCATIONS); |
||||
} |
||||
} |
||||
|
||||
private void createPropertiesTable() { |
||||
try { |
||||
var sql = "CREATE TABLE IF NOT EXISTS {0} ( {1} LONG PRIMARY KEY, {2} VARCHAR(255) NOT NULL, {3} INT NOT NULL, {4} VARCHAR(255))"; |
||||
sql = format(sql, TABLE_PROPERTIES, ID, NAME, TYPE, UNIT); |
||||
db.prepareStatement(sql).execute(); |
||||
} catch (SQLException e) { |
||||
throw databaseException(ERROR_FAILED_CREATE_TABLE,TABLE_PROPERTIES); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public Collection<Item> listItems(long companyId) throws UmbrellaException { |
||||
return List.of(); |
||||
} |
||||
|
||||
@Override |
||||
public Collection<Location> listLocations(long companyId) { |
||||
return List.of(); |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
/* © SRSoftware 2025 */ |
||||
package de.srsoftware.umbrella.stock; |
||||
|
||||
import static de.srsoftware.umbrella.core.ConnectionProvider.connect; |
||||
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException; |
||||
import static de.srsoftware.umbrella.stock.Constants.CONFIG_DATABASE; |
||||
|
||||
import de.srsoftware.configuration.Configuration; |
||||
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 java.util.Collection; |
||||
import java.util.List; |
||||
|
||||
public class StockApi extends BaseHandler implements StockService { |
||||
|
||||
private final StockDb stockDb; |
||||
|
||||
public StockApi(Configuration config) throws UmbrellaException { |
||||
super(); |
||||
var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE)); |
||||
stockDb = new SqliteDb(connect(dbFile)); |
||||
ModuleRegistry.add(this); |
||||
} |
||||
|
||||
@Override |
||||
public Collection<Object> redefineMe(long company_id) { |
||||
return List.of(); |
||||
} |
||||
} |
||||
@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
|
||||
/* © SRSoftware 2025 */ |
||||
package de.srsoftware.umbrella.stock; |
||||
|
||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException; |
||||
import de.srsoftware.umbrella.core.model.Item; |
||||
import de.srsoftware.umbrella.core.model.Location; |
||||
import java.util.Collection; |
||||
|
||||
public interface StockDb { |
||||
Collection<Item> listItems(long companyId) throws UmbrellaException; |
||||
Collection<Location> listLocations(long companyId); |
||||
} |
||||
Loading…
Reference in new issue