forked from ebhomengo/niki
100 lines
2.9 KiB
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.Currency, transaction.Amount, transaction.ActionType, transaction.Timestamp}
|
|
|
|
_, execErr := tx.StmtExecContext(newCtx, stmt, params...)
|
|
if execErr != nil {
|
|
err = richerror.New(op).WithErr(execErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgCantInsertTransaction)
|
|
|
|
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
|
|
}
|