all repos — piggy @ 46e32843c33c2a0a8c7cfb71a71b4456234057b0

Dead simple finance manager in Go, HTML and JS.

minor tweaks and fixes
Marco Andronaco andronacomarco@gmail.com
Sat, 05 Oct 2024 20:10:00 +0200
commit

46e32843c33c2a0a8c7cfb71a71b4456234057b0

parent

6eb6efa5eeb457d4ad0b4ce27e48c6b21dc42976

M main.gomain.go

@@ -2,10 +2,8 @@ package main

import ( "github.com/BiRabittoh/piggy/src/api" - "github.com/BiRabittoh/piggy/src/app" ) func main() { - app.InitDB() api.ListenAndServe() }
M src/api/routes.gosrc/api/routes.go

@@ -3,11 +3,15 @@

import ( "log" "net/http" + + "github.com/BiRabittoh/piggy/src/app" ) const address = ":3000" func ListenAndServe() { + app.InitDB() + http.Handle("GET /", http.FileServer(http.Dir("static"))) http.HandleFunc("GET /api/bookmakers", getBookmakers)
M src/app/init.gosrc/app/init.go

@@ -41,18 +41,7 @@ if err != nil {

log.Println("could not count bookmakers: " + err.Error()) } if bookmakersAmount == 0 { - err = DB.Create(&Bookmaker{Name: "Test"}).Error - if err != nil { - log.Fatal(err) - } - err = DB.Create(&Bookmaker{Name: "Test 2"}).Error - if err != nil { - log.Fatal(err) - } - err = DB.Create(&Bookmaker{Name: "Test Exchange", Exchange: true}).Error - if err != nil { - log.Fatal(err) - } + InsertSampleData() } err = DB.Model(&Bookmaker{}).Where(&Bookmaker{Exchange: true}).Pluck("id", &ExchangeIDs).Error

@@ -60,3 +49,27 @@ if err != nil {

log.Println("could not get exchange ids: " + err.Error()) } } + +func InsertSampleData() { + err := DB.Create(&Bookmaker{Name: "First Bookmaker"}).Error + if err != nil { + log.Fatal(err) + } + err = DB.Create(&Bookmaker{Name: "Second Bookmaker"}).Error + if err != nil { + log.Fatal(err) + } + err = DB.Create(&Bookmaker{Name: "Third Exchange", Exchange: true}).Error + if err != nil { + log.Fatal(err) + } + + err = DB.Create(&Account{Name: "First Account"}).Error + if err != nil { + log.Fatal(err) + } + err = DB.Create(&Account{Name: "Second Account"}).Error + if err != nil { + log.Fatal(err) + } +}
M src/app/models.gosrc/app/models.go

@@ -1,7 +1,6 @@

package app import ( - "log" "time" )

@@ -55,6 +54,8 @@ Won *bool `json:"won" gorm:"-"`

Date *time.Time `json:"date" gorm:"-"` Value *int `json:"value" gorm:"-"` + Bookmaker Bookmaker `json:"bookmaker" gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"` + Account Account `json:"account" gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"` SubEntries []SubEntry `json:"sub_entries" gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"` }

@@ -71,108 +72,3 @@ Date time.Time `json:"date" gorm:"not null;default:current_timestamp"`

Value *int `json:"value" gorm:"-"` } - -func (e *Entry) GetOdds() *uint { - v := uint(1) - for _, s := range e.SubEntries { - v *= s.Odds - } - return &v -} - -func (e *Entry) DidWin() *bool { - v := true - for _, s := range e.SubEntries { - if !s.Won { - v = false - return &v - } - } - return &v -} - -func (e *Entry) GetDate() *time.Time { - if len(e.SubEntries) == 0 { - return nil - } - - last := e.SubEntries[0].Date - for _, s := range e.SubEntries { - if s.Date.After(last) { - last = s.Date - } - } - return &last -} - -func (e *Entry) GetValue() (value int) { - if e.Won == nil || e.Odds == nil { - log.Fatalf("please, update e.Won and e.Odds first") - } - - if IsExchange(e.BookmakerID) { - r := (int(e.Amount) * (int(*e.Odds) - 100)) / 100 - if *e.Won { - value = int(e.Amount) - int(e.Amount)*int(e.Commission)/10000 - } else { - value = int(e.Refund) - r - } - } else { - if *e.Won { - value = (int(e.Amount) * int(*e.Odds) / 100) - int(e.Amount) - } else { - value = -int(e.Amount) + int(e.Refund) - } - } - - value += int(e.Bonus) - return -} - -func (r *Record) GetDate() *time.Time { - if len(r.Entries) == 0 { - return nil - } - - last := *r.Entries[0].Date - for _, e := range r.Entries { - if e.Date.After(last) { - last = *e.Date - } - } - return &last -} - -func FillEntryValues(entries []Entry) ([]Entry, int) { - var total int - for i := range entries { - entries[i].Odds = entries[i].GetOdds() - entries[i].Won = entries[i].DidWin() - entries[i].Date = entries[i].GetDate() - v := entries[i].GetValue() - entries[i].Value = &v - total += v - } - return entries, total -} - -func FillRecordValues(records []Record) ([]Record, int) { - var total int - for i := range records { - _, v := FillEntryValues(records[i].Entries) - records[i].Date = records[i].GetDate() - records[i].Value = &v - total += v - } - return records, total -} - -func GetRecords() (records []Record, total int, err error) { - err = DB.Preload("Entries.SubEntries").Find(&records).Error - if err != nil { - return - } - - records, total = FillRecordValues(records) - return -}
A src/app/records.go

@@ -0,0 +1,111 @@

+package app + +import ( + "log" + "time" +) + +func (e *Entry) GetOdds() *uint { + v := uint(1) + for _, s := range e.SubEntries { + v *= s.Odds + } + return &v +} + +func (e *Entry) DidWin() *bool { + v := true + for _, s := range e.SubEntries { + if !s.Won { + v = false + return &v + } + } + return &v +} + +func (e *Entry) GetDate() *time.Time { + if len(e.SubEntries) == 0 { + return nil + } + + last := e.SubEntries[0].Date + for _, s := range e.SubEntries { + if s.Date.After(last) { + last = s.Date + } + } + return &last +} + +func (e *Entry) GetValue() (value int) { + if e.Won == nil || e.Odds == nil { + log.Fatalf("please, update e.Won and e.Odds first") + } + + if IsExchange(e.BookmakerID) { + r := (int(e.Amount) * (int(*e.Odds) - 100)) / 100 + if *e.Won { + value = int(e.Amount) - int(e.Amount)*int(e.Commission)/10000 + } else { + value = int(e.Refund) - r + } + } else { + if *e.Won { + value = (int(e.Amount) * int(*e.Odds) / 100) - int(e.Amount) + } else { + value = -int(e.Amount) + int(e.Refund) + } + } + + value += int(e.Bonus) + return +} + +func (r *Record) GetDate() *time.Time { + if len(r.Entries) == 0 { + return nil + } + + last := *r.Entries[0].Date + for _, e := range r.Entries { + if e.Date.After(last) { + last = *e.Date + } + } + return &last +} + +func FillEntryValues(entries []Entry) ([]Entry, int) { + var total int + for i := range entries { + entries[i].Odds = entries[i].GetOdds() + entries[i].Won = entries[i].DidWin() + entries[i].Date = entries[i].GetDate() + v := entries[i].GetValue() + entries[i].Value = &v + total += v + } + return entries, total +} + +func FillRecordValues(records []Record) ([]Record, int) { + var total int + for i := range records { + _, v := FillEntryValues(records[i].Entries) + records[i].Date = records[i].GetDate() + records[i].Value = &v + total += v + } + return records, total +} + +func GetRecords() (records []Record, total int, err error) { + err = DB.Preload("Entries.Bookmaker").Preload("Entries.Account").Preload("Entries.SubEntries").Find(&records).Error + if err != nil { + return + } + + records, total = FillRecordValues(records) + return +}
M static/js/common.jsstatic/js/common.js

@@ -30,18 +30,37 @@ function formatDate(dateString) {

return (new Date(dateString)).toLocaleString(locale); } -function fixDate(date) { - date.toISOString().split('T')[0] +function formatDone(value, id) { + const input = document.createElement("input"); + input.type = "checkbox"; + input.checked = value; + input.disabled = true; + //input.setAttribute("data-id", id); + //input.onchange = undefined; + return input.outerHTML; } -async function myFetch(url) { - res = await fetch(url); +async function handleFetchResult(res) { if (!res.ok) { - console.error(res.text()) + console.error(await res.text()) return } return await res.json(); +} + +async function myFetch(url) { + res = await fetch(url); + return await handleFetchResult(res); +} + +async function myFetchPOST(url, body) { + const res = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: body ? JSON.stringify(body) : undefined, + }); + return await handleFetchResult(res); } async function getRecords() {
M static/js/records.jsstatic/js/records.js

@@ -1,15 +1,12 @@

document.addEventListener('DOMContentLoaded', function () { loadRecords(); - document.getElementById('new-record').addEventListener('click', function () { - createNewRecord(); - }); + document.getElementById('new-record').addEventListener('click', createNewRecord); }); const casino = { type: 'Arbitraggio', description: 'Prova', - date: fixDate(new Date()), entries: [ { bookmaker_id: 1,

@@ -23,6 +20,7 @@ {

description: "Punta", odds: 200, won: false, + date: new Date().toISOString(), } ] },

@@ -38,6 +36,7 @@ {

description: "Banca", odds: 195, won: true, + date: new Date().toISOString(), } ] },

@@ -47,7 +46,6 @@

const bank = { type: 'Bancata', description: 'Prova', - date: fixDate(new Date()), entries: [ { bookmaker_id: 1,

@@ -61,6 +59,7 @@ {

description: "Punta", odds: 133, won: true, + date: new Date().toISOString(), } ] },

@@ -76,6 +75,7 @@ {

description: "Banca", odds: 135, won: false, + date: new Date().toISOString(), } ] },

@@ -104,7 +104,7 @@ const tr = document.createElement('tr');

const fields = [ formatDate(record.created_at), - record.done, + formatDone(record.done, record.id), record.type, record.description, formatDate(record.date),

@@ -113,7 +113,7 @@ ];

for (const field of fields) { const td = document.createElement('td'); - td.innerText = field; + td.innerHTML = field; tr.appendChild(td); } table.appendChild(tr);

@@ -121,18 +121,8 @@ }

}); } - - -function createNewRecord() { - const recordStr = JSON.stringify(casino); - console.log(recordStr); - - fetch('/api/records', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: recordStr - }).then(response => response.json()) - .then(() => loadRecords()); +async function createNewRecord() { + await myFetchPOST("/api/records", casino); + await myFetchPOST("/api/records", bank) + loadRecords(); }