diff --git a/accounting/src/main/java/de/srsoftware/umbrella/accounting/AccountDb.java b/accounting/src/main/java/de/srsoftware/umbrella/accounting/AccountDb.java new file mode 100644 index 00000000..9b813ec9 --- /dev/null +++ b/accounting/src/main/java/de/srsoftware/umbrella/accounting/AccountDb.java @@ -0,0 +1,7 @@ +package de.srsoftware.umbrella.accounting; + +import de.srsoftware.umbrella.core.model.Account; + +public interface AccountDb { + Account save(Account account); +} diff --git a/accounting/src/main/java/de/srsoftware/umbrella/accounting/AccountingModule.java b/accounting/src/main/java/de/srsoftware/umbrella/accounting/AccountingModule.java index 1d520ae2..11f7ec24 100644 --- a/accounting/src/main/java/de/srsoftware/umbrella/accounting/AccountingModule.java +++ b/accounting/src/main/java/de/srsoftware/umbrella/accounting/AccountingModule.java @@ -1,8 +1,85 @@ package de.srsoftware.umbrella.accounting; +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.AccountingService; +import de.srsoftware.umbrella.core.constants.Field; +import de.srsoftware.umbrella.core.constants.Text; +import de.srsoftware.umbrella.core.exceptions.UmbrellaException; +import de.srsoftware.umbrella.core.model.Account; +import de.srsoftware.umbrella.core.model.Token; +import de.srsoftware.umbrella.core.model.UmbrellaUser; +import org.json.JSONObject; + +import java.io.IOException; +import java.util.Optional; + +import static de.srsoftware.tools.Optionals.nullIfEmpty; +import static de.srsoftware.umbrella.core.ConnectionProvider.connect; +import static de.srsoftware.umbrella.core.constants.Path.JSON; +import static de.srsoftware.umbrella.core.constants.Path.SEARCH; +import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.invalidField; +import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingField; +import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; public class AccountingModule extends BaseHandler implements AccountingService { + public static final String CONFIG_DATABASE = "umbrella.modules.accounting.database"; + private final AccountDb accountDb; + public AccountingModule(Configuration config) throws UmbrellaException { + super(); + var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingField(CONFIG_DATABASE)); + accountDb = new SqliteDb(connect(dbFile)); + ModuleRegistry.add(this); + } + + @Override + public boolean doPost(Path path, HttpExchange ex) throws IOException { + addCors(ex); + try { + Optional token = SessionToken.from(ex).map(Token::of); + var user = ModuleRegistry.userService().loadUser(token); + if (user.isEmpty()) return unauthorized(ex); + var head = path.pop(); + return switch (head) { + case null -> postEntry(user.get(),ex); + default -> super.doPost(path,ex); + }; + } catch (NumberFormatException e){ + return sendContent(ex,HTTP_BAD_REQUEST,"Invalid project id"); + } catch (UmbrellaException e){ + return send(ex,e); + } + } + + private boolean postEntry(UmbrellaUser user, HttpExchange ex) throws IOException { + var json = json(ex); + if (!json.has(Field.ACCOUNT)) throw missingField(Field.ACCOUNT); + if (!(json.get(Field.ACCOUNT) instanceof JSONObject acc)) throw invalidField(Field.ACCOUNT,JSON); + // TODO more tests + + Long accountId = null; + if (acc.has(Field.ID)) { + if (!(acc.get(Field.ID) instanceof Number accId)) throw invalidField(String.join(".",Field.ACCOUNT,Field.ID), Text.NUMBER); + if (accId.longValue() != 0) accountId = accId.longValue(); + } + if (accountId == null){ + if (!acc.has(Field.NAME)) throw missingField(String.join(".",Field.ACCOUNT,Field.NAME)); + var accountName = acc.getString(Field.NAME); + if (accountName.isBlank()) throw invalidField(String.join(".",Field.ACCOUNT,Field.NAME),Text.STRING); + + var currency = acc.has(Field.CURRENCY) ? nullIfEmpty(acc.getString(Field.CURRENCY)) : null; + + var account = accountDb.save(new Account(0, accountName, currency)); + accountId = account.id(); + } + + // TODO: save entry + + return notFound(ex); + } } diff --git a/accounting/src/main/java/de/srsoftware/umbrella/accounting/SqliteDb.java b/accounting/src/main/java/de/srsoftware/umbrella/accounting/SqliteDb.java new file mode 100644 index 00000000..03f57c8d --- /dev/null +++ b/accounting/src/main/java/de/srsoftware/umbrella/accounting/SqliteDb.java @@ -0,0 +1,12 @@ +package de.srsoftware.umbrella.accounting; + +import de.srsoftware.umbrella.core.BaseDb; +import de.srsoftware.umbrella.core.model.Account; + +import java.sql.Connection; + +public class SqliteDb extends BaseDb implements AccountDb { + public SqliteDb(Connection connection) { + super(connection); + } +} diff --git a/core/src/main/java/de/srsoftware/umbrella/core/constants/Field.java b/core/src/main/java/de/srsoftware/umbrella/core/constants/Field.java index 430e524a..2222cb8b 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/constants/Field.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/constants/Field.java @@ -3,6 +3,7 @@ package de.srsoftware.umbrella.core.constants; public class Field { public static final String ACTION = "action"; + public static final String ACCOUNT = "account"; public static final String ADDRESS = "address"; public static final String ALLOWED_STATES = "allowed_states"; public static final String AMOUNT = "amount"; diff --git a/core/src/main/java/de/srsoftware/umbrella/core/model/Account.java b/core/src/main/java/de/srsoftware/umbrella/core/model/Account.java new file mode 100644 index 00000000..f62c4b28 --- /dev/null +++ b/core/src/main/java/de/srsoftware/umbrella/core/model/Account.java @@ -0,0 +1,4 @@ +package de.srsoftware.umbrella.core.model; + +public record Account(long id, String name, String currency) { +}