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  }