quickpep 0.2.0 → 0.2.3

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: 0de11237c2ae3902d31629219f665928d639fb9cd385ea8e8534e490ec002f5a
4
- data.tar.gz: b5cf353cee4215b5ed18aeaac198324d2150965fdeec08ab34662917255d12c2
3
+ metadata.gz: d2b2877222c85adc6b6af50aeb05b84da3e33f7e0826def01fb4212d443758fb
4
+ data.tar.gz: 94da811b22114d193553586d60e5e810c6afdb333b7e4e7de6dbd6f4a5930a0c
5
5
  SHA512:
6
- metadata.gz: 44d5eebb58384292c90dc76472974486d9cec5b17427c582a5c4ad309099d8e614f34d174cc753172aafc3729bb3da2c374b1342454b0e4c74f8967a4007580b
7
- data.tar.gz: a68cabdf29c866f7506dd47b736c1017db128c614677e1563eea4f6d11829747425c73ed49a4e9b54ad6e2777ca157d754c2991f4c28d9d959a6b1a9c09ba62f
6
+ metadata.gz: d9fc43143a9d8768ae036501406bc2668847590e9f784e08322ca952663a3e9bb203f867eca58ff1606f6737021070c45618e27a81c68979b4f5db16a62b675e
7
+ data.tar.gz: c55dd271c48a2cc9e73c857cd347dea4ddc43ad3a9bee652b708602f9ebd86137b24a02df5c9184ee9d81c87a4f05cb961ddafbfccb2482335bddd0d7d4faeac
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,12 +61,51 @@ class QuickPep
60
61
 
61
62
  end
62
63
 
63
- def to_html()
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.select {| _, cost | cost < 0 }\
71
+ .map {|title, cost| [title, (100 / (tot / cost.abs)).round] }
72
+
73
+ def a.to_table()
74
+ TableFormatter.new(source: self,
75
+ labels: %w(Item %:), markdown: true).display
76
+ end
77
+
78
+ return a
79
+ end
80
+
81
+ def costs_summary()
82
+
83
+ a = %i(year month day).map {|x| annual_costs x}.transpose\
84
+ .map do |x|
85
+ [x.first.first, *x.map {|y| "%s%0.2f" % [@currency, y.last.abs]}]
86
+ end
87
+ TableFormatter.new(source: a, labels: %w(Title Year: Month: Day:),
88
+ markdown: true).display
89
+ end
64
90
 
65
- t = to_dx().to_table
66
- t.labels = %w(date title debit: credit: balance: uid:)
91
+ def to_html(titlex="Personal Budget #{@today.year}", title: titlex)
92
+
93
+ dx = to_dx()
94
+ t = dx.to_table
95
+ t.labels = %w(date: title debit: credit: balance: uid:)
67
96
  table = t.display markdown: true
68
- title = "Personal Budget #{Date.today.year}"
97
+
98
+ tot = total_expenses().abs
99
+ costs_per_interval = "
100
+ * daily: #{"%s%0.2f" % [@currency, (tot / 365.0)]}
101
+ * weekly: #{"%s%0.2f" % [@currency, (tot / 52.0)]}
102
+ * monthly: #{"%s%0.2f" % [@currency, (tot / 12.0)]}
103
+ * yearly: #{@currency + tot.to_s}
104
+ "
105
+
106
+ t2 = @input.to_table
107
+ t2.labels = %w(Title Amount: :Day: :Recurring: :Notes:)
108
+ table2 = t2.display markdown: true
69
109
 
70
110
  "<html>
71
111
  <head>
@@ -83,38 +123,92 @@ class QuickPep
83
123
  }
84
124
 
85
125
  }
126
+ table tr td, table thead th {padding: 0.3em; margin: 0.1em}
127
+ #input table {border: 4px; background-color: #d3a;}
128
+ #input table thead {color: #131;}
129
+ #input table tr, #input table td {border: 1px solid green; padding: 3px; background-color: #dea;}
130
+ #input table tr td {
131
+ text-align: center;
132
+ }
133
+ #summary div {background-color: transparent; float: left; margin: 0.3em; padding: 1.2em; border: 1px solid #18e}
134
+
135
+ #breakdown table {background-color: transparent; width: 190px}
136
+ #breakdown table tr {background-color: transparent;}
137
+ #costsum table {background-color: transparent; width: 400px}
138
+ #costsum table tr {background-color: transparent; border-bottom: 1px solid #888;}
139
+ #costsum table tr td {background-color: transparent; padding: 1.0em 0.5em; margin: 0.4em 0.2em}
140
+ #summary div ul {list-style-type: none; background-color: transparent; padding: 0.5em; }
141
+ .break {page-break-before: always}
142
+ #input {clear: both;}
143
+ footer {font-size: 0.8em; color: #888;}
86
144
  </style>
145
+
87
146
  </head>
88
147
  <body>
89
148
  <h1>#{title}</h1>
90
149
  #{RDiscount.new(table).to_html}
150
+ <div id='summary'>
151
+ <h2>Summary</h2>
152
+
153
+ <div id='breakdown'>
154
+ <h3>Breakdown</h3>
155
+ #{RDiscount.new(breakdown().to_table()).to_html}
156
+ </div>
157
+
158
+ <div id='costsum'>
159
+ <h3>Expense per item</h3>
160
+ #{RDiscount.new(costs_summary()).to_html}
161
+ </div>
162
+ <div>
163
+ <h3>Running expense</h3>
164
+
165
+ #{RDiscount.new(costs_per_interval).to_html}
166
+ </div>
167
+ </div>
168
+ <div id='input'>
169
+ <h3>Input</h3>
170
+
171
+ #{RDiscount.new(table2).to_html}
172
+ </div>
91
173
  <hr/>
92
- <footer>Generated by QuickPEP</footer>
174
+ <footer>Generated by QuickPEP; #{Time.now.strftime("%d %b %Y")}</footer>
93
175
  </body>
94
176
  </html>"
95
177
  end
96
178
 
179
+ def total_expenses()
180
+ to_dx().all.map {|x| x.debit.sub(/\D/,'').to_f}.sum
181
+ end
182
+
97
183
  def warnings()
98
184
  @warnings.each {|warning| puts warning.warn }
99
185
  end
100
186
 
187
+ def year_end_balance()
188
+ to_dx().all.last.balance.sub(/[^-0-9]+/,'').to_f
189
+ end
190
+
101
191
  private
102
192
 
103
193
  def calc_expenses(s)
104
194
 
105
- dx = Dynarex.new(s)
195
+ @input = dx = Dynarex.new(s)
106
196
 
107
197
  @h = dx.all.map {|x| [x.title, x]}.to_h
198
+ puts '@h: ' + @h.inspect if @debug
108
199
 
109
- @date_events = dx.all.flat_map do |rx|
200
+ date_events = dx.all.flat_map do |rx|
110
201
 
111
- title = [rx.title, rx.day, rx.recurring].join(' ')
202
+ recurring = rx.recurring.gsub(/(?:yearly|annually)/,'')
203
+ title = [rx.title, rx.day, recurring].join(' ')
112
204
  puts '1. title: ' + title.inspect if @debug
113
- e = EventNlp.new()
205
+ e = EventNlp.new(@today.to_time)
114
206
  e.project(title).map {|x| [x.to_date, e.parse(title).title]}
115
207
 
116
208
  end.clone.sort_by(&:first)
117
209
 
210
+ # remove any dates less than the current date
211
+ @date_events = date_events.reject {|date, _| date < @today }
118
212
 
119
213
  # identify the source of income
120
214
  found = dx.all.find {|x| x.amount[0] == '+'}
@@ -132,7 +226,8 @@ class QuickPep
132
226
  end
133
227
 
134
228
  credit, debit = 0.0, 0.0
135
- amount = @h[title].amount
229
+ puts 'title: ' + title.inspect if @debug
230
+ amount = @h[title] ? @h[title].amount : ''
136
231
 
137
232
  if amount[0] == '+' then
138
233
 
@@ -179,7 +274,7 @@ class QuickPep
179
274
  puts [title, debit, credit, balance].inspect if @debug
180
275
 
181
276
  row = {
182
- date: date.to_s,
277
+ date: date.strftime("%b %d"),
183
278
  title: title,
184
279
  debit: debit > 0 ? (@currency + "%.2f" % debit) : '',
185
280
  credit: credit > 0 ? (@currency + "%.2f" % credit) : '',
data.tar.gz.sig CHANGED
@@ -1,2 +1,3 @@
1
- %ss����B�#���T�Yp;a�u5��w#�3�W"|�EW����ȘJn��d_@r�69��c��e��3SF]ƺB\�f���È�� �w���j!w:U��SPOٓ3^D�s?z�`�&���k0B�IÞ�n�oK�]��1i-�'id��rЬ�I]U��
2
- w>@�\��[yvKNٝ geQ����6��6��de܃��U���#P'���'NX�#Eg�~qE�4�6sޓ�MT@7�Jt��Ӈ�j�CF|��k��ʣ�AX����M���[����1uµ��j$
1
+ ��=��A{�ܜ 8'1�\������X
2
+ y����jYFs�L��/�~��J��!WXpF7}(��A�,�i� "k��Y��sT��9�-�����% SwJ[CeHM9l�`�ݏ".�BH��5���G��sf���_�� *�+r�;���z!�Z��6��J_��5��*�����
3
+ �=�Cs?����<��V�Y�e��]�u�����} ��`J`|��2 X��-<~wś�:�Kc /e�7�c隷/u��J�{�c`���$@2�e�N�j�ؠ}�A(�Q�X�أ��R�
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.0
4
+ version: 0.2.3
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-21 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