package ledger import ( "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 { 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 (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) result = append(result, one) if err == io.EOF { return result, nil } if err != nil { return result, err } } } func readTransaction(r io.Reader) (transaction, error) { return transaction{}, io.EOF }