1
0
mirror of https://github.com/aclindsa/moneygo.git synced 2025-06-13 21:48:39 -04:00

Move accounts to store

This commit is contained in:
2017-12-07 20:47:55 -05:00
parent bec5152e53
commit 3326c3b292
11 changed files with 211 additions and 183 deletions

View 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
}

View File

@ -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

View File

@ -20,15 +20,50 @@ type UserStore interface {
DeleteUser(user *models.User) error
}
type SecurityInUseError struct {
Message string
}
func (e SecurityInUseError) Error() string {
return e.Message
}
type SecurityStore interface {
InsertSecurity(security *models.Security) error
GetSecurity(securityid int64, userid int64) (*models.Security, error)
GetSecurities(userid int64) (*[]*models.Security, error)
FindMatchingSecurities(userid int64, security *models.Security) (*[]*models.Security, error)
FindMatchingSecurities(security *models.Security) (*[]*models.Security, error)
UpdateSecurity(security *models.Security) error
DeleteSecurity(security *models.Security) error
}
type ParentAccountMissingError struct{}
func (pame ParentAccountMissingError) Error() string {
return "Parent account missing"
}
type TooMuchNestingError struct{}
func (tmne TooMuchNestingError) Error() string {
return "Too much account nesting"
}
type CircularAccountsError struct{}
func (cae CircularAccountsError) Error() string {
return "Would result in circular account relationship"
}
type AccountStore interface {
InsertAccount(account *models.Account) error
GetAccount(accountid int64, userid int64) (*models.Account, error)
GetAccounts(userid int64) (*[]*models.Account, error)
FindMatchingAccounts(account *models.Account) (*[]*models.Account, error)
UpdateAccount(account *models.Account) error
DeleteAccount(account *models.Account) error
}
type Tx interface {
Commit() error
Rollback() error
@ -36,6 +71,7 @@ type Tx interface {
SessionStore
UserStore
SecurityStore
AccountStore
}
type Store interface {