104 lines
1.9 KiB
Go
104 lines
1.9 KiB
Go
package ledger
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"time"
|
|
)
|
|
|
|
type File string
|
|
|
|
func NewFile(p string) (File, error) {
|
|
f := File(p)
|
|
_, err := f.Deltas()
|
|
return f, err
|
|
}
|
|
|
|
func (file File) Deltas(like ...Like) ([]Delta, error) {
|
|
transactions, err := file.transactions()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
result := make([]Delta, 0, len(transactions)*2)
|
|
for _, transaction := range transactions {
|
|
sums := map[string]float64{}
|
|
for _, acc := range transaction.recipients {
|
|
sums[acc.currency] += acc.value
|
|
delta := newDelta(
|
|
transaction.date,
|
|
transaction.description,
|
|
acc.name,
|
|
acc.value,
|
|
acc.currency,
|
|
)
|
|
if likes(like).all(delta) {
|
|
result = append(result, delta)
|
|
}
|
|
}
|
|
for currency, value := range sums {
|
|
if value == 0 {
|
|
continue
|
|
}
|
|
if transaction.payee == "" {
|
|
return nil, fmt.Errorf("didnt find net zero and no dumping ground payee set: %+v", transaction)
|
|
}
|
|
delta := newDelta(
|
|
transaction.date,
|
|
transaction.description,
|
|
transaction.payee,
|
|
value,
|
|
currency,
|
|
)
|
|
if likes(like).all(delta) {
|
|
result = append(result, delta)
|
|
}
|
|
}
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
type transaction struct {
|
|
date time.Time
|
|
description string
|
|
payee string
|
|
recipients []transactionRecipient
|
|
}
|
|
|
|
type transactionRecipient struct {
|
|
name string
|
|
value float64
|
|
currency string
|
|
}
|
|
|
|
func (t transaction) empty() bool {
|
|
return fmt.Sprint(t) == fmt.Sprint(transaction{})
|
|
}
|
|
|
|
func (file File) transactions() ([]transaction, error) {
|
|
f, err := os.Open(string(file))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer f.Close()
|
|
|
|
result := make([]transaction, 0)
|
|
for {
|
|
one, err := readTransaction(f)
|
|
if !one.empty() {
|
|
result = append(result, one)
|
|
}
|
|
if errors.Is(err, io.EOF) {
|
|
return result, nil
|
|
}
|
|
if err != nil {
|
|
return result, err
|
|
}
|
|
}
|
|
}
|
|
|
|
func readTransaction(r io.Reader) (transaction, error) {
|
|
return transaction{}, io.EOF
|
|
}
|