quickpep 0.1.4 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b1d800b406053b5a60a9974e32518ec1ec168f2239c47022e86abbc86068b6fc
4
- data.tar.gz: 9af8af2752cde50599b286177acdf358acf8b9c7c9e1437aab1671607892cd48
3
+ metadata.gz: eee7a9fb38833422910265d318aa4637b98e426fdc39b0a50d4d8da5f987021f
4
+ data.tar.gz: 0ed982bf1fcc5c01ab58616b20695716c365739d964f878b47c565bfac4bc92d
5
5
  SHA512:
6
- metadata.gz: 1d09c1c82b93b4a68475648177884d649be20cfbb8a8e3ed96ffc44491ef2cf5d6584e761b539ff802883fb4d6981e49355eb33dd873bbefe18d2cb00f587225
7
- data.tar.gz: 88c9fd772da20eb20c1813d30d3775ae747696a72d91ba1c4227219de8210102aeab7efaf86a744f6a6f5fa71087a494c5dfcd7d2b4700412820e9f3c3b41dcd
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, debug: false)
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,27 +61,153 @@ class QuickPep
60
61
 
61
62
  end
62
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
89
+
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:)
95
+ table = t.display markdown: true
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
+
109
+ "<html>
110
+ <head>
111
+ <meta name='viewport' content='width=device-width, initial-scale=1'>
112
+ <title>#{title}</title>
113
+ <style>
114
+ table {border-collapse: collapse; width: 700px}
115
+ tr:nth-child(even) {
116
+ background-color: #aca;
117
+ }
118
+ @media print {
119
+
120
+ tr:nth-child(even) {
121
+ background-color: #ccc;
122
+ }
123
+
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;}
143
+ </style>
144
+
145
+ </head>
146
+ <body>
147
+ <h1>#{title}</h1>
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>
172
+ <hr/>
173
+ <footer>Generated by QuickPEP; #{Time.now.strftime("%d %b %Y")}</footer>
174
+ </body>
175
+ </html>"
176
+ end
177
+
178
+ def total_expenses()
179
+ to_dx().all.map {|x| x.debit.sub(/\D/,'').to_f}.sum
180
+ end
181
+
63
182
  def warnings()
64
183
  @warnings.each {|warning| puts warning.warn }
65
184
  end
66
185
 
186
+ def year_end_balance()
187
+ to_dx().all.last.balance.sub(/[^-0-9]+/,'').to_f
188
+ end
189
+
67
190
  private
68
191
 
69
192
  def calc_expenses(s)
70
193
 
71
- dx = Dynarex.new(s)
194
+ @input = dx = Dynarex.new(s)
72
195
 
73
196
  @h = dx.all.map {|x| [x.title, x]}.to_h
197
+ puts '@h: ' + @h.inspect if @debug
74
198
 
75
- @date_events = dx.all.flat_map do |rx|
199
+ date_events = dx.all.flat_map do |rx|
76
200
 
77
- title = [rx.title, rx.day, rx.recurring].join(' ')
201
+ recurring = rx.recurring.gsub(/(?:yearly|annually)/,'')
202
+ title = [rx.title, rx.day, recurring].join(' ')
78
203
  puts '1. title: ' + title.inspect if @debug
79
- e = EventNlp.new()
204
+ e = EventNlp.new(@today.to_time)
80
205
  e.project(title).map {|x| [x.to_date, e.parse(title).title]}
81
206
 
82
207
  end.clone.sort_by(&:first)
83
208
 
209
+ # remove any dates less than the current date
210
+ @date_events = date_events.reject {|date, _| date < @today }
84
211
 
85
212
  # identify the source of income
86
213
  found = dx.all.find {|x| x.amount[0] == '+'}
@@ -98,7 +225,8 @@ class QuickPep
98
225
  end
99
226
 
100
227
  credit, debit = 0.0, 0.0
101
- amount = @h[title].amount
228
+ puts 'title: ' + title.inspect if @debug
229
+ amount = @h[title] ? @h[title].amount : ''
102
230
 
103
231
  if amount[0] == '+' then
104
232
 
@@ -145,7 +273,7 @@ class QuickPep
145
273
  puts [title, debit, credit, balance].inspect if @debug
146
274
 
147
275
  row = {
148
- date: date.to_s,
276
+ date: date.strftime("%b %d"),
149
277
  title: title,
150
278
  debit: debit > 0 ? (@currency + "%.2f" % debit) : '',
151
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.1.4
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-03 00:00:00.000000000 Z
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.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.6
59
+ version: 0.6.8
60
60
  - !ruby/object:Gem::Dependency
61
61
  name: dynarex
62
62
  requirement: !ruby/object:Gem::Requirement
@@ -66,7 +66,7 @@ dependencies:
66
66
  version: '1.9'
67
67
  - - ">="
68
68
  - !ruby/object:Gem::Version
69
- version: 1.9.8
69
+ version: 1.9.10
70
70
  type: :runtime
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
@@ -76,7 +76,7 @@ dependencies:
76
76
  version: '1.9'
77
77
  - - ">="
78
78
  - !ruby/object:Gem::Version
79
- version: 1.9.8
79
+ version: 1.9.10
80
80
  description:
81
81
  email: digital.robertson@gmail.com
82
82
  executables: []
metadata.gz.sig CHANGED
Binary file