Add description to money transfers

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2024-02-04 12:40:16 +01:00
parent a3523c0a16
commit 5d41188876
Signed by: luzifer
SSH key fingerprint: SHA256:/xtE5lCgiRDQr8SLxHMS92ZBlACmATUmF1crK16Ks4E
4 changed files with 39 additions and 16 deletions

View file

@ -228,7 +228,7 @@
aria-labelledby="transferMoneyModalLabel" aria-labelledby="transferMoneyModalLabel"
aria-hidden="true" aria-hidden="true"
> >
<div class="modal-dialog modal-sm"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h1 <h1
@ -306,6 +306,19 @@
</select> </select>
</div> </div>
<div class="mb-3">
<label
for="transferMoneyModalDescription"
class="form-label"
>Description</label>
<input
id="transferMoneyModalDescription"
v-model.number="modals.createTransfer.description"
type="text"
class="form-control"
>
</div>
<div class="mb-3"> <div class="mb-3">
<label <label
for="transferMoneyModalAmount" for="transferMoneyModalAmount"
@ -453,6 +466,7 @@ export default {
createTransfer: { createTransfer: {
amount: 0, amount: 0,
category: '', category: '',
description: '',
from: '', from: '',
to: '', to: '',
}, },
@ -550,6 +564,9 @@ export default {
if (this.modals.createTransfer.category) { if (this.modals.createTransfer.category) {
params.set('category', this.modals.createTransfer.category) params.set('category', this.modals.createTransfer.category)
} }
if (this.modals.createTransfer.description) {
params.set('description', this.modals.createTransfer.description)
}
return fetch(`/api/accounts/${this.modals.createTransfer.from}/transfer/${this.modals.createTransfer.to}?${params.toString()}`, { return fetch(`/api/accounts/${this.modals.createTransfer.from}/transfer/${this.modals.createTransfer.to}?${params.toString()}`, {
method: 'PUT', method: 'PUT',

View file

@ -54,7 +54,7 @@ func (a apiServer) handleCreateAccount(w http.ResponseWriter, r *http.Request) {
}) })
case database.AccountTypeCategory: case database.AccountTypeCategory:
err = a.dbc.TransferMoney(database.UnallocatedMoney, acc.ID, payload.StartingBalance) err = a.dbc.TransferMoney(database.UnallocatedMoney, acc.ID, payload.StartingBalance, "")
case database.AccountTypeTracking: case database.AccountTypeTracking:
_, err = a.dbc.CreateTransaction(database.Transaction{ _, err = a.dbc.CreateTransaction(database.Transaction{
@ -184,12 +184,12 @@ func (a apiServer) handleTransferMoney(w http.ResponseWriter, r *http.Request) {
} }
if category == uuid.Nil { if category == uuid.Nil {
if err = a.dbc.TransferMoney(from, to, amount); err != nil { if err = a.dbc.TransferMoney(from, to, amount, r.URL.Query().Get("description")); err != nil {
a.errorResponse(w, err, "transferring money", http.StatusInternalServerError) a.errorResponse(w, err, "transferring money", http.StatusInternalServerError)
return return
} }
} else { } else {
if err = a.dbc.TransferMoneyWithCategory(from, to, amount, category); err != nil { if err = a.dbc.TransferMoneyWithCategory(from, to, amount, r.URL.Query().Get("description"), category); err != nil {
a.errorResponse(w, err, "transferring money", http.StatusInternalServerError) a.errorResponse(w, err, "transferring money", http.StatusInternalServerError)
return return
} }

View file

@ -287,7 +287,7 @@ func (c *Client) MarkAccountReconciled(acc uuid.UUID) (err error) {
// TransferMoney creates new Transactions for the given account // TransferMoney creates new Transactions for the given account
// transfer. The account type of the from and to account must match // transfer. The account type of the from and to account must match
// for this to work. // for this to work.
func (c *Client) TransferMoney(from, to uuid.UUID, amount float64) (err error) { func (c *Client) TransferMoney(from, to uuid.UUID, amount float64, description string) (err error) {
var fromAcc, toAcc Account var fromAcc, toAcc Account
if fromAcc, err = c.GetAccount(from); err != nil { if fromAcc, err = c.GetAccount(from); err != nil {
@ -311,7 +311,8 @@ func (c *Client) TransferMoney(from, to uuid.UUID, amount float64) (err error) {
txs = []*Transaction{ txs = []*Transaction{
{ {
Time: time.Now().UTC(), Time: time.Now().UTC(),
Description: fmt.Sprintf("Transfer: %s → %s", fromAcc.Name, toAcc.Name), Payee: fmt.Sprintf("Transfer: %s → %s", fromAcc.Name, toAcc.Name),
Description: description,
Amount: -amount, Amount: -amount,
Account: uuid.NullUUID{UUID: from, Valid: true}, Account: uuid.NullUUID{UUID: from, Valid: true},
Category: uuid.NullUUID{}, Category: uuid.NullUUID{},
@ -320,7 +321,8 @@ func (c *Client) TransferMoney(from, to uuid.UUID, amount float64) (err error) {
}, },
{ {
Time: time.Now().UTC(), Time: time.Now().UTC(),
Description: fmt.Sprintf("Transfer: %s → %s", fromAcc.Name, toAcc.Name), Payee: fmt.Sprintf("Transfer: %s → %s", fromAcc.Name, toAcc.Name),
Description: description,
Amount: amount, Amount: amount,
Account: uuid.NullUUID{UUID: to, Valid: true}, Account: uuid.NullUUID{UUID: to, Valid: true},
Category: uuid.NullUUID{}, Category: uuid.NullUUID{},
@ -334,7 +336,8 @@ func (c *Client) TransferMoney(from, to uuid.UUID, amount float64) (err error) {
txs = []*Transaction{ txs = []*Transaction{
{ {
Time: time.Now().UTC(), Time: time.Now().UTC(),
Description: fmt.Sprintf("Transfer: %s → %s", fromAcc.Name, toAcc.Name), Payee: fmt.Sprintf("Transfer: %s → %s", fromAcc.Name, toAcc.Name),
Description: description,
Amount: -amount, Amount: -amount,
Account: uuid.NullUUID{}, Account: uuid.NullUUID{},
Category: uuid.NullUUID{UUID: from, Valid: true}, Category: uuid.NullUUID{UUID: from, Valid: true},
@ -343,7 +346,8 @@ func (c *Client) TransferMoney(from, to uuid.UUID, amount float64) (err error) {
}, },
{ {
Time: time.Now().UTC(), Time: time.Now().UTC(),
Description: fmt.Sprintf("Transfer: %s → %s", fromAcc.Name, toAcc.Name), Payee: fmt.Sprintf("Transfer: %s → %s", fromAcc.Name, toAcc.Name),
Description: description,
Amount: amount, Amount: amount,
Account: uuid.NullUUID{}, Account: uuid.NullUUID{},
Category: uuid.NullUUID{UUID: to, Valid: true}, Category: uuid.NullUUID{UUID: to, Valid: true},
@ -370,7 +374,7 @@ func (c *Client) TransferMoney(from, to uuid.UUID, amount float64) (err error) {
// TransferMoneyWithCategory creates new Transactions for the given // TransferMoneyWithCategory creates new Transactions for the given
// account transfer. This is not possible for category type accounts. // account transfer. This is not possible for category type accounts.
func (c *Client) TransferMoneyWithCategory(from, to uuid.UUID, amount float64, category uuid.UUID) (err error) { func (c *Client) TransferMoneyWithCategory(from, to uuid.UUID, amount float64, description string, category uuid.UUID) (err error) {
var fromAcc, toAcc Account var fromAcc, toAcc Account
if fromAcc, err = c.GetAccount(from); err != nil { if fromAcc, err = c.GetAccount(from); err != nil {
@ -390,7 +394,8 @@ func (c *Client) TransferMoneyWithCategory(from, to uuid.UUID, amount float64, c
if err = c.retryTx(func(tx *gorm.DB) (err error) { if err = c.retryTx(func(tx *gorm.DB) (err error) {
fromTx := Transaction{ fromTx := Transaction{
Time: time.Now().UTC(), Time: time.Now().UTC(),
Description: fmt.Sprintf("Transfer: %s → %s", fromAcc.Name, toAcc.Name), Payee: fmt.Sprintf("Transfer: %s → %s", fromAcc.Name, toAcc.Name),
Description: description,
Amount: -amount, Amount: -amount,
Account: uuid.NullUUID{UUID: from, Valid: true}, Account: uuid.NullUUID{UUID: from, Valid: true},
Category: uuid.NullUUID{}, Category: uuid.NullUUID{},
@ -404,7 +409,8 @@ func (c *Client) TransferMoneyWithCategory(from, to uuid.UUID, amount float64, c
toTx := Transaction{ toTx := Transaction{
Time: time.Now().UTC(), Time: time.Now().UTC(),
Description: fmt.Sprintf("Transfer: %s → %s", fromAcc.Name, toAcc.Name), Payee: fmt.Sprintf("Transfer: %s → %s", fromAcc.Name, toAcc.Name),
Description: description,
Amount: amount, Amount: amount,
Account: uuid.NullUUID{UUID: to, Valid: true}, Account: uuid.NullUUID{UUID: to, Valid: true},
Category: uuid.NullUUID{}, Category: uuid.NullUUID{},

View file

@ -94,7 +94,7 @@ func TestPairKeyRemoval(t *testing.T) {
testCheckAcctBal(t, bals, tb2.ID, 0) testCheckAcctBal(t, bals, tb2.ID, 0)
// Transfer some money // Transfer some money
require.NoError(t, dbc.TransferMoney(tb1.ID, tb2.ID, 500)) require.NoError(t, dbc.TransferMoney(tb1.ID, tb2.ID, 500, ""))
bals, err = dbc.ListAccountBalances(false) bals, err = dbc.ListAccountBalances(false)
require.NoError(t, err) require.NoError(t, err)
testCheckAcctBal(t, bals, tb1.ID, -500) testCheckAcctBal(t, bals, tb1.ID, -500)
@ -163,7 +163,7 @@ func TestTransactions(t *testing.T) {
testCheckAcctBal(t, bals, UnallocatedMoney, 1000) testCheckAcctBal(t, bals, UnallocatedMoney, 1000)
// Lets redistribute the money // Lets redistribute the money
require.NoError(t, dbc.TransferMoney(UnallocatedMoney, tc.ID, 500)) require.NoError(t, dbc.TransferMoney(UnallocatedMoney, tc.ID, 500, ""))
bals, err = dbc.ListAccountBalances(false) bals, err = dbc.ListAccountBalances(false)
require.NoError(t, err) require.NoError(t, err)
testCheckAcctBal(t, bals, tb1.ID, 1000) testCheckAcctBal(t, bals, tb1.ID, 1000)
@ -173,7 +173,7 @@ func TestTransactions(t *testing.T) {
testCheckAcctBal(t, bals, UnallocatedMoney, 500) testCheckAcctBal(t, bals, UnallocatedMoney, 500)
// Now transfer some money to another budget account // Now transfer some money to another budget account
require.NoError(t, dbc.TransferMoney(tb1.ID, tb2.ID, 100)) require.NoError(t, dbc.TransferMoney(tb1.ID, tb2.ID, 100, ""))
bals, err = dbc.ListAccountBalances(false) bals, err = dbc.ListAccountBalances(false)
require.NoError(t, err) require.NoError(t, err)
testCheckAcctBal(t, bals, tb1.ID, 900) testCheckAcctBal(t, bals, tb1.ID, 900)
@ -183,7 +183,7 @@ func TestTransactions(t *testing.T) {
testCheckAcctBal(t, bals, UnallocatedMoney, 500) testCheckAcctBal(t, bals, UnallocatedMoney, 500)
// And some to a tracking account (needs category) // And some to a tracking account (needs category)
require.NoError(t, dbc.TransferMoneyWithCategory(tb1.ID, tt.ID, 100, tc.ID)) require.NoError(t, dbc.TransferMoneyWithCategory(tb1.ID, tt.ID, 100, "", tc.ID))
bals, err = dbc.ListAccountBalances(false) bals, err = dbc.ListAccountBalances(false)
require.NoError(t, err) require.NoError(t, err)
testCheckAcctBal(t, bals, tb1.ID, 800) testCheckAcctBal(t, bals, tb1.ID, 800)