github.com/condensat/bank-core@v0.1.0/database/model/accountoperation.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 model
     6  
     7  import (
     8  	"math"
     9  	"time"
    10  )
    11  
    12  type AccountOperationID ID
    13  
    14  // AccountOperation model
    15  type AccountOperation struct {
    16  	ID        AccountOperationID `gorm:"primary_key;unique_index:idx_id_previd;"` // [PK] AccountOperation
    17  	AccountID AccountID          `gorm:"index;not null"`                          // [FK] Reference to Account table
    18  
    19  	SynchroneousType SynchroneousType `gorm:"index;not null;type:varchar(16)"` // [enum] Operation synchroneous type (sync, async-start, async-end)
    20  	OperationType    OperationType    `gorm:"index;not null;type:varchar(16)"` // [enum] Determine table for ReferenceID (deposit, withdraw, transfer, adjustment, none, other)
    21  	ReferenceID      RefID            `gorm:"index;not null"`                  // [optional - FK] Reference to related table with OperationType
    22  
    23  	Timestamp time.Time `gorm:"index;not null;type:timestamp"` // Operation timestamp
    24  	Amount    ZeroFloat `gorm:"default:0;not null"`            // Operation amount (can be negative)
    25  	Balance   ZeroFloat `gorm:"default:0;not null"`            // Account balance (strictly positive or zero)
    26  
    27  	LockAmount  ZeroFloat `gorm:"default:0;not null"` // Operation amount (can be negative)
    28  	TotalLocked ZeroFloat `gorm:"default:0;not null"` // Total locked (strictly positive or zero and less or equal than Balance)
    29  }
    30  
    31  func NewAccountOperation(ID AccountOperationID, accountID AccountID, synchroneousType SynchroneousType, operationType OperationType, referenceID RefID, timestamp time.Time, amount, balance, lockAmount, totalLocked Float) AccountOperation {
    32  	return AccountOperation{
    33  		ID:        ID,
    34  		AccountID: accountID,
    35  
    36  		SynchroneousType: synchroneousType,
    37  		OperationType:    operationType,
    38  		ReferenceID:      referenceID,
    39  
    40  		Timestamp: timestamp.UTC().Truncate(time.Second),
    41  		Amount:    &amount,
    42  		Balance:   &balance,
    43  
    44  		LockAmount:  &lockAmount,
    45  		TotalLocked: &totalLocked,
    46  	}
    47  }
    48  
    49  func NewInitOperation(accountID AccountID, referenceID RefID) AccountOperation {
    50  	return NewAccountOperation(0,
    51  		accountID,
    52  		SynchroneousTypeSync,
    53  		OperationTypeInit,
    54  		referenceID,
    55  		time.Now(),
    56  		0.0, 0.0,
    57  		0.0, 0.0,
    58  	)
    59  }
    60  
    61  func (p *AccountOperation) IsValid() bool {
    62  	return p.ID > 0 &&
    63  		p.AccountID > 0 &&
    64  
    65  		// check enums
    66  		p.OperationType.Valid() &&
    67  		p.SynchroneousType.Valid() &&
    68  
    69  		// check pointers
    70  		p.Amount != nil && p.Balance != nil &&
    71  		p.LockAmount != nil && p.TotalLocked != nil &&
    72  
    73  		// check positive balance and TotalLocked
    74  		*p.Balance >= 0 &&
    75  		*p.TotalLocked >= 0 &&
    76  		// check for max total locked
    77  		*p.TotalLocked <= *p.Balance &&
    78  
    79  		// check amount less or equals than balance
    80  		*p.Amount <= *p.Balance &&
    81  		// check lockAmount less or equals than totalLocked
    82  		*p.LockAmount <= *p.TotalLocked &&
    83  
    84  		// Check for zero operation
    85  		// allow zero operation for OperationTypeInit
    86  		(p.OperationType == OperationTypeInit || (math.Abs(float64(*p.Amount)) > 0.0 || math.Abs(float64(*p.LockAmount)) > 0.0))
    87  }
    88  
    89  func (p *AccountOperation) PreCheck() bool {
    90  	// deepcopy
    91  	operation := *p
    92  	// overwite operation IDs
    93  	operation.ID = 1
    94  
    95  	// operation should be valid
    96  	return operation.IsValid()
    97  }