feat: #74 properly use transactions
This commit was merged in pull request #90.
This commit is contained in:
@@ -109,8 +109,17 @@ func (s AccountImpl) UpdateName(user *types.User, id string, name string) (*type
|
||||
return nil, fmt.Errorf("could not parse Id: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
tx, err := s.db.Beginx()
|
||||
err = db.TransformAndLogDbError("account Update", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
_ = tx.Rollback()
|
||||
}()
|
||||
|
||||
var account types.Account
|
||||
err = s.db.Get(&account, `SELECT * FROM account WHERE user_id = ? AND id = ?`, user.Id, uuid)
|
||||
err = tx.Get(&account, `SELECT * FROM account WHERE user_id = ? AND id = ?`, user.Id, uuid)
|
||||
err = db.TransformAndLogDbError("account Update", nil, err)
|
||||
if err != nil {
|
||||
if err == db.ErrNotFound {
|
||||
@@ -124,7 +133,7 @@ func (s AccountImpl) UpdateName(user *types.User, id string, name string) (*type
|
||||
account.UpdatedAt = ×tamp
|
||||
account.UpdatedBy = &user.Id
|
||||
|
||||
r, err := s.db.NamedExec(`
|
||||
r, err := tx.NamedExec(`
|
||||
UPDATE account
|
||||
SET
|
||||
name = :name,
|
||||
@@ -137,6 +146,12 @@ func (s AccountImpl) UpdateName(user *types.User, id string, name string) (*type
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
err = db.TransformAndLogDbError("account Update", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &account, nil
|
||||
}
|
||||
|
||||
@@ -192,8 +207,17 @@ func (s AccountImpl) Delete(user *types.User, id string) error {
|
||||
return fmt.Errorf("could not parse Id: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
tx, err := s.db.Beginx()
|
||||
err = db.TransformAndLogDbError("account Delete", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
_ = tx.Rollback()
|
||||
}()
|
||||
|
||||
transactionsCount := 0
|
||||
err = s.db.Get(&transactionsCount, `SELECT COUNT(*) FROM "transaction" WHERE user_id = ? AND account_id = ?`, user.Id, uuid)
|
||||
err = tx.Get(&transactionsCount, `SELECT COUNT(*) FROM "transaction" WHERE user_id = ? AND account_id = ?`, user.Id, uuid)
|
||||
err = db.TransformAndLogDbError("account Delete", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -202,10 +226,17 @@ func (s AccountImpl) Delete(user *types.User, id string) error {
|
||||
return fmt.Errorf("account has transactions, cannot delete: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
res, err := s.db.Exec("DELETE FROM account WHERE id = ? and user_id = ?", uuid, user.Id)
|
||||
res, err := tx.Exec("DELETE FROM account WHERE id = ? and user_id = ?", uuid, user.Id)
|
||||
err = db.TransformAndLogDbError("account Delete", res, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
err = db.TransformAndLogDbError("account Delete", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -58,12 +58,21 @@ func (s TransactionImpl) Add(user *types.User, transactionInput types.Transactio
|
||||
return nil, ErrUnauthorized
|
||||
}
|
||||
|
||||
transaction, err := s.validateAndEnrichTransaction(nil, user.Id, transactionInput)
|
||||
tx, err := s.db.Beginx()
|
||||
err = db.TransformAndLogDbError("transaction Add", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
_ = tx.Rollback()
|
||||
}()
|
||||
|
||||
transaction, err := s.validateAndEnrichTransaction(tx, nil, user.Id, transactionInput)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r, err := s.db.NamedExec(`
|
||||
r, err := tx.NamedExec(`
|
||||
INSERT INTO "transaction" (id, user_id, account_id, treasure_chest_id, value, timestamp, note, error, created_at, created_by)
|
||||
VALUES (:id, :user_id, :account_id, :treasure_chest_id, :value, :timestamp, :note, :error, :created_at, :created_by)`, transaction)
|
||||
err = db.TransformAndLogDbError("transaction Insert", r, err)
|
||||
@@ -72,27 +81,33 @@ func (s TransactionImpl) Add(user *types.User, transactionInput types.Transactio
|
||||
}
|
||||
|
||||
if transaction.AccountId != nil {
|
||||
r, err = s.db.Exec(`
|
||||
r, err = tx.Exec(`
|
||||
UPDATE account
|
||||
SET current_balance = current_balance + ?
|
||||
WHERE id = ? AND user_id = ?`, transaction.Value, transaction.AccountId, user.Id)
|
||||
err = db.TransformAndLogDbError("transaction Update", r, err)
|
||||
err = db.TransformAndLogDbError("transaction Add", r, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if transaction.TreasureChestId != nil {
|
||||
r, err = s.db.Exec(`
|
||||
r, err = tx.Exec(`
|
||||
UPDATE treasure_chest
|
||||
SET current_balance = current_balance + ?
|
||||
WHERE id = ? AND user_id = ?`, transaction.Value, transaction.TreasureChestId, user.Id)
|
||||
err = db.TransformAndLogDbError("transaction Update", r, err)
|
||||
err = db.TransformAndLogDbError("transaction Add", r, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
err = db.TransformAndLogDbError("transaction Add", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return transaction, nil
|
||||
}
|
||||
|
||||
@@ -107,8 +122,17 @@ func (s TransactionImpl) Update(user *types.User, input types.TransactionInput)
|
||||
return nil, fmt.Errorf("could not parse Id: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
tx, err := s.db.Beginx()
|
||||
err = db.TransformAndLogDbError("transaction Update", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
_ = tx.Rollback()
|
||||
}()
|
||||
|
||||
transaction := &types.Transaction{}
|
||||
err = s.db.Get(transaction, `SELECT * FROM "transaction" WHERE user_id = ? AND id = ?`, user.Id, uuid)
|
||||
err = tx.Get(transaction, `SELECT * FROM "transaction" WHERE user_id = ? AND id = ?`, user.Id, uuid)
|
||||
err = db.TransformAndLogDbError("transaction Update", nil, err)
|
||||
if err != nil {
|
||||
if err == db.ErrNotFound {
|
||||
@@ -118,7 +142,7 @@ func (s TransactionImpl) Update(user *types.User, input types.TransactionInput)
|
||||
}
|
||||
|
||||
if transaction.AccountId != nil {
|
||||
r, err := s.db.Exec(`
|
||||
r, err := tx.Exec(`
|
||||
UPDATE account
|
||||
SET current_balance = current_balance - ?
|
||||
WHERE id = ? AND user_id = ?`, transaction.Value, transaction.AccountId, user.Id)
|
||||
@@ -128,7 +152,7 @@ func (s TransactionImpl) Update(user *types.User, input types.TransactionInput)
|
||||
}
|
||||
}
|
||||
if transaction.TreasureChestId != nil {
|
||||
r, err := s.db.Exec(`
|
||||
r, err := tx.Exec(`
|
||||
UPDATE treasure_chest
|
||||
SET current_balance = current_balance - ?
|
||||
WHERE id = ? AND user_id = ?`, transaction.Value, transaction.TreasureChestId, user.Id)
|
||||
@@ -138,13 +162,13 @@ func (s TransactionImpl) Update(user *types.User, input types.TransactionInput)
|
||||
}
|
||||
}
|
||||
|
||||
transaction, err = s.validateAndEnrichTransaction(transaction, user.Id, input)
|
||||
transaction, err = s.validateAndEnrichTransaction(tx, transaction, user.Id, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if transaction.AccountId != nil {
|
||||
r, err := s.db.Exec(`
|
||||
r, err := tx.Exec(`
|
||||
UPDATE account
|
||||
SET current_balance = current_balance + ?
|
||||
WHERE id = ? AND user_id = ?`, transaction.Value, transaction.AccountId, user.Id)
|
||||
@@ -154,7 +178,7 @@ func (s TransactionImpl) Update(user *types.User, input types.TransactionInput)
|
||||
}
|
||||
}
|
||||
if transaction.TreasureChestId != nil {
|
||||
r, err := s.db.Exec(`
|
||||
r, err := tx.Exec(`
|
||||
UPDATE treasure_chest
|
||||
SET current_balance = current_balance + ?
|
||||
WHERE id = ? AND user_id = ?`, transaction.Value, transaction.TreasureChestId, user.Id)
|
||||
@@ -164,7 +188,7 @@ func (s TransactionImpl) Update(user *types.User, input types.TransactionInput)
|
||||
}
|
||||
}
|
||||
|
||||
r, err := s.db.NamedExec(`
|
||||
r, err := tx.NamedExec(`
|
||||
UPDATE "transaction"
|
||||
SET
|
||||
account_id = :account_id,
|
||||
@@ -182,6 +206,12 @@ func (s TransactionImpl) Update(user *types.User, input types.TransactionInput)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
err = db.TransformAndLogDbError("transaction Update", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return transaction, nil
|
||||
}
|
||||
|
||||
@@ -236,7 +266,16 @@ func (s TransactionImpl) Delete(user *types.User, id string) error {
|
||||
return fmt.Errorf("could not parse Id: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
r, err := s.db.Exec(`
|
||||
tx, err := s.db.Beginx()
|
||||
err = db.TransformAndLogDbError("transaction Delete", nil, err)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer func() {
|
||||
_ = tx.Rollback()
|
||||
}()
|
||||
|
||||
r, err := tx.Exec(`
|
||||
UPDATE account
|
||||
SET current_balance = current_balance - (SELECT value FROM "transaction" WHERE id = ? AND user_id = ?)
|
||||
WHERE id = (SELECT account_id FROM "transaction" WHERE id = ? AND user_id = ?)
|
||||
@@ -245,7 +284,7 @@ func (s TransactionImpl) Delete(user *types.User, id string) error {
|
||||
if err != nil && err != db.ErrNotFound {
|
||||
return err
|
||||
}
|
||||
r, err = s.db.Exec(`
|
||||
r, err = tx.Exec(`
|
||||
UPDATE treasure_chest
|
||||
SET current_balance = current_balance - (SELECT value FROM "transaction" WHERE id = ? AND user_id = ?)
|
||||
WHERE id = (SELECT treasure_chest_id FROM "transaction" WHERE id = ? AND user_id = ?)
|
||||
@@ -255,12 +294,18 @@ func (s TransactionImpl) Delete(user *types.User, id string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
r, err = s.db.Exec("DELETE FROM \"transaction\" WHERE id = ? AND user_id = ?", uuid, user.Id)
|
||||
r, err = tx.Exec("DELETE FROM \"transaction\" WHERE id = ? AND user_id = ?", uuid, user.Id)
|
||||
err = db.TransformAndLogDbError("transaction Delete", r, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
err = db.TransformAndLogDbError("transaction RecalculateBalances", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -365,7 +410,7 @@ func (s TransactionImpl) RecalculateBalances(user *types.User) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s TransactionImpl) validateAndEnrichTransaction(oldTransaction *types.Transaction, userId uuid.UUID, input types.TransactionInput) (*types.Transaction, error) {
|
||||
func (s TransactionImpl) validateAndEnrichTransaction(tx *sqlx.Tx, oldTransaction *types.Transaction, userId uuid.UUID, input types.TransactionInput) (*types.Transaction, error) {
|
||||
|
||||
var (
|
||||
id uuid.UUID
|
||||
@@ -403,7 +448,7 @@ func (s TransactionImpl) validateAndEnrichTransaction(oldTransaction *types.Tran
|
||||
return nil, fmt.Errorf("could not parse accountId: %w", ErrBadRequest)
|
||||
}
|
||||
accountUuid = &temp
|
||||
err = s.db.Get(&rowCount, `SELECT COUNT(*) FROM account WHERE id = ? AND user_id = ?`, accountUuid, userId)
|
||||
err = tx.Get(&rowCount, `SELECT COUNT(*) FROM account WHERE id = ? AND user_id = ?`, accountUuid, userId)
|
||||
err = db.TransformAndLogDbError("transaction validate", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -422,7 +467,7 @@ func (s TransactionImpl) validateAndEnrichTransaction(oldTransaction *types.Tran
|
||||
return nil, fmt.Errorf("could not parse treasureChestId: %w", ErrBadRequest)
|
||||
}
|
||||
treasureChestUuid = &temp
|
||||
err = s.db.Get(&rowCount, `SELECT COUNT(*) FROM treasure_chest WHERE id = ? AND user_id = ?`, treasureChestUuid, userId)
|
||||
err = tx.Get(&rowCount, `SELECT COUNT(*) FROM treasure_chest WHERE id = ? AND user_id = ?`, treasureChestUuid, userId)
|
||||
err = db.TransformAndLogDbError("transaction validate", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -117,8 +117,17 @@ func (s TreasureChestImpl) Update(user *types.User, idStr, parentId, name string
|
||||
return nil, fmt.Errorf("could not parse Id: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
tx, err := s.db.Beginx()
|
||||
err = db.TransformAndLogDbError("treasureChest Update", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
_ = tx.Rollback()
|
||||
}()
|
||||
|
||||
treasureChest := &types.TreasureChest{}
|
||||
err = s.db.Get(treasureChest, `SELECT * FROM treasure_chest WHERE user_id = ? AND id = ?`, user.Id, id)
|
||||
err = tx.Get(treasureChest, `SELECT * FROM treasure_chest WHERE user_id = ? AND id = ?`, user.Id, id)
|
||||
err = db.TransformAndLogDbError("treasureChest Update", nil, err)
|
||||
if err != nil {
|
||||
if err == db.ErrNotFound {
|
||||
@@ -134,7 +143,7 @@ func (s TreasureChestImpl) Update(user *types.User, idStr, parentId, name string
|
||||
return nil, err
|
||||
}
|
||||
var childCount int
|
||||
err = s.db.Get(&childCount, `SELECT COUNT(*) FROM treasure_chest WHERE user_id = ? AND parent_id = ?`, user.Id, id)
|
||||
err = tx.Get(&childCount, `SELECT COUNT(*) FROM treasure_chest WHERE user_id = ? AND parent_id = ?`, user.Id, id)
|
||||
err = db.TransformAndLogDbError("treasureChest Update", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -152,7 +161,7 @@ func (s TreasureChestImpl) Update(user *types.User, idStr, parentId, name string
|
||||
treasureChest.UpdatedAt = ×tamp
|
||||
treasureChest.UpdatedBy = &user.Id
|
||||
|
||||
r, err := s.db.NamedExec(`
|
||||
r, err := tx.NamedExec(`
|
||||
UPDATE treasure_chest
|
||||
SET
|
||||
parent_id = :parent_id,
|
||||
@@ -167,6 +176,12 @@ func (s TreasureChestImpl) Update(user *types.User, idStr, parentId, name string
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
err = db.TransformAndLogDbError("treasureChest Update", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return treasureChest, nil
|
||||
}
|
||||
|
||||
@@ -222,8 +237,17 @@ func (s TreasureChestImpl) Delete(user *types.User, idStr string) error {
|
||||
return fmt.Errorf("could not parse Id: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
tx, err := s.db.Beginx()
|
||||
err = db.TransformAndLogDbError("treasureChest Delete", nil, err)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer func() {
|
||||
_ = tx.Rollback()
|
||||
}()
|
||||
|
||||
childCount := 0
|
||||
err = s.db.Get(&childCount, `SELECT COUNT(*) FROM treasure_chest WHERE user_id = ? AND parent_id = ?`, user.Id, id)
|
||||
err = tx.Get(&childCount, `SELECT COUNT(*) FROM treasure_chest WHERE user_id = ? AND parent_id = ?`, user.Id, id)
|
||||
err = db.TransformAndLogDbError("treasureChest Delete", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -234,7 +258,7 @@ func (s TreasureChestImpl) Delete(user *types.User, idStr string) error {
|
||||
}
|
||||
|
||||
transactionsCount := 0
|
||||
err = s.db.Get(&transactionsCount, `SELECT COUNT(*) FROM "transaction" WHERE user_id = ? AND treasure_chest_id = ?`, user.Id, id)
|
||||
err = tx.Get(&transactionsCount, `SELECT COUNT(*) FROM "transaction" WHERE user_id = ? AND treasure_chest_id = ?`, user.Id, id)
|
||||
err = db.TransformAndLogDbError("treasureChest Delete", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -243,12 +267,18 @@ func (s TreasureChestImpl) Delete(user *types.User, idStr string) error {
|
||||
return fmt.Errorf("treasure chest has transactions: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
r, err := s.db.Exec(`DELETE FROM treasure_chest WHERE id = ? AND user_id = ?`, id, user.Id)
|
||||
r, err := tx.Exec(`DELETE FROM treasure_chest WHERE id = ? AND user_id = ?`, id, user.Id)
|
||||
err = db.TransformAndLogDbError("treasureChest Delete", r, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
err = db.TransformAndLogDbError("treasureChest Delete", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user