View Javadoc
1   /*
2    * MoneyWise: Finance Application
3    * Copyright 2012-2026. Tony Washer
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6    * use this file except in compliance with the License.  You may obtain a copy
7    * of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
14   * License for the specific language governing permissions and limitations under
15   * the License.
16   */
17  package io.github.tonywasher.joceanus.moneywise.quicken.file;
18  
19  import io.github.tonywasher.joceanus.oceanus.date.OceanusDate;
20  import io.github.tonywasher.joceanus.oceanus.date.OceanusDateFormatter;
21  import io.github.tonywasher.joceanus.oceanus.decimal.OceanusDecimalParser;
22  import io.github.tonywasher.joceanus.oceanus.decimal.OceanusMoney;
23  import io.github.tonywasher.joceanus.oceanus.decimal.OceanusRate;
24  import io.github.tonywasher.joceanus.oceanus.format.OceanusDataFormatter;
25  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransaction;
26  import io.github.tonywasher.joceanus.moneywise.quicken.definitions.MoneyWiseQEventLineType;
27  import io.github.tonywasher.joceanus.moneywise.quicken.file.MoneyWiseQIFLine.MoneyWiseQIFCategoryLine;
28  import io.github.tonywasher.joceanus.moneywise.quicken.file.MoneyWiseQIFLine.MoneyWiseQIFClearedLine;
29  import io.github.tonywasher.joceanus.moneywise.quicken.file.MoneyWiseQIFLine.MoneyWiseQIFDateLine;
30  import io.github.tonywasher.joceanus.moneywise.quicken.file.MoneyWiseQIFLine.MoneyWiseQIFMoneyLine;
31  import io.github.tonywasher.joceanus.moneywise.quicken.file.MoneyWiseQIFLine.MoneyWiseQIFPayeeLine;
32  import io.github.tonywasher.joceanus.moneywise.quicken.file.MoneyWiseQIFLine.MoneyWiseQIFStringLine;
33  import io.github.tonywasher.joceanus.moneywise.quicken.file.MoneyWiseQIFLine.MoneyWiseQIFXferAccountLine;
34  
35  import java.util.List;
36  import java.util.Objects;
37  
38  /**
39   * Class representing a QIF Event record.
40   */
41  public class MoneyWiseQIFEvent
42          extends MoneyWiseQIFEventRecord<MoneyWiseQEventLineType> {
43      /**
44       * The Date.
45       */
46      private final OceanusDate theDate;
47  
48      /**
49       * The Cleared Flag.
50       */
51      private final Boolean isCleared;
52  
53      /**
54       * Constructor.
55       *
56       * @param pFile  the QIF File
57       * @param pTrans the transaction
58       */
59      protected MoneyWiseQIFEvent(final MoneyWiseQIFFile pFile,
60                                  final MoneyWiseTransaction pTrans) {
61          /* Call super-constructor */
62          super(pFile, MoneyWiseQEventLineType.class);
63  
64          /* Store values */
65          theDate = pTrans.getDate();
66          isCleared = pTrans.isReconciled();
67  
68          /* Add the lines */
69          addLine(new MoneyWiseQIFEventDateLine(theDate));
70          addLine(new MoneyWiseQIFEventClearedLine(isCleared));
71  
72          /* Add the reference line if it exists */
73          final String myRef = pTrans.getReference();
74          if (myRef != null) {
75              recordReference(myRef);
76          }
77  
78          /* Add the comment line if it exists */
79          final String myComment = pTrans.getComments();
80          if (myComment != null) {
81              recordComment(myComment);
82          }
83      }
84  
85      /**
86       * Constructor for opening balance.
87       *
88       * @param pFile      the QIF File
89       * @param pStartDate the start date
90       */
91      protected MoneyWiseQIFEvent(final MoneyWiseQIFFile pFile,
92                                  final OceanusDate pStartDate) {
93          /* Call super-constructor */
94          super(pFile, MoneyWiseQEventLineType.class);
95  
96          /* Store values */
97          theDate = pStartDate;
98          isCleared = true;
99  
100         /* Add the lines */
101         addLine(new MoneyWiseQIFEventDateLine(theDate));
102         addLine(new MoneyWiseQIFEventClearedLine(isCleared));
103         addLine(new MoneyWiseQIFEventPayeeDescLine("Opening Balance"));
104     }
105 
106     /**
107      * Constructor.
108      *
109      * @param pFile      the QIF File
110      * @param pFormatter the Data Formatter
111      * @param pLines     the data lines
112      */
113     protected MoneyWiseQIFEvent(final MoneyWiseQIFFile pFile,
114                                 final OceanusDataFormatter pFormatter,
115                                 final List<String> pLines) {
116         /* Call super-constructor */
117         super(pFile, MoneyWiseQEventLineType.class);
118 
119         /* Determine details */
120         OceanusDate myDate = null;
121         Boolean myCleared = null;
122 
123         /* Current split record */
124         MoneyWiseQIFSplitEvent mySplit = null;
125 
126         /* Obtain parsers */
127         final OceanusDateFormatter myDateParser = pFormatter.getDateFormatter();
128         final OceanusDecimalParser myDecParser = pFormatter.getDecimalParser();
129 
130         /* Loop through the lines */
131         for (String myLine : pLines) {
132             /* Determine the category */
133             final MoneyWiseQEventLineType myType = MoneyWiseQEventLineType.parseLine(myLine);
134             if (myType != null) {
135                 /* Access data */
136                 final String myData = myLine.substring(myType.getSymbol().length());
137 
138                 /* Switch on line type */
139                 switch (myType) {
140                     case DATE:
141                         final OceanusDate myDateDay = myDateParser.parseDateBase(myData, MoneyWiseQIFWriter.QIF_BASEYEAR);
142                         addLine(new MoneyWiseQIFEventDateLine(myDateDay));
143                         myDate = myDateDay;
144                         break;
145                     case CLEARED:
146                         final Boolean myFlag = myData.equals(MoneyWiseQIFLine.QIF_RECONCILED);
147                         addLine(new MoneyWiseQIFEventClearedLine(myFlag));
148                         myCleared = myFlag;
149                         break;
150                     case AMOUNT:
151                         OceanusMoney myMoney = myDecParser.parseMoneyValue(myData);
152                         addLine(new MoneyWiseQIFEventAmountLine(myMoney));
153                         break;
154                     case COMMENT:
155                         addLine(new MoneyWiseQIFEventCommentLine(myData));
156                         break;
157                     case REFERENCE:
158                         addLine(new MoneyWiseQIFEventReferenceLine(myData));
159                         break;
160                     case PAYEE:
161                         addLine(new MoneyWiseQIFEventPayeeDescLine(myData));
162                         break;
163                     case CATEGORY:
164                         /* Check for account and category */
165                         MoneyWiseQIFAccount myAccount = MoneyWiseQIFXferAccountLine.parseAccount(pFile, myData);
166                         MoneyWiseQIFEventCategory myCategory = MoneyWiseQIFCategoryLine.parseCategory(pFile, myData);
167                         if (myAccount != null) {
168                             /* Look for account classes */
169                             final List<MoneyWiseQIFClass> myClasses = MoneyWiseQIFXferAccountLine.parseAccountClasses(pFile, myData);
170                             addLine(new MoneyWiseQIFEventAccountLine(myAccount, myClasses));
171                         } else {
172                             /* Look for category classes */
173                             final List<MoneyWiseQIFClass> myClasses = MoneyWiseQIFCategoryLine.parseCategoryClasses(pFile, myData);
174                             addLine(new MoneyWiseQIFEventCategoryLine(myCategory, myClasses));
175                             convertPayee();
176                         }
177                         break;
178                     case SPLITCATEGORY:
179                         /* Check for account */
180                         myAccount = MoneyWiseQIFXferAccountLine.parseAccount(pFile, myData);
181                         myCategory = MoneyWiseQIFCategoryLine.parseCategory(pFile, myData);
182                         if (myAccount != null) {
183                             /* Look for account classes */
184                             final List<MoneyWiseQIFClass> myClasses = MoneyWiseQIFXferAccountLine.parseAccountClasses(pFile, myData);
185                             mySplit = new MoneyWiseQIFSplitEvent(pFile, myAccount, myClasses);
186                         } else {
187                             /* Look for category classes */
188                             final List<MoneyWiseQIFClass> myClasses = MoneyWiseQIFCategoryLine.parseCategoryClasses(pFile, myData);
189                             mySplit = new MoneyWiseQIFSplitEvent(pFile, myCategory, myClasses);
190                             convertPayee();
191                         }
192 
193                         /* Record new split record */
194                         addRecord(mySplit);
195                         break;
196                     case SPLITAMOUNT:
197                         myMoney = myDecParser.parseMoneyValue(myData);
198                         Objects.requireNonNull(mySplit).setSplitAmount(myMoney);
199                         break;
200                     case SPLITPERCENT:
201                         final OceanusRate myRate = myDecParser.parseRateValue(myData);
202                         Objects.requireNonNull(mySplit).setSplitPercentage(myRate);
203                         break;
204                     case SPLITCOMMENT:
205                         Objects.requireNonNull(mySplit).setSplitComment(myData);
206                         break;
207                     default:
208                         break;
209                 }
210             }
211         }
212 
213         /* Build details */
214         theDate = myDate;
215         isCleared = myCleared;
216     }
217 
218     @Override
219     public OceanusDate getDate() {
220         return theDate;
221     }
222 
223     @Override
224     public Boolean isCleared() {
225         return isCleared;
226     }
227 
228     /**
229      * record reference.
230      *
231      * @param pReference the reference
232      */
233     private void recordReference(final String pReference) {
234         /* Add reference line */
235         addLine(new MoneyWiseQIFEventReferenceLine(pReference));
236     }
237 
238     /**
239      * record comment.
240      *
241      * @param pComment the comment
242      */
243     private void recordComment(final String pComment) {
244         /* Add comment line */
245         addLine(new MoneyWiseQIFEventCommentLine(pComment));
246     }
247 
248     /**
249      * record payee.
250      *
251      * @param pPayee the payee
252      */
253     protected void recordPayee(final MoneyWiseQIFPayee pPayee) {
254         /* Add payee line */
255         addLine(new MoneyWiseQIFEventPayeeLine(pPayee));
256     }
257 
258     /**
259      * record payee description.
260      *
261      * @param pPayeeDesc the payee description
262      */
263     protected void recordPayee(final String pPayeeDesc) {
264         /* Add payee line */
265         addLine(new MoneyWiseQIFEventPayeeDescLine(pPayeeDesc));
266     }
267 
268     /**
269      * record amount.
270      *
271      * @param pAmount the amount
272      */
273     protected void recordAmount(final OceanusMoney pAmount) {
274         /* Add amount line */
275         addLine(new MoneyWiseQIFEventAmountLine(pAmount));
276     }
277 
278     /**
279      * record transfer account.
280      *
281      * @param pAccount the account
282      */
283     protected void recordAccount(final MoneyWiseQIFAccount pAccount) {
284         /* Add account line */
285         addLine(new MoneyWiseQIFEventAccountLine(pAccount));
286     }
287 
288     /**
289      * record transfer account.
290      *
291      * @param pAccount the account
292      * @param pClasses the classes
293      */
294     protected void recordAccount(final MoneyWiseQIFAccount pAccount,
295                                  final List<MoneyWiseQIFClass> pClasses) {
296         /* Add account line */
297         addLine(new MoneyWiseQIFEventAccountLine(pAccount, pClasses));
298     }
299 
300     /**
301      * record category.
302      *
303      * @param pCategory the category
304      */
305     protected void recordCategory(final MoneyWiseQIFEventCategory pCategory) {
306         /* Add category line */
307         addLine(new MoneyWiseQIFEventCategoryLine(pCategory));
308     }
309 
310     /**
311      * record category.
312      *
313      * @param pCategory the category
314      * @param pClasses  the classes
315      */
316     protected void recordCategory(final MoneyWiseQIFEventCategory pCategory,
317                                   final List<MoneyWiseQIFClass> pClasses) {
318         /* Add category line */
319         addLine(new MoneyWiseQIFEventCategoryLine(pCategory, pClasses));
320     }
321 
322     /**
323      * record new Split record for transfer.
324      *
325      * @param pAccount the account
326      * @param pAmount  the amount
327      * @param pComment the comment
328      */
329     protected void recordSplitRecord(final MoneyWiseQIFAccount pAccount,
330                                      final OceanusMoney pAmount,
331                                      final String pComment) {
332         /* Create new split and add it */
333         final MoneyWiseQIFSplitEvent mySplit = new MoneyWiseQIFSplitEvent(getFile(), pAccount);
334         mySplit.setSplitAmount(pAmount);
335         if (pComment != null) {
336             mySplit.setSplitComment(pComment);
337         }
338         addRecord(mySplit);
339     }
340 
341     /**
342      * record new Split record for transfer.
343      *
344      * @param pAccount the account
345      * @param pClasses the classes
346      * @param pAmount  the amount
347      * @param pComment the comment
348      */
349     protected void recordSplitRecord(final MoneyWiseQIFAccount pAccount,
350                                      final List<MoneyWiseQIFClass> pClasses,
351                                      final OceanusMoney pAmount,
352                                      final String pComment) {
353         /* Create new split and add it */
354         final MoneyWiseQIFSplitEvent mySplit = new MoneyWiseQIFSplitEvent(getFile(), pAccount, pClasses);
355         mySplit.setSplitAmount(pAmount);
356         if (pComment != null) {
357             mySplit.setSplitComment(pComment);
358         }
359         addRecord(mySplit);
360     }
361 
362     /**
363      * record new Split record for category.
364      *
365      * @param pCategory the category
366      * @param pAmount   the amount
367      * @param pComment  the comment
368      */
369     protected void recordSplitRecord(final MoneyWiseQIFEventCategory pCategory,
370                                      final OceanusMoney pAmount,
371                                      final String pComment) {
372         /* Create new split and add it */
373         final MoneyWiseQIFSplitEvent mySplit = new MoneyWiseQIFSplitEvent(getFile(), pCategory);
374         mySplit.setSplitAmount(pAmount);
375         if (pComment != null) {
376             mySplit.setSplitComment(pComment);
377         }
378         addRecord(mySplit);
379     }
380 
381     /**
382      * record new Split record for category.
383      *
384      * @param pCategory the category
385      * @param pClasses  the classes
386      * @param pAmount   the amount
387      * @param pComment  the comment
388      */
389     protected void recordSplitRecord(final MoneyWiseQIFEventCategory pCategory,
390                                      final List<MoneyWiseQIFClass> pClasses,
391                                      final OceanusMoney pAmount,
392                                      final String pComment) {
393         /* Create new split and add it */
394         final MoneyWiseQIFSplitEvent mySplit = new MoneyWiseQIFSplitEvent(getFile(), pCategory, pClasses);
395         mySplit.setSplitAmount(pAmount);
396         if (pComment != null) {
397             mySplit.setSplitComment(pComment);
398         }
399         addRecord(mySplit);
400     }
401 
402     /**
403      * Convert Payee.
404      */
405     private void convertPayee() {
406         /* Look for a payee line */
407         final MoneyWiseQIFLine<MoneyWiseQEventLineType> myLine = getLine(MoneyWiseQEventLineType.PAYEE);
408         if (myLine instanceof MoneyWiseQIFEventPayeeDescLine myDesc) {
409             /* Access payee */
410             final String myName = myDesc.getValue();
411 
412             /* Register the payee */
413             final MoneyWiseQIFPayee myPayee = getFile().registerPayee(myName);
414             addLine(new MoneyWiseQIFEventPayeeLine(myPayee));
415         }
416     }
417 
418     /**
419      * The Event Date line.
420      */
421     public static class MoneyWiseQIFEventDateLine
422             extends MoneyWiseQIFDateLine<MoneyWiseQEventLineType> {
423         /**
424          * Constructor.
425          *
426          * @param pDate the Date
427          */
428         protected MoneyWiseQIFEventDateLine(final OceanusDate pDate) {
429             /* Call super-constructor */
430             super(pDate);
431         }
432 
433         @Override
434         public MoneyWiseQEventLineType getLineType() {
435             return MoneyWiseQEventLineType.DATE;
436         }
437     }
438 
439     /**
440      * The Event Reference line.
441      */
442     public static class MoneyWiseQIFEventReferenceLine
443             extends MoneyWiseQIFStringLine<MoneyWiseQEventLineType> {
444         /**
445          * Constructor.
446          *
447          * @param pRef the Reference
448          */
449         protected MoneyWiseQIFEventReferenceLine(final String pRef) {
450             /* Call super-constructor */
451             super(pRef);
452         }
453 
454         @Override
455         public MoneyWiseQEventLineType getLineType() {
456             return MoneyWiseQEventLineType.REFERENCE;
457         }
458 
459         /**
460          * Obtain Reference.
461          *
462          * @return the reference
463          */
464         public String getReference() {
465             return getValue();
466         }
467     }
468 
469     /**
470      * The Event Comment line.
471      */
472     public static class MoneyWiseQIFEventCommentLine
473             extends MoneyWiseQIFStringLine<MoneyWiseQEventLineType> {
474         /**
475          * Constructor.
476          *
477          * @param pComment the comment
478          */
479         protected MoneyWiseQIFEventCommentLine(final String pComment) {
480             /* Call super-constructor */
481             super(pComment);
482         }
483 
484         @Override
485         public MoneyWiseQEventLineType getLineType() {
486             return MoneyWiseQEventLineType.COMMENT;
487         }
488 
489         /**
490          * Obtain Comment.
491          *
492          * @return the comment
493          */
494         public String getComment() {
495             return getValue();
496         }
497     }
498 
499     /**
500      * The Event Cleared line.
501      */
502     public static class MoneyWiseQIFEventClearedLine
503             extends MoneyWiseQIFClearedLine<MoneyWiseQEventLineType> {
504         /**
505          * Constructor.
506          *
507          * @param pCleared is the event cleared?
508          */
509         protected MoneyWiseQIFEventClearedLine(final Boolean pCleared) {
510             /* Call super-constructor */
511             super(pCleared);
512         }
513 
514         @Override
515         public MoneyWiseQEventLineType getLineType() {
516             return MoneyWiseQEventLineType.CLEARED;
517         }
518     }
519 
520     /**
521      * The Event Payee Account line.
522      */
523     public static class MoneyWiseQIFEventPayeeLine
524             extends MoneyWiseQIFPayeeLine<MoneyWiseQEventLineType> {
525         /**
526          * Constructor.
527          *
528          * @param pPayee the payee
529          */
530         protected MoneyWiseQIFEventPayeeLine(final MoneyWiseQIFPayee pPayee) {
531             /* Call super-constructor */
532             super(pPayee);
533         }
534 
535         @Override
536         public MoneyWiseQEventLineType getLineType() {
537             return MoneyWiseQEventLineType.PAYEE;
538         }
539     }
540 
541     /**
542      * The Event Payee Description line.
543      */
544     public static class MoneyWiseQIFEventPayeeDescLine
545             extends MoneyWiseQIFStringLine<MoneyWiseQEventLineType> {
546         /**
547          * Constructor.
548          *
549          * @param pPayee the payee description
550          */
551         protected MoneyWiseQIFEventPayeeDescLine(final String pPayee) {
552             /* Call super-constructor */
553             super(pPayee);
554         }
555 
556         @Override
557         public MoneyWiseQEventLineType getLineType() {
558             return MoneyWiseQEventLineType.PAYEE;
559         }
560     }
561 
562     /**
563      * The Event Amount line.
564      */
565     public static class MoneyWiseQIFEventAmountLine
566             extends MoneyWiseQIFMoneyLine<MoneyWiseQEventLineType> {
567         /**
568          * Constructor.
569          *
570          * @param pAmount the amount
571          */
572         protected MoneyWiseQIFEventAmountLine(final OceanusMoney pAmount) {
573             /* Call super-constructor */
574             super(pAmount);
575         }
576 
577         @Override
578         public MoneyWiseQEventLineType getLineType() {
579             return MoneyWiseQEventLineType.AMOUNT;
580         }
581 
582         /**
583          * Obtain Amount.
584          *
585          * @return the amount
586          */
587         public OceanusMoney getAmount() {
588             return getMoney();
589         }
590     }
591 
592     /**
593      * The Event Account line.
594      */
595     public static class MoneyWiseQIFEventAccountLine
596             extends MoneyWiseQIFXferAccountLine<MoneyWiseQEventLineType> {
597         /**
598          * Constructor.
599          *
600          * @param pAccount the account
601          */
602         protected MoneyWiseQIFEventAccountLine(final MoneyWiseQIFAccount pAccount) {
603             /* Call super-constructor */
604             super(pAccount);
605         }
606 
607         /**
608          * Constructor.
609          *
610          * @param pAccount the account
611          * @param pClasses the classes
612          */
613         protected MoneyWiseQIFEventAccountLine(final MoneyWiseQIFAccount pAccount,
614                                                final List<MoneyWiseQIFClass> pClasses) {
615             /* Call super-constructor */
616             super(pAccount, pClasses);
617         }
618 
619         @Override
620         public MoneyWiseQEventLineType getLineType() {
621             return MoneyWiseQEventLineType.CATEGORY;
622         }
623     }
624 
625     /**
626      * The Event Category line.
627      */
628     public static class MoneyWiseQIFEventCategoryLine
629             extends MoneyWiseQIFCategoryLine<MoneyWiseQEventLineType> {
630         /**
631          * Constructor.
632          *
633          * @param pCategory the category
634          */
635         protected MoneyWiseQIFEventCategoryLine(final MoneyWiseQIFEventCategory pCategory) {
636             /* Call super-constructor */
637             super(pCategory);
638         }
639 
640         /**
641          * Constructor.
642          *
643          * @param pCategory the category
644          * @param pClasses  the classes
645          */
646         protected MoneyWiseQIFEventCategoryLine(final MoneyWiseQIFEventCategory pCategory,
647                                                 final List<MoneyWiseQIFClass> pClasses) {
648             /* Call super-constructor */
649             super(pCategory, pClasses);
650         }
651 
652         @Override
653         public MoneyWiseQEventLineType getLineType() {
654             return MoneyWiseQEventLineType.CATEGORY;
655         }
656     }
657 }