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 11f7ec24..262061e5 100644 --- a/accounting/src/main/java/de/srsoftware/umbrella/accounting/AccountingModule.java +++ b/accounting/src/main/java/de/srsoftware/umbrella/accounting/AccountingModule.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.util.Optional; import static de.srsoftware.tools.Optionals.nullIfEmpty; +import static de.srsoftware.umbrella.accounting.Constants.CONFIG_DATABASE; 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; @@ -27,7 +28,6 @@ import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFi 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 { @@ -74,7 +74,7 @@ public class AccountingModule extends BaseHandler implements AccountingService { var currency = acc.has(Field.CURRENCY) ? nullIfEmpty(acc.getString(Field.CURRENCY)) : null; - var account = accountDb.save(new Account(0, accountName, currency)); + var account = accountDb.save(new Account(0, accountName, currency, user.id())); accountId = account.id(); } diff --git a/accounting/src/main/java/de/srsoftware/umbrella/accounting/Constants.java b/accounting/src/main/java/de/srsoftware/umbrella/accounting/Constants.java new file mode 100644 index 00000000..9031166c --- /dev/null +++ b/accounting/src/main/java/de/srsoftware/umbrella/accounting/Constants.java @@ -0,0 +1,8 @@ +package de.srsoftware.umbrella.accounting; + +public class Constants { + public static final String CONFIG_DATABASE = "umbrella.modules.accounting.database"; + + public static final String TABLE_ACCOUNTS = "accounts"; + public static final String TABLE_TRANSACTIONS = "transactions"; +} diff --git a/accounting/src/main/java/de/srsoftware/umbrella/accounting/SqliteDb.java b/accounting/src/main/java/de/srsoftware/umbrella/accounting/SqliteDb.java index 03f57c8d..ad144e19 100644 --- a/accounting/src/main/java/de/srsoftware/umbrella/accounting/SqliteDb.java +++ b/accounting/src/main/java/de/srsoftware/umbrella/accounting/SqliteDb.java @@ -1,12 +1,88 @@ package de.srsoftware.umbrella.accounting; +import de.srsoftware.tools.jdbc.Query; import de.srsoftware.umbrella.core.BaseDb; +import de.srsoftware.umbrella.core.constants.Field; import de.srsoftware.umbrella.core.model.Account; import java.sql.Connection; +import java.sql.SQLException; + +import static de.srsoftware.tools.NotImplemented.notImplemented; +import static de.srsoftware.umbrella.accounting.Constants.TABLE_ACCOUNTS; +import static de.srsoftware.umbrella.accounting.Constants.TABLE_TRANSACTIONS; +import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.failedToCreateTable; +import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.failedToStoreObject; +import static java.text.MessageFormat.format; public class SqliteDb extends BaseDb implements AccountDb { public SqliteDb(Connection connection) { super(connection); } + + @Override + protected int createTables() { + var version = createSettingsTable(); + switch (version){ + case 0: + createAccountsTable(); + createTransactionsTable(); + } + return setCurrentVersion(1); + } + + private void createAccountsTable() { + var sql = """ + CREATE TABLE IF NOT EXISTS {0} ( + {1} INTEGER PRIMARY KEY, + {2} VARCHAR(255) NOT NULL, + {3} LONG NOT NULL, + {4} CURRENCY VARCHAR(16) + );"""; + + try { + sql = format(sql,TABLE_ACCOUNTS, Field.ID, Field.NAME, Field.OWNER, Field.CURRENCY); + var stmt = db.prepareStatement(sql); + stmt.execute(); + stmt.close(); + } catch (SQLException e) { + throw failedToCreateTable(TABLE_ACCOUNTS).causedBy(e); + } + } + + private void createTransactionsTable() { + var sql = """ + CREATE TABLE IF NOT EXISTS {0} ( + {1} LONG NOT NULL, + {2} LONG NOT NULL, + {3} VARCHAR(255) NOT NULL, + {4} VARCHAR(255) NOT NULL, + {5} DOUBLE NOT NULL, + {6} TEXT + );"""; + try { + sql = format(sql,TABLE_TRANSACTIONS,Field.ACCOUNT,Field.TIMESTAMP,Field.SOURCE,Field.DESTINATION, Field.AMOUNT,Field.DESCRIPTION); + var stmt = db.prepareStatement(sql); + stmt.execute(); + stmt.close(); + } catch (SQLException e) { + throw failedToCreateTable(TABLE_TRANSACTIONS).causedBy(e); + } + } + + @Override + public Account save(Account account) { + if (account.id() == 0) try { // new account + var rs = Query.insertInto(TABLE_ACCOUNTS,Field.NAME, Field.CURRENCY, Field.OWNER).values(account.name(),account.currency(),account.ownerId()).execute(db).getGeneratedKeys(); + Long newId = null; + if (rs.next()) newId = rs.getLong(1); + rs.close(); + if (newId == null) throw failedToStoreObject(account); + return account.withId(newId); + } catch (SQLException e) { + throw failedToStoreObject(account).causedBy(e); + } else { + throw notImplemented(this,"save(account)"); + } + } } diff --git a/backend/build.gradle.kts b/backend/build.gradle.kts index 94839ead..fc93936e 100644 --- a/backend/build.gradle.kts +++ b/backend/build.gradle.kts @@ -11,6 +11,7 @@ application{ } dependencies{ + implementation(project(":accounting")); implementation(project(":bookmark")); implementation(project(":bus")); implementation(project(":company")) @@ -47,6 +48,7 @@ tasks.jar { .map(::zipTree) // OR .map { zipTree(it) } from(dependencies) dependsOn( + ":accounting:jar", ":bookmark:jar", ":bus:jar", ":company:jar", diff --git a/backend/src/main/java/de/srsoftware/umbrella/backend/Application.java b/backend/src/main/java/de/srsoftware/umbrella/backend/Application.java index 42e76b2a..edd2e11b 100644 --- a/backend/src/main/java/de/srsoftware/umbrella/backend/Application.java +++ b/backend/src/main/java/de/srsoftware/umbrella/backend/Application.java @@ -9,11 +9,13 @@ import static java.lang.System.Logger.Level.INFO; import com.sun.net.httpserver.HttpServer; import de.srsoftware.configuration.JsonConfig; import de.srsoftware.tools.ColorLogger; +import de.srsoftware.umbrella.accounting.AccountingModule; import de.srsoftware.umbrella.bookmarks.BookmarkApi; import de.srsoftware.umbrella.company.CompanyModule; import de.srsoftware.umbrella.contact.ContactModule; import de.srsoftware.umbrella.core.SettingsService; import de.srsoftware.umbrella.core.Util; +import de.srsoftware.umbrella.core.api.AccountingService; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.documents.DocumentApi; import de.srsoftware.umbrella.files.FileModule; @@ -92,6 +94,7 @@ public class Application { new WikiModule(config).bindPath("/api/wiki").on(server); new FileModule(config).bindPath("/api/files").on(server); new SettingsService(config).bindPath("/api/settings").on(server); + new AccountingModule(config).bindPath("/api/accounting").on(server); } catch (Exception e) { LOG.log(ERROR,"Startup failed",e); System.exit(-1); 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 dff11922..5ecb60ee 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/ModuleRegistry.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/ModuleRegistry.java @@ -5,6 +5,7 @@ package de.srsoftware.umbrella.core; import de.srsoftware.umbrella.core.api.*; public class ModuleRegistry { + private AccountingService accountingService; private BookmarkService bookmarkService; private CompanyService companyService; private ContactService contactService; @@ -29,23 +30,24 @@ public class ModuleRegistry { public static void add(Object service) { switch (service) { - case BookmarkService bs: singleton.bookmarkService = bs; break; - case CompanyService cs: singleton.companyService = cs; break; - case ContactService cs: singleton.contactService = cs; break; - case DocumentService ds: singleton.documentService = ds; break; - case FileService fs: singleton.fileService = fs; break; - case StockService is: singleton.stockService = is; break; - case MarkdownService ms: singleton.markdownService = ms; break; - case NoteService ns: singleton.noteService = ns; break; - case PollService ps: singleton.pollService = ps; break; - case PostBox pb: singleton.postBox = pb; break; - case ProjectService ps: singleton.projectService = ps; break; - case TagService ts: singleton.tagService = ts; break; - case TaskService ts: singleton.taskService = ts; break; - case TimeService ts: singleton.timeService = ts; break; - case Translator tr: singleton.translator = tr; break; - case UserService us: singleton.userService = us; break; - case WikiService ws: singleton.wikiService = ws; break; + case AccountingService as: singleton.accountingService = as; break; + case BookmarkService bs: singleton.bookmarkService = bs; break; + case CompanyService cs: singleton.companyService = cs; break; + case ContactService cs: singleton.contactService = cs; break; + case DocumentService ds: singleton.documentService = ds; break; + case FileService fs: singleton.fileService = fs; break; + case StockService is: singleton.stockService = is; break; + case MarkdownService ms: singleton.markdownService = ms; break; + case NoteService ns: singleton.noteService = ns; break; + case PollService ps: singleton.pollService = ps; break; + case PostBox pb: singleton.postBox = pb; break; + case ProjectService ps: singleton.projectService = ps; break; + case TagService ts: singleton.tagService = ts; break; + case TaskService ts: singleton.taskService = ts; break; + case TimeService ts: singleton.timeService = ts; break; + case Translator tr: singleton.translator = tr; break; + case UserService us: singleton.userService = us; break; + case WikiService ws: singleton.wikiService = ws; break; case null: break; default: System.getLogger(ModuleRegistry.class.getSimpleName()).log(System.Logger.Level.WARNING,"Trying to add untracked class {0}",service.getClass().getSimpleName()); } 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 2222cb8b..485a151b 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 @@ -44,6 +44,7 @@ public class Field { public static final String DELIVERY = "delivery"; public static final String DELIVERY_DATE = "delivery_date"; public static final String DESCRIPTION = "description"; + public static final String DESTINATION = "destination"; public static final String DOCUMENT = "document"; public static final String DOCUMENT_ID = "document_id"; public static final String DOC_TYPE_ID = "document_type_id"; 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 index f62c4b28..1abb8365 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/model/Account.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/model/Account.java @@ -1,4 +1,7 @@ package de.srsoftware.umbrella.core.model; -public record Account(long id, String name, String currency) { +public record Account(long id, String name, String currency, long ownerId) { + public Account withId(long newId) { + return new Account(newId,name,currency,ownerId); + } }