Add endpoint to add funds (#99)
Closes #91 Reviewed-on: #99
This commit was merged in pull request #99.
This commit is contained in:
141
backend/db.go
141
backend/db.go
@@ -428,10 +428,9 @@ func (db *Db) CompleteTask(taskId int) error {
|
||||
return err
|
||||
}
|
||||
|
||||
for userRow := range tx.Query("select id, weight from users").Range(&err) {
|
||||
for userRow := range tx.Query("select id from users").Range(&err) {
|
||||
var userId int
|
||||
var userWeight float64
|
||||
err = userRow.Scan(&userId, &userWeight)
|
||||
err = userRow.Scan(&userId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -444,42 +443,7 @@ func (db *Db) CompleteTask(taskId int) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Calculate the sums of all weights
|
||||
var sumOfWeights float64
|
||||
err = tx.Query("select sum(weight) from allowances where user_id = ? and weight > 0").Bind(userId).ScanSingle(&sumOfWeights)
|
||||
sumOfWeights += userWeight
|
||||
|
||||
remainingReward := reward
|
||||
|
||||
if sumOfWeights > 0 {
|
||||
// Distribute the reward to the allowances
|
||||
for allowanceRow := range tx.Query("select id, weight, target, balance from allowances where user_id = ? and weight > 0 order by (target - balance) asc").Bind(userId).Range(&err) {
|
||||
var allowanceId, allowanceTarget, allowanceBalance int
|
||||
var allowanceWeight float64
|
||||
err = allowanceRow.Scan(&allowanceId, &allowanceWeight, &allowanceTarget, &allowanceBalance)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Calculate the amount to add to the allowance
|
||||
amount := int((allowanceWeight / sumOfWeights) * float64(remainingReward))
|
||||
if allowanceBalance+amount > allowanceTarget {
|
||||
// If the amount reaches past the target, set it to the target
|
||||
amount = allowanceTarget - allowanceBalance
|
||||
}
|
||||
sumOfWeights -= allowanceWeight
|
||||
err = tx.Query("update allowances set balance = balance + ? where id = ? and user_id = ?").
|
||||
Bind(amount, allowanceId, userId).Exec()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
remainingReward -= amount
|
||||
}
|
||||
}
|
||||
|
||||
// Add the remaining reward to the user
|
||||
err = tx.Query("update users set balance = balance + ? where id = ?").
|
||||
Bind(remainingReward, userId).Exec()
|
||||
err := db.addDistributedReward(tx, userId, reward)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -494,6 +458,52 @@ func (db *Db) CompleteTask(taskId int) error {
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (db *Db) addDistributedReward(tx *mysqlite.Tx, userId int, reward int) error {
|
||||
var userWeight float64
|
||||
err := tx.Query("select weight from users where id = ?").Bind(userId).ScanSingle(&userWeight)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Calculate the sums of all weights
|
||||
var sumOfWeights float64
|
||||
err = tx.Query("select sum(weight) from allowances where user_id = ? and weight > 0").Bind(userId).ScanSingle(&sumOfWeights)
|
||||
sumOfWeights += userWeight
|
||||
|
||||
remainingReward := reward
|
||||
|
||||
if sumOfWeights > 0 {
|
||||
// Distribute the reward to the allowances
|
||||
for allowanceRow := range tx.Query("select id, weight, target, balance from allowances where user_id = ? and weight > 0 order by (target - balance) asc").Bind(userId).Range(&err) {
|
||||
var allowanceId, allowanceTarget, allowanceBalance int
|
||||
var allowanceWeight float64
|
||||
err = allowanceRow.Scan(&allowanceId, &allowanceWeight, &allowanceTarget, &allowanceBalance)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Calculate the amount to add to the allowance
|
||||
amount := int((allowanceWeight / sumOfWeights) * float64(remainingReward))
|
||||
if allowanceBalance+amount > allowanceTarget {
|
||||
// If the amount reaches past the target, set it to the target
|
||||
amount = allowanceTarget - allowanceBalance
|
||||
}
|
||||
sumOfWeights -= allowanceWeight
|
||||
err = tx.Query("update allowances set balance = balance + ? where id = ? and user_id = ?").
|
||||
Bind(amount, allowanceId, userId).Exec()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
remainingReward -= amount
|
||||
}
|
||||
}
|
||||
|
||||
// Add the remaining reward to the user
|
||||
err = tx.Query("update users set balance = balance + ? where id = ?").
|
||||
Bind(remainingReward, userId).Exec()
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *Db) AddHistory(userId int, allowance *PostHistory) error {
|
||||
tx, err := db.db.Begin()
|
||||
if err != nil {
|
||||
@@ -532,3 +542,56 @@ func (db *Db) GetHistory(userId int) ([]History, error) {
|
||||
}
|
||||
return history, nil
|
||||
}
|
||||
|
||||
func (db *Db) AddAllowanceAmount(userId int, allowanceId int, request AddAllowanceAmountRequest) error {
|
||||
tx, err := db.db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.MustRollback()
|
||||
|
||||
// Convert amount to integer (cents)
|
||||
remainingAmount := int(math.Round(request.Amount * 100))
|
||||
|
||||
// Insert history entry
|
||||
err = tx.Query("insert into history (user_id, timestamp, amount, description) values (?, ?, ?, ?)").
|
||||
Bind(userId, time.Now().Unix(), remainingAmount, request.Description).
|
||||
Exec()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Fetch the target and progress of the specified allowance
|
||||
var target, progress int
|
||||
err = tx.Query("select target, balance from allowances where id = ? and user_id = ?").
|
||||
Bind(allowanceId, userId).ScanSingle(&target, &progress)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Calculate the amount to add to the current allowance
|
||||
toAdd := remainingAmount
|
||||
if progress+toAdd > target {
|
||||
toAdd = target - progress
|
||||
}
|
||||
remainingAmount -= toAdd
|
||||
|
||||
// Update the current allowance
|
||||
if toAdd > 0 {
|
||||
err = tx.Query("update allowances set balance = balance + ? where id = ? and user_id = ?").
|
||||
Bind(toAdd, allowanceId, userId).Exec()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// If there's remaining amount, distribute it to the user's allowances
|
||||
if remainingAmount > 0 {
|
||||
err = db.addDistributedReward(tx, userId, remainingAmount)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user