github.com/condensat/bank-core@v0.1.0/database/query/withdraw.go (about) 1 // Copyright 2020 Condensat Tech. All rights reserved. 2 // Use of this source code is governed by a MIT 3 // license that can be found in the LICENSE file. 4 5 package query 6 7 import ( 8 "errors" 9 "time" 10 11 "github.com/condensat/bank-core/database" 12 "github.com/condensat/bank-core/database/model" 13 14 "github.com/jinzhu/gorm" 15 ) 16 17 var ( 18 ErrInvalidWithdrawID = errors.New("Invalid WithdrawID") 19 ErrInvalidWithdrawAmount = errors.New("Invalid Amount") 20 ErrInvalidWithdrawAccount = errors.New("Invalid Withdraw Account") 21 ErrInvalidWithdrawAccountCurrency = errors.New("Invalid Withdraw Account Currency") 22 ErrInvalidBatchMode = errors.New("Invalid BatchMode") 23 ) 24 25 func AddWithdraw(db database.Context, from, to model.AccountID, amount model.Float, batch model.BatchMode, data model.WithdrawData) (model.Withdraw, error) { 26 gdb := db.DB().(*gorm.DB) 27 if db == nil { 28 return model.Withdraw{}, database.ErrInvalidDatabase 29 } 30 31 if from == 0 { 32 return model.Withdraw{}, ErrInvalidAccountID 33 } 34 if to == 0 { 35 return model.Withdraw{}, ErrInvalidAccountID 36 } 37 if from == to { 38 return model.Withdraw{}, ErrInvalidAccountID 39 } 40 accountFrom, err := GetAccountByID(db, from) 41 if err != nil { 42 return model.Withdraw{}, ErrInvalidWithdrawAccount 43 } 44 accountTo, err := GetAccountByID(db, to) 45 if err != nil { 46 return model.Withdraw{}, ErrInvalidWithdrawAccount 47 } 48 if accountFrom.CurrencyName != accountTo.CurrencyName { 49 return model.Withdraw{}, ErrInvalidWithdrawAccountCurrency 50 } 51 52 if amount <= 0.0 { 53 return model.Withdraw{}, ErrInvalidWithdrawAmount 54 } 55 if len(batch) == 0 { 56 return model.Withdraw{}, ErrInvalidBatchMode 57 } 58 59 timestamp := time.Now().UTC().Truncate(time.Second) 60 result := model.Withdraw{ 61 Timestamp: timestamp, 62 From: from, 63 To: to, 64 Amount: &amount, 65 Batch: batch, 66 Data: data, 67 } 68 err = gdb.Create(&result).Error 69 if err != nil { 70 return model.Withdraw{}, err 71 } 72 73 return result, nil 74 } 75 76 func GetWithdraw(db database.Context, ID model.WithdrawID) (model.Withdraw, error) { 77 gdb := db.DB().(*gorm.DB) 78 if db == nil { 79 return model.Withdraw{}, database.ErrInvalidDatabase 80 } 81 82 if ID == 0 { 83 return model.Withdraw{}, ErrInvalidWithdrawID 84 } 85 86 var result model.Withdraw 87 err := gdb. 88 Where(&model.Withdraw{ID: ID}). 89 First(&result).Error 90 if err != nil { 91 return model.Withdraw{}, err 92 } 93 94 return result, nil 95 } 96 97 func FindWithdrawByCurrencyNameAndStatus(db database.Context, currency model.CurrencyName, status model.WithdrawStatus) ([]model.Withdraw, error) { 98 gdb := db.DB().(*gorm.DB) 99 100 subQueryAccount := gdb.Model(&model.Account{}). 101 Select("id"). 102 Where("currency_name = ?", currency). 103 SubQuery() 104 105 subQueryInfo := gdb.Model(&model.WithdrawInfo{}). 106 Select("withdraw_id"). 107 Where("status = ?", status). 108 SubQuery() 109 110 var list []*model.Withdraw 111 err := gdb.Model(&model.Withdraw{}). 112 Joins("JOIN (?) AS a ON withdraw.from = a.id", subQueryAccount). 113 Joins("JOIN (?) AS i ON withdraw.id = i.withdraw_id", subQueryInfo). 114 Order("id ASC"). 115 Find(&list).Error 116 117 if err != nil && err != gorm.ErrRecordNotFound { 118 return nil, err 119 } 120 121 return convertWithdraws(list), nil 122 } 123 124 func FindWithdrawByUser(db database.Context, userID model.UserID) ([]model.Withdraw, error) { 125 gdb := db.DB().(*gorm.DB) 126 127 if userID == 0 { 128 return nil, ErrInvalidUserID 129 } 130 131 subQueryAccount := gdb.Model(&model.Account{}). 132 Select("id"). 133 Where("user_id = ?", userID). 134 SubQuery() 135 136 var list []*model.Withdraw 137 err := gdb.Model(&model.Withdraw{}). 138 Joins("JOIN (?) AS a ON withdraw.from = a.id", subQueryAccount). 139 Order("id ASC"). 140 Find(&list).Error 141 142 if err != nil && err != gorm.ErrRecordNotFound { 143 return nil, err 144 } 145 146 return convertWithdraws(list), nil 147 } 148 149 type WithdrawInfos struct { 150 Count int 151 Active int 152 } 153 154 func WithdrawsInfos(db database.Context) (WithdrawInfos, error) { 155 gdb := db.DB().(*gorm.DB) 156 if gdb == nil { 157 return WithdrawInfos{}, database.ErrInvalidDatabase 158 } 159 160 var totalWithdraws int64 161 err := gdb.Model(&model.Withdraw{}). 162 Count(&totalWithdraws).Error 163 if err != nil { 164 return WithdrawInfos{}, err 165 } 166 167 subQueryLast := gdb.Model(&model.WithdrawInfo{}). 168 Select("MAX(id)"). 169 Group("withdraw_id"). 170 SubQuery() 171 172 var activeWithdraws int64 173 err = gdb.Model(&model.WithdrawInfo{}). 174 Where("id IN (?)", subQueryLast). 175 Where("status <> ?", model.WithdrawStatusSettled). 176 Count(&activeWithdraws).Error 177 if err != nil { 178 return WithdrawInfos{}, err 179 } 180 181 return WithdrawInfos{ 182 Count: int(totalWithdraws), 183 Active: int(activeWithdraws), 184 }, nil 185 } 186 187 func convertWithdraws(list []*model.Withdraw) []model.Withdraw { 188 var result []model.Withdraw 189 for _, curr := range list { 190 if curr != nil { 191 result = append(result, *curr) 192 } 193 } 194 195 return result[:] 196 }