github.com/condensat/bank-core@v0.1.0/database/query/operationinfo.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 ErrInvalidOperationInfoID = errors.New("Invalid OperationInfo") 19 ErrOperationInfoUpdateNotPermitted = errors.New("OperationInfo Update Not Permitted") 20 ErrInvalidTransactionID = errors.New("Invalid Transaction ID") 21 ErrInvalidOperationAmount = errors.New("Invalid Operation Amount") 22 ) 23 24 // AddOperationInfo 25 func AddOperationInfo(db database.Context, operation model.OperationInfo) (model.OperationInfo, error) { 26 gdb := db.DB().(*gorm.DB) 27 if db == nil { 28 return model.OperationInfo{}, database.ErrInvalidDatabase 29 } 30 31 if operation.ID != 0 { 32 return model.OperationInfo{}, ErrOperationInfoUpdateNotPermitted 33 } 34 35 if operation.CryptoAddressID == 0 { 36 return model.OperationInfo{}, ErrInvalidCryptoAddressID 37 } 38 39 if len(operation.TxID) == 0 { 40 return model.OperationInfo{}, ErrInvalidTransactionID 41 } 42 if operation.Amount < 0.0 { 43 return model.OperationInfo{}, ErrInvalidOperationAmount 44 } 45 46 operation.Timestamp = time.Now().UTC().Truncate(time.Second) 47 48 err := gdb. 49 Assign(operation). 50 Create(&operation).Error 51 if err != nil { 52 return model.OperationInfo{}, err 53 } 54 55 return operation, nil 56 } 57 58 // GetOperationInfo 59 func GetOperationInfo(db database.Context, operationID model.OperationInfoID) (model.OperationInfo, error) { 60 gdb := db.DB().(*gorm.DB) 61 if db == nil { 62 return model.OperationInfo{}, database.ErrInvalidDatabase 63 } 64 65 if operationID == 0 { 66 return model.OperationInfo{}, ErrInvalidOperationInfoID 67 } 68 69 var result model.OperationInfo 70 err := gdb. 71 Where(model.OperationInfo{ 72 ID: operationID, 73 }). 74 First(&result).Error 75 if err != nil { 76 return model.OperationInfo{}, err 77 } 78 79 return result, nil 80 } 81 82 // GetOperationInfoByTxId 83 func GetOperationInfoByTxId(db database.Context, txID model.TxID) (model.OperationInfo, error) { 84 gdb := db.DB().(*gorm.DB) 85 if db == nil { 86 return model.OperationInfo{}, database.ErrInvalidDatabase 87 } 88 89 if len(txID) == 0 { 90 return model.OperationInfo{}, ErrInvalidTransactionID 91 } 92 93 var result model.OperationInfo 94 err := gdb. 95 Where(model.OperationInfo{ 96 TxID: txID, 97 }). 98 First(&result).Error 99 if err != nil { 100 return model.OperationInfo{}, err 101 } 102 103 return result, nil 104 } 105 106 // GetOperationInfoByCryptoAddress 107 func GetOperationInfoByCryptoAddress(db database.Context, cryptoAddressID model.CryptoAddressID) ([]model.OperationInfo, error) { 108 gdb := db.DB().(*gorm.DB) 109 if db == nil { 110 return nil, database.ErrInvalidDatabase 111 } 112 113 if cryptoAddressID == 0 { 114 return nil, ErrInvalidCryptoAddressID 115 } 116 117 var list []*model.OperationInfo 118 err := gdb. 119 Where(model.OperationInfo{ 120 CryptoAddressID: cryptoAddressID, 121 }). 122 Find(&list).Error 123 if err != nil { 124 return nil, err 125 } 126 127 return convertOperationInfoList(list), nil 128 } 129 130 func FindCryptoAddressesNotInOperationInfo(db database.Context, chain model.String) ([]model.CryptoAddress, error) { 131 gdb := db.DB().(*gorm.DB) 132 if db == nil { 133 return nil, database.ErrInvalidDatabase 134 } 135 136 /* 137 select l.* from crypto_address as l 138 WHERE l.chain = 'bitcoin-testnet' 139 AND l.id NOT IN 140 ( 141 SELECT r.crypto_address_id 142 FROM operation_info as r 143 ); 144 */ 145 146 var list []*model.CryptoAddress 147 notInQuery := gdb.Model(&model.OperationInfo{}). 148 Select("crypto_address_id"). 149 SubQuery() 150 151 err := gdb.Model(&model.CryptoAddress{}). 152 Where("chain = ?", chain). 153 Where("id NOT IN ?", notInQuery). 154 Find(&list).Error 155 156 if err != nil && err != gorm.ErrRecordNotFound { 157 return nil, err 158 } 159 160 return converCryptoAddressList(list), nil 161 } 162 163 func FindCryptoAddressesByOperationInfoState(db database.Context, chain model.String, states ...model.String) ([]model.CryptoAddress, error) { 164 gdb := db.DB().(*gorm.DB) 165 166 uniq := make(map[model.String]model.String) 167 for _, state := range states { 168 // skip empty states 169 if len(state) == 0 { 170 continue 171 } 172 uniq[state] = state 173 } 174 175 // slice uniq map 176 var slice []model.String 177 for state := range uniq { 178 slice = append(slice, state) 179 } 180 181 // state must not be empty 182 if len(slice) == 0 { 183 return nil, ErrInvalidOperationStatus 184 } 185 186 subQueryState := gdb.Model(&model.OperationStatus{}). 187 Select("operation_info_id"). 188 Where("state IN (?)", slice). 189 SubQuery() 190 subQueryInfo := gdb.Model(&model.OperationInfo{}). 191 Select("id, crypto_address_id"). 192 SubQuery() 193 194 var list []*model.CryptoAddress 195 err := gdb.Model(&model.CryptoAddress{}). 196 Joins("JOIN (?) AS oi ON crypto_address.id = oi.crypto_address_id", subQueryInfo). 197 Joins("JOIN (?) AS os ON oi.id = os.operation_info_id", subQueryState). 198 Where("chain = ?", chain). 199 Find(&list).Error 200 201 if err != nil && err != gorm.ErrRecordNotFound { 202 return nil, err 203 } 204 205 return converCryptoAddressList(list), nil 206 } 207 208 func DepositPagingCount(db database.Context, countByPage int) (int, error) { 209 if countByPage <= 0 { 210 countByPage = 1 211 } 212 213 switch gdb := db.DB().(type) { 214 case *gorm.DB: 215 216 var result int 217 err := gdb. 218 Model(&model.OperationInfo{}). 219 Count(&result).Error 220 var partialPage int 221 if result%countByPage > 0 { 222 partialPage = 1 223 } 224 return result/countByPage + partialPage, err 225 226 default: 227 return 0, database.ErrInvalidDatabase 228 } 229 } 230 231 func DepositPage(db database.Context, operationInfoID model.OperationInfoID, countByPage int) ([]model.OperationInfoID, error) { 232 switch gdb := db.DB().(type) { 233 case *gorm.DB: 234 235 if countByPage <= 0 { 236 countByPage = 1 237 } 238 239 var list []*model.OperationInfo 240 err := gdb.Model(&model.User{}). 241 Select("id"). 242 Where("id >= ?", operationInfoID). 243 Order("id ASC"). 244 Limit(countByPage). 245 Find(&list).Error 246 247 if err != nil && err != gorm.ErrRecordNotFound { 248 return nil, err 249 } 250 251 return convertOperationInfoIDs(list), nil 252 253 default: 254 return nil, database.ErrInvalidDatabase 255 } 256 } 257 258 func convertOperationInfoIDs(list []*model.OperationInfo) []model.OperationInfoID { 259 var result []model.OperationInfoID 260 for _, curr := range list { 261 if curr != nil { 262 result = append(result, curr.ID) 263 } 264 } 265 266 return result[:] 267 } 268 269 func convertOperationInfoList(list []*model.OperationInfo) []model.OperationInfo { 270 var result []model.OperationInfo 271 for _, curr := range list { 272 if curr == nil { 273 continue 274 } 275 result = append(result, *curr) 276 } 277 278 return result[:] 279 }