This file is indexed.

/usr/share/doc/libghc-hledger-lib-doc/html/src/Hledger-Data-Journal.html is in libghc-hledger-lib-doc 0.22-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
<title>Hledger/Data/Journal.hs</title>
<link type='text/css' rel='stylesheet' href='hscolour.css' />
</head>
<body>
<pre><a name="line-1"></a><span class='hs-comment'>{-|
<a name="line-2"></a>
<a name="line-3"></a>A 'Journal' is a set of transactions, plus optional related data.  This is
<a name="line-4"></a>hledger's primary data object. It is usually parsed from a journal file or
<a name="line-5"></a>other data format (see "Hledger.Read").
<a name="line-6"></a>
<a name="line-7"></a>-}</span>
<a name="line-8"></a>
<a name="line-9"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Hledger</span><span class='hs-varop'>.</span><span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Journal</span> <span class='hs-layout'>(</span>
<a name="line-10"></a>  <span class='hs-comment'>-- * Parsing helpers</span>
<a name="line-11"></a>  <span class='hs-varid'>addHistoricalPrice</span><span class='hs-layout'>,</span>
<a name="line-12"></a>  <span class='hs-varid'>addModifierTransaction</span><span class='hs-layout'>,</span>
<a name="line-13"></a>  <span class='hs-varid'>addPeriodicTransaction</span><span class='hs-layout'>,</span>
<a name="line-14"></a>  <span class='hs-varid'>addTimeLogEntry</span><span class='hs-layout'>,</span>
<a name="line-15"></a>  <span class='hs-varid'>addTransaction</span><span class='hs-layout'>,</span>
<a name="line-16"></a>  <span class='hs-varid'>journalApplyAliases</span><span class='hs-layout'>,</span>
<a name="line-17"></a>  <span class='hs-varid'>journalBalanceTransactions</span><span class='hs-layout'>,</span>
<a name="line-18"></a>  <span class='hs-varid'>journalCanonicaliseAmounts</span><span class='hs-layout'>,</span>
<a name="line-19"></a>  <span class='hs-varid'>journalConvertAmountsToCost</span><span class='hs-layout'>,</span>
<a name="line-20"></a>  <span class='hs-varid'>journalFinalise</span><span class='hs-layout'>,</span>
<a name="line-21"></a>  <span class='hs-comment'>-- * Filtering</span>
<a name="line-22"></a>  <span class='hs-varid'>filterJournalPostings</span><span class='hs-layout'>,</span>
<a name="line-23"></a>  <span class='hs-varid'>filterJournalTransactions</span><span class='hs-layout'>,</span>
<a name="line-24"></a>  <span class='hs-comment'>-- * Querying</span>
<a name="line-25"></a>  <span class='hs-varid'>journalAccountNames</span><span class='hs-layout'>,</span>
<a name="line-26"></a>  <span class='hs-varid'>journalAccountNamesUsed</span><span class='hs-layout'>,</span>
<a name="line-27"></a>  <span class='hs-comment'>-- journalAmountAndPriceCommodities,</span>
<a name="line-28"></a>  <span class='hs-varid'>journalAmounts</span><span class='hs-layout'>,</span>
<a name="line-29"></a>  <span class='hs-comment'>-- journalCanonicalCommodities,</span>
<a name="line-30"></a>  <span class='hs-varid'>journalDateSpan</span><span class='hs-layout'>,</span>
<a name="line-31"></a>  <span class='hs-varid'>journalFilePath</span><span class='hs-layout'>,</span>
<a name="line-32"></a>  <span class='hs-varid'>journalFilePaths</span><span class='hs-layout'>,</span>
<a name="line-33"></a>  <span class='hs-varid'>journalPostings</span><span class='hs-layout'>,</span>
<a name="line-34"></a>  <span class='hs-comment'>-- * Standard account types</span>
<a name="line-35"></a>  <span class='hs-varid'>journalBalanceSheetAccountQuery</span><span class='hs-layout'>,</span>
<a name="line-36"></a>  <span class='hs-varid'>journalProfitAndLossAccountQuery</span><span class='hs-layout'>,</span>
<a name="line-37"></a>  <span class='hs-varid'>journalIncomeAccountQuery</span><span class='hs-layout'>,</span>
<a name="line-38"></a>  <span class='hs-varid'>journalExpenseAccountQuery</span><span class='hs-layout'>,</span>
<a name="line-39"></a>  <span class='hs-varid'>journalAssetAccountQuery</span><span class='hs-layout'>,</span>
<a name="line-40"></a>  <span class='hs-varid'>journalLiabilityAccountQuery</span><span class='hs-layout'>,</span>
<a name="line-41"></a>  <span class='hs-varid'>journalEquityAccountQuery</span><span class='hs-layout'>,</span>
<a name="line-42"></a>  <span class='hs-varid'>journalCashAccountQuery</span><span class='hs-layout'>,</span>
<a name="line-43"></a>  <span class='hs-comment'>-- * Misc</span>
<a name="line-44"></a>  <span class='hs-varid'>matchpats</span><span class='hs-layout'>,</span>
<a name="line-45"></a>  <span class='hs-varid'>nullctx</span><span class='hs-layout'>,</span>
<a name="line-46"></a>  <span class='hs-varid'>nulljournal</span><span class='hs-layout'>,</span>
<a name="line-47"></a>  <span class='hs-comment'>-- * Tests</span>
<a name="line-48"></a>  <span class='hs-varid'>samplejournal</span><span class='hs-layout'>,</span>
<a name="line-49"></a>  <span class='hs-varid'>tests_Hledger_Data_Journal</span><span class='hs-layout'>,</span>
<a name="line-50"></a><span class='hs-layout'>)</span>
<a name="line-51"></a><span class='hs-keyword'>where</span>
<a name="line-52"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Monad</span>
<a name="line-53"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>List</span>
<a name="line-54"></a><span class='hs-comment'>-- import Data.Map (findWithDefault)</span>
<a name="line-55"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Maybe</span>
<a name="line-56"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Ord</span>
<a name="line-57"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Time</span><span class='hs-varop'>.</span><span class='hs-conid'>Calendar</span>
<a name="line-58"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Time</span><span class='hs-varop'>.</span><span class='hs-conid'>LocalTime</span>
<a name="line-59"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Tree</span>
<a name="line-60"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Safe</span> <span class='hs-layout'>(</span><span class='hs-varid'>headDef</span><span class='hs-layout'>)</span>
<a name="line-61"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>System</span><span class='hs-varop'>.</span><span class='hs-conid'>Time</span> <span class='hs-layout'>(</span><span class='hs-conid'>ClockTime</span><span class='hs-layout'>(</span><span class='hs-conid'>TOD</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-62"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Test</span><span class='hs-varop'>.</span><span class='hs-conid'>HUnit</span>
<a name="line-63"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Text</span><span class='hs-varop'>.</span><span class='hs-conid'>Printf</span>
<a name="line-64"></a><span class='hs-keyword'>import</span> <span class='hs-keyword'>qualified</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Map</span> <span class='hs-keyword'>as</span> <span class='hs-conid'>M</span>
<a name="line-65"></a>
<a name="line-66"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Hledger</span><span class='hs-varop'>.</span><span class='hs-conid'>Utils</span>
<a name="line-67"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Hledger</span><span class='hs-varop'>.</span><span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Types</span>
<a name="line-68"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Hledger</span><span class='hs-varop'>.</span><span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>AccountName</span>
<a name="line-69"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Hledger</span><span class='hs-varop'>.</span><span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Amount</span>
<a name="line-70"></a><span class='hs-comment'>-- import Hledger.Data.Commodity</span>
<a name="line-71"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Hledger</span><span class='hs-varop'>.</span><span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Dates</span>
<a name="line-72"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Hledger</span><span class='hs-varop'>.</span><span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Transaction</span>
<a name="line-73"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Hledger</span><span class='hs-varop'>.</span><span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Posting</span>
<a name="line-74"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Hledger</span><span class='hs-varop'>.</span><span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>TimeLog</span>
<a name="line-75"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Hledger</span><span class='hs-varop'>.</span><span class='hs-conid'>Query</span>
<a name="line-76"></a>
<a name="line-77"></a>
<a name="line-78"></a><a name="instance%20Show%20Journal"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>Show</span> <span class='hs-conid'>Journal</span> <span class='hs-keyword'>where</span>
<a name="line-79"></a>  <span class='hs-varid'>show</span> <span class='hs-varid'>j</span>
<a name="line-80"></a>    <span class='hs-keyglyph'>|</span> <span class='hs-varid'>debugLevel</span> <span class='hs-varop'>&lt;</span> <span class='hs-num'>3</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>printf</span> <span class='hs-str'>"Journal %s with %d transactions, %d accounts"</span>
<a name="line-81"></a>             <span class='hs-layout'>(</span><span class='hs-varid'>journalFilePath</span> <span class='hs-varid'>j</span><span class='hs-layout'>)</span>
<a name="line-82"></a>             <span class='hs-layout'>(</span><span class='hs-varid'>length</span> <span class='hs-layout'>(</span><span class='hs-varid'>jtxns</span> <span class='hs-varid'>j</span><span class='hs-layout'>)</span> <span class='hs-varop'>+</span>
<a name="line-83"></a>              <span class='hs-varid'>length</span> <span class='hs-layout'>(</span><span class='hs-varid'>jmodifiertxns</span> <span class='hs-varid'>j</span><span class='hs-layout'>)</span> <span class='hs-varop'>+</span>
<a name="line-84"></a>              <span class='hs-varid'>length</span> <span class='hs-layout'>(</span><span class='hs-varid'>jperiodictxns</span> <span class='hs-varid'>j</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-85"></a>             <span class='hs-layout'>(</span><span class='hs-varid'>length</span> <span class='hs-varid'>accounts</span><span class='hs-layout'>)</span>
<a name="line-86"></a>    <span class='hs-keyglyph'>|</span> <span class='hs-varid'>debugLevel</span> <span class='hs-varop'>&lt;</span> <span class='hs-num'>6</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>printf</span> <span class='hs-str'>"Journal %s with %d transactions, %d accounts: %s"</span>
<a name="line-87"></a>             <span class='hs-layout'>(</span><span class='hs-varid'>journalFilePath</span> <span class='hs-varid'>j</span><span class='hs-layout'>)</span>
<a name="line-88"></a>             <span class='hs-layout'>(</span><span class='hs-varid'>length</span> <span class='hs-layout'>(</span><span class='hs-varid'>jtxns</span> <span class='hs-varid'>j</span><span class='hs-layout'>)</span> <span class='hs-varop'>+</span>
<a name="line-89"></a>              <span class='hs-varid'>length</span> <span class='hs-layout'>(</span><span class='hs-varid'>jmodifiertxns</span> <span class='hs-varid'>j</span><span class='hs-layout'>)</span> <span class='hs-varop'>+</span>
<a name="line-90"></a>              <span class='hs-varid'>length</span> <span class='hs-layout'>(</span><span class='hs-varid'>jperiodictxns</span> <span class='hs-varid'>j</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-91"></a>             <span class='hs-layout'>(</span><span class='hs-varid'>length</span> <span class='hs-varid'>accounts</span><span class='hs-layout'>)</span>
<a name="line-92"></a>             <span class='hs-layout'>(</span><span class='hs-varid'>show</span> <span class='hs-varid'>accounts</span><span class='hs-layout'>)</span>
<a name="line-93"></a>    <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>printf</span> <span class='hs-str'>"Journal %s with %d transactions, %d accounts: %s, commodity styles: %s"</span>
<a name="line-94"></a>             <span class='hs-layout'>(</span><span class='hs-varid'>journalFilePath</span> <span class='hs-varid'>j</span><span class='hs-layout'>)</span>
<a name="line-95"></a>             <span class='hs-layout'>(</span><span class='hs-varid'>length</span> <span class='hs-layout'>(</span><span class='hs-varid'>jtxns</span> <span class='hs-varid'>j</span><span class='hs-layout'>)</span> <span class='hs-varop'>+</span>
<a name="line-96"></a>              <span class='hs-varid'>length</span> <span class='hs-layout'>(</span><span class='hs-varid'>jmodifiertxns</span> <span class='hs-varid'>j</span><span class='hs-layout'>)</span> <span class='hs-varop'>+</span>
<a name="line-97"></a>              <span class='hs-varid'>length</span> <span class='hs-layout'>(</span><span class='hs-varid'>jperiodictxns</span> <span class='hs-varid'>j</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-98"></a>             <span class='hs-layout'>(</span><span class='hs-varid'>length</span> <span class='hs-varid'>accounts</span><span class='hs-layout'>)</span>
<a name="line-99"></a>             <span class='hs-layout'>(</span><span class='hs-varid'>show</span> <span class='hs-varid'>accounts</span><span class='hs-layout'>)</span>
<a name="line-100"></a>             <span class='hs-layout'>(</span><span class='hs-varid'>show</span> <span class='hs-varop'>$</span> <span class='hs-varid'>jcommoditystyles</span> <span class='hs-varid'>j</span><span class='hs-layout'>)</span>
<a name="line-101"></a>             <span class='hs-comment'>-- ++ (show $ journalTransactions l)</span>
<a name="line-102"></a>             <span class='hs-keyword'>where</span> <span class='hs-varid'>accounts</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>flatten</span> <span class='hs-varop'>$</span> <span class='hs-varid'>journalAccountNameTree</span> <span class='hs-varid'>j</span>
<a name="line-103"></a>
<a name="line-104"></a><span class='hs-comment'>-- showJournalDebug j = unlines [</span>
<a name="line-105"></a><span class='hs-comment'>--                       show j</span>
<a name="line-106"></a><span class='hs-comment'>--                      ,show (jtxns j)</span>
<a name="line-107"></a><span class='hs-comment'>--                      ,show (jmodifiertxns j)</span>
<a name="line-108"></a><span class='hs-comment'>--                      ,show (jperiodictxns j)</span>
<a name="line-109"></a><span class='hs-comment'>--                      ,show $ open_timelog_entries j</span>
<a name="line-110"></a><span class='hs-comment'>--                      ,show $ historical_prices j</span>
<a name="line-111"></a><span class='hs-comment'>--                      ,show $ final_comment_lines j</span>
<a name="line-112"></a><span class='hs-comment'>--                      ,show $ jContext j</span>
<a name="line-113"></a><span class='hs-comment'>--                      ,show $ map fst $ files j</span>
<a name="line-114"></a><span class='hs-comment'>--                      ]</span>
<a name="line-115"></a>
<a name="line-116"></a><a name="nulljournal"></a><span class='hs-definition'>nulljournal</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span>
<a name="line-117"></a><span class='hs-definition'>nulljournal</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Journal</span> <span class='hs-layout'>{</span> <span class='hs-varid'>jmodifiertxns</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>[]</span>
<a name="line-118"></a>                      <span class='hs-layout'>,</span> <span class='hs-varid'>jperiodictxns</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>[]</span>
<a name="line-119"></a>                      <span class='hs-layout'>,</span> <span class='hs-varid'>jtxns</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>[]</span>
<a name="line-120"></a>                      <span class='hs-layout'>,</span> <span class='hs-varid'>open_timelog_entries</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>[]</span>
<a name="line-121"></a>                      <span class='hs-layout'>,</span> <span class='hs-varid'>historical_prices</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>[]</span>
<a name="line-122"></a>                      <span class='hs-layout'>,</span> <span class='hs-varid'>final_comment_lines</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>[]</span>
<a name="line-123"></a>                      <span class='hs-layout'>,</span> <span class='hs-varid'>jContext</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>nullctx</span>
<a name="line-124"></a>                      <span class='hs-layout'>,</span> <span class='hs-varid'>files</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>[]</span>
<a name="line-125"></a>                      <span class='hs-layout'>,</span> <span class='hs-varid'>filereadtime</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>TOD</span> <span class='hs-num'>0</span> <span class='hs-num'>0</span>
<a name="line-126"></a>                      <span class='hs-layout'>,</span> <span class='hs-varid'>jcommoditystyles</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>M</span><span class='hs-varop'>.</span><span class='hs-varid'>fromList</span> <span class='hs-conid'>[]</span>
<a name="line-127"></a>                      <span class='hs-layout'>}</span>
<a name="line-128"></a>
<a name="line-129"></a><a name="nullctx"></a><span class='hs-definition'>nullctx</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>JournalContext</span>
<a name="line-130"></a><span class='hs-definition'>nullctx</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Ctx</span> <span class='hs-layout'>{</span> <span class='hs-varid'>ctxYear</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Nothing</span><span class='hs-layout'>,</span> <span class='hs-varid'>ctxCommodityAndStyle</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Nothing</span><span class='hs-layout'>,</span> <span class='hs-varid'>ctxAccount</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>[]</span><span class='hs-layout'>,</span> <span class='hs-varid'>ctxAliases</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>[]</span> <span class='hs-layout'>}</span>
<a name="line-131"></a>
<a name="line-132"></a><a name="journalFilePath"></a><span class='hs-definition'>journalFilePath</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>FilePath</span>
<a name="line-133"></a><span class='hs-definition'>journalFilePath</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>fst</span> <span class='hs-varop'>.</span> <span class='hs-varid'>mainfile</span>
<a name="line-134"></a>
<a name="line-135"></a><a name="journalFilePaths"></a><span class='hs-definition'>journalFilePaths</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>FilePath</span><span class='hs-keyglyph'>]</span>
<a name="line-136"></a><span class='hs-definition'>journalFilePaths</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>map</span> <span class='hs-varid'>fst</span> <span class='hs-varop'>.</span> <span class='hs-varid'>files</span>
<a name="line-137"></a>
<a name="line-138"></a><a name="mainfile"></a><span class='hs-definition'>mainfile</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>FilePath</span><span class='hs-layout'>,</span> <span class='hs-conid'>String</span><span class='hs-layout'>)</span>
<a name="line-139"></a><span class='hs-definition'>mainfile</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>headDef</span> <span class='hs-layout'>(</span><span class='hs-str'>""</span><span class='hs-layout'>,</span> <span class='hs-str'>""</span><span class='hs-layout'>)</span> <span class='hs-varop'>.</span> <span class='hs-varid'>files</span>
<a name="line-140"></a>
<a name="line-141"></a><a name="addTransaction"></a><span class='hs-definition'>addTransaction</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Transaction</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Journal</span>
<a name="line-142"></a><span class='hs-definition'>addTransaction</span> <span class='hs-varid'>t</span> <span class='hs-varid'>l0</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>l0</span> <span class='hs-layout'>{</span> <span class='hs-varid'>jtxns</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>t</span> <span class='hs-conop'>:</span> <span class='hs-varid'>jtxns</span> <span class='hs-varid'>l0</span> <span class='hs-layout'>}</span>
<a name="line-143"></a>
<a name="line-144"></a><a name="addModifierTransaction"></a><span class='hs-definition'>addModifierTransaction</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ModifierTransaction</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Journal</span>
<a name="line-145"></a><span class='hs-definition'>addModifierTransaction</span> <span class='hs-varid'>mt</span> <span class='hs-varid'>l0</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>l0</span> <span class='hs-layout'>{</span> <span class='hs-varid'>jmodifiertxns</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>mt</span> <span class='hs-conop'>:</span> <span class='hs-varid'>jmodifiertxns</span> <span class='hs-varid'>l0</span> <span class='hs-layout'>}</span>
<a name="line-146"></a>
<a name="line-147"></a><a name="addPeriodicTransaction"></a><span class='hs-definition'>addPeriodicTransaction</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>PeriodicTransaction</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Journal</span>
<a name="line-148"></a><span class='hs-definition'>addPeriodicTransaction</span> <span class='hs-varid'>pt</span> <span class='hs-varid'>l0</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>l0</span> <span class='hs-layout'>{</span> <span class='hs-varid'>jperiodictxns</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>pt</span> <span class='hs-conop'>:</span> <span class='hs-varid'>jperiodictxns</span> <span class='hs-varid'>l0</span> <span class='hs-layout'>}</span>
<a name="line-149"></a>
<a name="line-150"></a><a name="addHistoricalPrice"></a><span class='hs-definition'>addHistoricalPrice</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>HistoricalPrice</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Journal</span>
<a name="line-151"></a><span class='hs-definition'>addHistoricalPrice</span> <span class='hs-varid'>h</span> <span class='hs-varid'>l0</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>l0</span> <span class='hs-layout'>{</span> <span class='hs-varid'>historical_prices</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>h</span> <span class='hs-conop'>:</span> <span class='hs-varid'>historical_prices</span> <span class='hs-varid'>l0</span> <span class='hs-layout'>}</span>
<a name="line-152"></a>
<a name="line-153"></a><a name="addTimeLogEntry"></a><span class='hs-definition'>addTimeLogEntry</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>TimeLogEntry</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Journal</span>
<a name="line-154"></a><span class='hs-definition'>addTimeLogEntry</span> <span class='hs-varid'>tle</span> <span class='hs-varid'>l0</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>l0</span> <span class='hs-layout'>{</span> <span class='hs-varid'>open_timelog_entries</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>tle</span> <span class='hs-conop'>:</span> <span class='hs-varid'>open_timelog_entries</span> <span class='hs-varid'>l0</span> <span class='hs-layout'>}</span>
<a name="line-155"></a>
<a name="line-156"></a><a name="journalPostings"></a><span class='hs-definition'>journalPostings</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>Posting</span><span class='hs-keyglyph'>]</span>
<a name="line-157"></a><span class='hs-definition'>journalPostings</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>concatMap</span> <span class='hs-varid'>tpostings</span> <span class='hs-varop'>.</span> <span class='hs-varid'>jtxns</span>
<a name="line-158"></a>
<a name="line-159"></a><a name="journalAccountNamesUsed"></a><span class='hs-comment'>-- | All account names used in this journal.</span>
<a name="line-160"></a><span class='hs-definition'>journalAccountNamesUsed</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>AccountName</span><span class='hs-keyglyph'>]</span>
<a name="line-161"></a><span class='hs-definition'>journalAccountNamesUsed</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>sort</span> <span class='hs-varop'>.</span> <span class='hs-varid'>accountNamesFromPostings</span> <span class='hs-varop'>.</span> <span class='hs-varid'>journalPostings</span>
<a name="line-162"></a>
<a name="line-163"></a><a name="journalAccountNames"></a><span class='hs-definition'>journalAccountNames</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>AccountName</span><span class='hs-keyglyph'>]</span>
<a name="line-164"></a><span class='hs-definition'>journalAccountNames</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>sort</span> <span class='hs-varop'>.</span> <span class='hs-varid'>expandAccountNames</span> <span class='hs-varop'>.</span> <span class='hs-varid'>journalAccountNamesUsed</span>
<a name="line-165"></a>
<a name="line-166"></a><a name="journalAccountNameTree"></a><span class='hs-definition'>journalAccountNameTree</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Tree</span> <span class='hs-conid'>AccountName</span>
<a name="line-167"></a><span class='hs-definition'>journalAccountNameTree</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>accountNameTreeFrom</span> <span class='hs-varop'>.</span> <span class='hs-varid'>journalAccountNames</span>
<a name="line-168"></a>
<a name="line-169"></a><span class='hs-comment'>-- standard account types</span>
<a name="line-170"></a>
<a name="line-171"></a><a name="journalProfitAndLossAccountQuery"></a><span class='hs-comment'>-- | A query for Profit &amp; Loss accounts in this journal.</span>
<a name="line-172"></a><span class='hs-comment'>-- Cf &lt;<a href="http://en.wikipedia.org/wiki/Chart_of_accounts#Profit_.26_Loss_accounts">http://en.wikipedia.org/wiki/Chart_of_accounts#Profit_.26_Loss_accounts</a>&gt;.</span>
<a name="line-173"></a><span class='hs-definition'>journalProfitAndLossAccountQuery</span>  <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Query</span>
<a name="line-174"></a><span class='hs-definition'>journalProfitAndLossAccountQuery</span> <span class='hs-varid'>j</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Or</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>journalIncomeAccountQuery</span> <span class='hs-varid'>j</span>
<a name="line-175"></a>                                               <span class='hs-layout'>,</span><span class='hs-varid'>journalExpenseAccountQuery</span> <span class='hs-varid'>j</span>
<a name="line-176"></a>                                               <span class='hs-keyglyph'>]</span>
<a name="line-177"></a>
<a name="line-178"></a><a name="journalIncomeAccountQuery"></a><span class='hs-comment'>-- | A query for Income (Revenue) accounts in this journal.</span>
<a name="line-179"></a><span class='hs-comment'>-- This is currently hard-coded to the case-insensitive regex @^(income|revenue)s?(:|$)@.</span>
<a name="line-180"></a><span class='hs-definition'>journalIncomeAccountQuery</span>  <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Query</span>
<a name="line-181"></a><span class='hs-definition'>journalIncomeAccountQuery</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Acct</span> <span class='hs-str'>"^(income|revenue)s?(:|$)"</span>
<a name="line-182"></a>
<a name="line-183"></a><a name="journalExpenseAccountQuery"></a><span class='hs-comment'>-- | A query for Expense accounts in this journal.</span>
<a name="line-184"></a><span class='hs-comment'>-- This is currently hard-coded to the case-insensitive regex @^expenses?(:|$)@.</span>
<a name="line-185"></a><span class='hs-definition'>journalExpenseAccountQuery</span>  <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Query</span>
<a name="line-186"></a><span class='hs-definition'>journalExpenseAccountQuery</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Acct</span> <span class='hs-str'>"^expenses?(:|$)"</span>
<a name="line-187"></a>
<a name="line-188"></a><a name="journalBalanceSheetAccountQuery"></a><span class='hs-comment'>-- | A query for Asset, Liability &amp; Equity accounts in this journal.</span>
<a name="line-189"></a><span class='hs-comment'>-- Cf &lt;<a href="http://en.wikipedia.org/wiki/Chart_of_accounts#Balance_Sheet_Accounts">http://en.wikipedia.org/wiki/Chart_of_accounts#Balance_Sheet_Accounts</a>&gt;.</span>
<a name="line-190"></a><span class='hs-definition'>journalBalanceSheetAccountQuery</span>  <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Query</span>
<a name="line-191"></a><span class='hs-definition'>journalBalanceSheetAccountQuery</span> <span class='hs-varid'>j</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Or</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>journalAssetAccountQuery</span> <span class='hs-varid'>j</span>
<a name="line-192"></a>                                              <span class='hs-layout'>,</span><span class='hs-varid'>journalLiabilityAccountQuery</span> <span class='hs-varid'>j</span>
<a name="line-193"></a>                                              <span class='hs-layout'>,</span><span class='hs-varid'>journalEquityAccountQuery</span> <span class='hs-varid'>j</span>
<a name="line-194"></a>                                              <span class='hs-keyglyph'>]</span>
<a name="line-195"></a>
<a name="line-196"></a><a name="journalAssetAccountQuery"></a><span class='hs-comment'>-- | A query for Asset accounts in this journal.</span>
<a name="line-197"></a><span class='hs-comment'>-- This is currently hard-coded to the case-insensitive regex @^assets?(:|$)@.</span>
<a name="line-198"></a><span class='hs-definition'>journalAssetAccountQuery</span>  <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Query</span>
<a name="line-199"></a><span class='hs-definition'>journalAssetAccountQuery</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Acct</span> <span class='hs-str'>"^assets?(:|$)"</span>
<a name="line-200"></a>
<a name="line-201"></a><a name="journalLiabilityAccountQuery"></a><span class='hs-comment'>-- | A query for Liability accounts in this journal.</span>
<a name="line-202"></a><span class='hs-comment'>-- This is currently hard-coded to the case-insensitive regex @^liabilit(y|ies)(:|$)@.</span>
<a name="line-203"></a><span class='hs-definition'>journalLiabilityAccountQuery</span>  <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Query</span>
<a name="line-204"></a><span class='hs-definition'>journalLiabilityAccountQuery</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Acct</span> <span class='hs-str'>"^liabilit(y|ies)(:|$)"</span>
<a name="line-205"></a>
<a name="line-206"></a><a name="journalEquityAccountQuery"></a><span class='hs-comment'>-- | A query for Equity accounts in this journal.</span>
<a name="line-207"></a><span class='hs-comment'>-- This is currently hard-coded to the case-insensitive regex @^equity(:|$)@.</span>
<a name="line-208"></a><span class='hs-definition'>journalEquityAccountQuery</span>  <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Query</span>
<a name="line-209"></a><span class='hs-definition'>journalEquityAccountQuery</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Acct</span> <span class='hs-str'>"^equity(:|$)"</span>
<a name="line-210"></a>
<a name="line-211"></a><a name="journalCashAccountQuery"></a><span class='hs-comment'>-- | A query for Cash (-equivalent) accounts in this journal (ie,</span>
<a name="line-212"></a><span class='hs-comment'>-- accounts which appear on the cashflow statement.)  This is currently</span>
<a name="line-213"></a><span class='hs-comment'>-- hard-coded to be all the Asset accounts except for those containing the</span>
<a name="line-214"></a><span class='hs-comment'>-- case-insensitive regex @(receivable|A/R)@.</span>
<a name="line-215"></a><span class='hs-definition'>journalCashAccountQuery</span>  <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Query</span>
<a name="line-216"></a><span class='hs-definition'>journalCashAccountQuery</span> <span class='hs-varid'>j</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>And</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>journalAssetAccountQuery</span> <span class='hs-varid'>j</span><span class='hs-layout'>,</span> <span class='hs-conid'>Not</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Acct</span> <span class='hs-str'>"(receivable|A/R)"</span><span class='hs-keyglyph'>]</span>
<a name="line-217"></a>
<a name="line-218"></a><span class='hs-comment'>-- Various kinds of filtering on journals. We do it differently depending</span>
<a name="line-219"></a><span class='hs-comment'>-- on the command.</span>
<a name="line-220"></a>
<a name="line-221"></a><span class='hs-comment'>-------------------------------------------------------------------------------</span>
<a name="line-222"></a><span class='hs-comment'>-- filtering V2</span>
<a name="line-223"></a>
<a name="line-224"></a><a name="filterJournalPostings"></a><span class='hs-comment'>-- | Keep only postings matching the query expression.</span>
<a name="line-225"></a><span class='hs-comment'>-- This can leave unbalanced transactions.</span>
<a name="line-226"></a><span class='hs-definition'>filterJournalPostings</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Query</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Journal</span>
<a name="line-227"></a><span class='hs-definition'>filterJournalPostings</span> <span class='hs-varid'>q</span> <span class='hs-varid'>j</span><span class='hs-keyglyph'>@</span><span class='hs-conid'>Journal</span><span class='hs-layout'>{</span><span class='hs-varid'>jtxns</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>ts</span><span class='hs-layout'>}</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>j</span><span class='hs-layout'>{</span><span class='hs-varid'>jtxns</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>map</span> <span class='hs-varid'>filtertransactionpostings</span> <span class='hs-varid'>ts</span><span class='hs-layout'>}</span>
<a name="line-228"></a>    <span class='hs-keyword'>where</span>
<a name="line-229"></a>      <span class='hs-varid'>filtertransactionpostings</span> <span class='hs-varid'>t</span><span class='hs-keyglyph'>@</span><span class='hs-conid'>Transaction</span><span class='hs-layout'>{</span><span class='hs-varid'>tpostings</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>ps</span><span class='hs-layout'>}</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>t</span><span class='hs-layout'>{</span><span class='hs-varid'>tpostings</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>filter</span> <span class='hs-layout'>(</span><span class='hs-varid'>q</span> <span class='hs-varop'>`matchesPosting`</span><span class='hs-layout'>)</span> <span class='hs-varid'>ps</span><span class='hs-layout'>}</span>
<a name="line-230"></a>
<a name="line-231"></a><a name="filterJournalTransactions"></a><span class='hs-comment'>-- | Keep only transactions matching the query expression.</span>
<a name="line-232"></a><span class='hs-definition'>filterJournalTransactions</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Query</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Journal</span>
<a name="line-233"></a><span class='hs-definition'>filterJournalTransactions</span> <span class='hs-varid'>q</span> <span class='hs-varid'>j</span><span class='hs-keyglyph'>@</span><span class='hs-conid'>Journal</span><span class='hs-layout'>{</span><span class='hs-varid'>jtxns</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>ts</span><span class='hs-layout'>}</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>j</span><span class='hs-layout'>{</span><span class='hs-varid'>jtxns</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>filter</span> <span class='hs-layout'>(</span><span class='hs-varid'>q</span> <span class='hs-varop'>`matchesTransaction`</span><span class='hs-layout'>)</span> <span class='hs-varid'>ts</span><span class='hs-layout'>}</span>
<a name="line-234"></a>
<a name="line-235"></a><span class='hs-comment'>{-
<a name="line-236"></a>-------------------------------------------------------------------------------
<a name="line-237"></a>-- filtering V1
<a name="line-238"></a>
<a name="line-239"></a>-- | Keep only transactions we are interested in, as described by the
<a name="line-240"></a>-- filter specification.
<a name="line-241"></a>filterJournalTransactions :: FilterSpec -&gt; Journal -&gt; Journal
<a name="line-242"></a>filterJournalTransactions FilterSpec{datespan=datespan
<a name="line-243"></a>                                    ,cleared=cleared
<a name="line-244"></a>                                    -- ,real=real
<a name="line-245"></a>                                    -- ,empty=empty
<a name="line-246"></a>                                    ,acctpats=apats
<a name="line-247"></a>                                    ,descpats=dpats
<a name="line-248"></a>                                    ,depth=depth
<a name="line-249"></a>                                    ,fMetadata=md
<a name="line-250"></a>                                    } =
<a name="line-251"></a>    filterJournalTransactionsByClearedStatus cleared .
<a name="line-252"></a>    filterJournalPostingsByDepth depth .
<a name="line-253"></a>    filterJournalTransactionsByAccount apats .
<a name="line-254"></a>    filterJournalTransactionsByMetadata md .
<a name="line-255"></a>    filterJournalTransactionsByDescription dpats .
<a name="line-256"></a>    filterJournalTransactionsByDate datespan
<a name="line-257"></a>
<a name="line-258"></a>-- | Keep only postings we are interested in, as described by the filter
<a name="line-259"></a>-- specification. This can leave unbalanced transactions.
<a name="line-260"></a>filterJournalPostings :: FilterSpec -&gt; Journal -&gt; Journal
<a name="line-261"></a>filterJournalPostings FilterSpec{datespan=datespan
<a name="line-262"></a>                                ,cleared=cleared
<a name="line-263"></a>                                ,real=real
<a name="line-264"></a>                                ,empty=empty
<a name="line-265"></a>                                ,acctpats=apats
<a name="line-266"></a>                                ,descpats=dpats
<a name="line-267"></a>                                ,depth=depth
<a name="line-268"></a>                                ,fMetadata=md
<a name="line-269"></a>                                } =
<a name="line-270"></a>    filterJournalPostingsByRealness real .
<a name="line-271"></a>    filterJournalPostingsByClearedStatus cleared .
<a name="line-272"></a>    filterJournalPostingsByEmpty empty .
<a name="line-273"></a>    filterJournalPostingsByDepth depth .
<a name="line-274"></a>    filterJournalPostingsByAccount apats .
<a name="line-275"></a>    filterJournalTransactionsByMetadata md .
<a name="line-276"></a>    filterJournalTransactionsByDescription dpats .
<a name="line-277"></a>    filterJournalTransactionsByDate datespan
<a name="line-278"></a>
<a name="line-279"></a>-- | Keep only transactions whose metadata matches all metadata specifications.
<a name="line-280"></a>filterJournalTransactionsByMetadata :: [(String,String)] -&gt; Journal -&gt; Journal
<a name="line-281"></a>filterJournalTransactionsByMetadata pats j@Journal{jtxns=ts} = j{jtxns=filter matchmd ts}
<a name="line-282"></a>    where matchmd t = all (`elem` tmetadata t) pats
<a name="line-283"></a>
<a name="line-284"></a>-- | Keep only transactions whose description matches the description patterns.
<a name="line-285"></a>filterJournalTransactionsByDescription :: [String] -&gt; Journal -&gt; Journal
<a name="line-286"></a>filterJournalTransactionsByDescription pats j@Journal{jtxns=ts} = j{jtxns=filter matchdesc ts}
<a name="line-287"></a>    where matchdesc = matchpats pats . tdescription
<a name="line-288"></a>
<a name="line-289"></a>-- | Keep only transactions which fall between begin and end dates.
<a name="line-290"></a>-- We include transactions on the begin date and exclude transactions on the end
<a name="line-291"></a>-- date, like ledger.  An empty date string means no restriction.
<a name="line-292"></a>filterJournalTransactionsByDate :: DateSpan -&gt; Journal -&gt; Journal
<a name="line-293"></a>filterJournalTransactionsByDate (DateSpan begin end) j@Journal{jtxns=ts} = j{jtxns=filter match ts}
<a name="line-294"></a>    where match t = maybe True (tdate t&gt;=) begin &amp;&amp; maybe True (tdate t&lt;) end
<a name="line-295"></a>
<a name="line-296"></a>-- | Keep only transactions which have the requested cleared/uncleared
<a name="line-297"></a>-- status, if there is one.
<a name="line-298"></a>filterJournalTransactionsByClearedStatus :: Maybe Bool -&gt; Journal -&gt; Journal
<a name="line-299"></a>filterJournalTransactionsByClearedStatus Nothing j = j
<a name="line-300"></a>filterJournalTransactionsByClearedStatus (Just val) j@Journal{jtxns=ts} = j{jtxns=filter match ts}
<a name="line-301"></a>    where match = (==val).tstatus
<a name="line-302"></a>
<a name="line-303"></a>-- | Keep only postings which have the requested cleared/uncleared status,
<a name="line-304"></a>-- if there is one.
<a name="line-305"></a>filterJournalPostingsByClearedStatus :: Maybe Bool -&gt; Journal -&gt; Journal
<a name="line-306"></a>filterJournalPostingsByClearedStatus Nothing j = j
<a name="line-307"></a>filterJournalPostingsByClearedStatus (Just c) j@Journal{jtxns=ts} = j{jtxns=map filterpostings ts}
<a name="line-308"></a>    where filterpostings t@Transaction{tpostings=ps} = t{tpostings=filter ((==c) . postingCleared) ps}
<a name="line-309"></a>
<a name="line-310"></a>-- | Strip out any virtual postings, if the flag is true, otherwise do
<a name="line-311"></a>-- no filtering.
<a name="line-312"></a>filterJournalPostingsByRealness :: Bool -&gt; Journal -&gt; Journal
<a name="line-313"></a>filterJournalPostingsByRealness False j = j
<a name="line-314"></a>filterJournalPostingsByRealness True j@Journal{jtxns=ts} = j{jtxns=map filterpostings ts}
<a name="line-315"></a>    where filterpostings t@Transaction{tpostings=ps} = t{tpostings=filter isReal ps}
<a name="line-316"></a>
<a name="line-317"></a>-- | Strip out any postings with zero amount, unless the flag is true.
<a name="line-318"></a>filterJournalPostingsByEmpty :: Bool -&gt; Journal -&gt; Journal
<a name="line-319"></a>filterJournalPostingsByEmpty True j = j
<a name="line-320"></a>filterJournalPostingsByEmpty False j@Journal{jtxns=ts} = j{jtxns=map filterpostings ts}
<a name="line-321"></a>    where filterpostings t@Transaction{tpostings=ps} = t{tpostings=filter (not . isEmptyPosting) ps}
<a name="line-322"></a>
<a name="line-323"></a>-- -- | Keep only transactions which affect accounts deeper than the specified depth.
<a name="line-324"></a>-- filterJournalTransactionsByDepth :: Maybe Int -&gt; Journal -&gt; Journal
<a name="line-325"></a>-- filterJournalTransactionsByDepth Nothing j = j
<a name="line-326"></a>-- filterJournalTransactionsByDepth (Just d) j@Journal{jtxns=ts} =
<a name="line-327"></a>--     j{jtxns=(filter (any ((&lt;= d+1) . accountNameLevel . paccount) . tpostings) ts)}
<a name="line-328"></a>
<a name="line-329"></a>-- | Strip out any postings to accounts deeper than the specified depth
<a name="line-330"></a>-- (and any transactions which have no postings as a result).
<a name="line-331"></a>filterJournalPostingsByDepth :: Maybe Int -&gt; Journal -&gt; Journal
<a name="line-332"></a>filterJournalPostingsByDepth Nothing j = j
<a name="line-333"></a>filterJournalPostingsByDepth (Just d) j@Journal{jtxns=ts} =
<a name="line-334"></a>    j{jtxns=filter (not . null . tpostings) $ map filtertxns ts}
<a name="line-335"></a>    where filtertxns t@Transaction{tpostings=ps} =
<a name="line-336"></a>              t{tpostings=filter ((&lt;= d) . accountNameLevel . paccount) ps}
<a name="line-337"></a>
<a name="line-338"></a>-- | Keep only postings which affect accounts matched by the account patterns.
<a name="line-339"></a>-- This can leave transactions unbalanced.
<a name="line-340"></a>filterJournalPostingsByAccount :: [String] -&gt; Journal -&gt; Journal
<a name="line-341"></a>filterJournalPostingsByAccount apats j@Journal{jtxns=ts} = j{jtxns=map filterpostings ts}
<a name="line-342"></a>    where filterpostings t@Transaction{tpostings=ps} = t{tpostings=filter (matchpats apats . paccount) ps}
<a name="line-343"></a>
<a name="line-344"></a>-- | Keep only transactions which affect accounts matched by the account patterns.
<a name="line-345"></a>-- More precisely: each positive account pattern excludes transactions
<a name="line-346"></a>-- which do not contain a posting to a matched account, and each negative
<a name="line-347"></a>-- account pattern excludes transactions containing a posting to a matched
<a name="line-348"></a>-- account.
<a name="line-349"></a>filterJournalTransactionsByAccount :: [String] -&gt; Journal -&gt; Journal
<a name="line-350"></a>filterJournalTransactionsByAccount apats j@Journal{jtxns=ts} = j{jtxns=filter tmatch ts}
<a name="line-351"></a>    where
<a name="line-352"></a>      tmatch t = (null positives || any positivepmatch ps) &amp;&amp; (null negatives || not (any negativepmatch ps)) where ps = tpostings t
<a name="line-353"></a>      positivepmatch p = any (`amatch` a) positives where a = paccount p
<a name="line-354"></a>      negativepmatch p = any (`amatch` a) negatives where a = paccount p
<a name="line-355"></a>      amatch pat a = regexMatchesCI (abspat pat) a
<a name="line-356"></a>      (negatives,positives) = partition isnegativepat apats
<a name="line-357"></a>
<a name="line-358"></a>-}</span>
<a name="line-359"></a>
<a name="line-360"></a><a name="journalApplyAliases"></a><span class='hs-comment'>-- | Apply additional account aliases (eg from the command-line) to all postings in a journal.</span>
<a name="line-361"></a><span class='hs-definition'>journalApplyAliases</span> <span class='hs-keyglyph'>::</span> <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-conid'>AccountName</span><span class='hs-layout'>,</span><span class='hs-conid'>AccountName</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Journal</span>
<a name="line-362"></a><span class='hs-definition'>journalApplyAliases</span> <span class='hs-varid'>aliases</span> <span class='hs-varid'>j</span><span class='hs-keyglyph'>@</span><span class='hs-conid'>Journal</span><span class='hs-layout'>{</span><span class='hs-varid'>jtxns</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>ts</span><span class='hs-layout'>}</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>j</span><span class='hs-layout'>{</span><span class='hs-varid'>jtxns</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>map</span> <span class='hs-varid'>fixtransaction</span> <span class='hs-varid'>ts</span><span class='hs-layout'>}</span>
<a name="line-363"></a>    <span class='hs-keyword'>where</span>
<a name="line-364"></a>      <span class='hs-varid'>fixtransaction</span> <span class='hs-varid'>t</span><span class='hs-keyglyph'>@</span><span class='hs-conid'>Transaction</span><span class='hs-layout'>{</span><span class='hs-varid'>tpostings</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>ps</span><span class='hs-layout'>}</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>t</span><span class='hs-layout'>{</span><span class='hs-varid'>tpostings</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>map</span> <span class='hs-varid'>fixposting</span> <span class='hs-varid'>ps</span><span class='hs-layout'>}</span>
<a name="line-365"></a>      <span class='hs-varid'>fixposting</span> <span class='hs-varid'>p</span><span class='hs-keyglyph'>@</span><span class='hs-conid'>Posting</span><span class='hs-layout'>{</span><span class='hs-varid'>paccount</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>a</span><span class='hs-layout'>}</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>p</span><span class='hs-layout'>{</span><span class='hs-varid'>paccount</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>accountNameApplyAliases</span> <span class='hs-varid'>aliases</span> <span class='hs-varid'>a</span><span class='hs-layout'>}</span>
<a name="line-366"></a>
<a name="line-367"></a><a name="journalFinalise"></a><span class='hs-comment'>-- | Do post-parse processing on a journal to make it ready for use: check</span>
<a name="line-368"></a><span class='hs-comment'>-- all transactions balance, canonicalise amount formats, close any open</span>
<a name="line-369"></a><span class='hs-comment'>-- timelog entries and so on.</span>
<a name="line-370"></a><span class='hs-definition'>journalFinalise</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ClockTime</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>LocalTime</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>FilePath</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>JournalContext</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Either</span> <span class='hs-conid'>String</span> <span class='hs-conid'>Journal</span>
<a name="line-371"></a><span class='hs-definition'>journalFinalise</span> <span class='hs-varid'>tclock</span> <span class='hs-varid'>tlocal</span> <span class='hs-varid'>path</span> <span class='hs-varid'>txt</span> <span class='hs-varid'>ctx</span> <span class='hs-varid'>j</span><span class='hs-keyglyph'>@</span><span class='hs-conid'>Journal</span><span class='hs-layout'>{</span><span class='hs-varid'>files</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>fs</span><span class='hs-layout'>}</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-372"></a>  <span class='hs-layout'>(</span><span class='hs-varid'>journalBalanceTransactions</span> <span class='hs-varop'>$</span>
<a name="line-373"></a>    <span class='hs-varid'>journalCanonicaliseAmounts</span> <span class='hs-varop'>$</span>
<a name="line-374"></a>    <span class='hs-varid'>journalCloseTimeLogEntries</span> <span class='hs-varid'>tlocal</span>
<a name="line-375"></a>    <span class='hs-varid'>j</span><span class='hs-layout'>{</span><span class='hs-varid'>files</span><span class='hs-keyglyph'>=</span><span class='hs-layout'>(</span><span class='hs-varid'>path</span><span class='hs-layout'>,</span><span class='hs-varid'>txt</span><span class='hs-layout'>)</span><span class='hs-conop'>:</span><span class='hs-varid'>fs</span><span class='hs-layout'>,</span> <span class='hs-varid'>filereadtime</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>tclock</span><span class='hs-layout'>,</span> <span class='hs-varid'>jContext</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>ctx</span><span class='hs-layout'>}</span><span class='hs-layout'>)</span>
<a name="line-376"></a>  <span class='hs-varop'>&gt;&gt;=</span> <span class='hs-varid'>journalCheckBalanceAssertions</span>
<a name="line-377"></a>
<a name="line-378"></a><a name="journalCheckBalanceAssertions"></a><span class='hs-comment'>-- | Check any balance assertions in the journal and return an error</span>
<a name="line-379"></a><span class='hs-comment'>-- message if any of them fail.</span>
<a name="line-380"></a><span class='hs-definition'>journalCheckBalanceAssertions</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Either</span> <span class='hs-conid'>String</span> <span class='hs-conid'>Journal</span>
<a name="line-381"></a><span class='hs-definition'>journalCheckBalanceAssertions</span> <span class='hs-varid'>j</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-382"></a>  <span class='hs-keyword'>let</span> <span class='hs-varid'>postingsByAccount</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>groupBy</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>p1</span> <span class='hs-varid'>p2</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>paccount</span> <span class='hs-varid'>p1</span> <span class='hs-varop'>==</span> <span class='hs-varid'>paccount</span> <span class='hs-varid'>p2</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span>
<a name="line-383"></a>                          <span class='hs-varid'>sortBy</span> <span class='hs-layout'>(</span><span class='hs-varid'>comparing</span> <span class='hs-varid'>paccount</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span>
<a name="line-384"></a>                          <span class='hs-varid'>journalPostings</span> <span class='hs-varid'>j</span>
<a name="line-385"></a>  <span class='hs-varid'>forM_</span> <span class='hs-varid'>postingsByAccount</span> <span class='hs-varid'>checkBalanceAssertionsForAccount</span>
<a name="line-386"></a>  <span class='hs-conid'>Right</span> <span class='hs-varid'>j</span>
<a name="line-387"></a>
<a name="line-388"></a><a name="checkBalanceAssertionsForAccount"></a><span class='hs-comment'>-- Check any balance assertions in this sequence of postings to a single account.</span>
<a name="line-389"></a><span class='hs-definition'>checkBalanceAssertionsForAccount</span> <span class='hs-keyglyph'>::</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>Posting</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Either</span> <span class='hs-conid'>String</span> <span class='hs-conid'>()</span>
<a name="line-390"></a><span class='hs-definition'>checkBalanceAssertionsForAccount</span> <span class='hs-varid'>ps</span>
<a name="line-391"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>null</span> <span class='hs-varid'>errs</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Right</span> <span class='hs-conid'>()</span>
<a name="line-392"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Left</span> <span class='hs-varop'>$</span> <span class='hs-varid'>head</span> <span class='hs-varid'>errs</span>
<a name="line-393"></a>  <span class='hs-keyword'>where</span>
<a name="line-394"></a>    <span class='hs-varid'>errs</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>fst</span> <span class='hs-varop'>$</span>
<a name="line-395"></a>           <span class='hs-varid'>foldl'</span> <span class='hs-varid'>checkBalanceAssertion</span> <span class='hs-layout'>(</span><span class='hs-conid'>[]</span><span class='hs-layout'>,</span><span class='hs-varid'>nullmixedamt</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span>
<a name="line-396"></a>           <span class='hs-varid'>splitAssertions</span> <span class='hs-varop'>$</span>
<a name="line-397"></a>           <span class='hs-varid'>sortBy</span> <span class='hs-layout'>(</span><span class='hs-varid'>comparing</span> <span class='hs-varid'>postingDate</span><span class='hs-layout'>)</span> <span class='hs-varid'>ps</span>
<a name="line-398"></a>
<a name="line-399"></a><a name="checkBalanceAssertion"></a><span class='hs-comment'>-- Given a starting balance, accumulated errors, and a non-null sequence of</span>
<a name="line-400"></a><span class='hs-comment'>-- postings to a single account with a balance assertion in the last:</span>
<a name="line-401"></a><span class='hs-comment'>-- check that the final balance matches the balance assertion.</span>
<a name="line-402"></a><span class='hs-comment'>-- If it does, return the new balance, otherwise add an error to the</span>
<a name="line-403"></a><span class='hs-comment'>-- error list. Intended to be called from a fold.</span>
<a name="line-404"></a><span class='hs-definition'>checkBalanceAssertion</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>[</span><span class='hs-conid'>String</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>,</span><span class='hs-conid'>MixedAmount</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>Posting</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>[</span><span class='hs-conid'>String</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>,</span><span class='hs-conid'>MixedAmount</span><span class='hs-layout'>)</span>
<a name="line-405"></a><span class='hs-definition'>checkBalanceAssertion</span> <span class='hs-layout'>(</span><span class='hs-varid'>errs</span><span class='hs-layout'>,</span><span class='hs-varid'>bal</span><span class='hs-layout'>)</span> <span class='hs-varid'>ps</span>
<a name="line-406"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>null</span> <span class='hs-varid'>ps</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>errs</span><span class='hs-layout'>,</span><span class='hs-varid'>bal</span><span class='hs-layout'>)</span>
<a name="line-407"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>isNothing</span> <span class='hs-varid'>assertion</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>errs</span><span class='hs-layout'>,</span><span class='hs-varid'>bal</span><span class='hs-layout'>)</span>
<a name="line-408"></a>  <span class='hs-keyglyph'>|</span>
<a name="line-409"></a>    <span class='hs-comment'>-- bal' /= assertedbal  -- MixedAmount's Eq instance currently gets confused by different precisions</span>
<a name="line-410"></a>    <span class='hs-varid'>not</span> <span class='hs-varop'>$</span> <span class='hs-varid'>isReallyZeroMixedAmount</span> <span class='hs-layout'>(</span><span class='hs-varid'>bal'</span> <span class='hs-comment'>-</span> <span class='hs-varid'>assertedbal</span><span class='hs-layout'>)</span>
<a name="line-411"></a>      <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>errs</span><span class='hs-varop'>++</span><span class='hs-keyglyph'>[</span><span class='hs-varid'>err</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>,</span> <span class='hs-varid'>bal'</span><span class='hs-layout'>)</span>
<a name="line-412"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>errs</span><span class='hs-layout'>,</span><span class='hs-varid'>bal'</span><span class='hs-layout'>)</span>
<a name="line-413"></a>  <span class='hs-keyword'>where</span>
<a name="line-414"></a>    <span class='hs-varid'>p</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>last</span> <span class='hs-varid'>ps</span>
<a name="line-415"></a>    <span class='hs-varid'>assertion</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>pbalanceassertion</span> <span class='hs-varid'>p</span>
<a name="line-416"></a>    <span class='hs-conid'>Just</span> <span class='hs-varid'>assertedbal</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>assertion</span>
<a name="line-417"></a>    <span class='hs-varid'>bal'</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>sum</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>bal</span><span class='hs-keyglyph'>]</span> <span class='hs-varop'>++</span> <span class='hs-varid'>map</span> <span class='hs-varid'>pamount</span> <span class='hs-varid'>ps</span>
<a name="line-418"></a>    <span class='hs-varid'>err</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>printf</span> <span class='hs-str'>"Balance assertion failed for account %s on %s\n%safter\n   %s\nexpected balance is %s, actual balance was %s."</span>
<a name="line-419"></a>                 <span class='hs-layout'>(</span><span class='hs-varid'>paccount</span> <span class='hs-varid'>p</span><span class='hs-layout'>)</span>
<a name="line-420"></a>                 <span class='hs-layout'>(</span><span class='hs-varid'>show</span> <span class='hs-varop'>$</span> <span class='hs-varid'>postingDate</span> <span class='hs-varid'>p</span><span class='hs-layout'>)</span>
<a name="line-421"></a>                 <span class='hs-layout'>(</span><span class='hs-varid'>maybe</span> <span class='hs-str'>""</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-str'>"In\n"</span><span class='hs-varop'>++</span><span class='hs-layout'>)</span><span class='hs-varop'>.</span><span class='hs-varid'>show</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span> <span class='hs-varid'>ptransaction</span> <span class='hs-varid'>p</span><span class='hs-layout'>)</span>
<a name="line-422"></a>                 <span class='hs-layout'>(</span><span class='hs-varid'>show</span> <span class='hs-varid'>p</span><span class='hs-layout'>)</span>
<a name="line-423"></a>                 <span class='hs-layout'>(</span><span class='hs-varid'>showMixedAmount</span> <span class='hs-varid'>assertedbal</span><span class='hs-layout'>)</span>
<a name="line-424"></a>                 <span class='hs-layout'>(</span><span class='hs-varid'>showMixedAmount</span> <span class='hs-varid'>bal'</span><span class='hs-layout'>)</span>
<a name="line-425"></a>
<a name="line-426"></a><a name="splitAssertions"></a><span class='hs-comment'>-- Given a sequence of postings to a single account, split it into</span>
<a name="line-427"></a><span class='hs-comment'>-- sub-sequences consisting of ordinary postings followed by a single</span>
<a name="line-428"></a><span class='hs-comment'>-- balance-asserting posting. Postings not followed by a balance</span>
<a name="line-429"></a><span class='hs-comment'>-- assertion are discarded.</span>
<a name="line-430"></a><span class='hs-definition'>splitAssertions</span> <span class='hs-keyglyph'>::</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>Posting</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-keyglyph'>[</span><span class='hs-conid'>Posting</span><span class='hs-keyglyph'>]</span><span class='hs-keyglyph'>]</span>
<a name="line-431"></a><span class='hs-definition'>splitAssertions</span> <span class='hs-varid'>ps</span>
<a name="line-432"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>null</span> <span class='hs-varid'>rest</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>[]</span><span class='hs-keyglyph'>]</span>
<a name="line-433"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>ps'</span><span class='hs-varop'>++</span><span class='hs-keyglyph'>[</span><span class='hs-varid'>head</span> <span class='hs-varid'>rest</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>)</span><span class='hs-conop'>:</span><span class='hs-varid'>splitAssertions</span> <span class='hs-layout'>(</span><span class='hs-varid'>tail</span> <span class='hs-varid'>rest</span><span class='hs-layout'>)</span>
<a name="line-434"></a>  <span class='hs-keyword'>where</span>
<a name="line-435"></a>    <span class='hs-layout'>(</span><span class='hs-varid'>ps'</span><span class='hs-layout'>,</span><span class='hs-varid'>rest</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>break</span> <span class='hs-layout'>(</span><span class='hs-varid'>isJust</span> <span class='hs-varop'>.</span> <span class='hs-varid'>pbalanceassertion</span><span class='hs-layout'>)</span> <span class='hs-varid'>ps</span>
<a name="line-436"></a>    
<a name="line-437"></a><a name="journalBalanceTransactions"></a><span class='hs-comment'>-- | Fill in any missing amounts and check that all journal transactions</span>
<a name="line-438"></a><span class='hs-comment'>-- balance, or return an error message. This is done after parsing all</span>
<a name="line-439"></a><span class='hs-comment'>-- amounts and working out the canonical commodities, since balancing</span>
<a name="line-440"></a><span class='hs-comment'>-- depends on display precision. Reports only the first error encountered.</span>
<a name="line-441"></a><span class='hs-definition'>journalBalanceTransactions</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Either</span> <span class='hs-conid'>String</span> <span class='hs-conid'>Journal</span>
<a name="line-442"></a><span class='hs-definition'>journalBalanceTransactions</span> <span class='hs-varid'>j</span><span class='hs-keyglyph'>@</span><span class='hs-conid'>Journal</span><span class='hs-layout'>{</span><span class='hs-varid'>jtxns</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>ts</span><span class='hs-layout'>,</span> <span class='hs-varid'>jcommoditystyles</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>ss</span><span class='hs-layout'>}</span> <span class='hs-keyglyph'>=</span>
<a name="line-443"></a>  <span class='hs-keyword'>case</span> <span class='hs-varid'>sequence</span> <span class='hs-varop'>$</span> <span class='hs-varid'>map</span> <span class='hs-varid'>balance</span> <span class='hs-varid'>ts</span> <span class='hs-keyword'>of</span> <span class='hs-conid'>Right</span> <span class='hs-varid'>ts'</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Right</span> <span class='hs-varid'>j</span><span class='hs-layout'>{</span><span class='hs-varid'>jtxns</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>map</span> <span class='hs-varid'>txnTieKnot</span> <span class='hs-varid'>ts'</span><span class='hs-layout'>}</span>
<a name="line-444"></a>                                    <span class='hs-conid'>Left</span> <span class='hs-varid'>e</span>    <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Left</span> <span class='hs-varid'>e</span>
<a name="line-445"></a>      <span class='hs-keyword'>where</span> <span class='hs-varid'>balance</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>balanceTransaction</span> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-varid'>ss</span><span class='hs-layout'>)</span>
<a name="line-446"></a>
<a name="line-447"></a><a name="journalCanonicaliseAmounts"></a><span class='hs-comment'>-- | Convert all the journal's posting amounts (not price amounts) to</span>
<a name="line-448"></a><span class='hs-comment'>-- their canonical display settings. Ie, all amounts in a given</span>
<a name="line-449"></a><span class='hs-comment'>-- commodity will use (a) the display settings of the first, and (b)</span>
<a name="line-450"></a><span class='hs-comment'>-- the greatest precision, of the posting amounts in that commodity.</span>
<a name="line-451"></a><span class='hs-definition'>journalCanonicaliseAmounts</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Journal</span>
<a name="line-452"></a><span class='hs-definition'>journalCanonicaliseAmounts</span> <span class='hs-varid'>j</span><span class='hs-keyglyph'>@</span><span class='hs-conid'>Journal</span><span class='hs-layout'>{</span><span class='hs-varid'>jtxns</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>ts</span><span class='hs-layout'>}</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>j''</span>
<a name="line-453"></a>    <span class='hs-keyword'>where</span>
<a name="line-454"></a>      <span class='hs-varid'>j''</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>j'</span><span class='hs-layout'>{</span><span class='hs-varid'>jtxns</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>map</span> <span class='hs-varid'>fixtransaction</span> <span class='hs-varid'>ts</span><span class='hs-layout'>}</span>
<a name="line-455"></a>      <span class='hs-varid'>j'</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>j</span><span class='hs-layout'>{</span><span class='hs-varid'>jcommoditystyles</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>canonicalStyles</span> <span class='hs-varop'>$</span> <span class='hs-varid'>journalAmounts</span> <span class='hs-varid'>j</span><span class='hs-layout'>}</span>
<a name="line-456"></a>      <span class='hs-varid'>fixtransaction</span> <span class='hs-varid'>t</span><span class='hs-keyglyph'>@</span><span class='hs-conid'>Transaction</span><span class='hs-layout'>{</span><span class='hs-varid'>tpostings</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>ps</span><span class='hs-layout'>}</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>t</span><span class='hs-layout'>{</span><span class='hs-varid'>tpostings</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>map</span> <span class='hs-varid'>fixposting</span> <span class='hs-varid'>ps</span><span class='hs-layout'>}</span>
<a name="line-457"></a>      <span class='hs-varid'>fixposting</span> <span class='hs-varid'>p</span><span class='hs-keyglyph'>@</span><span class='hs-conid'>Posting</span><span class='hs-layout'>{</span><span class='hs-varid'>pamount</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>a</span><span class='hs-layout'>}</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>p</span><span class='hs-layout'>{</span><span class='hs-varid'>pamount</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>fixmixedamount</span> <span class='hs-varid'>a</span><span class='hs-layout'>}</span>
<a name="line-458"></a>      <span class='hs-varid'>fixmixedamount</span> <span class='hs-layout'>(</span><span class='hs-conid'>Mixed</span> <span class='hs-keyword'>as</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Mixed</span> <span class='hs-varop'>$</span> <span class='hs-varid'>map</span> <span class='hs-varid'>fixamount</span> <span class='hs-keyword'>as</span>
<a name="line-459"></a>      <span class='hs-varid'>fixamount</span> <span class='hs-varid'>a</span><span class='hs-keyglyph'>@</span><span class='hs-conid'>Amount</span><span class='hs-layout'>{</span><span class='hs-varid'>acommodity</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>c</span><span class='hs-layout'>}</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>a</span><span class='hs-layout'>{</span><span class='hs-varid'>astyle</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>journalCommodityStyle</span> <span class='hs-varid'>j'</span> <span class='hs-varid'>c</span><span class='hs-layout'>}</span>
<a name="line-460"></a>
<a name="line-461"></a><a name="journalCommodityStyle"></a><span class='hs-comment'>-- | Get this journal's canonical amount style for the given commodity, or the null style.</span>
<a name="line-462"></a><span class='hs-definition'>journalCommodityStyle</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Commodity</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>AmountStyle</span>
<a name="line-463"></a><span class='hs-definition'>journalCommodityStyle</span> <span class='hs-varid'>j</span> <span class='hs-varid'>c</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>M</span><span class='hs-varop'>.</span><span class='hs-varid'>findWithDefault</span> <span class='hs-varid'>amountstyle</span> <span class='hs-varid'>c</span> <span class='hs-varop'>$</span> <span class='hs-varid'>jcommoditystyles</span> <span class='hs-varid'>j</span>
<a name="line-464"></a>
<a name="line-465"></a><span class='hs-comment'>-- -- | Apply this journal's historical price records to unpriced amounts where possible.</span>
<a name="line-466"></a><span class='hs-comment'>-- journalApplyHistoricalPrices :: Journal -&gt; Journal</span>
<a name="line-467"></a><span class='hs-comment'>-- journalApplyHistoricalPrices j@Journal{jtxns=ts} = j{jtxns=map fixtransaction ts}</span>
<a name="line-468"></a><span class='hs-comment'>--     where</span>
<a name="line-469"></a><span class='hs-comment'>--       fixtransaction t@Transaction{tdate=d, tpostings=ps} = t{tpostings=map fixposting ps}</span>
<a name="line-470"></a><span class='hs-comment'>--        where</span>
<a name="line-471"></a><span class='hs-comment'>--         fixposting p@Posting{pamount=a} = p{pamount=fixmixedamount a}</span>
<a name="line-472"></a><span class='hs-comment'>--         fixmixedamount (Mixed as) = Mixed $ map fixamount as</span>
<a name="line-473"></a><span class='hs-comment'>--         fixamount = fixprice</span>
<a name="line-474"></a><span class='hs-comment'>--         fixprice a@Amount{price=Just _} = a</span>
<a name="line-475"></a><span class='hs-comment'>--         fixprice a@Amount{commodity=c} = a{price=maybe Nothing (Just . UnitPrice) $ journalHistoricalPriceFor j d c}</span>
<a name="line-476"></a>
<a name="line-477"></a><span class='hs-comment'>-- -- | Get the price for a commodity on the specified day from the price database, if known.</span>
<a name="line-478"></a><span class='hs-comment'>-- -- Does only one lookup step, ie will not look up the price of a price.</span>
<a name="line-479"></a><span class='hs-comment'>-- journalHistoricalPriceFor :: Journal -&gt; Day -&gt; Commodity -&gt; Maybe MixedAmount</span>
<a name="line-480"></a><span class='hs-comment'>-- journalHistoricalPriceFor j d Commodity{symbol=s} = do</span>
<a name="line-481"></a><span class='hs-comment'>--   let ps = reverse $ filter ((&lt;= d).hdate) $ filter ((s==).hsymbol) $ sortBy (comparing hdate) $ historical_prices j</span>
<a name="line-482"></a><span class='hs-comment'>--   case ps of (HistoricalPrice{hamount=a}:_) -&gt; Just a</span>
<a name="line-483"></a><span class='hs-comment'>--              _ -&gt; Nothing</span>
<a name="line-484"></a>
<a name="line-485"></a><a name="journalCloseTimeLogEntries"></a><span class='hs-comment'>-- | Close any open timelog sessions in this journal using the provided current time.</span>
<a name="line-486"></a><span class='hs-definition'>journalCloseTimeLogEntries</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>LocalTime</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Journal</span>
<a name="line-487"></a><span class='hs-definition'>journalCloseTimeLogEntries</span> <span class='hs-varid'>now</span> <span class='hs-varid'>j</span><span class='hs-keyglyph'>@</span><span class='hs-conid'>Journal</span><span class='hs-layout'>{</span><span class='hs-varid'>jtxns</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>ts</span><span class='hs-layout'>,</span> <span class='hs-varid'>open_timelog_entries</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>es</span><span class='hs-layout'>}</span> <span class='hs-keyglyph'>=</span>
<a name="line-488"></a>  <span class='hs-varid'>j</span><span class='hs-layout'>{</span><span class='hs-varid'>jtxns</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>ts</span> <span class='hs-varop'>++</span> <span class='hs-layout'>(</span><span class='hs-varid'>timeLogEntriesToTransactions</span> <span class='hs-varid'>now</span> <span class='hs-varid'>es</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <span class='hs-varid'>open_timelog_entries</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>[]</span><span class='hs-layout'>}</span>
<a name="line-489"></a>
<a name="line-490"></a><a name="journalConvertAmountsToCost"></a><span class='hs-comment'>-- | Convert all this journal's amounts to cost by applying their prices, if any.</span>
<a name="line-491"></a><span class='hs-definition'>journalConvertAmountsToCost</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Journal</span>
<a name="line-492"></a><span class='hs-definition'>journalConvertAmountsToCost</span> <span class='hs-varid'>j</span><span class='hs-keyglyph'>@</span><span class='hs-conid'>Journal</span><span class='hs-layout'>{</span><span class='hs-varid'>jtxns</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>ts</span><span class='hs-layout'>}</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>j</span><span class='hs-layout'>{</span><span class='hs-varid'>jtxns</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>map</span> <span class='hs-varid'>fixtransaction</span> <span class='hs-varid'>ts</span><span class='hs-layout'>}</span>
<a name="line-493"></a>    <span class='hs-keyword'>where</span>
<a name="line-494"></a>      <span class='hs-comment'>-- similar to journalCanonicaliseAmounts</span>
<a name="line-495"></a>      <span class='hs-varid'>fixtransaction</span> <span class='hs-varid'>t</span><span class='hs-keyglyph'>@</span><span class='hs-conid'>Transaction</span><span class='hs-layout'>{</span><span class='hs-varid'>tpostings</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>ps</span><span class='hs-layout'>}</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>t</span><span class='hs-layout'>{</span><span class='hs-varid'>tpostings</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>map</span> <span class='hs-varid'>fixposting</span> <span class='hs-varid'>ps</span><span class='hs-layout'>}</span>
<a name="line-496"></a>      <span class='hs-varid'>fixposting</span> <span class='hs-varid'>p</span><span class='hs-keyglyph'>@</span><span class='hs-conid'>Posting</span><span class='hs-layout'>{</span><span class='hs-varid'>pamount</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>a</span><span class='hs-layout'>}</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>p</span><span class='hs-layout'>{</span><span class='hs-varid'>pamount</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>fixmixedamount</span> <span class='hs-varid'>a</span><span class='hs-layout'>}</span>
<a name="line-497"></a>      <span class='hs-varid'>fixmixedamount</span> <span class='hs-layout'>(</span><span class='hs-conid'>Mixed</span> <span class='hs-keyword'>as</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Mixed</span> <span class='hs-varop'>$</span> <span class='hs-varid'>map</span> <span class='hs-varid'>fixamount</span> <span class='hs-keyword'>as</span>
<a name="line-498"></a>      <span class='hs-varid'>fixamount</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>canonicaliseAmount</span> <span class='hs-layout'>(</span><span class='hs-varid'>jcommoditystyles</span> <span class='hs-varid'>j</span><span class='hs-layout'>)</span> <span class='hs-varop'>.</span> <span class='hs-varid'>costOfAmount</span>
<a name="line-499"></a>
<a name="line-500"></a><span class='hs-comment'>-- -- | Get this journal's unique, display-preference-canonicalised commodities, by symbol.</span>
<a name="line-501"></a><span class='hs-comment'>-- journalCanonicalCommodities :: Journal -&gt; M.Map String Commodity</span>
<a name="line-502"></a><span class='hs-comment'>-- journalCanonicalCommodities j = canonicaliseCommodities $ journalAmountCommodities j</span>
<a name="line-503"></a>
<a name="line-504"></a><span class='hs-comment'>-- -- | Get all this journal's amounts' commodities, in the order parsed.</span>
<a name="line-505"></a><span class='hs-comment'>-- journalAmountCommodities :: Journal -&gt; [Commodity]</span>
<a name="line-506"></a><span class='hs-comment'>-- journalAmountCommodities = map acommodity . concatMap amounts . journalAmounts</span>
<a name="line-507"></a>
<a name="line-508"></a><span class='hs-comment'>-- -- | Get all this journal's amount and price commodities, in the order parsed.</span>
<a name="line-509"></a><span class='hs-comment'>-- journalAmountAndPriceCommodities :: Journal -&gt; [Commodity]</span>
<a name="line-510"></a><span class='hs-comment'>-- journalAmountAndPriceCommodities = concatMap amountCommodities . concatMap amounts . journalAmounts</span>
<a name="line-511"></a>
<a name="line-512"></a><span class='hs-comment'>-- -- | Get this amount's commodity and any commodities referenced in its price.</span>
<a name="line-513"></a><span class='hs-comment'>-- amountCommodities :: Amount -&gt; [Commodity]</span>
<a name="line-514"></a><span class='hs-comment'>-- amountCommodities Amount{acommodity=c,aprice=p} =</span>
<a name="line-515"></a><span class='hs-comment'>--     case p of Nothing -&gt; [c]</span>
<a name="line-516"></a><span class='hs-comment'>--               Just (UnitPrice ma)  -&gt; c:(concatMap amountCommodities $ amounts ma)</span>
<a name="line-517"></a><span class='hs-comment'>--               Just (TotalPrice ma) -&gt; c:(concatMap amountCommodities $ amounts ma)</span>
<a name="line-518"></a>
<a name="line-519"></a><a name="journalMixedAmounts"></a><span class='hs-comment'>-- | Get all this journal's (mixed) amounts, in the order parsed.</span>
<a name="line-520"></a><span class='hs-definition'>journalMixedAmounts</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>MixedAmount</span><span class='hs-keyglyph'>]</span>
<a name="line-521"></a><span class='hs-definition'>journalMixedAmounts</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>map</span> <span class='hs-varid'>pamount</span> <span class='hs-varop'>.</span> <span class='hs-varid'>journalPostings</span>
<a name="line-522"></a>
<a name="line-523"></a><a name="journalAmounts"></a><span class='hs-comment'>-- | Get all this journal's component amounts, roughly in the order parsed.</span>
<a name="line-524"></a><span class='hs-definition'>journalAmounts</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>Amount</span><span class='hs-keyglyph'>]</span>
<a name="line-525"></a><span class='hs-definition'>journalAmounts</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>concatMap</span> <span class='hs-varid'>flatten</span> <span class='hs-varop'>.</span> <span class='hs-varid'>journalMixedAmounts</span> <span class='hs-keyword'>where</span> <span class='hs-varid'>flatten</span> <span class='hs-layout'>(</span><span class='hs-conid'>Mixed</span> <span class='hs-keyword'>as</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>as</span>
<a name="line-526"></a>
<a name="line-527"></a><a name="journalDateSpan"></a><span class='hs-comment'>-- | The (fully specified) date span containing this journal's transactions,</span>
<a name="line-528"></a><span class='hs-comment'>-- or DateSpan Nothing Nothing if there are none.</span>
<a name="line-529"></a><span class='hs-definition'>journalDateSpan</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Journal</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>DateSpan</span>
<a name="line-530"></a><span class='hs-definition'>journalDateSpan</span> <span class='hs-varid'>j</span>
<a name="line-531"></a>    <span class='hs-keyglyph'>|</span> <span class='hs-varid'>null</span> <span class='hs-varid'>ts</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>DateSpan</span> <span class='hs-conid'>Nothing</span> <span class='hs-conid'>Nothing</span>
<a name="line-532"></a>    <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>DateSpan</span> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-varop'>$</span> <span class='hs-varid'>tdate</span> <span class='hs-varop'>$</span> <span class='hs-varid'>head</span> <span class='hs-varid'>ts</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-varop'>$</span> <span class='hs-varid'>addDays</span> <span class='hs-num'>1</span> <span class='hs-varop'>$</span> <span class='hs-varid'>tdate</span> <span class='hs-varop'>$</span> <span class='hs-varid'>last</span> <span class='hs-varid'>ts</span><span class='hs-layout'>)</span>
<a name="line-533"></a>    <span class='hs-keyword'>where</span>
<a name="line-534"></a>      <span class='hs-varid'>ts</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>sortBy</span> <span class='hs-layout'>(</span><span class='hs-varid'>comparing</span> <span class='hs-varid'>tdate</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span> <span class='hs-varid'>jtxns</span> <span class='hs-varid'>j</span>
<a name="line-535"></a>
<a name="line-536"></a><span class='hs-comment'>-- Misc helpers</span>
<a name="line-537"></a>
<a name="line-538"></a><a name="matchpats"></a><span class='hs-comment'>-- | Check if a set of hledger account/description filter patterns matches the</span>
<a name="line-539"></a><span class='hs-comment'>-- given account name or entry description.  Patterns are case-insensitive</span>
<a name="line-540"></a><span class='hs-comment'>-- regular expressions. Prefixed with not:, they become anti-patterns.</span>
<a name="line-541"></a><span class='hs-definition'>matchpats</span> <span class='hs-keyglyph'>::</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>String</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bool</span>
<a name="line-542"></a><span class='hs-definition'>matchpats</span> <span class='hs-varid'>pats</span> <span class='hs-varid'>str</span> <span class='hs-keyglyph'>=</span>
<a name="line-543"></a>    <span class='hs-layout'>(</span><span class='hs-varid'>null</span> <span class='hs-varid'>positives</span> <span class='hs-varop'>||</span> <span class='hs-varid'>any</span> <span class='hs-varid'>match</span> <span class='hs-varid'>positives</span><span class='hs-layout'>)</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-layout'>(</span><span class='hs-varid'>null</span> <span class='hs-varid'>negatives</span> <span class='hs-varop'>||</span> <span class='hs-varid'>not</span> <span class='hs-layout'>(</span><span class='hs-varid'>any</span> <span class='hs-varid'>match</span> <span class='hs-varid'>negatives</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-544"></a>    <span class='hs-keyword'>where</span>
<a name="line-545"></a>      <span class='hs-layout'>(</span><span class='hs-varid'>negatives</span><span class='hs-layout'>,</span><span class='hs-varid'>positives</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>partition</span> <span class='hs-varid'>isnegativepat</span> <span class='hs-varid'>pats</span>
<a name="line-546"></a>      <span class='hs-varid'>match</span> <span class='hs-str'>""</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>True</span>
<a name="line-547"></a>      <span class='hs-varid'>match</span> <span class='hs-varid'>pat</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>regexMatchesCI</span> <span class='hs-layout'>(</span><span class='hs-varid'>abspat</span> <span class='hs-varid'>pat</span><span class='hs-layout'>)</span> <span class='hs-varid'>str</span>
<a name="line-548"></a>
<a name="line-549"></a><a name="negateprefix"></a><span class='hs-definition'>negateprefix</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>"not:"</span>
<a name="line-550"></a>
<a name="line-551"></a><a name="isnegativepat"></a><span class='hs-definition'>isnegativepat</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>negateprefix</span> <span class='hs-varop'>`isPrefixOf`</span><span class='hs-layout'>)</span>
<a name="line-552"></a>
<a name="line-553"></a><a name="abspat"></a><span class='hs-definition'>abspat</span> <span class='hs-varid'>pat</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>if</span> <span class='hs-varid'>isnegativepat</span> <span class='hs-varid'>pat</span> <span class='hs-keyword'>then</span> <span class='hs-varid'>drop</span> <span class='hs-layout'>(</span><span class='hs-varid'>length</span> <span class='hs-varid'>negateprefix</span><span class='hs-layout'>)</span> <span class='hs-varid'>pat</span> <span class='hs-keyword'>else</span> <span class='hs-varid'>pat</span>
<a name="line-554"></a>
<a name="line-555"></a><span class='hs-comment'>-- debug helpers</span>
<a name="line-556"></a><span class='hs-comment'>-- traceAmountPrecision a = trace (show $ map (precision . acommodity) $ amounts a) a</span>
<a name="line-557"></a><span class='hs-comment'>-- tracePostingsCommodities ps = trace (show $ map ((map (precision . acommodity) . amounts) . pamount) ps) ps</span>
<a name="line-558"></a>
<a name="line-559"></a><span class='hs-comment'>-- tests</span>
<a name="line-560"></a>
<a name="line-561"></a><span class='hs-comment'>-- A sample journal for testing, similar to data/sample.journal:</span>
<a name="line-562"></a><span class='hs-comment'>--</span>
<a name="line-563"></a><span class='hs-comment'>-- 2008/01/01 income</span>
<a name="line-564"></a><span class='hs-comment'>--     assets:bank:checking  $1</span>
<a name="line-565"></a><span class='hs-comment'>--     income:salary</span>
<a name="line-566"></a><span class='hs-comment'>--</span>
<a name="line-567"></a><span class='hs-comment'>-- 2008/06/01 gift</span>
<a name="line-568"></a><span class='hs-comment'>--     assets:bank:checking  $1</span>
<a name="line-569"></a><span class='hs-comment'>--     income:gifts</span>
<a name="line-570"></a><span class='hs-comment'>--</span>
<a name="line-571"></a><span class='hs-comment'>-- 2008/06/02 save</span>
<a name="line-572"></a><span class='hs-comment'>--     assets:bank:saving  $1</span>
<a name="line-573"></a><span class='hs-comment'>--     assets:bank:checking</span>
<a name="line-574"></a><span class='hs-comment'>--</span>
<a name="line-575"></a><span class='hs-comment'>-- 2008/06/03 * eat &amp; shop</span>
<a name="line-576"></a><span class='hs-comment'>--     expenses:food      $1</span>
<a name="line-577"></a><span class='hs-comment'>--     expenses:supplies  $1</span>
<a name="line-578"></a><span class='hs-comment'>--     assets:cash</span>
<a name="line-579"></a><span class='hs-comment'>--</span>
<a name="line-580"></a><span class='hs-comment'>-- 2008/12/31 * pay off</span>
<a name="line-581"></a><span class='hs-comment'>--     liabilities:debts  $1</span>
<a name="line-582"></a><span class='hs-comment'>--     assets:bank:checking</span>
<a name="line-583"></a><span class='hs-comment'>--</span>
<a name="line-584"></a><span class='hs-conid'>Right</span> <span class='hs-varid'>samplejournal</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>journalBalanceTransactions</span> <span class='hs-varop'>$</span> 
<a name="line-585"></a>         <span class='hs-varid'>nulljournal</span>
<a name="line-586"></a>         <span class='hs-layout'>{</span><span class='hs-varid'>jtxns</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyglyph'>[</span>
<a name="line-587"></a>           <span class='hs-varid'>txnTieKnot</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Transaction</span> <span class='hs-layout'>{</span>
<a name="line-588"></a>             <span class='hs-varid'>tdate</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>parsedate</span> <span class='hs-str'>"2008/01/01"</span><span class='hs-layout'>,</span>
<a name="line-589"></a>             <span class='hs-varid'>tdate2</span><span class='hs-keyglyph'>=</span><span class='hs-conid'>Nothing</span><span class='hs-layout'>,</span>
<a name="line-590"></a>             <span class='hs-varid'>tstatus</span><span class='hs-keyglyph'>=</span><span class='hs-conid'>False</span><span class='hs-layout'>,</span>
<a name="line-591"></a>             <span class='hs-varid'>tcode</span><span class='hs-keyglyph'>=</span><span class='hs-str'>""</span><span class='hs-layout'>,</span>
<a name="line-592"></a>             <span class='hs-varid'>tdescription</span><span class='hs-keyglyph'>=</span><span class='hs-str'>"income"</span><span class='hs-layout'>,</span>
<a name="line-593"></a>             <span class='hs-varid'>tcomment</span><span class='hs-keyglyph'>=</span><span class='hs-str'>""</span><span class='hs-layout'>,</span>
<a name="line-594"></a>             <span class='hs-varid'>ttags</span><span class='hs-keyglyph'>=</span><span class='hs-conid'>[]</span><span class='hs-layout'>,</span>
<a name="line-595"></a>             <span class='hs-varid'>tpostings</span><span class='hs-keyglyph'>=</span>
<a name="line-596"></a>                 <span class='hs-keyglyph'>[</span><span class='hs-str'>"assets:bank:checking"</span> <span class='hs-varop'>`post`</span> <span class='hs-varid'>usd</span> <span class='hs-num'>1</span>
<a name="line-597"></a>                 <span class='hs-layout'>,</span><span class='hs-str'>"income:salary"</span> <span class='hs-varop'>`post`</span> <span class='hs-varid'>missingamt</span>
<a name="line-598"></a>                 <span class='hs-keyglyph'>]</span><span class='hs-layout'>,</span>
<a name="line-599"></a>             <span class='hs-varid'>tpreceding_comment_lines</span><span class='hs-keyglyph'>=</span><span class='hs-str'>""</span>
<a name="line-600"></a>           <span class='hs-layout'>}</span>
<a name="line-601"></a>          <span class='hs-layout'>,</span>
<a name="line-602"></a>           <span class='hs-varid'>txnTieKnot</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Transaction</span> <span class='hs-layout'>{</span>
<a name="line-603"></a>             <span class='hs-varid'>tdate</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>parsedate</span> <span class='hs-str'>"2008/06/01"</span><span class='hs-layout'>,</span>
<a name="line-604"></a>             <span class='hs-varid'>tdate2</span><span class='hs-keyglyph'>=</span><span class='hs-conid'>Nothing</span><span class='hs-layout'>,</span>
<a name="line-605"></a>             <span class='hs-varid'>tstatus</span><span class='hs-keyglyph'>=</span><span class='hs-conid'>False</span><span class='hs-layout'>,</span>
<a name="line-606"></a>             <span class='hs-varid'>tcode</span><span class='hs-keyglyph'>=</span><span class='hs-str'>""</span><span class='hs-layout'>,</span>
<a name="line-607"></a>             <span class='hs-varid'>tdescription</span><span class='hs-keyglyph'>=</span><span class='hs-str'>"gift"</span><span class='hs-layout'>,</span>
<a name="line-608"></a>             <span class='hs-varid'>tcomment</span><span class='hs-keyglyph'>=</span><span class='hs-str'>""</span><span class='hs-layout'>,</span>
<a name="line-609"></a>             <span class='hs-varid'>ttags</span><span class='hs-keyglyph'>=</span><span class='hs-conid'>[]</span><span class='hs-layout'>,</span>
<a name="line-610"></a>             <span class='hs-varid'>tpostings</span><span class='hs-keyglyph'>=</span>
<a name="line-611"></a>                 <span class='hs-keyglyph'>[</span><span class='hs-str'>"assets:bank:checking"</span> <span class='hs-varop'>`post`</span> <span class='hs-varid'>usd</span> <span class='hs-num'>1</span>
<a name="line-612"></a>                 <span class='hs-layout'>,</span><span class='hs-str'>"income:gifts"</span> <span class='hs-varop'>`post`</span> <span class='hs-varid'>missingamt</span>
<a name="line-613"></a>                 <span class='hs-keyglyph'>]</span><span class='hs-layout'>,</span>
<a name="line-614"></a>             <span class='hs-varid'>tpreceding_comment_lines</span><span class='hs-keyglyph'>=</span><span class='hs-str'>""</span>
<a name="line-615"></a>           <span class='hs-layout'>}</span>
<a name="line-616"></a>          <span class='hs-layout'>,</span>
<a name="line-617"></a>           <span class='hs-varid'>txnTieKnot</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Transaction</span> <span class='hs-layout'>{</span>
<a name="line-618"></a>             <span class='hs-varid'>tdate</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>parsedate</span> <span class='hs-str'>"2008/06/02"</span><span class='hs-layout'>,</span>
<a name="line-619"></a>             <span class='hs-varid'>tdate2</span><span class='hs-keyglyph'>=</span><span class='hs-conid'>Nothing</span><span class='hs-layout'>,</span>
<a name="line-620"></a>             <span class='hs-varid'>tstatus</span><span class='hs-keyglyph'>=</span><span class='hs-conid'>False</span><span class='hs-layout'>,</span>
<a name="line-621"></a>             <span class='hs-varid'>tcode</span><span class='hs-keyglyph'>=</span><span class='hs-str'>""</span><span class='hs-layout'>,</span>
<a name="line-622"></a>             <span class='hs-varid'>tdescription</span><span class='hs-keyglyph'>=</span><span class='hs-str'>"save"</span><span class='hs-layout'>,</span>
<a name="line-623"></a>             <span class='hs-varid'>tcomment</span><span class='hs-keyglyph'>=</span><span class='hs-str'>""</span><span class='hs-layout'>,</span>
<a name="line-624"></a>             <span class='hs-varid'>ttags</span><span class='hs-keyglyph'>=</span><span class='hs-conid'>[]</span><span class='hs-layout'>,</span>
<a name="line-625"></a>             <span class='hs-varid'>tpostings</span><span class='hs-keyglyph'>=</span>
<a name="line-626"></a>                 <span class='hs-keyglyph'>[</span><span class='hs-str'>"assets:bank:saving"</span> <span class='hs-varop'>`post`</span> <span class='hs-varid'>usd</span> <span class='hs-num'>1</span>
<a name="line-627"></a>                 <span class='hs-layout'>,</span><span class='hs-str'>"assets:bank:checking"</span> <span class='hs-varop'>`post`</span> <span class='hs-varid'>usd</span> <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-num'>1</span><span class='hs-layout'>)</span>
<a name="line-628"></a>                 <span class='hs-keyglyph'>]</span><span class='hs-layout'>,</span>
<a name="line-629"></a>             <span class='hs-varid'>tpreceding_comment_lines</span><span class='hs-keyglyph'>=</span><span class='hs-str'>""</span>
<a name="line-630"></a>           <span class='hs-layout'>}</span>
<a name="line-631"></a>          <span class='hs-layout'>,</span>
<a name="line-632"></a>           <span class='hs-varid'>txnTieKnot</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Transaction</span> <span class='hs-layout'>{</span>
<a name="line-633"></a>             <span class='hs-varid'>tdate</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>parsedate</span> <span class='hs-str'>"2008/06/03"</span><span class='hs-layout'>,</span>
<a name="line-634"></a>             <span class='hs-varid'>tdate2</span><span class='hs-keyglyph'>=</span><span class='hs-conid'>Nothing</span><span class='hs-layout'>,</span>
<a name="line-635"></a>             <span class='hs-varid'>tstatus</span><span class='hs-keyglyph'>=</span><span class='hs-conid'>True</span><span class='hs-layout'>,</span>
<a name="line-636"></a>             <span class='hs-varid'>tcode</span><span class='hs-keyglyph'>=</span><span class='hs-str'>""</span><span class='hs-layout'>,</span>
<a name="line-637"></a>             <span class='hs-varid'>tdescription</span><span class='hs-keyglyph'>=</span><span class='hs-str'>"eat &amp; shop"</span><span class='hs-layout'>,</span>
<a name="line-638"></a>             <span class='hs-varid'>tcomment</span><span class='hs-keyglyph'>=</span><span class='hs-str'>""</span><span class='hs-layout'>,</span>
<a name="line-639"></a>             <span class='hs-varid'>ttags</span><span class='hs-keyglyph'>=</span><span class='hs-conid'>[]</span><span class='hs-layout'>,</span>
<a name="line-640"></a>             <span class='hs-varid'>tpostings</span><span class='hs-keyglyph'>=</span><span class='hs-keyglyph'>[</span><span class='hs-str'>"expenses:food"</span> <span class='hs-varop'>`post`</span> <span class='hs-varid'>usd</span> <span class='hs-num'>1</span>
<a name="line-641"></a>                       <span class='hs-layout'>,</span><span class='hs-str'>"expenses:supplies"</span> <span class='hs-varop'>`post`</span> <span class='hs-varid'>usd</span> <span class='hs-num'>1</span>
<a name="line-642"></a>                       <span class='hs-layout'>,</span><span class='hs-str'>"assets:cash"</span> <span class='hs-varop'>`post`</span> <span class='hs-varid'>missingamt</span>
<a name="line-643"></a>                       <span class='hs-keyglyph'>]</span><span class='hs-layout'>,</span>
<a name="line-644"></a>             <span class='hs-varid'>tpreceding_comment_lines</span><span class='hs-keyglyph'>=</span><span class='hs-str'>""</span>
<a name="line-645"></a>           <span class='hs-layout'>}</span>
<a name="line-646"></a>          <span class='hs-layout'>,</span>
<a name="line-647"></a>           <span class='hs-varid'>txnTieKnot</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Transaction</span> <span class='hs-layout'>{</span>
<a name="line-648"></a>             <span class='hs-varid'>tdate</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>parsedate</span> <span class='hs-str'>"2008/12/31"</span><span class='hs-layout'>,</span>
<a name="line-649"></a>             <span class='hs-varid'>tdate2</span><span class='hs-keyglyph'>=</span><span class='hs-conid'>Nothing</span><span class='hs-layout'>,</span>
<a name="line-650"></a>             <span class='hs-varid'>tstatus</span><span class='hs-keyglyph'>=</span><span class='hs-conid'>False</span><span class='hs-layout'>,</span>
<a name="line-651"></a>             <span class='hs-varid'>tcode</span><span class='hs-keyglyph'>=</span><span class='hs-str'>""</span><span class='hs-layout'>,</span>
<a name="line-652"></a>             <span class='hs-varid'>tdescription</span><span class='hs-keyglyph'>=</span><span class='hs-str'>"pay off"</span><span class='hs-layout'>,</span>
<a name="line-653"></a>             <span class='hs-varid'>tcomment</span><span class='hs-keyglyph'>=</span><span class='hs-str'>""</span><span class='hs-layout'>,</span>
<a name="line-654"></a>             <span class='hs-varid'>ttags</span><span class='hs-keyglyph'>=</span><span class='hs-conid'>[]</span><span class='hs-layout'>,</span>
<a name="line-655"></a>             <span class='hs-varid'>tpostings</span><span class='hs-keyglyph'>=</span><span class='hs-keyglyph'>[</span><span class='hs-str'>"liabilities:debts"</span> <span class='hs-varop'>`post`</span> <span class='hs-varid'>usd</span> <span class='hs-num'>1</span>
<a name="line-656"></a>                       <span class='hs-layout'>,</span><span class='hs-str'>"assets:bank:checking"</span> <span class='hs-varop'>`post`</span> <span class='hs-varid'>usd</span> <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-num'>1</span><span class='hs-layout'>)</span>
<a name="line-657"></a>                       <span class='hs-keyglyph'>]</span><span class='hs-layout'>,</span>
<a name="line-658"></a>             <span class='hs-varid'>tpreceding_comment_lines</span><span class='hs-keyglyph'>=</span><span class='hs-str'>""</span>
<a name="line-659"></a>           <span class='hs-layout'>}</span>
<a name="line-660"></a>          <span class='hs-keyglyph'>]</span>
<a name="line-661"></a>         <span class='hs-layout'>}</span>
<a name="line-662"></a>
<a name="line-663"></a><a name="tests_Hledger_Data_Journal"></a><span class='hs-definition'>tests_Hledger_Data_Journal</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>TestList</span> <span class='hs-varop'>$</span>
<a name="line-664"></a> <span class='hs-keyglyph'>[</span>
<a name="line-665"></a>  <span class='hs-comment'>-- "query standard account types" ~:</span>
<a name="line-666"></a>  <span class='hs-comment'>--  do</span>
<a name="line-667"></a>  <span class='hs-comment'>--   let j = journal1</span>
<a name="line-668"></a>  <span class='hs-comment'>--   journalBalanceSheetAccountNames j `is` ["assets","assets:a","equity","equity:q","equity:q:qq","liabilities","liabilities:l"]</span>
<a name="line-669"></a>  <span class='hs-comment'>--   journalProfitAndLossAccountNames j `is` ["expenses","expenses:e","income","income:i"]</span>
<a name="line-670"></a> <span class='hs-keyglyph'>]</span>
</pre></body>
</html>