Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add smart statement export #14

Merged
merged 1 commit into from
Oct 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ package n26
import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"os"

"golang.org/x/oauth2"
)
Expand Down Expand Up @@ -224,7 +227,7 @@ func NewClient(a Auth) (*Client, error) {
return (*Client)(c.Client(ctx, tok)), nil
}

func (c *Client) n26Request(requestMethod, endpoint string, params map[string]string) []byte {
func (c *Client) n26RawRequest(requestMethod, endpoint string, params map[string]string, callback func(io.Reader) error) error {
var req *http.Request
var err error

Expand All @@ -244,7 +247,15 @@ func (c *Client) n26Request(requestMethod, endpoint string, params map[string]st
res, err := (*http.Client)(c).Do(req)
check(err)
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
return callback(res.Body)
}
func (c *Client) n26Request(requestMethod, endpoint string, params map[string]string) []byte {
var body []byte
err := c.n26RawRequest(requestMethod, endpoint, params, func(r io.Reader) error {
var err error
body, err = ioutil.ReadAll(r)
return err
})
check(err)
return body
}
Expand Down Expand Up @@ -358,6 +369,23 @@ func (auth *Client) GetTransactions(from, to TimeStamp, limit string) (*Transact
return transactions, nil
}

// Get transactions for the given time window as N26 CSV file. Stored as 'smrt_statement.csv'
func (auth *Client) GetSmartStatementCsv(from, to TimeStamp) error {
//Filter is applied only if both values are set
if from.IsZero() || to.IsZero() {
return errors.New("Start and end time must be set")
}
return auth.n26RawRequest(http.MethodGet, fmt.Sprintf("/api/smrt/reports/%v/%v/statements", from.AsMillis(), to.AsMillis()), nil, func(r io.Reader) error {
file, err := os.Create("smrt_statement.csv")
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(file, r)
return err
})
}

func (auth *Client) GetStatements(retType string) (string, *Statements) {
body := auth.n26Request(http.MethodGet, "/api/statements", nil)
statements := &Statements{}
Expand Down
30 changes: 22 additions & 8 deletions cmd/n26/n26.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,8 @@ func main() {
},
{
Name: "transactions",
Usage: "list your past transactions. Supports CSV output",
ArgsUsage: "[csv|json|table]",
Usage: "list your past transactions. Supports CSV output.",
ArgsUsage: "[csv|json|table|smartcsv]",
Flags: []cli.Flag{
cli.StringFlag{Name: "limit", Value: "10", Usage: "retrieve last N transactions. Default to 10."},
cli.StringFlag{Name: "from", Usage: "retrieve transactions from this date. " +
Expand All @@ -239,18 +239,32 @@ func main() {
},
Action: func(c *cli.Context) (err error) {
const dateFormat = "2006-01-02"
var from, to n26.TimeStamp
if c.IsSet("from") {
from.Time, err = time.Parse(dateFormat, c.String("from"))
check(err)
}
if c.IsSet("to") {
to.Time, err = time.Parse(dateFormat, c.String("to"))
check(err)
}
API, err := authentication()
check(err)

if c.Args().First() == "smartcsv" {
if from.IsZero() || to.IsZero() {
fmt.Println("Start and end time must be set for smart CSV!")
return nil
}
err = API.GetSmartStatementCsv(from, to)
fmt.Println("Report saved as smrt_statement.csv.")
return
}
writer, err := getTransactionWriter(c.Args().First())
check(err)
limit := c.String("limit")
var transactions *n26.Transactions
if c.IsSet("from") && c.IsSet("to") {
var from, to n26.TimeStamp
from.Time, err = time.Parse(dateFormat, c.String("from"))
check(err)
to.Time, err = time.Parse(dateFormat, c.String("to"))
check(err)
if !from.IsZero() && !to.IsZero() {
transactions, err = API.GetTransactions(from, to, limit)
} else {
transactions, err = API.GetLastTransactions(limit)
Expand Down