implemented removal of transactions
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -297,7 +297,15 @@ public class AccountingModule extends BaseHandler implements AccountingService {
|
|||||||
var key = body(ex);
|
var key = body(ex);
|
||||||
var tags = accountDb.searchTagsContaining(key,accountId);
|
var tags = accountDb.searchTagsContaining(key,accountId);
|
||||||
if (tags.size()<10) tags.addAll(tagService().search(key,user));
|
if (tags.size()<10) tags.addAll(tagService().search(key,user));
|
||||||
return sendContent(ex,tags);
|
return sendContent(ex,egalize(tags,key));
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> egalize(Set<String> tags, String key) {
|
||||||
|
var result = new HashSet<String>();
|
||||||
|
var lower = key.toLowerCase();
|
||||||
|
var len = key.length();
|
||||||
|
for (var tag : tags) result.add(tag.toLowerCase().startsWith(lower) ? key + tag.substring(len) : tag);
|
||||||
|
return result.stream().sorted(String.CASE_INSENSITIVE_ORDER).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean postToAccount(long accountId, Path path, UmbrellaUser user, HttpExchange ex) throws IOException {
|
private boolean postToAccount(long accountId, Path path, UmbrellaUser user, HttpExchange ex) throws IOException {
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ public class SqliteDb extends BaseDb implements AccountDb {
|
|||||||
var timestamp = transaction.date().toEpochSecond(ZoneOffset.UTC);
|
var timestamp = transaction.date().toEpochSecond(ZoneOffset.UTC);
|
||||||
if (transaction.id() == 0) {
|
if (transaction.id() == 0) {
|
||||||
try {
|
try {
|
||||||
var rs = Query.insertInto(TABLE_TRANSACTIONS, Field.ACCOUNT, Field.TIMESTAMP, Field.SOURCE, Field.DESTINATION, Field.AMOUNT, Field.DESCRIPTION)
|
var rs = insertInto(TABLE_TRANSACTIONS, Field.ACCOUNT, Field.TIMESTAMP, Field.SOURCE, Field.DESTINATION, Field.AMOUNT, Field.DESCRIPTION)
|
||||||
.values(transaction.accountId(), timestamp, transaction.source().value(), transaction.destination().value(), transaction.amount(), transaction.purpose())
|
.values(transaction.accountId(), timestamp, transaction.source().value(), transaction.destination().value(), transaction.amount(), transaction.purpose())
|
||||||
.execute(db).getGeneratedKeys();
|
.execute(db).getGeneratedKeys();
|
||||||
if (rs.next()) transaction = transaction.withId(rs.getLong(1));
|
if (rs.next()) transaction = transaction.withId(rs.getLong(1));
|
||||||
@@ -233,9 +233,13 @@ public class SqliteDb extends BaseDb implements AccountDb {
|
|||||||
}
|
}
|
||||||
} else if (transaction.isDirty()) {
|
} else if (transaction.isDirty()) {
|
||||||
try {
|
try {
|
||||||
Query.replaceInto(TABLE_TRANSACTIONS, Field.ID, Field.ACCOUNT, Field.TIMESTAMP, Field.SOURCE, Field.DESTINATION, Field.AMOUNT, Field.DESCRIPTION)
|
if (transaction.amount() == 0) {
|
||||||
|
delete().from(TABLE_TRANSACTIONS).where(Field.ID, equal(transaction.id())).where(ACCOUNT, equal(transaction.accountId())).execute(db);
|
||||||
|
} else {
|
||||||
|
replaceInto(TABLE_TRANSACTIONS, Field.ID, Field.ACCOUNT, Field.TIMESTAMP, Field.SOURCE, Field.DESTINATION, Field.AMOUNT, Field.DESCRIPTION)
|
||||||
.values(transaction.id(), transaction.accountId(), timestamp, transaction.source().value(), transaction.destination().value(), transaction.amount(), transaction.purpose())
|
.values(transaction.id(), transaction.accountId(), timestamp, transaction.source().value(), transaction.destination().value(), transaction.amount(), transaction.purpose())
|
||||||
.execute(db).close();
|
.execute(db).close();
|
||||||
|
}
|
||||||
return transaction.clearDirtyState();
|
return transaction.clearDirtyState();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw failedToStoreObject(transaction);
|
throw failedToStoreObject(transaction);
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ public class Transaction implements Mappable {
|
|||||||
Field.DESTINATION, destination.toMap(),
|
Field.DESTINATION, destination.toMap(),
|
||||||
Field.AMOUNT, amount,
|
Field.AMOUNT, amount,
|
||||||
Field.PURPOSE, purpose,
|
Field.PURPOSE, purpose,
|
||||||
Field.TAGS, tags
|
Field.TAGS, tags.stream().sorted().toList()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,9 @@
|
|||||||
|
|
||||||
let { id } = $props();
|
let { id } = $props();
|
||||||
let account = $state(null);
|
let account = $state(null);
|
||||||
|
let filter = $state([]);
|
||||||
let transactions = $state([]);
|
let transactions = $state([]);
|
||||||
let users = {};
|
let users = {};
|
||||||
|
|
||||||
let sums = {};
|
let sums = {};
|
||||||
|
|
||||||
function calcSums(){
|
function calcSums(){
|
||||||
@@ -27,6 +27,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addToFilter(tag){
|
||||||
|
filter.push(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checker(taglist, filter){
|
||||||
|
return filter.every(tag => taglist.includes(tag));
|
||||||
|
}
|
||||||
|
|
||||||
|
function dropTag(tag){
|
||||||
|
filter = filter.filter(x => x != tag);
|
||||||
|
}
|
||||||
|
|
||||||
async function load(){
|
async function load(){
|
||||||
let url = api(`accounting/${id}`);
|
let url = api(`accounting/${id}`);
|
||||||
let res = await get(url);
|
let res = await get(url);
|
||||||
@@ -51,6 +63,17 @@
|
|||||||
.amount{ text-align: right }
|
.amount{ text-align: right }
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
{#if filter.length > 0}
|
||||||
|
<fieldset>
|
||||||
|
<legend>{t('filter by tags')}</legend>
|
||||||
|
<div class="taglist">
|
||||||
|
{#each filter as tag,i}
|
||||||
|
<span class="tag">{tag} <button onclick={() => dropTag(tag)} class="symbol"></button></span>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
{/if}
|
||||||
{#if account}
|
{#if account}
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>{account.name}</legend>
|
<legend>{account.name}</legend>
|
||||||
@@ -68,7 +91,9 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each transactions as transaction, i}
|
{#each transactions as transaction, i}
|
||||||
<Transaction {account} {transaction} {users} />
|
{#if checker(transaction.tags,filter)}
|
||||||
|
<Transaction {account} {addToFilter} {transaction} {users} />
|
||||||
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
|
|
||||||
import { api, drop, patch, post } from '../../urls.svelte';
|
import { api, drop, patch, post } from '../../urls.svelte';
|
||||||
import { error, yikes } from '../../warn.svelte';
|
import { error, yikes } from '../../warn.svelte';
|
||||||
|
import { t } from '../../translations.svelte';
|
||||||
let { account, addToFilter = tag => {}, transaction, users } = $props();
|
let { account, addToFilter = tag => {}, transaction, users } = $props();
|
||||||
|
let hidden = $state(false);
|
||||||
|
|
||||||
async function dropTag(tag){
|
async function dropTag(tag){
|
||||||
var url = api(`accounting/transaction/${transaction.id}/tag`)
|
var url = api(`accounting/transaction/${transaction.id}/tag`)
|
||||||
@@ -47,6 +49,7 @@
|
|||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
yikes();
|
yikes();
|
||||||
transaction.tags.push(tag.display);
|
transaction.tags.push(tag.display);
|
||||||
|
transaction.tags.sort();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
error(res);
|
error(res);
|
||||||
@@ -54,7 +57,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function setAmount(amount){
|
async function setAmount(amount){
|
||||||
return await update({amount});
|
let result = await update({amount});
|
||||||
|
hidden = (amount == 0);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
async function setDate(date){
|
async function setDate(date){
|
||||||
return await update({date});
|
return await update({date});
|
||||||
@@ -85,6 +90,7 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
{#if !hidden}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<LineEditor type="date" wrapper="span" editable="true" value={transaction.date} onSet={setDate} />
|
<LineEditor type="date" wrapper="span" editable="true" value={transaction.date} onSet={setDate} />
|
||||||
@@ -92,10 +98,10 @@
|
|||||||
{#each Object.entries(users) as [id,user]}
|
{#each Object.entries(users) as [id,user]}
|
||||||
<td class="amount">
|
<td class="amount">
|
||||||
{#if id == transaction.source.id}
|
{#if id == transaction.source.id}
|
||||||
-<LineEditor type="number" wrapper="span" editable="true" value={(+transaction.amount).toFixed(2)} onSet={setAmount} /> {account.currency}
|
-<LineEditor type="number" wrapper="span" editable="true" value={(+transaction.amount).toFixed(2)} onSet={setAmount} title={t('Set to zero in order to drop the transaction')} /> {account.currency}
|
||||||
{/if}
|
{/if}
|
||||||
{#if id == transaction.destination.id}
|
{#if id == transaction.destination.id}
|
||||||
<LineEditor type="number" wrapper="span" editable="true" value={(+transaction.amount).toFixed(2)} onSet={setAmount} /> {account.currency}
|
<LineEditor type="number" wrapper="span" editable="true" value={(+transaction.amount).toFixed(2)} onSet={setAmount} title={t('Set to zero in order to drop the transaction')} /> {account.currency}
|
||||||
{/if}
|
{/if}
|
||||||
</td>
|
</td>
|
||||||
{/each}
|
{/each}
|
||||||
@@ -121,3 +127,4 @@
|
|||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/if}
|
||||||
Reference in New Issue
Block a user