github.com/pbberlin/go-pwa@v0.0.0-20220328105622-7c26e0ca1ab8/pkg/db/model-entry.go (about)

     1  package db
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"log"
     7  	"strings"
     8  	"time"
     9  
    10  	"gorm.io/gorm"
    11  	"gorm.io/gorm/clause"
    12  )
    13  
    14  // Entry into the app
    15  type Entry struct {
    16  	// gorm.Model
    17  	ID uint `gorm:"primarykey"`
    18  
    19  	Name          string
    20  	Desc          string
    21  	Comment       string
    22  	UpsertCounter int
    23  
    24  	// has one => primary key and object
    25  	// gorm.io/docs/has_one.html
    26  	// only a single category; category is not unique
    27  	CategoryID int
    28  	Category   Category
    29  
    30  	// multiple tags - unique to this entry - for instance also addresses
    31  	CreditCards []CreditCard
    32  
    33  	Tags []Tag `gorm:"many2many:entry_tags;"` // multiple tags - reusable to other entries
    34  }
    35  
    36  // EntryTag for cutomized M to N table
    37  //   established via SetupJoinTable()
    38  type EntryTag struct {
    39  	EntryID uint `gorm:"primaryKey"`
    40  	TagID   uint `gorm:"primaryKey"`
    41  	Type    string
    42  	// CreatedAt time.Time
    43  	UpdatedAt time.Time
    44  	// DeletedAt gorm.DeletedAt
    45  }
    46  
    47  var entries = []Entry{} // if len(entries) > 20, switch to map
    48  
    49  func loadEntries() {
    50  	if len(entries) < 1 {
    51  		// SELECT * FROM entries;
    52  		res := db.Preload(clause.Associations).Find(&entries)
    53  		if res.Error != nil {
    54  			errStr := fmt.Sprintf("  %v", res.Error)
    55  			log.Print(colorRed, errStr, res.Error, colorReset)
    56  		} else {
    57  			log.Printf("%2v entries cached", res.RowsAffected)
    58  		}
    59  	}
    60  }
    61  
    62  // ByName returns by name
    63  func (e *Entry) ByName(s string) (Entry, error) {
    64  	loadEntries()
    65  	for i := 0; i < len(entries); i++ {
    66  		if entries[i].Name == s {
    67  			return entries[i], nil
    68  		}
    69  	}
    70  	return Entry{}, fmt.Errorf("Entry %q not found", s)
    71  }
    72  
    73  // ByID returns by ID
    74  func (e *Entry) ByID(id uint) (Entry, error) {
    75  	loadEntries()
    76  	for i := 0; i < len(entries); i++ {
    77  		if entries[i].ID == id {
    78  			return entries[i], nil
    79  		}
    80  	}
    81  	return Entry{}, fmt.Errorf("Entry %q not found", id)
    82  }
    83  
    84  // MarshalJSON only essential data
    85  func (e Entry) MarshalJSON() ([]byte, error) {
    86  
    87  	et := struct {
    88  		Cnt  string
    89  		Cat  string
    90  		CCs  string
    91  		Tags string
    92  	}{}
    93  	et.Cnt = fmt.Sprintf("ID%v: %v", e.ID, e.Name)
    94  	if e.Comment != "" {
    95  		et.Cnt = fmt.Sprintf("%v - %v", et.Cnt, e.Comment)
    96  	}
    97  	if e.Category.ID > 0 {
    98  		et.Cat = fmt.Sprintf("ID%v: %v", e.Category.ID, e.Category.Name)
    99  	}
   100  
   101  	ccs := ""
   102  	for _, cc := range e.CreditCards {
   103  		ccs = fmt.Sprintf("%v;   ID%v-%v-%v", ccs, cc.ID, cc.Issuer, cc.Number)
   104  	}
   105  	et.CCs = ccs
   106  
   107  	tgs := ""
   108  	for _, tg := range e.Tags {
   109  		tgs = fmt.Sprintf("%v;   ID%v-%v-%v", tgs, tg.ID, tg.Name, tg.CategoryID)
   110  	}
   111  	et.Tags = tgs
   112  
   113  	j, err := json.Marshal(et)
   114  	if err != nil {
   115  		return nil, err
   116  	}
   117  
   118  	js := strings.Split(string(j), "\n")
   119  	js2 := []string{}
   120  	for _, row := range js {
   121  		if strings.Contains(row, `"Cat":""`) {
   122  			row = strings.ReplaceAll(row, `"Cat":""`, "")
   123  		}
   124  		if strings.Contains(row, `"CCs":""`) {
   125  			row = strings.ReplaceAll(row, `"CCs":""`, "")
   126  			// continue
   127  		}
   128  		if strings.Contains(row, `"Tags":""`) {
   129  			row = strings.ReplaceAll(row, `"Tags":""`, "")
   130  			// continue
   131  		}
   132  		row = strings.ReplaceAll(row, ",,,", ",")
   133  		row = strings.ReplaceAll(row, ",,", ",")
   134  		row = strings.ReplaceAll(row, ",}", "}")
   135  		if false {
   136  			log.Printf("\trow\t%v", row)
   137  		}
   138  		js2 = append(js2, row)
   139  	}
   140  
   141  	ret := []byte(strings.Join(js2, "\n"))
   142  	return ret, nil
   143  }
   144  
   145  func (e *Entry) BeforeCreate(tx *gorm.DB) (err error) {
   146  	e.UpsertCounter += 10
   147  	return nil
   148  }
   149  func (e *Entry) BeforeUpdate(tx *gorm.DB) (err error) {
   150  	e.UpsertCounter++
   151  	return nil
   152  }