niki/domain/wallet/repository/postgres/insert_transaction.go

100 lines
2.9 KiB
Go

package postgres
import (
"context"
"git.gocasts.ir/ebhomengo/niki/domain/wallet/entity"
"git.gocasts.ir/ebhomengo/niki/pkg/database/postgres"
errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg"
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
)
func (db *DB) InsertTransaction(ctx context.Context, transaction entity.Transaction) (balance float64, err error) {
const op = richerror.Op("wallet.repo.InsertTransaction")
query := `INSERT INTO Transactions (user_id, amount ,currency ,action_type, timestamp) values ($1, $2, $3, $4, $5)`
stmt, stErr := db.conn.PrepareStatement(ctx, postgres.StatementKeyWalletInsertTransaction, query)
if stErr != nil {
err = richerror.New(op).WithErr(stErr).WithKind(richerror.KindUnexpected)
return
}
txHolder, newCtx := postgres.GetDBTxHolderFromContextOrNew(ctx)
tx, txErr := txHolder.BeginTx(newCtx, db.conn.Conn())
if txErr != nil {
err = richerror.New(op).WithErr(txErr).WithKind(richerror.KindUnexpected)
return
}
defer func() {
if tx != nil {
if err != nil {
if rbErr := tx.Rollback(); rbErr != nil {
// log rbErr
}
} else if cErr := tx.Commit(); cErr != nil {
// log cErr
}
}
}()
params := []any{transaction.UserID, transaction.Amount, transaction.Currency, transaction.ActionType, transaction.Timestamp}
_, execErr := tx.StmtExecContext(newCtx, stmt, params...)
if execErr != nil {
err = richerror.New(op).WithErr(execErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgFailedQuery)
return
}
newBalance, blanceErr := db.UpsertBalance(newCtx, transaction.UserID, transaction.Amount)
if blanceErr != nil {
err = richerror.New(op).WithErr(blanceErr)
return
}
balance = newBalance
return
}
func (db *DB) UpsertBalance(newCtx context.Context, userID uint64, amount float64) (balance float64, err error) {
const op = richerror.Op("wallet.repo.UpdateBalance")
txHolder, _ := postgres.GetDBTxHolderFromContextOrNew(newCtx)
tx, txErr := txHolder.Conn()
if txErr != nil {
err = richerror.New(op).WithMessage(errmsg.ErrorMsgCantUpsertBalance).WithKind(richerror.KindUnexpected)
return
}
if tx == nil {
err = richerror.New(op).WithMessage(errmsg.ErrorMsgCantUpsertBalance).WithKind(richerror.KindUnexpected)
return
}
upsertQuery := `INSERT INTO wallets (user_id, balance) VALUES ($1, $2)
ON CONFLICT (user_id) DO UPDATE SET balance = wallets.balance + $2
RETURNING balance`
upsertStmt, stErr := db.conn.PrepareStatement(newCtx, postgres.StatementKeyWalletUpsertBalance, upsertQuery)
if stErr != nil {
err = richerror.New(op).WithMessage(errmsg.ErrorMsgFailedQuery).WithKind(richerror.KindUnexpected)
return
}
row := tx.StmtQueryRowContext(newCtx, upsertStmt, userID, amount)
sErr := row.Scan(&balance)
if sErr != nil {
err = richerror.New(op).WithMessage(errmsg.ErrorMsgCantScanQueryResult).WithKind(richerror.KindUnexpected)
return
}
return balance, nil
}