mirror of
				https://github.com/aclindsa/moneygo.git
				synced 2025-10-30 17:33:26 -04:00 
			
		
		
		
	Move accounts to store
This commit is contained in:
		
							
								
								
									
										133
									
								
								internal/store/db/accounts.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								internal/store/db/accounts.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,133 @@ | ||||
| package db | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"github.com/aclindsa/moneygo/internal/models" | ||||
| 	"github.com/aclindsa/moneygo/internal/store" | ||||
| ) | ||||
|  | ||||
| func (tx *Tx) GetAccount(accountid int64, userid int64) (*models.Account, error) { | ||||
| 	var account models.Account | ||||
|  | ||||
| 	err := tx.SelectOne(&account, "SELECT * from accounts where UserId=? AND AccountId=?", userid, accountid) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &account, nil | ||||
| } | ||||
|  | ||||
| func (tx *Tx) GetAccounts(userid int64) (*[]*models.Account, error) { | ||||
| 	var accounts []*models.Account | ||||
|  | ||||
| 	_, err := tx.Select(&accounts, "SELECT * from accounts where UserId=?", userid) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &accounts, nil | ||||
| } | ||||
|  | ||||
| func (tx *Tx) FindMatchingAccounts(account *models.Account) (*[]*models.Account, error) { | ||||
| 	var accounts []*models.Account | ||||
|  | ||||
| 	_, err := tx.Select(&accounts, "SELECT * from accounts where UserId=? AND SecurityId=? AND Type=? AND Name=? AND ParentAccountId=? ORDER BY AccountId ASC", account.UserId, account.SecurityId, account.Type, account.Name, account.ParentAccountId) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &accounts, nil | ||||
| } | ||||
|  | ||||
| func (tx *Tx) insertUpdateAccount(account *models.Account, insert bool) error { | ||||
| 	found := make(map[int64]bool) | ||||
| 	if !insert { | ||||
| 		found[account.AccountId] = true | ||||
| 	} | ||||
| 	parentid := account.ParentAccountId | ||||
| 	depth := 0 | ||||
| 	for parentid != -1 { | ||||
| 		depth += 1 | ||||
| 		if depth > 100 { | ||||
| 			return store.TooMuchNestingError{} | ||||
| 		} | ||||
|  | ||||
| 		var a models.Account | ||||
| 		err := tx.SelectOne(&a, "SELECT * from accounts where AccountId=?", parentid) | ||||
| 		if err != nil { | ||||
| 			return store.ParentAccountMissingError{} | ||||
| 		} | ||||
|  | ||||
| 		// Insertion by itself can never result in circular dependencies | ||||
| 		if insert { | ||||
| 			break | ||||
| 		} | ||||
|  | ||||
| 		found[parentid] = true | ||||
| 		parentid = a.ParentAccountId | ||||
| 		if _, ok := found[parentid]; ok { | ||||
| 			return store.CircularAccountsError{} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if insert { | ||||
| 		err := tx.Insert(account) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} else { | ||||
| 		oldacct, err := tx.GetAccount(account.AccountId, account.UserId) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		account.AccountVersion = oldacct.AccountVersion + 1 | ||||
|  | ||||
| 		count, err := tx.Update(account) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if count != 1 { | ||||
| 			return errors.New("Updated more than one account") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (tx *Tx) InsertAccount(account *models.Account) error { | ||||
| 	return tx.insertUpdateAccount(account, true) | ||||
| } | ||||
|  | ||||
| func (tx *Tx) UpdateAccount(account *models.Account) error { | ||||
| 	return tx.insertUpdateAccount(account, false) | ||||
| } | ||||
|  | ||||
| func (tx *Tx) DeleteAccount(account *models.Account) error { | ||||
| 	if account.ParentAccountId != -1 { | ||||
| 		// Re-parent splits to this account's parent account if this account isn't a root account | ||||
| 		_, err := tx.Exec("UPDATE splits SET AccountId=? WHERE AccountId=?", account.ParentAccountId, account.AccountId) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} else { | ||||
| 		// Delete splits if this account is a root account | ||||
| 		_, err := tx.Exec("DELETE FROM splits WHERE AccountId=?", account.AccountId) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Re-parent child accounts to this account's parent account | ||||
| 	_, err := tx.Exec("UPDATE accounts SET ParentAccountId=? WHERE ParentAccountId=?", account.ParentAccountId, account.AccountId) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	count, err := tx.Delete(account) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if count != 1 { | ||||
| 		return errors.New("Was going to delete more than one account") | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
| @@ -3,16 +3,9 @@ package db | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"github.com/aclindsa/moneygo/internal/models" | ||||
| 	"github.com/aclindsa/moneygo/internal/store" | ||||
| ) | ||||
|  | ||||
| type SecurityInUseError struct { | ||||
| 	message string | ||||
| } | ||||
|  | ||||
| func (e SecurityInUseError) Error() string { | ||||
| 	return e.message | ||||
| } | ||||
|  | ||||
| func (tx *Tx) GetSecurity(securityid int64, userid int64) (*models.Security, error) { | ||||
| 	var s models.Security | ||||
|  | ||||
| @@ -33,10 +26,10 @@ func (tx *Tx) GetSecurities(userid int64) (*[]*models.Security, error) { | ||||
| 	return &securities, nil | ||||
| } | ||||
|  | ||||
| func (tx *Tx) FindMatchingSecurities(userid int64, security *models.Security) (*[]*models.Security, error) { | ||||
| func (tx *Tx) FindMatchingSecurities(security *models.Security) (*[]*models.Security, error) { | ||||
| 	var securities []*models.Security | ||||
|  | ||||
| 	_, err := tx.Select(&securities, "SELECT * from securities where UserId=? AND Type=? AND AlternateId=? AND Preciseness=?", userid, security.Type, security.AlternateId, security.Precision) | ||||
| 	_, err := tx.Select(&securities, "SELECT * from securities where UserId=? AND Type=? AND AlternateId=? AND Preciseness=?", security.UserId, security.Type, security.AlternateId, security.Precision) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -67,14 +60,14 @@ func (tx *Tx) DeleteSecurity(s *models.Security) error { | ||||
| 	accounts, err := tx.SelectInt("SELECT count(*) from accounts where UserId=? and SecurityId=?", s.UserId, s.SecurityId) | ||||
|  | ||||
| 	if accounts != 0 { | ||||
| 		return SecurityInUseError{"One or more accounts still use this security"} | ||||
| 		return store.SecurityInUseError{"One or more accounts still use this security"} | ||||
| 	} | ||||
|  | ||||
| 	user, err := tx.GetUser(s.UserId) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} else if user.DefaultCurrency == s.SecurityId { | ||||
| 		return SecurityInUseError{"Cannot delete security which is user's default currency"} | ||||
| 		return store.SecurityInUseError{"Cannot delete security which is user's default currency"} | ||||
| 	} | ||||
|  | ||||
| 	// Remove all prices involving this security (either of this security, or | ||||
|   | ||||
		Reference in New Issue
	
	Block a user