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 }