aboutsummaryrefslogtreecommitdiffstats
path: root/beancount_extras_kris7t/plugins/selective_implicit_prices_test.py
diff options
context:
space:
mode:
Diffstat (limited to 'beancount_extras_kris7t/plugins/selective_implicit_prices_test.py')
-rw-r--r--beancount_extras_kris7t/plugins/selective_implicit_prices_test.py410
1 files changed, 410 insertions, 0 deletions
diff --git a/beancount_extras_kris7t/plugins/selective_implicit_prices_test.py b/beancount_extras_kris7t/plugins/selective_implicit_prices_test.py
new file mode 100644
index 0000000..6ead45d
--- /dev/null
+++ b/beancount_extras_kris7t/plugins/selective_implicit_prices_test.py
@@ -0,0 +1,410 @@
1__copyright__ = "Copyright (C) 2015-2017 Martin Blais, " + \
2 "2020 Kristóf Marussy <kristof@marussy.com>"
3__license__ = "GNU GPLv2"
4
5import unittest
6
7from beancount.core.number import D
8from beancount.core import data
9from beancount.parser import cmptest
10from beancount import loader
11
12from beancount_extras_kris7t.plugins import selective_implicit_prices as implicit_prices
13
14
15class TestImplicitPrices(cmptest.TestCase):
16
17 @loader.load_doc()
18 def test_add_implicit_prices__all_cases(self, entries, _, options_map):
19 """
20 1702-04-02 commodity USD
21 implicit-prices: TRUE
22
23 2013-01-01 commodity HOOL
24 implicit-prices: TRUE
25
26 2013-01-01 open Assets:Account1
27 2013-01-01 open Assets:Account2
28 2013-01-01 open Assets:Other
29
30 ;; An explicit price directive.
31 2013-02-01 price USD 1.10 CAD
32
33 2013-04-01 * "A transaction with a price conversion."
34 Assets:Account1 150 USD @ 1.12 CAD
35 Assets:Other
36
37 ;; This should book at price at the cost.
38 2013-04-02 * "A transaction with a cost."
39 Assets:Account1 1500 HOOL {520 USD}
40 Assets:Other
41
42 ;; This one should be IGNORED because it books against the above.
43 2013-04-03 * "A transaction with a cost that reduces an existing position"
44 Assets:Account1 -500 HOOL {520 USD}
45 Assets:Other
46
47 ;; This one should generate the price, even if it is reducing.
48 2013-04-04 * "A transaction with a cost that reduces existing position, with price"
49 Assets:Account1 -100 HOOL {520 USD} @ 530 USD
50 Assets:Other
51
52 ;; This is not reducing and should also book a price at cost.
53 2013-04-05 * "A transaction with another cost that is not reducing."
54 Assets:Account1 500 HOOL {540 USD}
55 Assets:Other
56
57 ;; The price here overrides the cost and should create an entry.
58 2013-04-06 * "A transaction with a cost and a price."
59 Assets:Account1 500 HOOL {540 USD} @ 560 USD
60 Assets:Other
61 """
62 self.assertEqual(12, len(entries))
63 new_entries, _ = implicit_prices.add_implicit_prices(entries, options_map)
64 price_entries = [entry for entry in new_entries if isinstance(entry, data.Price)]
65
66 self.assertEqualEntries("""
67 1702-04-02 commodity USD
68 implicit-prices: TRUE
69
70 2013-01-01 commodity HOOL
71 implicit-prices: TRUE
72
73 2013-01-01 open Assets:Account1
74 2013-01-01 open Assets:Account2
75 2013-01-01 open Assets:Other
76
77 2013-02-01 price USD 1.10 CAD
78
79 2013-04-01 * "A transaction with a price conversion."
80 Assets:Account1 150 USD @ 1.12 CAD
81 Assets:Other -168.00 CAD
82
83 2013-04-01 price USD 1.12 CAD
84
85 2013-04-02 * "A transaction with a cost."
86 Assets:Account1 1500 HOOL {520 USD}
87 Assets:Other -780000 USD
88
89 2013-04-02 price HOOL 520 USD
90
91 2013-04-03 * "A transaction with a cost that reduces an existing position"
92 Assets:Account1 -500 HOOL {520 USD}
93 Assets:Other 260000 USD
94
95 2013-04-04 * "A transaction with a cost that reduces existing position, with price"
96 Assets:Account1 -100 HOOL {520 USD} @ 530 USD
97 Assets:Other 52000 USD
98
99 2013-04-04 price HOOL 530 USD
100
101 2013-04-05 * "A transaction with another cost that is not reducing."
102 Assets:Account1 500 HOOL {540 USD}
103 Assets:Other -270000 USD
104
105 2013-04-05 price HOOL 540 USD
106
107 2013-04-06 * "A transaction with a cost and a price."
108 Assets:Account1 500 HOOL {540 USD} @ 560 USD
109 Assets:Other -270000 USD
110
111 2013-04-06 price HOOL 560 USD
112 """, new_entries)
113
114 self.assertEqual(6, len(price_entries))
115 expected_values = [(x[0], x[1], D(x[2])) for x in [
116 ('USD', 'CAD', '1.10'),
117 ('USD', 'CAD', '1.12'),
118 ('HOOL', 'USD', '520.00'),
119 ('HOOL', 'USD', '530.00'),
120 ('HOOL', 'USD', '540.00'),
121 ('HOOL', 'USD', '560.00')
122 ]]
123 for expected, price in zip(expected_values, price_entries):
124 actual = (price.currency, price.amount.currency, price.amount.number)
125 self.assertEqual(expected, actual)
126
127 @loader.load_doc()
128 def test_add_implicit_prices__other_account(self, entries, errors, options_map):
129 """
130 2013-01-01 commodity HOOL
131 implicit-prices: TRUE
132
133 2013-01-01 open Assets:Account1
134 2013-01-01 open Assets:Account2 "NONE"
135 2013-01-01 open Assets:Other
136
137 2013-04-01 *
138 Assets:Account1 1500 HOOL {520 USD}
139 Assets:Other
140
141 2013-04-02 *
142 Assets:Account2 1500 HOOL {530 USD}
143 Assets:Other
144
145 2013-04-10 * "Reduces existing position in account 1"
146 Assets:Account1 -100 HOOL {520 USD}
147 Assets:Other 52000 USD
148
149 2013-04-11 * "Does not find an existing position in account 2"
150 Assets:Account2 -200 HOOL {531 USD}
151 Assets:Other 106200 USD
152
153 """
154 new_entries, _ = implicit_prices.add_implicit_prices(entries, options_map)
155 self.assertEqualEntries("""
156 2013-01-01 commodity HOOL
157 implicit-prices: TRUE
158
159 2013-01-01 open Assets:Account1
160 2013-01-01 open Assets:Account2 "NONE"
161 2013-01-01 open Assets:Other
162
163 2013-04-01 *
164 Assets:Account1 1500 HOOL {520 USD}
165 Assets:Other -780000 USD
166
167 2013-04-02 *
168 Assets:Account2 1500 HOOL {530 USD}
169 Assets:Other -795000 USD
170
171 2013-04-01 price HOOL 520 USD
172
173 2013-04-02 price HOOL 530 USD
174
175 2013-04-10 * "Reduces existing position in account 1"
176 Assets:Account1 -100 HOOL {520 USD}
177 Assets:Other 52000 USD
178
179 2013-04-11 * "Does not find an existing position in account 2"
180 Assets:Account2 -200 HOOL {531 USD}
181 Assets:Other 106200 USD
182
183 ;; Because a match was not found against the inventory, a price will be added.
184 2013-04-11 price HOOL 531 USD
185
186 """, new_entries)
187
188 @loader.load_doc()
189 def test_add_implicit_prices__duplicates_on_same_transaction(self,
190 entries, _, options_map):
191 """
192 2013-01-01 commodity HOOL
193 implicit-prices: TRUE
194
195 2013-01-01 open Assets:Account1
196 2013-01-01 open Assets:Account2
197 2013-01-01 open Assets:Other
198
199 2013-04-01 * "Allowed because of same price"
200 Assets:Account1 1500 HOOL {520 USD}
201 Assets:Account2 1500 HOOL {520 USD}
202 Assets:Other
203
204 2013-04-02 * "Second one is disallowed because of different price"
205 Assets:Account1 1500 HOOL {520 USD}
206 Assets:Account2 1500 HOOL {530 USD}
207 Assets:Other
208
209 """
210 new_entries, errors = implicit_prices.add_implicit_prices(entries, options_map)
211 self.assertEqual([], [type(error) for error in errors])
212 self.assertEqualEntries("""
213 2013-01-01 commodity HOOL
214 implicit-prices: TRUE
215
216 2013-01-01 open Assets:Account1
217 2013-01-01 open Assets:Account2
218 2013-01-01 open Assets:Other
219
220 2013-04-01 * "Allowed because of same price"
221 Assets:Account1 1500 HOOL {520 USD}
222 Assets:Account2 1500 HOOL {520 USD}
223 Assets:Other -1560000 USD
224
225 2013-04-01 price HOOL 520 USD
226
227 2013-04-02 * "Second one is disallowed because of different price"
228 Assets:Account1 1500 HOOL {520 USD}
229 Assets:Account2 1500 HOOL {530 USD}
230 Assets:Other -1575000 USD
231
232 2013-04-02 price HOOL 520 USD
233 2013-04-02 price HOOL 530 USD ;; Allowed for now.
234
235 """, new_entries)
236
237 @loader.load_doc()
238 def test_add_implicit_prices__duplicates_on_different_transactions(self,
239 entries, _,
240 options_map):
241 """
242 2013-01-01 commodity HOOL
243 implicit-prices: TRUE
244
245 2013-01-01 open Assets:Account1
246 2013-01-01 open Assets:Account2
247 2013-01-01 open Assets:Other
248
249 2013-04-01 * "Allowed because of same price #1"
250 Assets:Account1 1500 HOOL {520 USD}
251 Assets:Other
252
253 2013-04-01 * "Allowed because of same price #2"
254 Assets:Account2 1500 HOOL {520 USD}
255 Assets:Other
256
257 2013-04-02 * "Second one is disallowed because of different price #1"
258 Assets:Account1 1500 HOOL {520 USD}
259 Assets:Other
260
261 2013-04-02 * "Second one is disallowed because of different price #2"
262 Assets:Account2 1500 HOOL {530 USD}
263 Assets:Other
264
265 """
266 new_entries, errors = implicit_prices.add_implicit_prices(entries, options_map)
267 self.assertEqual([], [type(error) for error in errors])
268 self.assertEqualEntries("""
269 2013-01-01 commodity HOOL
270 implicit-prices: TRUE
271
272 2013-01-01 open Assets:Account1
273 2013-01-01 open Assets:Account2
274 2013-01-01 open Assets:Other
275
276 2013-04-01 * "Allowed because of same price #1"
277 Assets:Account1 1500 HOOL {520 USD}
278 Assets:Other -780000 USD
279
280 2013-04-01 * "Allowed because of same price #2"
281 Assets:Account2 1500 HOOL {520 USD}
282 Assets:Other -780000 USD
283
284 2013-04-01 price HOOL 520 USD
285
286 2013-04-02 * "Second one is disallowed because of different price #1"
287 Assets:Account1 1500 HOOL {520 USD}
288 Assets:Other -780000 USD
289
290 2013-04-02 * "Second one is disallowed because of different price #2"
291 Assets:Account2 1500 HOOL {530 USD}
292 Assets:Other -795000 USD
293
294 2013-04-02 price HOOL 520 USD
295 2013-04-02 price HOOL 530 USD ;; Allowed for now.
296
297 """, new_entries)
298
299 @loader.load_doc()
300 def test_add_implicit_prices__duplicates_overloaded(self, entries, _, options_map):
301 """
302 2013-01-01 commodity HOOL
303 implicit-prices: TRUE
304
305 2013-01-01 open Assets:Account1
306 2013-01-01 open Assets:Other
307
308 2013-04-01 * "Allowed, sets the price for that day"
309 Assets:Account1 1500 HOOL {520 USD}
310 Assets:Other
311
312 2013-04-01 * "Will be ignored, price for the day already set"
313 Assets:Account1 1500 HOOL {530 USD}
314 Assets:Other
315
316 2013-04-01 * "Should be ignored too, price for the day already set"
317 Assets:Account1 1500 HOOL {530 USD}
318 Assets:Other
319 """
320 new_entries, errors = implicit_prices.add_implicit_prices(entries, options_map)
321 self.assertEqual([], [type(error) for error in errors])
322 self.assertEqualEntries("""
323 2013-01-01 commodity HOOL
324 implicit-prices: TRUE
325
326 2013-01-01 open Assets:Account1
327 2013-01-01 open Assets:Other
328
329 2013-04-01 * "Allowed, sets the price for that day"
330 Assets:Account1 1500 HOOL {520 USD}
331 Assets:Other -780000 USD
332
333 2013-04-01 * "Will be ignored, price for the day already set"
334 Assets:Account1 1500 HOOL {530 USD}
335 Assets:Other -795000 USD
336
337 2013-04-01 * "Should be ignored too, price for the day already set"
338 Assets:Account1 1500 HOOL {530 USD}
339 Assets:Other -795000 USD
340
341 2013-04-01 price HOOL 520 USD
342 2013-04-01 price HOOL 530 USD
343
344 """, new_entries)
345
346 @loader.load_doc()
347 def test_add_implicit_prices__not_enabled(self, entries, errors, options_map):
348 """
349 2013-01-01 open Assets:Account1
350 2013-01-01 open Assets:Other
351
352 2013-04-01 *
353 Assets:Account1 1500 HOOL {520 USD}
354 Assets:Other
355 """
356 new_entries, _ = implicit_prices.add_implicit_prices(entries, options_map)
357 self.assertEqualEntries("""
358 2013-01-01 open Assets:Account1
359 2013-01-01 open Assets:Other
360
361 2013-04-01 *
362 Assets:Account1 1500 HOOL {520 USD}
363 Assets:Other -780000 USD
364 """, new_entries)
365
366 @loader.load_doc()
367 def test_add_implicit_prices__disabled(self, entries, errors, options_map):
368 """
369 2013-01-01 commodity HOOL
370 implicit-prices: FALSE
371
372 2013-01-01 open Assets:Account1
373 2013-01-01 open Assets:Other
374
375 2013-04-01 *
376 Assets:Account1 1500 HOOL {520 USD}
377 Assets:Other
378 """
379 new_entries, _ = implicit_prices.add_implicit_prices(entries, options_map)
380 self.assertEqualEntries("""
381 2013-01-01 commodity HOOL
382 implicit-prices: FALSE
383
384 2013-01-01 open Assets:Account1
385 2013-01-01 open Assets:Other
386
387 2013-04-01 *
388 Assets:Account1 1500 HOOL {520 USD}
389 Assets:Other -780000 USD
390 """, new_entries)
391
392 @loader.load_doc()
393 def test_add_implicit_prices__invalid(self, entries, errors, options_map):
394 """
395 2013-01-01 commodity HOOL
396 implicit-prices: "yes"
397
398 2013-01-01 open Assets:Account1
399 2013-01-01 open Assets:Other
400
401 2013-04-01 *
402 Assets:Account1 1500 HOOL {520 USD}
403 Assets:Other
404 """
405 _, new_errors = implicit_prices.add_implicit_prices(entries, options_map)
406 self.assertRegex(new_errors[0].message, '^implicit-prices must be Boolean')
407
408
409if __name__ == '__main__':
410 unittest.main()