Compare commits
10 Commits
641ebf1c93
...
271d612642
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
271d612642 | ||
|
|
a7355d58e8 | ||
|
|
0fd4bbeb09 | ||
|
|
228f916283 | ||
|
|
cca0b163b7 | ||
|
|
8927de633b | ||
|
|
a93b9dfc46 | ||
|
|
dafac49126 | ||
|
|
e36f08deba | ||
|
|
4858286bd6 |
@@ -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
1
cmd/clitest/moolah.dat
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../../../../../Sync/Core/tmp/moolah.dat
|
||||||
@@ -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);
|
||||||
16
cmd/clitest/public/index.html
Normal file
16
cmd/clitest/public/index.html
Normal 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>
|
||||||
85
cmd/clitest/public/transactions.html
Normal file
85
cmd/clitest/public/transactions.html
Normal 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>
|
||||||
@@ -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")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user