transfer-allowances (#143)
Reviewed-on: #143
This commit was merged in pull request #143.
This commit is contained in:
@@ -711,3 +711,71 @@ func (db *Db) AddAllowanceAmount(userId int, allowanceId int, request AddAllowan
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (db *Db) TransferAllowance(fromId int, toId int, amount float64) error {
|
||||
if fromId == toId {
|
||||
return nil
|
||||
}
|
||||
amountCents := int(math.Round(amount * 100.0))
|
||||
if amountCents <= 0 {
|
||||
return fmt.Errorf("amount must be positive")
|
||||
}
|
||||
|
||||
tx, err := db.db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.MustRollback()
|
||||
|
||||
// Fetch from allowance (user_id, balance)
|
||||
var fromUserId int
|
||||
var fromBalance int
|
||||
err = tx.Query("select user_id, balance from allowances where id = ?").Bind(fromId).ScanSingle(&fromUserId, &fromBalance)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Fetch to allowance (user_id, target, balance)
|
||||
var toUserId int
|
||||
var toTarget int
|
||||
var toBalance int
|
||||
err = tx.Query("select user_id, target, balance from allowances where id = ?").Bind(toId).ScanSingle(&toUserId, &toTarget, &toBalance)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ensure same owner
|
||||
if fromUserId != toUserId {
|
||||
return fmt.Errorf(ErrDifferentUsers)
|
||||
}
|
||||
|
||||
// Calculate how much the 'to' goal still needs
|
||||
remainingTo := toTarget - toBalance
|
||||
if remainingTo <= 0 {
|
||||
// Nothing to transfer
|
||||
return fmt.Errorf("target already reached")
|
||||
}
|
||||
|
||||
// Limit transfer to what 'to' still needs
|
||||
transfer := amountCents
|
||||
if transfer > remainingTo {
|
||||
transfer = remainingTo
|
||||
}
|
||||
|
||||
// Ensure 'from' has enough balance
|
||||
if fromBalance < transfer {
|
||||
return fmt.Errorf(ErrInsufficientFunds)
|
||||
}
|
||||
|
||||
// Perform updates
|
||||
err = tx.Query("update allowances set balance = balance - ? where id = ? and user_id = ?").Bind(transfer, fromId, fromUserId).Exec()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = tx.Query("update allowances set balance = balance + ? where id = ? and user_id = ?").Bind(transfer, toId, toUserId).Exec()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user