summaryrefslogtreecommitdiffstats
path: root/cli/src/main.rs
blob: 18d422ae798467e781cef7684fc16a9536c13963 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use chrono::naive::NaiveDate;
use rust_decimal::Decimal;
use std::path::PathBuf;
use std::str::FromStr;
use structopt::StructOpt;

mod model;

//TODO relative ("yesterday", "-2d", etc)
fn parse_date(s: &str) -> Result<NaiveDate, String> {
    NaiveDate::parse_from_str(s, "%Y-%m-%d").map_err(|e| e.to_string())
}

#[derive(Debug)]
#[derive(StructOpt)]
enum Command {
    Insert {
        kind: model::TransactionKind,
        #[structopt(long)]
        account: String,

        // #[structopt(long = "category", multiple = true, number_of_values = 1)]
        // category: Vec<String>,
        #[structopt(long)]
        category: String,

        #[structopt(long, parse(try_from_str = Decimal::from_str))]
        amount: Decimal,

        description: String,
        #[structopt(long, parse(try_from_str = parse_date))]
        date: Option<NaiveDate>,
    },
    List {
        target: ListTarget,
    }
}

#[derive(Debug)]
#[derive(StructOpt)]
enum ListTarget {
    Categories,
}

impl std::str::FromStr for ListTarget {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "categories" => Ok(ListTarget::Categories),
            _ => Err(format!("Unknown listable: {:?}", s)),
        }
    }
}

#[derive(Debug)]
#[derive(StructOpt)]
struct Mn {
    #[structopt(subcommand)]
    command: Command,
}

fn main() {
    let mut store = model::Store::open(PathBuf::from("store")).unwrap();
    let args = Mn::from_args();
    eprintln!("{:?}", args);
    match args.command {
        Command::Insert {
            kind,
            account,
            category,
            amount,
            description,
            date,
        } => {
            let transaction = model::Transaction {
                kind,
                to: account,
                from: "Default".to_string(),
                category,
                amount,
                description,
                date: match date {
                    Some(date) => date,
                    None => chrono::offset::Local::today().naive_utc(),
                },
            };
            eprintln!("{:?}", transaction);
            println!("{}", transaction.id());
            store.push(transaction);
            store.write().unwrap();
        }
        Command::List {
            target: ListTarget::Categories
        } => {
            println!("{:?}", store.categories());
        }
    }
}