transactions 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +11 -0
- data/LICENSE.md +21 -0
- data/README.md +245 -0
- data/bin/transactions +20 -0
- data/lib/transactions.rb +12 -0
- data/lib/transactions/main.rb +32 -0
- data/lib/transactions/options.rb +89 -0
- data/lib/transactions/parser.rb +162 -0
- data/lib/transactions/version.rb +4 -0
- metadata +56 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d1fb2dde0117abbbd982a133959573444cb4b0fd
|
4
|
+
data.tar.gz: 27fbf80ef838f35511f3a9337ac7746c159b811f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dfc5cc11724b32935bfb1b63936404109f9d384a3936dd28ab899e32ac0e11d55e51ef58491dfe9312d83ba62fcf6eb921bbd2f4d7091655e83c4e2d8b80d33c
|
7
|
+
data.tar.gz: e7d1c09de955ccde03a27024783c3eb9e5bd3ea7e6e4a875712da422ad03cd9ef30724ae6aa934d8b2437318762e242d326b9aa39b832ebb55b809c03c3298dc
|
data/CHANGELOG.md
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2013 Randy Schneck
|
2
|
+
|
3
|
+
The MIT License (MIT)
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
9
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
10
|
+
so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,245 @@
|
|
1
|
+
# [transactions](http://computercrayons.com/transactions)
|
2
|
+
|
3
|
+
## Description
|
4
|
+
|
5
|
+
transactions is a command line application for managing your finances using a
|
6
|
+
plain text format (yaml or json). All transactions are written to a text file
|
7
|
+
by hand similar to a checkbook register. This text file is your ledger and it
|
8
|
+
can handle most financial bookkeeping needs.
|
9
|
+
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
### Requirements
|
14
|
+
|
15
|
+
Before you can get started with *transaction*, the following must be installed
|
16
|
+
on your system. Note that RubyGems is included with Ruby since version 1.9.
|
17
|
+
|
18
|
+
* [Ruby](http://www.ruby-lang.org/en/downloads/)
|
19
|
+
* [RubyGems](http://rubygems.org/pages/download)
|
20
|
+
|
21
|
+
The best way to install transactions is via RubyGems. At the terminal prompt, run
|
22
|
+
the following command:
|
23
|
+
|
24
|
+
`gem install transactions`
|
25
|
+
|
26
|
+
|
27
|
+
## Additional Information
|
28
|
+
|
29
|
+
### Using the program
|
30
|
+
|
31
|
+
1. create a ledger file
|
32
|
+
* you can copy and paste the example ledger below into a text file named
|
33
|
+
"ledger.yaml" if you just want to try out the program. If this is your
|
34
|
+
style of bookkeeping, then just edit the file with your own info using
|
35
|
+
your favorite text editor.
|
36
|
+
* run this command `transactions bal` and see the output.
|
37
|
+
* by default, "transactions" looks in the current directory for a file
|
38
|
+
named "ledger.yaml".
|
39
|
+
* you can use the -f option to specify a different file (eg. `transactions
|
40
|
+
-f example.yaml bal`)
|
41
|
+
2. run `transactions reg`
|
42
|
+
* this is a register for all transactions
|
43
|
+
* notice that every transaction prints multiple times
|
44
|
+
* this happens because each transaction affects multiple accounts
|
45
|
+
3. to make the register more useful try `transactions reg assets:checking`
|
46
|
+
* this will limit the register to assets:checking (case is ignored)
|
47
|
+
* this would be equivalent to printing a checkbook register from
|
48
|
+
"ledger.yaml"
|
49
|
+
* more than one account can be included eg. assets:checking expenses:food
|
50
|
+
* this limit by string of text also works with the balance command.
|
51
|
+
4. see keeping a ledger below for information about general accounting
|
52
|
+
principles to help you with your own ledger.
|
53
|
+
|
54
|
+
|
55
|
+
### Sample Ledger File
|
56
|
+
|
57
|
+
# This is a sample ledger file
|
58
|
+
# this line and the one above are comments that will be ignored
|
59
|
+
# during processing! Comments can also be placed at the end of
|
60
|
+
# a line (see below for examples).
|
61
|
+
|
62
|
+
- date: 2013/01/01
|
63
|
+
transaction: Opening Balances
|
64
|
+
Assets:Checking: 251.0
|
65
|
+
Assets:Savings: 5005.3
|
66
|
+
Assets:IRA: 22510.92
|
67
|
+
Liabilities:CreditCard: -931.32
|
68
|
+
Liabilities:Salliemae: -10189.05
|
69
|
+
Equity:OpeningBalances: -16646.85
|
70
|
+
|
71
|
+
- date: 2013/01/07
|
72
|
+
transaction: Trader Joe's
|
73
|
+
Expenses:Food:Groceries: 58.77
|
74
|
+
Assets:Checking: -58.77
|
75
|
+
|
76
|
+
- date: 2013/01/09
|
77
|
+
transaction: Student Loan Payment
|
78
|
+
Liabilities:Salliemae: 103.3
|
79
|
+
Expenses:Interest:StudentLoan: 15.04
|
80
|
+
Assets:Checking: -118.34
|
81
|
+
|
82
|
+
- date: 2013/02/11
|
83
|
+
transaction: Deposit Paycheck
|
84
|
+
Assets:Checking: 1242.87
|
85
|
+
Income:JobName: -1242.87
|
86
|
+
|
87
|
+
- date: 2013/02/11
|
88
|
+
transaction: Visa Payment
|
89
|
+
Expenses:Interest:CreditCard: 10.0
|
90
|
+
Liabilities:CreditCard: 130.0
|
91
|
+
Assets:Checking: -140.0
|
92
|
+
|
93
|
+
- date: 2013/02/25
|
94
|
+
transaction: PG&E
|
95
|
+
Expenses:Utilities:Electric: 75
|
96
|
+
Assets:Checking: -75
|
97
|
+
|
98
|
+
- date: 2013/02/25
|
99
|
+
transaction: Verizon # Switch to Virgin Mobile
|
100
|
+
Expenses:Phone: 55.72
|
101
|
+
Assets:Checking: -55.72
|
102
|
+
|
103
|
+
- date: 2013/02/26
|
104
|
+
transaction: Ike's Lair # good sandwich
|
105
|
+
Expenses:Food:Dining: 22.31
|
106
|
+
Assets:Checking: -22.31
|
107
|
+
|
108
|
+
# a transaction requires only one space as a separator but can also be
|
109
|
+
# aligned as above. The choice is yours!
|
110
|
+
|
111
|
+
- date: 2013/02/26
|
112
|
+
transaction: Money Transfer
|
113
|
+
Assets:Savings: 494.7
|
114
|
+
Assets:Checking: -494.7
|
115
|
+
|
116
|
+
|
117
|
+
|
118
|
+
### Keeping a Ledger
|
119
|
+
|
120
|
+
Although the program doesn't limit you on naming your accounts, it is highly
|
121
|
+
recommended to use some standard conventions in order to facilitate easier
|
122
|
+
understanding of your finances by your accountant. The five base accounts that
|
123
|
+
you should use are:
|
124
|
+
|
125
|
+
+ Assets
|
126
|
+
* what you own
|
127
|
+
* a debit or withdrawal will be a negative number
|
128
|
+
* a deposit will be a positive number
|
129
|
+
+ Liabilities
|
130
|
+
* what you owe
|
131
|
+
* a payment towards a liability will be a positive number
|
132
|
+
* borrowing on a liability will be a negative number
|
133
|
+
+ Equity
|
134
|
+
* what you have accumulated over time
|
135
|
+
* Equity = Assets - Liabilities
|
136
|
+
+ Income
|
137
|
+
* your earnings from society
|
138
|
+
* this will always be a negative number (seems weird but you'll get used to
|
139
|
+
it)
|
140
|
+
* think of Income as a withdrawal from society and that is why it is
|
141
|
+
negative
|
142
|
+
+ Expenses
|
143
|
+
* things you spent your assets on or incurred liabilities for
|
144
|
+
* a purchase or expense will be a positive number
|
145
|
+
* a return or refund will be a negative number
|
146
|
+
|
147
|
+
Everything falls under one of these five categories but also belongs in a
|
148
|
+
sub-account. Sub-accounts are created by appending a colon and the name of the
|
149
|
+
sub-account after one of the main accounts. Some examples for account names
|
150
|
+
could then be `Assets:Savings`, `Income:My Job`, `Expenses:Food:Groceries`,
|
151
|
+
`Expenses:Food:Dining`, `Liabilities:Credit Card`.
|
152
|
+
|
153
|
+
See the example ledger above for the complete syntax.
|
154
|
+
|
155
|
+
|
156
|
+
### Start your own ledger
|
157
|
+
|
158
|
+
1. Create an empty text file named "ledger.yaml"
|
159
|
+
2. Enter your opening balances as the first transaction using the Equity
|
160
|
+
account (see example ledger above)
|
161
|
+
* The accounting equation that makes this work is `Equity = Assets -
|
162
|
+
Liabilities`
|
163
|
+
* Your Assets are positive numbers (unless your checking account is in the
|
164
|
+
negative == BAD!)
|
165
|
+
* Your Liabilities are negative since they bring down your net worth
|
166
|
+
* The difference of your Assets and Liabilities is balanced to zero with
|
167
|
+
the equity account.
|
168
|
+
* A negative equity in our ledger means a positive net worth (your assets
|
169
|
+
are greater than your liabilities).
|
170
|
+
* A positive equity in our ledger means a negative net worth (your
|
171
|
+
liabilities are greater than your assets).
|
172
|
+
3. Enter transactions (be consistent with your account naming).
|
173
|
+
4. The best way to be consistent is to run `transactions bal` to see all your
|
174
|
+
accounts before creating your new entry.
|
175
|
+
5. Transaction names can be whatever you want to help remind you of the
|
176
|
+
transaction.
|
177
|
+
6. The date is formatted as `YYYY/MM/DD` (this is important for the date
|
178
|
+
limiting options to function)
|
179
|
+
|
180
|
+
|
181
|
+
### Some (hopefully) Helpful Notes
|
182
|
+
|
183
|
+
* Assets, Liabilities, and Equity accounts are called "Real" accounts since
|
184
|
+
their balances are not zeroed out at the end of an accounting period.
|
185
|
+
* While this is unfortunate in the case of your Liabilities, it is
|
186
|
+
beneficial to your Assets.
|
187
|
+
* Income and Expense accounts are called "Nominal" accounts since they begin at
|
188
|
+
zero at the start of a new accounting period.
|
189
|
+
* Income is used for expenses, to pay liabilities, or put into an asset
|
190
|
+
account as it comes in from society and thus starts at zero every
|
191
|
+
accounting period
|
192
|
+
* Expenses start over every accounting period (you can't claim already
|
193
|
+
claimed Expenses
|
194
|
+
|
195
|
+
|
196
|
+
### Examples
|
197
|
+
|
198
|
+
Trial Balance - list of all accounts in the ledger and their balances
|
199
|
+
|
200
|
+
transactions balance
|
201
|
+
|
202
|
+
Balance Sheet - What you own and owe
|
203
|
+
|
204
|
+
transactions balance assets liabilities
|
205
|
+
|
206
|
+
Income Statement - measures cash flow / profitability (income vs expenses)
|
207
|
+
|
208
|
+
transactions balance income expenses
|
209
|
+
|
210
|
+
Limit by date
|
211
|
+
|
212
|
+
transactions -b 2013/01/01 -e 2013/12/31 balance
|
213
|
+
|
214
|
+
* this will show the entire year of 2013 inclusive of the dates used as
|
215
|
+
arguments.
|
216
|
+
* the date limits work for balance, register, and print commands.
|
217
|
+
* the totals for income and expenses will be accurate with date limits since
|
218
|
+
they are nominal accounts that reset at the beginning of a new accounting
|
219
|
+
period.
|
220
|
+
* the totals for assets and liabilities are the amounts that the accounts
|
221
|
+
changed during the accounting period. To see the totals that you actually
|
222
|
+
have in your assets or liabilities the date limits must be left out.
|
223
|
+
|
224
|
+
|
225
|
+
## Contributing
|
226
|
+
|
227
|
+
How to get your work merged into the project?
|
228
|
+
|
229
|
+
* Fork the project.
|
230
|
+
* Clone your fork ( git clone git@github.com:<username>/transactions.git ).
|
231
|
+
* Create a topic branch for your change ( git checkout -b my_new_feature ).
|
232
|
+
* Hack away, add tests. Not necessarily in that order.
|
233
|
+
* Make sure everything still passes by running rake.
|
234
|
+
* If necessary, rebase your commits into logical chunks, without errors.
|
235
|
+
* Push the branch up ( git push origin my_new_feature ).
|
236
|
+
* Create a pull request against randyschneck/transactions and describe what
|
237
|
+
your change does and the why you think it should be merged.
|
238
|
+
|
239
|
+
|
240
|
+
## Credits
|
241
|
+
|
242
|
+
Written by Randy A. Schneck (rasch@computercrayons.com)
|
243
|
+
|
244
|
+
see [LICENSE.md](https://github.com/randyschneck/transactions/blob/master/LICENSE.md)
|
245
|
+
|
data/bin/transactions
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift File.join(File.dirname(__FILE__), "..", "lib") # For use/testing when not installed
|
4
|
+
|
5
|
+
require 'transactions'
|
6
|
+
|
7
|
+
t = Transaction::Parser.new
|
8
|
+
|
9
|
+
if ARGV[0]
|
10
|
+
command = ARGV[0]
|
11
|
+
unless %w(balance bal register reg print).include? command
|
12
|
+
puts "That's not an option. Type 'transactions --help' for more info."
|
13
|
+
end
|
14
|
+
t.send(:parse, "balance") if %w(balance bal).include? command
|
15
|
+
t.send(:parse, "register") if %w(register reg).include? command
|
16
|
+
t.send(:parse, "print") if 'print' == command
|
17
|
+
else
|
18
|
+
puts "At least one command is required. Type 'transactions --help' for more info."
|
19
|
+
end
|
20
|
+
|
data/lib/transactions.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) # For use/testing when not installed
|
2
|
+
|
3
|
+
# stdlib
|
4
|
+
require 'yaml'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
# internal requires
|
8
|
+
require 'transactions/version'
|
9
|
+
require 'transactions/options'
|
10
|
+
require 'transactions/main'
|
11
|
+
require 'transactions/parser'
|
12
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Transaction
|
2
|
+
|
3
|
+
class Parser
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@options = Options.new.options
|
7
|
+
@default_ledger = 'ledger.yaml'
|
8
|
+
if @options[:file]
|
9
|
+
ledger = File.read @options[:file]
|
10
|
+
else
|
11
|
+
if File.exists? File.expand_path(@default_ledger)
|
12
|
+
ledger = File.read(File.expand_path(@default_ledger))
|
13
|
+
else
|
14
|
+
abort "There is no 'ledger.yaml' file in the current directory."
|
15
|
+
end
|
16
|
+
end
|
17
|
+
@ledger = YAML::load ledger if ledger != ""
|
18
|
+
@ledger = [] if ledger == ""
|
19
|
+
@date = Time.now.strftime "%Y/%m/%d"
|
20
|
+
if @options[:sort] == 'tran' # sort by transaction
|
21
|
+
@ledger.sort_by! { |h| h['transaction'] }
|
22
|
+
elsif @options[:sort] == 'date' # sort by date
|
23
|
+
@ledger.sort_by! { |h| h['date'] }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
include Transaction
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module Transaction
|
2
|
+
|
3
|
+
class Options
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@options = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def options
|
10
|
+
OptionParser.new do |opts|
|
11
|
+
|
12
|
+
opts.banner = "Usage: transactions [options] COMMAND [ARGS] ..."
|
13
|
+
|
14
|
+
opts.on("-f", "--file PATH", "PATH to yaml file to parse") do |x|
|
15
|
+
@options[:file] = x
|
16
|
+
end
|
17
|
+
|
18
|
+
opts.on("-c", "--current",
|
19
|
+
"don't include entries with future dates") do |x|
|
20
|
+
@options[:current] = x
|
21
|
+
end
|
22
|
+
|
23
|
+
opts.on("-b", "--begin DATE", "set begin date, DATE: YYYY/MM/DD") do |x|
|
24
|
+
@options[:begin] = x
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on("-e", "--end DATE", "set end date, DATE: YYYY/MM/DD") do |x|
|
28
|
+
@options[:end] = x
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on("-s", "--subtotal", "show sub-totals for balance") do |x|
|
32
|
+
@options[:subtotal] = x
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on("-E", "--empty", "show accounts with zero balance") do |x|
|
36
|
+
@options[:empty] = x
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.on("-S", "--sort ARG", "sort by field, ARG can be date or tran") do |x|
|
40
|
+
@options[:sort] = x
|
41
|
+
end
|
42
|
+
|
43
|
+
opts.on("-w", "--wide", "print 132 columns wide for register") do |x|
|
44
|
+
@options[:wide] = x
|
45
|
+
end
|
46
|
+
|
47
|
+
#opts.on("-C", "--cleared", "only include cleared transactions") do |x|
|
48
|
+
# @options[:cleared] = x
|
49
|
+
#end
|
50
|
+
|
51
|
+
#opts.on("-U", "--uncleared", "only include uncleared transactions") do |x|
|
52
|
+
# @options[:uncleared] = x
|
53
|
+
#end
|
54
|
+
|
55
|
+
opts.on_tail("-h", "--help", "show this help message") do
|
56
|
+
puts opts
|
57
|
+
abort self.commands_help
|
58
|
+
end
|
59
|
+
|
60
|
+
opts.on_tail("-v", "--version", "show version") do
|
61
|
+
abort "#{Transaction::VERSION}"
|
62
|
+
end
|
63
|
+
|
64
|
+
end.parse!
|
65
|
+
|
66
|
+
@options
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
def commands_help
|
72
|
+
<<-COMMANDHELP
|
73
|
+
|
74
|
+
COMMANDS
|
75
|
+
--------
|
76
|
+
balance [ACCOUNT].. Prints account balances, limited to ACCOUNTS.
|
77
|
+
'bal' can be used as a shortcut.
|
78
|
+
register [ACCOUNT].. Prints account register, limited to ACCOUNTS.
|
79
|
+
'reg' can be used as a shortcut.
|
80
|
+
print Prints transactions formatted for export to ledger.
|
81
|
+
Can be limited by date but not ACCOUNT.
|
82
|
+
COMMANDHELP
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
@@ -0,0 +1,162 @@
|
|
1
|
+
module Transaction
|
2
|
+
|
3
|
+
def parse(cmd)
|
4
|
+
|
5
|
+
@accounts = {}
|
6
|
+
@running_total = 0
|
7
|
+
|
8
|
+
def transaction_print(x)
|
9
|
+
puts "#{x['date']} #{x['transaction']}"
|
10
|
+
x.each do |k, v |
|
11
|
+
puts sprintf(" %-30.30s % .2f", k, v) if v.is_a? Numeric
|
12
|
+
end
|
13
|
+
puts ""
|
14
|
+
end
|
15
|
+
|
16
|
+
def transaction_balance(k, v)
|
17
|
+
@accounts[k] += v if v.is_a? Numeric
|
18
|
+
end
|
19
|
+
|
20
|
+
def transaction_register(x, k, v, running_total)
|
21
|
+
if v.is_a? Numeric
|
22
|
+
if @options[:wide] # for printing 132 columns wide
|
23
|
+
t = "%10s %-44s %-44s %15.2f %15.2f"
|
24
|
+
puts sprintf(t, x['date'], x['transaction'][0..42],
|
25
|
+
k[0..42], v, running_total)
|
26
|
+
else # for printing 78 columns wide (default)
|
27
|
+
t = "%10s %-20s %-24s %10.2f %10.2f"
|
28
|
+
puts sprintf(t, x['date'], x['transaction'][0..18],
|
29
|
+
k[0..22], v, running_total)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def transaction_command(cmd, x, k, v)
|
35
|
+
ARGV.map! { |z| z.downcase }
|
36
|
+
if ARGV[1..-1].any? { |arg| k.downcase.include? arg }
|
37
|
+
@running_total += v if v.is_a? Numeric
|
38
|
+
if cmd == 'print'
|
39
|
+
transaction_print(x)
|
40
|
+
elsif cmd == 'balance'
|
41
|
+
transaction_balance(k, v)
|
42
|
+
elsif cmd == 'register'
|
43
|
+
transaction_register(x, k, v, @running_total)
|
44
|
+
end
|
45
|
+
elsif !ARGV[1]
|
46
|
+
@running_total += v if v.is_a? Numeric
|
47
|
+
if cmd == 'print'
|
48
|
+
transaction_print(x)
|
49
|
+
elsif cmd == 'balance'
|
50
|
+
transaction_balance(k, v)
|
51
|
+
elsif cmd == 'register'
|
52
|
+
transaction_register(x, k, v, @running_total)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
@ledger.each do |x|
|
58
|
+
total = 0
|
59
|
+
x.each do |k, v|
|
60
|
+
total += v if v.is_a? Numeric
|
61
|
+
@accounts[k] ||= 0 if v.is_a? Numeric
|
62
|
+
|
63
|
+
if @options[:current]
|
64
|
+
if @options[:begin]
|
65
|
+
if x['date'] <= @date && x['date'] >= @options[:begin]
|
66
|
+
transaction_command(cmd, x, k, v); break if cmd == 'print'
|
67
|
+
end
|
68
|
+
else
|
69
|
+
if x['date'] <= @date
|
70
|
+
transaction_command(cmd, x, k, v); break if cmd == 'print'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
elsif @options[:begin] || @options[:end]
|
74
|
+
if @options[:begin] && @options[:end]
|
75
|
+
if @options[:begin] <= x['date'] and x['date'] <= @options[:end]
|
76
|
+
transaction_command(cmd, x, k, v); break if cmd == 'print'
|
77
|
+
end
|
78
|
+
elsif @options[:begin]
|
79
|
+
if x['date'] >= @options[:begin]
|
80
|
+
transaction_command(cmd, x, k, v); break if cmd == 'print'
|
81
|
+
end
|
82
|
+
elsif @options[:end]
|
83
|
+
if x['date'] <= @options[:end]
|
84
|
+
transaction_command(cmd, x, k, v); break if cmd == 'print'
|
85
|
+
end
|
86
|
+
end
|
87
|
+
else
|
88
|
+
transaction_command(cmd, x, k, v); break if cmd == 'print'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
if total.round(2) != 0
|
92
|
+
abort <<-EOF
|
93
|
+
You have an UNBALANCED Transaction
|
94
|
+
#{x}
|
95
|
+
Your total is off by #{sprintf("%.2f", -total)}
|
96
|
+
EOF
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
if cmd == 'balance'
|
102
|
+
accounts_total = 0
|
103
|
+
main_accounts = {}
|
104
|
+
|
105
|
+
if ARGV[1] && !@options[:subtotal]
|
106
|
+
ARGV[1..-1].each do |arg|
|
107
|
+
@accounts.sort.each do |k, v|
|
108
|
+
if k.downcase.include? arg
|
109
|
+
accounts_total += v
|
110
|
+
v = v.round(2)
|
111
|
+
if @options[:empty]
|
112
|
+
puts sprintf("%16.2f %s", v, k)
|
113
|
+
else
|
114
|
+
puts sprintf("%16.2f %s", v, k) if v != 0
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
puts "#{'-' * 16}"
|
120
|
+
puts sprintf("%16.2f", accounts_total)
|
121
|
+
|
122
|
+
elsif @options[:subtotal]
|
123
|
+
summary_total = 0
|
124
|
+
@accounts.each do |k, v|
|
125
|
+
x = k.split(':')
|
126
|
+
main_accounts[x[0].to_sym] ||= 0
|
127
|
+
main_accounts[x[0].to_sym] += v
|
128
|
+
main_accounts.each do |account, value|
|
129
|
+
main_accounts[account] = value.round(2)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
main_accounts.sort.each do |k, v|
|
133
|
+
if ARGV[1]
|
134
|
+
ARGV.map! { |x| x.downcase }
|
135
|
+
ARGV[1..-1].each do |arg|
|
136
|
+
puts "#{sprintf("%16.2f %s", v, k)}" if k.to_s.downcase.include? arg
|
137
|
+
summary_total += v if k.to_s.downcase.include? arg
|
138
|
+
end
|
139
|
+
else
|
140
|
+
puts "#{sprintf("%16.2f %s", v, k)}"
|
141
|
+
summary_total += v
|
142
|
+
end
|
143
|
+
end
|
144
|
+
puts "#{"-" * 16}"
|
145
|
+
puts "#{sprintf("%16.2f", summary_total.round(2))}"
|
146
|
+
|
147
|
+
else
|
148
|
+
@accounts.sort.each do |k, v|
|
149
|
+
v = v.round(2)
|
150
|
+
if @options[:empty]
|
151
|
+
puts sprintf("%16.2f %s", v, k)
|
152
|
+
else
|
153
|
+
puts sprintf("%16.2f %s", v, k) if v != 0
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
metadata
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: transactions
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Randy Schneck
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-06-27 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: |2
|
14
|
+
A small but powerful command line application to help manage finances.
|
15
|
+
Transactions are entered into a text file using yaml and reports are
|
16
|
+
generated by parsing this data.
|
17
|
+
email: rasch@computercrayons.com
|
18
|
+
executables:
|
19
|
+
- transactions
|
20
|
+
extensions: []
|
21
|
+
extra_rdoc_files: []
|
22
|
+
files:
|
23
|
+
- bin/transactions
|
24
|
+
- lib/transactions/main.rb
|
25
|
+
- lib/transactions/options.rb
|
26
|
+
- lib/transactions/parser.rb
|
27
|
+
- lib/transactions/version.rb
|
28
|
+
- lib/transactions.rb
|
29
|
+
- LICENSE.md
|
30
|
+
- README.md
|
31
|
+
- CHANGELOG.md
|
32
|
+
homepage: https://github.com/randyschneck/transactions
|
33
|
+
licenses:
|
34
|
+
- MIT
|
35
|
+
metadata: {}
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options: []
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
requirements: []
|
51
|
+
rubyforge_project:
|
52
|
+
rubygems_version: 2.0.2
|
53
|
+
signing_key:
|
54
|
+
specification_version: 4
|
55
|
+
summary: A bookkeeping application to help manage your finances.
|
56
|
+
test_files: []
|