fix(treasurechest): make parentId actually null/nil instead of uuid.Nil
All checks were successful
Build Docker Image / Build-Docker-Image (push) Successful in 5m0s
Build and Push Docker Image / Build-And-Push-Docker-Image (push) Successful in 5m25s

This commit was merged in pull request #117.
This commit is contained in:
2025-05-19 19:56:06 +02:00
parent b18863038c
commit 7a691ec263
8 changed files with 54 additions and 39 deletions

View File

@@ -228,7 +228,7 @@ func (h TransactionImpl) getTransactionData(accounts []*types.Account, treasureC
treasureChestMap := make(map[uuid.UUID]string, 0)
root := ""
for _, treasureChest := range treasureChests {
if treasureChest.ParentId == uuid.Nil {
if treasureChest.ParentId == nil {
root = treasureChest.Name + " > "
treasureChestMap[treasureChest.Id] = treasureChest.Name
} else {

View File

@@ -0,0 +1,3 @@
UPDATE treasure_chest
SET parent_id = NULL
WHERE parent_id = "00000000-0000-0000-0000-000000000000";

View File

@@ -6,7 +6,7 @@ import (
)
var (
safeInputRegex = regexp.MustCompile(`^[a-zA-Z0-9ÄÖÜäöüß, -]+$`)
safeInputRegex = regexp.MustCompile(`^[a-zA-Z0-9ÄÖÜäöüß,& -]+$`)
)
func validateString(value string, fieldName string) error {

View File

@@ -424,6 +424,7 @@ func (s TransactionImpl) RecalculateBalances(user *types.User) error {
if err != nil {
return err
}
}
}
@@ -493,14 +494,17 @@ func (s TransactionImpl) validateAndEnrichTransaction(tx *sqlx.Tx, oldTransactio
return nil, fmt.Errorf("could not parse treasureChestId: %w", ErrBadRequest)
}
treasureChestUuid = &temp
err = tx.Get(&rowCount, `SELECT COUNT(*) FROM treasure_chest WHERE id = ? AND user_id = ?`, treasureChestUuid, userId)
var treasureChest types.TreasureChest
err = tx.Get(&treasureChest, `SELECT * FROM treasure_chest WHERE id = ? AND user_id = ?`, treasureChestUuid, userId)
err = db.TransformAndLogDbError("transaction validate", nil, err)
if err != nil {
if err == db.ErrNotFound {
return nil, fmt.Errorf("treasure chest not found: %w", ErrBadRequest)
}
return nil, err
}
if rowCount == 0 {
log.Error("transaction validate: %v", err)
return nil, fmt.Errorf("treasure chest not found: %w", ErrBadRequest)
if treasureChest.ParentId == nil {
return nil, fmt.Errorf("treasure chest is a group: %w", ErrBadRequest)
}
}

View File

@@ -65,16 +65,16 @@ func (s TreasureChestImpl) Add(user *types.User, parentId, name string) (*types.
return nil, err
}
parentUuid := uuid.Nil
var parentUuid *uuid.UUID
if parentId != "" {
parent, err := s.Get(user, parentId)
if err != nil {
return nil, err
}
if parent.ParentId != uuid.Nil {
if parent.ParentId != nil {
return nil, fmt.Errorf("only a depth of 1 allowed: %w", ErrBadRequest)
}
parentUuid = parent.Id
parentUuid = &parent.Id
}
treasureChest := &types.TreasureChest{
@@ -137,7 +137,7 @@ func (s TreasureChestImpl) Update(user *types.User, idStr, parentId, name string
return nil, types.ErrInternal
}
parentUuid := uuid.Nil
var parentUuid *uuid.UUID
if parentId != "" {
parent, err := s.Get(user, parentId)
if err != nil {
@@ -149,11 +149,11 @@ func (s TreasureChestImpl) Update(user *types.User, idStr, parentId, name string
if err != nil {
return nil, err
}
if parent.ParentId != uuid.Nil || childCount > 0 {
if parent.ParentId != nil || childCount > 0 {
return nil, fmt.Errorf("only one level allowed: %w", ErrBadRequest)
}
parentUuid = parent.Id
parentUuid = &parent.Id
}
timestamp := s.clock.Now()
@@ -292,10 +292,10 @@ func sortTree(nodes []*types.TreasureChest) []*types.TreasureChest {
children := make(map[uuid.UUID][]*types.TreasureChest)
for _, node := range nodes {
if node.ParentId == uuid.Nil {
if node.ParentId == nil {
roots = append(roots, node)
} else {
children[node.ParentId] = append(children[node.ParentId], node)
children[*node.ParentId] = append(children[*node.ParentId], node)
}
}

View File

@@ -27,10 +27,10 @@ templ Transaction(items templ.Component, filter types.TransactionItemsFilter, ac
<select name="treasure-chest-id" class="bg-white input">
<option value="">- Filter Treasure Chest -</option>
for _, parent := range treasureChests {
if parent.ParentId == uuid.Nil {
if parent.ParentId == nil {
<optgroup label={ parent.Name }>
for _, child := range treasureChests {
if child.ParentId == parent.Id {
if *child.ParentId == parent.Id {
<option
value={ child.Id.String() }
selected?={ filter.TreasureChestId == child.Id.String() }
@@ -158,19 +158,21 @@ templ EditTransaction(transaction *types.Transaction, accounts []*types.Account,
}
</select>
<label for="treasure-chest-id" class="text-sm text-gray-500">Treasure Chest</label>
<select
name="treasure-chest-id"
class="bg-white input"
>
<option value="">-</option>
for _, treasureChest := range treasureChests {
<option selected?={ treasureChest.Id.String() == treasureChestId } value={ treasureChest.Id.String() }>
if treasureChest.ParentId != uuid.Nil {
&nbsp;&nbsp;&nbsp;{ treasureChest.Name }
} else {
{ treasureChest.Name }
<select name="treasure-chest-id" class="bg-white input">
<option value="">- Filter Treasure Chest -</option>
for _, parent := range treasureChests {
if parent.ParentId == nil {
<optgroup label={ parent.Name }>
for _, child := range treasureChests {
if *child.ParentId == parent.Id {
<option
value={ child.Id.String() }
selected?={ treasureChestId == child.Id.String() }
>{ child.Name }</option>
}
}
</optgroup>
}
</option>
}
</select>
</div>

View File

@@ -41,7 +41,9 @@ templ EditTreasureChest(treasureChest *types.TreasureChest, parents []*types.Tre
} else {
id = treasureChest.Id.String()
name = treasureChest.Name
parentId = treasureChest.ParentId
if treasureChest.ParentId != nil {
parentId = *treasureChest.ParentId
}
cancelUrl = "/treasurechest/" + id
}
}}
@@ -93,23 +95,27 @@ templ EditTreasureChest(treasureChest *types.TreasureChest, parents []*types.Tre
templ TreasureChestItem(treasureChest *types.TreasureChest) {
{{
var identation string
if treasureChest.ParentId != uuid.Nil {
viewTransactions := ""
if treasureChest.ParentId != nil {
identation = " mt-2 ml-36"
} else {
identation = " mt-8"
viewTransactions = "hidden"
}
}}
<div id="treasurechest" class={ "border-1 border-gray-300 w-full p-4 bg-gray-50 rounded-lg" + identation }>
<div class="text-xl flex justify-end items-center gap-4">
<p class="mr-auto">{ treasureChest.Name }</p>
if treasureChest.ParentId != nil {
if treasureChest.CurrentBalance < 0 {
<p class="mr-20 text-red-700">{ displayBalance(treasureChest.CurrentBalance) }</p>
} else {
<p class="mr-20 text-green-700">{ displayBalance(treasureChest.CurrentBalance) }</p>
}
}
<a
href={ templ.URL("/transaction?treasure-chest-id=" + treasureChest.Id.String()) }
class="button button-neglect px-1 flex items-center gap-2"
class={ "button button-neglect px-1 flex items-center gap-2 " + viewTransactions }
title="View transactions"
>
@svg.Eye()
@@ -147,7 +153,7 @@ func filterNoChildNoSelf(nodes []*types.TreasureChest, selfId string) []*types.T
var result []*types.TreasureChest
for _, node := range nodes {
if node.ParentId == uuid.Nil && node.Id.String() != selfId {
if node.ParentId == nil && node.Id.String() != selfId {
result = append(result, node)
}
}

View File

@@ -13,7 +13,7 @@ import (
// Imagne a TreasureChest for free time activities, where some money is spend in cash and some other with credit card
type TreasureChest struct {
Id uuid.UUID
ParentId uuid.UUID `db:"parent_id"`
ParentId *uuid.UUID `db:"parent_id"`
UserId uuid.UUID `db:"user_id"`
Name string