diff --git a/accounting/src/main/java/de/srsoftware/umbrella/accounting/AccountDb.java b/accounting/src/main/java/de/srsoftware/umbrella/accounting/AccountDb.java index b025c70c..9c4b8850 100644 --- a/accounting/src/main/java/de/srsoftware/umbrella/accounting/AccountDb.java +++ b/accounting/src/main/java/de/srsoftware/umbrella/accounting/AccountDb.java @@ -16,7 +16,7 @@ public interface AccountDb { Collection getMembers(long accountId); - Optional lastTransaction(long accountId, String source, String dest, double amount); + Optional lastTransaction(long accountId, String source, String destination, Double amount); Collection listAccounts(long userId); 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 bc2e7a8e..f2421dc2 100644 --- a/accounting/src/main/java/de/srsoftware/umbrella/accounting/AccountingModule.java +++ b/accounting/src/main/java/de/srsoftware/umbrella/accounting/AccountingModule.java @@ -311,12 +311,11 @@ public class AccountingModule extends BaseHandler implements AccountingService { var source = src.get(src.has(Field.ID) ? Field.ID : Field.DISPLAY).toString(); if (!json.has(Field.DESTINATION)) throw missingField(Field.DESTINATION); if (!(json.get(Field.DESTINATION) instanceof JSONObject dst)) throw invalidField(Field.SOURCE,JSON); - var dest = dst.get(dst.has(Field.ID) ? Field.ID : Field.DISPLAY).toString(); - if (!json.has(Field.AMOUNT)) throw missingField(Field.AMOUNT); - if (!(json.get(Field.AMOUNT) instanceof Number amt)) throw invalidField(Field.AMOUNT,Text.NUMBER); - var amount = amt.doubleValue(); + String destination = dst.has(Field.ID) ? dst.get(Field.ID).toString() : dst.has(Field.DISPLAY) ? dst.get(Field.DISPLAY).toString() : null; + Double amount = null; + if (json.has(Field.AMOUNT) && json.get(Field.AMOUNT) instanceof Number amt) amount = amt.doubleValue(); - var transaction = accountDb.lastTransaction(accountId, source, dest, amount); + var transaction = accountDb.lastTransaction(accountId, source, destination, amount); return transaction.isPresent() ? sendContent(ex,transaction.get()) : 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 index 844de420..8fe43af4 100644 --- a/accounting/src/main/java/de/srsoftware/umbrella/accounting/SqliteDb.java +++ b/accounting/src/main/java/de/srsoftware/umbrella/accounting/SqliteDb.java @@ -170,22 +170,42 @@ public class SqliteDb extends BaseDb implements AccountDb { } @Override - public Optional lastTransaction(long accountId, String source, String dest, double amount) { + public Optional lastTransaction(long accountId, String source, String destination, Double amount) { try { - var rs = select(ALL).from(TABLE_TRANSACTIONS) - .where(ACCOUNT,equal(accountId)).where(SOURCE,equal(source)).where(DESTINATION,equal(dest)).where(AMOUNT,equal(amount)) - .sort(ID+" DESC") - .limit(1) - .exec(db); + var query = select(ALL).from(TABLE_TRANSACTIONS).where(ACCOUNT,equal(accountId)); + if (source != null) query = query.where(SOURCE,equal(source)); + if (destination != null) query = query.where(DESTINATION,equal(destination)); + if (amount != null) query = query.where(AMOUNT,equal(amount)); + var rs = query.sort(ID+" DESC").limit(1).exec(db); Transaction ta = null; if (rs.next()) ta = Transaction.of(rs); rs.close(); + + if (ta == null && amount != null) { // try to search by amount, ignore source and dest + rs = select(ALL).from(TABLE_TRANSACTIONS).where(ACCOUNT, equal(accountId)).where(AMOUNT, equal(amount)) + .sort(ID + " DESC").limit(1).exec(db); + if (rs.next()) ta = Transaction.of(rs); + rs.close(); + } + + if (ta == null && source != null && destination != null) { // try to search by amount, ignore source and dest + rs = select(ALL).from(TABLE_TRANSACTIONS) + .where(SOURCE,equal(source)) + .where(DESTINATION,equal(destination)) + .where(ACCOUNT, equal(accountId)) + .sort(ID + " DESC").limit(1).exec(db); + if (rs.next()) ta = Transaction.of(rs); + rs.close(); + } + + if (ta != null){ var tags = ta.tags(); rs = select(TAG).from(TABLE_TAGS_TRANSACTIONS).leftJoin(TAG_ID,TABLE_TAGS,ID).where(TRANSACTION_ID,equal(ta.id())).exec(db); while (rs.next()) tags.add(rs.getString(1)); rs.close(); } + return nullable(ta); } catch (SQLException e) { throw failedToSearchDb(t(Text.ACCOUNTING)); 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 82bd368b..8de21189 100644 --- a/backend/src/main/java/de/srsoftware/umbrella/backend/Application.java +++ b/backend/src/main/java/de/srsoftware/umbrella/backend/Application.java @@ -14,7 +14,6 @@ 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.exceptions.UmbrellaException; import de.srsoftware.umbrella.documents.DocumentApi; import de.srsoftware.umbrella.files.FileModule; @@ -34,7 +33,6 @@ import de.srsoftware.umbrella.translations.Translations; import de.srsoftware.umbrella.user.UserModule; import de.srsoftware.umbrella.web.WebHandler; import de.srsoftware.umbrella.wiki.WikiModule; -import java.io.File; import java.io.IOException; import java.net.InetSocketAddress; import java.util.concurrent.Executors; diff --git a/core/src/main/java/de/srsoftware/umbrella/core/Util.java b/core/src/main/java/de/srsoftware/umbrella/core/Util.java index 5bc43929..db67a3fc 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/Util.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/Util.java @@ -15,7 +15,6 @@ import static java.lang.System.Logger.Level.*; import static java.lang.System.Logger.Level.WARNING; import static java.nio.charset.StandardCharsets.UTF_8; -import com.xrbpowered.jparsedown.JParsedown; import de.srsoftware.tools.Mappable; import de.srsoftware.tools.Query; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; @@ -32,7 +31,6 @@ import java.time.LocalDateTime; import java.time.ZoneId; import java.util.HashMap; import java.util.Map; -import java.util.regex.Pattern; import org.json.JSONObject; public class Util { diff --git a/frontend/src/routes/accounting/account.svelte b/frontend/src/routes/accounting/account.svelte index 02167396..a82d9078 100644 --- a/frontend/src/routes/accounting/account.svelte +++ b/frontend/src/routes/accounting/account.svelte @@ -4,7 +4,7 @@ import { error, yikes } from '../../warn.svelte'; import { t } from '../../translations.svelte'; - import EntryForm from './add_entry.svelte'; + import EntryForm from './add_entry_new.svelte'; import Transaction from './transaction.svelte'; let { id } = $props(); @@ -163,5 +163,5 @@ - + {/if} \ No newline at end of file diff --git a/frontend/src/routes/accounting/add_entry_new.svelte b/frontend/src/routes/accounting/add_entry_new.svelte new file mode 100644 index 00000000..90627146 --- /dev/null +++ b/frontend/src/routes/accounting/add_entry_new.svelte @@ -0,0 +1,205 @@ + + + + +
+ {#if new_account} + {t('create_new_object',{object:t('account')})} + + {t('account name')} + + + + {t('currency')} + + + +
+ {t('first transaction')} + {:else} + {t('add_object',{object:t('transaction')})} + + {/if} + + {t('date')} + + + + + {t('amount')} + + focusOnEnter(e,'source-input')} /> {entry.account.currency} + + + {t('source')} + + + {t('destination')} + + + + {t('purpose')} + + + {t('tags')} + + + + + + +
diff --git a/markdown/src/main/java/de/srsoftware/umbrella/markdown/MarkdownApi.java b/markdown/src/main/java/de/srsoftware/umbrella/markdown/MarkdownApi.java index 0c417eb8..989d4780 100644 --- a/markdown/src/main/java/de/srsoftware/umbrella/markdown/MarkdownApi.java +++ b/markdown/src/main/java/de/srsoftware/umbrella/markdown/MarkdownApi.java @@ -14,11 +14,8 @@ import de.srsoftware.configuration.Configuration; import de.srsoftware.tools.Path; import de.srsoftware.umbrella.core.BaseHandler; import de.srsoftware.umbrella.core.ModuleRegistry; -import de.srsoftware.umbrella.core.Util; import de.srsoftware.umbrella.core.api.MarkdownService; -import de.srsoftware.umbrella.core.constants.Field; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; - import java.io.File; import java.io.IOException; import java.io.InputStream;