ana-ledger/ledger/file.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
}