/
utils.go
197 lines (152 loc) · 4.79 KB
/
utils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
package models
import (
"log"
"github.com/Arcady1/go-rest-api/pkg/utils"
"github.com/google/uuid"
)
func createAccount(amount float64) (string, error) {
log.Println("models.createAccount", amount)
accountId := uuid.New().String()
_, err := DB.Query("INSERT INTO accounts(account_id, balance) VALUES ($1, $2);", accountId, amount)
if err != nil {
return "", err
}
return accountId, nil
}
func createUser(userId, accountId string) error {
log.Println("models.createUser", userId, accountId)
_, err := DB.Query("INSERT INTO users(user_id, account_id) VALUES ($1, $2);", userId, accountId)
if err != nil {
return err
}
return nil
}
func findUserById(user *users, userId string) error {
log.Println("models.findUserById", userId)
rows, err := DB.Query("SELECT * FROM users WHERE user_id = $1 LIMIT 1;", userId)
if err != nil {
return err
}
for rows.Next() {
err = rows.Scan(&user.UserId, &user.AccountId)
if err != nil {
return err
}
}
rows.Close()
return nil
}
func findOrder(order *orders, accountId, serviceId, orderId string) error {
log.Println("models.findOrder", accountId, serviceId, orderId)
rows, err := DB.Query("SELECT * FROM orders WHERE (account_id = $1) AND (order_id = $2) AND (service_id = $3) LIMIT 1;", accountId, orderId, serviceId)
if err != nil {
return err
}
for rows.Next() {
err = rows.Scan(&order.Id, &order.OrderId, &order.AccountId, &order.ServiceId, &order.Cost, &order.Status)
if err != nil {
return err
}
}
rows.Close()
return nil
}
func getUserBalanceByAccountId(accountId string) (float64, error) {
log.Println("models.getUserBalanceByAccountId", accountId)
var (
account_id string
currentBalance float64
)
rows, err := DB.Query("SELECT * FROM accounts WHERE account_id = $1 LIMIT 1;", accountId)
if err != nil {
return 0, err
}
for rows.Next() {
err = rows.Scan(&account_id, ¤tBalance)
if err != nil {
return 0, err
}
}
rows.Close()
return currentBalance, nil
}
func updateUserAccountBalance(accountId string, balance float64) error {
log.Println("models.updateUserAccountBalance", accountId, balance)
balance, err := utils.PrepareAmountValue(balance)
if err != nil {
return err
}
_, err = DB.Query("UPDATE accounts SET balance = $1 WHERE account_id = $2;", balance, accountId)
if err != nil {
return err
}
return nil
}
func createdNewOrder(accountId, serviceId, orderId string, cost float64) error {
log.Println("models.createdNewOrder", accountId, serviceId, orderId, cost)
id := uuid.New().String()
_, err := DB.Query("INSERT INTO orders(id, order_id, account_id, service_id, cost, status) VALUES ($1, $2, $3, $4, $5, 'reserved');", id, orderId, accountId, serviceId, cost)
if err != nil {
return err
}
return nil
}
func reserveMoney(accountId, serviceId, orderId string, cost, accountBalance float64) error {
log.Println("models.reserveMoney", accountId, serviceId, orderId, cost)
// Reserve money
err := createdNewOrder(accountId, serviceId, orderId, cost)
if err != nil {
return err
}
// Write-off money from the user's account if there is no error on reserving money
newBalance := accountBalance - cost
err = updateUserAccountBalance(accountId, newBalance)
if err != nil {
return err
}
return nil
}
func updateOrder(accountId, serviceId, orderId, status string, amount float64) error {
log.Println("models.updateOrder", accountId, serviceId, orderId, status)
// Update order status 'canceled'
if status == "canceled" {
_, err := DB.Query("UPDATE orders SET status = 'canceled' WHERE (account_id = $1) AND (order_id = $2) AND (service_id = $3);", accountId, orderId, serviceId)
if err != nil {
return err
}
} else if status == "succeed" {
// Update order status 'succeed'
_, err := DB.Query("UPDATE orders SET status = 'succeed', cost = $1 WHERE (account_id = $2) AND (order_id = $3) AND (service_id = $4);", amount, accountId, orderId, serviceId)
if err != nil {
return err
}
}
return nil
}
func updateMoneyReserve(accountId, serviceId, orderId, status string, orderCost, amount float64) error {
log.Println("models.updateMoneyReserve", accountId, serviceId, orderId, orderCost, amount)
// Update the order
err := updateOrder(accountId, serviceId, orderId, status, amount)
if err != nil {
return err
}
// Refund the user if it is impossible to write off the money OR 'amount < orderCost'
if status == "succeed" {
var (
accountBalance float64
newBalance float64
)
// Get the user's account balance
accountBalance, err = getUserBalanceByAccountId(accountId)
if err != nil {
return err
}
// Update the user's account balance. 'orderCost - amount' != 0 when the 'amount < orderCost'
newBalance = accountBalance + (orderCost - amount)
err = updateUserAccountBalance(accountId, newBalance)
if err != nil {
return err
}
}
return nil
}