Compare commits

...

10 Commits

Author SHA1 Message Date
Bel LaPointe
271d612642 todoer 2023-10-27 22:22:07 -06:00
Bel LaPointe
a7355d58e8 todo 2023-10-27 22:21:42 -06:00
Bel LaPointe
0fd4bbeb09 fiddling 2023-10-27 22:15:02 -06:00
Bel LaPointe
228f916283 / is a helper page 2023-10-27 22:05:20 -06:00
Bel LaPointe
cca0b163b7 draw graph of withdrawal:0123 on /transactions page 2023-10-27 21:56:33 -06:00
Bel LaPointe
8927de633b watercss too fat for graph 2023-10-27 21:47:41 -06:00
Bel LaPointe
a93b9dfc46 at least it is viewable 2023-10-27 21:42:49 -06:00
Bel LaPointe
dafac49126 halfway to moolah2 2023-10-27 21:28:31 -06:00
Bel LaPointe
e36f08deba clean routing and move .html to ./public/ 2023-10-27 20:59:42 -06:00
Bel LaPointe
4858286bd6 move api to /api/* 2023-10-27 20:50:27 -06:00
7 changed files with 160 additions and 25 deletions

View File

@@ -42,12 +42,6 @@ func main() {
if err != nil { if err != nil {
panic(err) panic(err)
} }
deltas, err := f.Deltas()
if err != nil {
panic(err)
}
deltas = deltas.Group(ledger.GroupName(*groupName), ledger.GroupDate(*groupDate))
bpis := make(ledger.BPIs) bpis := make(ledger.BPIs)
if *bpiPath != "" { if *bpiPath != "" {
@@ -57,28 +51,44 @@ func main() {
} }
} }
like := ledger.Likes{ledger.LikeName(*likeName)}
if *httpOutput != "" { if *httpOutput != "" {
like = append(like, ledger.LikeBefore(*likeBefore))
like = append(like, ledger.LikeAfter(*likeAfter))
foo := func(w http.ResponseWriter, r *http.Request) { foo := func(w http.ResponseWriter, r *http.Request) {
if !strings.HasPrefix(r.URL.Path, "/api") {
http.FileServer(http.Dir("./public")).ServeHTTP(w, r)
return
}
switch r.URL.Path { switch r.URL.Path {
case "/bal", "/reg": case "/api/transactions":
case "/ui": reqF := f
f, err := os.Open("./index.html") if queryF := r.URL.Query().Get("f"); queryF != "" {
reqF, err = ledger.NewFiles(queryF)
if err != nil {
panic(err)
}
}
deltas, err := reqF.Deltas()
if err != nil { if err != nil {
panic(err) panic(err)
} }
defer f.Close() json.NewEncoder(w).Encode(map[string]any{
io.Copy(w, f) "deltas": deltas.Like(ledger.LikeAfter(time.Now().Add(-1 * time.Hour * 24 * 365 / 2).Format("2006-01"))),
return "balances": deltas.Balances().Like("^AssetAccount:").WithBPIs(bpis),
default: })
http.NotFound(w, r)
return return
} }
deltas, err := f.Deltas()
if err != nil {
panic(err)
}
deltas = deltas.Group(ledger.GroupName(*groupName), ledger.GroupDate(*groupDate))
like := ledger.Likes{
ledger.LikeName(*likeName),
ledger.LikeBefore(*likeBefore),
ledger.LikeAfter(*likeAfter),
}
foolike := make(ledger.Likes, 0) foolike := make(ledger.Likes, 0)
for _, v := range r.URL.Query()["likeName"] { for _, v := range r.URL.Query()["likeName"] {
foolike = append(foolike, ledger.LikeName(v)) foolike = append(foolike, ledger.LikeName(v))
@@ -92,8 +102,7 @@ func main() {
if len(foolike) == 0 { if len(foolike) == 0 {
foolike = like foolike = like
} }
deltas = deltas.Like(foolike...)
deltas := deltas.Like(foolike...)
// MODIFIERS // MODIFIERS
for i, whatIf := range r.URL.Query()["whatIf"] { for i, whatIf := range r.URL.Query()["whatIf"] {
@@ -281,9 +290,9 @@ func main() {
} }
return chart return chart
} }
primary := toChart(r.URL.Path == "/bal", r.URL.Query().Get("chart"), register) primary := toChart(r.URL.Path == "/api/bal", r.URL.Query().Get("chart"), register)
if len(predicted) > 0 { if len(predicted) > 0 {
primary.Overlap(toChart(r.URL.Path == "/bal", "line", predicted)) primary.Overlap(toChart(r.URL.Path == "/api/bal", "line", predicted))
} }
if err := primary.Render(w); err != nil { if err := primary.Render(w); err != nil {
panic(err) panic(err)
@@ -298,6 +307,12 @@ func main() {
panic(err) panic(err)
} }
} else { } else {
deltas, err := f.Deltas()
if err != nil {
panic(err)
}
deltas = deltas.Group(ledger.GroupName(*groupName), ledger.GroupDate(*groupDate))
like := ledger.Likes{ledger.LikeName(*likeName)}
if *likeLedger { if *likeLedger {
like = append(like, ledger.LikeBefore(*likeBefore)) like = append(like, ledger.LikeBefore(*likeBefore))
like = append(like, ledger.LikeAfter(*likeAfter)) like = append(like, ledger.LikeAfter(*likeAfter))

1
cmd/clitest/moolah.dat Symbolic link
View File

@@ -0,0 +1 @@
../../../../../../Sync/Core/tmp/moolah.dat

View File

@@ -1,5 +1,6 @@
<html style="height: calc(100% - 4em);"> <html style="height: calc(100% - 4em);">
<header> <header>
<nolink rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/light.css">
<script> <script>
function http(method, remote, callback, body) { function http(method, remote, callback, body) {
var xmlhttp = new XMLHttpRequest(); var xmlhttp = new XMLHttpRequest();
@@ -17,12 +18,12 @@
function callback(responseBody, responseStatus) { function callback(responseBody, responseStatus) {
} }
function draw(form) { function draw(form) {
path = "/bal" path = "/api/bal"
query = "?x=y" query = "?x=y"
Array.from(form.elements).forEach((input) => { Array.from(form.elements).forEach((input) => {
query += "&" + input.name + "=" + input.value; query += "&" + input.name + "=" + input.value;
if (input.name == "mode") { if (input.name == "mode") {
path = "/" + input.value; path = "/api/" + input.value;
} }
}); });
console.log(path, query); console.log(path, query);

View File

@@ -0,0 +1,16 @@
<html style="height: calc(100% - 4em);">
<header>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/dark.css">
</header>
<body style="height: 100%;">
<h1>Moolah2 Hub</h1>
<ul style="line-height: 3em;">
<li><a href="/transactions.html">Transactions on Shared Chase</a></li>
<li><a href="/explore.html">Explore Bel's Money</a></li>
<li><a href="/api/bal?x=y&mode=bal&likeName=AssetAccount&chart=stack&predictionMonths=120&bpi=true&zoomStart=2023-06&prediction=interest=AssetAccount:Cash%20\$%200.02&prediction=contributions=AssetAccount:Bonds%20$%201875&prediction=interest=AssetAccount:Monthly%20\$%200.03&prediction=contributions=AssetAccount:Monthly%20$%202500&predictFixedGrowth=VBTLX=0.02&predictFixedGrowth=GLD=0.02&predictFixedGrowth=FXAIX=0.03&predictFixedGrowth=FSPSX=0.03&whatIf=AssetAccount:Cash%20$%20-.10000&=">Project Bel's Net Worth</a></li>
<li><a href="/api/reg?x=y&mode=reg&likeName=Withdrawal:&chart=stack&predictionMonths=3&bpi=false&zoomStart=2023-01&prediction=autoContributions=&predictFixedGrowth=VBTLX=0&whatIf=AssetAccount:Cash%20$%20-.10000&=">Expect Bel's Expenses</a></li>
</ul>
</body>
<footer>
</footer>
</html>

View File

@@ -0,0 +1,85 @@
<html>
<header>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/dark.css">
<script>
function http(method, remote, callback, body) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
callback(xmlhttp.responseText, xmlhttp.status)
}
};
xmlhttp.open(method, remote, true);
if (typeof body == "undefined") {
body = null
}
xmlhttp.send(body);
}
function callback(responseBody, responseStatus) {
}
var f = String(window.location).split("/transactions.html")[1]
if (!f) {
f = "/moolah.dat"
}
f = "." + f
function init() {
load(f)
}
function load(f) {
http("GET", "/api/transactions?f="+f, (body, status) => {
var d = JSON.parse(body)
loadBalances(d.balances)
loadDeltas(d.deltas)
})
}
function loadBalances(balances) {
var result = `<table>`
for (var k in balances) {
result += `<tr style="display: flex; flex-direction: row; width: 100%; justify-content: space-between;"><td>${k}</td><td>${Math.floor(balances[k]["$"])}</td></tr>`
}
result += `</table>`
document.getElementById("bal").innerHTML = result
}
function loadDeltas(deltas) {
console.log(deltas[0])
for (var i = 0; i < deltas.length/2; i++) {
tmp = deltas[i]
deltas[i] = deltas[deltas.length-1-i]
deltas[deltas.length-1-i] = tmp
}
console.log(deltas[0])
var result = `<table>`
for (var k of deltas) {
result += `<tr>`
result += ` <td>${k.Date}</td>`
result += ` <td>${k.Description}</td>`
result += ` <td>${k.Name}</td>`
result += ` <td style="text-align: right">${k.Currency}</td>`
result += ` <td style="text-align: right">${k.Value}</td>`
result += `</tr>`
}
result += `</table>`
document.getElementById("reg").innerHTML = result
}
</script>
</header>
<body onload="init();">
<h2>Moolah2</h2>
<details>
<summary>Balance</summary>
<div id="bal">
</div>
<details>
<summary><i>Look at this graph</i></summary>
<iframe style="background: white; width: 100%;" src="/api/reg?x=y&mode=reg&likeName=Withdrawal:[0123]&chart=stack&predictionMonths=6&prediction=autoContributions=&bpi=true&zoomStart=2023-01"></iframe>
</details>
</details>
<details open>
<summary>Register</summary>
<div id="reg">
</div>
</details>
</body>
<footer>
</footer>
</html>

View File

@@ -2,6 +2,8 @@ package ledger
import ( import (
"fmt" "fmt"
"maps"
"regexp"
"strings" "strings"
) )
@@ -9,6 +11,17 @@ type Balances map[string]Balance
type Balance map[Currency]float64 type Balance map[Currency]float64
func (balances Balances) Like(pattern string) Balances {
result := make(Balances)
p := regexp.MustCompile(pattern)
for k, v := range balances {
if p.MatchString(k) {
result[k] = maps.Clone(v)
}
}
return result
}
func (balances Balances) WithBPIs(bpis BPIs) Balances { func (balances Balances) WithBPIs(bpis BPIs) Balances {
return balances.WithBPIsAt(bpis, "9") return balances.WithBPIsAt(bpis, "9")
} }

View File

@@ -1,4 +1,6 @@
todo: todo:
- cicd on not gogs,gitness but gitea; registry-app.inhome.blapointe.com:5001/docker
stuff
- html version can accept new transactions for moolah - html version can accept new transactions for moolah
scheduled: [] scheduled: []
done: done:
@@ -65,3 +67,5 @@ done:
- todo: predictWhatIf=2023-10=AssetAccount:Cash=$=-7000 changes too much when removing - todo: predictWhatIf=2023-10=AssetAccount:Cash=$=-7000 changes too much when removing
7k from prinicple 7k from prinicple
ts: Fri Oct 27 20:37:12 MDT 2023 ts: Fri Oct 27 20:37:12 MDT 2023
- todo: cicd on not gogs,gitness but gitea
ts: Fri Oct 27 22:22:04 MDT 2023