This repository has been archived by the owner on Jun 7, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
withdrawal.go
126 lines (109 loc) · 3.42 KB
/
withdrawal.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
package main
import (
"context"
"go.mongodb.org/mongo-driver/bson/primitive"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
var withdrawalCollection = DB.Collection("withdrawals")
type Withdrawal struct {
ID primitive.ObjectID `bson:"_id"`
Amount int64 `bson:"amount"`
Transactions []WithdrawalTransaction `bson:"transactions"`
ReceiverContractID string `bson:"receiverContractID"`
Status string `bson:"status"`
Comment string `bson:"comment"`
}
type WithdrawalTransaction struct {
ID primitive.ObjectID `bson:"_id"`
Amount int64 `bson:"amount"`
Comment string `bson:"comment"`
SenderContractID string `bson:"senderContractID"`
ReceiverContractID string `bson:"receiverContractID"`
Status string `bson:"status"`
}
func (w Withdrawal) Create() (Withdrawal, error) {
trs, err := w.generateTransactions()
if err != nil {
return w, err
}
w.ID = primitive.NewObjectID()
w.Transactions = trs
w.Status = "failed"
//todo to-lower
for _, tr := range trs {
if tr.Status != "Accepted" {
w.Status = tr.Status
} else {
w.Status = "accepted"
}
}
_, err = withdrawalCollection.InsertOne(context.TODO(), w)
if err != nil {
return w, status.Errorf(codes.Internal, err.Error())
}
return w, nil
}
func (w Withdrawal) generateTransactions() ([]WithdrawalTransaction, error) {
accounts := Account{}.List()
withdrawSum := getBalanceSum()
defaultStatus := "pending"
amount := w.Amount
comment := w.Comment
var withdrawalTransactions []WithdrawalTransaction
if amount > withdrawSum {
return withdrawalTransactions, status.Errorf(codes.OutOfRange, "not enough sum for withdraw")
}
for _, acc := range accounts {
if amount == 0 {
break
}
availSumForWithdraw := acc.Balance
if availSumForWithdraw >= amount {
withdrawalTransactions = append(withdrawalTransactions, WithdrawalTransaction{
ID: primitive.NewObjectID(),
Amount: amount,
Comment: comment,
SenderContractID: acc.ContractID,
ReceiverContractID: w.ReceiverContractID,
Status: defaultStatus})
amount -= amount
} else if availSumForWithdraw <= amount {
withdrawalTransactions = append(withdrawalTransactions, WithdrawalTransaction{
ID: primitive.NewObjectID(),
Amount: availSumForWithdraw,
Comment: comment,
SenderContractID: acc.ContractID,
ReceiverContractID: w.ReceiverContractID,
Status: defaultStatus})
amount -= availSumForWithdraw
}
}
for i, tr := range withdrawalTransactions {
trCode, err := tr.makeTransaction()
withdrawalTransactions[i].Status = trCode
if err != nil {
return withdrawalTransactions, err
}
}
return withdrawalTransactions, nil
}
//todo rename
func (w WithdrawalTransaction) makeTransaction() (string, error) {
acc := Account{ContractID: w.SenderContractID}
trCode, err := acc.SendMoneyToQiwi(w.Amount, w.ReceiverContractID, w.Comment)
if err != nil {
return trCode, status.Errorf(codes.Aborted, "withdraw error")
}
//todo to-lower
w.Status = trCode
return trCode, nil
}
func getBalanceSum() int64 {
var b int64
accounts := Account{}.List()
for _, acc := range accounts {
b += acc.Balance
}
return b
}