quickpep 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/quickpep.rb +104 -11
- data.tar.gz.sig +0 -0
- metadata +4 -4
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eee7a9fb38833422910265d318aa4637b98e426fdc39b0a50d4d8da5f987021f
|
4
|
+
data.tar.gz: 0ed982bf1fcc5c01ab58616b20695716c365739d964f878b47c565bfac4bc92d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 754edefa43a185656451fcd3ddb948cd3cffebb8da581d379c4d752294634141271369dadb2929deff799f5d2b7bdbf16acc46c59cdb79038c2e36629cbaec93
|
7
|
+
data.tar.gz: 18a9cc3eb80d9942c887f346699f993d237ddcd456a41db28107279ab2e1914b1d0530c09b4328e29709edad380f48c0489a9edd0d33bd8cacbc8c8baeb9baf5
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/lib/quickpep.rb
CHANGED
@@ -11,16 +11,17 @@ require 'event_nlp'
|
|
11
11
|
class QuickPep
|
12
12
|
using ColouredText
|
13
13
|
|
14
|
-
attr_reader :to_s, :to_dx
|
14
|
+
attr_reader :to_s, :to_dx, :input
|
15
15
|
|
16
|
-
def initialize(s, balance: 0, currency: '', today: Date.today,
|
16
|
+
def initialize(s, balance: 0, currency: '', today: Date.today,
|
17
|
+
ignorewarnings: false, debug: false)
|
17
18
|
|
18
19
|
@balance, @currency, @debug = balance, currency, debug
|
19
20
|
@today = today
|
20
21
|
@warnings = []
|
21
22
|
@to_s = calc_expenses(s)
|
22
23
|
|
23
|
-
warnings() if @warnings.any?
|
24
|
+
warnings() if @warnings.any? and not ignorewarnings
|
24
25
|
|
25
26
|
end
|
26
27
|
|
@@ -60,12 +61,51 @@ class QuickPep
|
|
60
61
|
|
61
62
|
end
|
62
63
|
|
63
|
-
|
64
|
+
# Each expense annually as a percentage of total expenses
|
65
|
+
#
|
66
|
+
def breakdown()
|
67
|
+
|
68
|
+
tot = total_expenses().abs
|
69
|
+
r = annual_costs()
|
70
|
+
a = r.map {|title, cost| [title, (100 / (tot / cost.abs)).round] }
|
71
|
+
|
72
|
+
def a.to_table()
|
73
|
+
TableFormatter.new(source: self,
|
74
|
+
labels: %w(Item %:), markdown: true).display
|
75
|
+
end
|
76
|
+
|
77
|
+
return a
|
78
|
+
end
|
79
|
+
|
80
|
+
def costs_summary()
|
81
|
+
|
82
|
+
a = %i(year month day).map {|x| annual_costs x}.transpose\
|
83
|
+
.map do |x|
|
84
|
+
[x.first.first, *x.map {|y| "%s%0.2f" % [@currency, y.last.abs]}]
|
85
|
+
end
|
86
|
+
TableFormatter.new(source: a, labels: %w(Title Year: Month: Day:),
|
87
|
+
markdown: true).display
|
88
|
+
end
|
64
89
|
|
65
|
-
|
66
|
-
|
90
|
+
def to_html(titlex="Personal Budget #{@today.year}", title: titlex)
|
91
|
+
|
92
|
+
dx = to_dx()
|
93
|
+
t = dx.to_table
|
94
|
+
t.labels = %w(date: title debit: credit: balance: uid:)
|
67
95
|
table = t.display markdown: true
|
68
96
|
|
97
|
+
tot = year_end_balance().abs
|
98
|
+
costs_per_interval = "
|
99
|
+
* daily: #{"%s%0.2f" % [@currency, (tot / 365.0)]}
|
100
|
+
* weekly: #{"%s%0.2f" % [@currency, (tot / 52.0)]}
|
101
|
+
* monthly: #{"%s%0.2f" % [@currency, (tot / 12.0)]}
|
102
|
+
* yearly: #{@currency + tot.to_s}
|
103
|
+
"
|
104
|
+
|
105
|
+
t2 = @input.to_table
|
106
|
+
t2.labels = %w(Title Amount: :Day: :Recurring: :Notes:)
|
107
|
+
table2 = t2.display markdown: true
|
108
|
+
|
69
109
|
"<html>
|
70
110
|
<head>
|
71
111
|
<meta name='viewport' content='width=device-width, initial-scale=1'>
|
@@ -82,32 +122,84 @@ class QuickPep
|
|
82
122
|
}
|
83
123
|
|
84
124
|
}
|
125
|
+
table tr td, table thead th {padding: 0.3em; margin: 0.1em}
|
126
|
+
#input table {border: 4px; background-color: #d3a;}
|
127
|
+
#input table thead {color: #131;}
|
128
|
+
#input table tr, #input table td {border: 1px solid green; padding: 3px; background-color: #dea;}
|
129
|
+
#input table tr td {
|
130
|
+
text-align: center;
|
131
|
+
}
|
132
|
+
#summary div {background-color: transparent; float: left; margin: 0.3em; padding: 1.2em; border: 1px solid #18e}
|
133
|
+
|
134
|
+
#breakdown table {background-color: transparent; width: 190px}
|
135
|
+
#breakdown table tr {background-color: transparent;}
|
136
|
+
#costsum table {background-color: transparent; width: 400px}
|
137
|
+
#costsum table tr {background-color: transparent; border-bottom: 1px solid #888;}
|
138
|
+
#costsum table tr td {background-color: transparent; padding: 1.0em 0.5em; margin: 0.4em 0.2em}
|
139
|
+
#summary div ul {list-style-type: none; background-color: transparent; padding: 0.5em; }
|
140
|
+
.break {page-break-before: always}
|
141
|
+
#input {clear: both;}
|
142
|
+
footer {font-size: 0.8em; color: #888;}
|
85
143
|
</style>
|
144
|
+
|
86
145
|
</head>
|
87
146
|
<body>
|
88
147
|
<h1>#{title}</h1>
|
89
148
|
#{RDiscount.new(table).to_html}
|
149
|
+
<div id='summary'>
|
150
|
+
<h2>Summary</h2>
|
151
|
+
|
152
|
+
<div id='breakdown'>
|
153
|
+
<h3>Breakdown</h3>
|
154
|
+
#{RDiscount.new(breakdown().to_table()).to_html}
|
155
|
+
</div>
|
156
|
+
|
157
|
+
<div id='costsum'>
|
158
|
+
<h3>Expense per item</h3>
|
159
|
+
#{RDiscount.new(costs_summary()).to_html}
|
160
|
+
</div>
|
161
|
+
<div>
|
162
|
+
<h3>Running expense</h3>
|
163
|
+
|
164
|
+
#{RDiscount.new(costs_per_interval).to_html}
|
165
|
+
</div>
|
166
|
+
</div>
|
167
|
+
<div id='input'>
|
168
|
+
<h3>Input</h3>
|
169
|
+
|
170
|
+
#{RDiscount.new(table2).to_html}
|
171
|
+
</div>
|
90
172
|
<hr/>
|
91
|
-
<footer>Generated by QuickPEP</footer>
|
173
|
+
<footer>Generated by QuickPEP; #{Time.now.strftime("%d %b %Y")}</footer>
|
92
174
|
</body>
|
93
175
|
</html>"
|
94
176
|
end
|
95
177
|
|
178
|
+
def total_expenses()
|
179
|
+
to_dx().all.map {|x| x.debit.sub(/\D/,'').to_f}.sum
|
180
|
+
end
|
181
|
+
|
96
182
|
def warnings()
|
97
183
|
@warnings.each {|warning| puts warning.warn }
|
98
184
|
end
|
99
185
|
|
186
|
+
def year_end_balance()
|
187
|
+
to_dx().all.last.balance.sub(/[^-0-9]+/,'').to_f
|
188
|
+
end
|
189
|
+
|
100
190
|
private
|
101
191
|
|
102
192
|
def calc_expenses(s)
|
103
193
|
|
104
|
-
dx = Dynarex.new(s)
|
194
|
+
@input = dx = Dynarex.new(s)
|
105
195
|
|
106
196
|
@h = dx.all.map {|x| [x.title, x]}.to_h
|
197
|
+
puts '@h: ' + @h.inspect if @debug
|
107
198
|
|
108
199
|
date_events = dx.all.flat_map do |rx|
|
109
200
|
|
110
|
-
|
201
|
+
recurring = rx.recurring.gsub(/(?:yearly|annually)/,'')
|
202
|
+
title = [rx.title, rx.day, recurring].join(' ')
|
111
203
|
puts '1. title: ' + title.inspect if @debug
|
112
204
|
e = EventNlp.new(@today.to_time)
|
113
205
|
e.project(title).map {|x| [x.to_date, e.parse(title).title]}
|
@@ -133,7 +225,8 @@ class QuickPep
|
|
133
225
|
end
|
134
226
|
|
135
227
|
credit, debit = 0.0, 0.0
|
136
|
-
|
228
|
+
puts 'title: ' + title.inspect if @debug
|
229
|
+
amount = @h[title] ? @h[title].amount : ''
|
137
230
|
|
138
231
|
if amount[0] == '+' then
|
139
232
|
|
@@ -180,7 +273,7 @@ class QuickPep
|
|
180
273
|
puts [title, debit, credit, balance].inspect if @debug
|
181
274
|
|
182
275
|
row = {
|
183
|
-
date: date.
|
276
|
+
date: date.strftime("%b %d"),
|
184
277
|
title: title,
|
185
278
|
debit: debit > 0 ? (@currency + "%.2f" % debit) : '',
|
186
279
|
credit: credit > 0 ? (@currency + "%.2f" % credit) : '',
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quickpep
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Robertson
|
@@ -35,7 +35,7 @@ cert_chain:
|
|
35
35
|
kmcJnzHNiVwSBry7rnILYU3ouLJeHEtQY1v/S4KqPXGNS1FPvas3Wb429Cui2LtB
|
36
36
|
CkYfvLZCZS1SZGB2dGilreNS
|
37
37
|
-----END CERTIFICATE-----
|
38
|
-
date: 2022-05-
|
38
|
+
date: 2022-05-04 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: event_nlp
|
@@ -46,7 +46,7 @@ dependencies:
|
|
46
46
|
version: '0.6'
|
47
47
|
- - ">="
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version: 0.6.
|
49
|
+
version: 0.6.8
|
50
50
|
type: :runtime
|
51
51
|
prerelease: false
|
52
52
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -56,7 +56,7 @@ dependencies:
|
|
56
56
|
version: '0.6'
|
57
57
|
- - ">="
|
58
58
|
- !ruby/object:Gem::Version
|
59
|
-
version: 0.6.
|
59
|
+
version: 0.6.8
|
60
60
|
- !ruby/object:Gem::Dependency
|
61
61
|
name: dynarex
|
62
62
|
requirement: !ruby/object:Gem::Requirement
|
metadata.gz.sig
CHANGED
Binary file
|