package model import ( "fmt" "regexp" "strings" "time" "gitnet.fr/deblan/budget/database/manager" ) type Transaction struct { ID uint `gorm:"primaryKey" json:"id"` ShortLabel string `gorm:"not null" json:"short_label"` Label string `gorm:"not null" json:"label"` Reference string `gorm:"not null" json:"reference"` Information string `json:"information"` OperationType string `gorm:"not null" json:"operation_type"` AccountedAt time.Time `json:"accounted_at"` BankCategory string `json:"bank_category"` BankSubCategory string `json:"bank_sub_category"` Debit float64 `json:"debit"` Credit float64 `json:"credit"` Date time.Time `json:"date"` BankAccountID int `gorm:"not null" json:"-"` BankAccount *BankAccount `json:"bank_account"` CategoryID *int `json:"-"` Category *Category `json:"category"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } func NewTransaction(label string) *Transaction { transaction := Transaction{} return &transaction } func (t *Transaction) MatchRule(rule CategoryRule) (bool, int) { match := true counter := 0 if rule.Contain != nil { v := strings.ToLower(*rule.Contain) match = strings.Contains(strings.ToLower(t.Label), v) || strings.Contains(strings.ToLower(t.ShortLabel), v) || strings.Contains(strings.ToLower(t.Reference), v) if match { counter += 8 } } if rule.Match != nil { res, _ := regexp.MatchString(*rule.Match, t.Label) match = match && res if match { counter += 8 } } if rule.BankCategory != nil { v := strings.ToLower(*rule.BankCategory) match = match && (strings.Contains(strings.ToLower(t.BankCategory), v) || strings.Contains(strings.ToLower(t.BankSubCategory), v)) if match { counter += 6 } } if rule.Amount != nil { match = match && t.Debit == *rule.Amount if match { counter += 4 } } if rule.DateFrom != nil { match = match && t.Date.After(*rule.DateFrom) if match { counter += 2 } } if rule.DateTo != nil { match = match && t.Date.Before(*rule.DateTo) if match { counter += 2 } } if match { fmt.Printf("%+v\n", match) } return match, counter } func (t *Transaction) MatchCategory(category Category) (bool, int) { maxCounter := 0 match := false for _, rule := range category.Rules { m, c := t.MatchRule(rule) if m { match = true if c > maxCounter { maxCounter = c } } } return match, maxCounter } func ImportTransactions(content string, bankAccountID int, format string) ([]Transaction, error) { var datas []Transaction var err error if format == "revolut" { datas, err = ImportRevolutTransactions(content, bankAccountID) } else if format == "banque_populaire" { datas, err = ImportBanquePopulaireTransactions(content, bankAccountID) } else if format == "caisse_epargne" { datas, err = ImportCaisseEpargneTransactions(content, bankAccountID) } UpdateTransactionsCategories() return datas, err } func UpdateTransactionsCategories() []Transaction { var categories []Category var transactions []Transaction var datas []Transaction manager.Get().Db.Model(Category{}).Preload("Rules").Find(&categories) manager.Get().Db.Model(Transaction{}).Find(&transactions) for _, transaction := range transactions { transaction.CategoryID = nil maxCounter := -1 for _, category := range categories { match, counter := transaction.MatchCategory(category) if match && counter > maxCounter { maxCounter = counter var id int id = int(category.ID) transaction.CategoryID = &id } } manager.Get().Db.Model(Transaction{}).Where("id = ?", transaction.ID).Save(&transaction) datas = append(datas, transaction) } return datas }