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.data.validate;
18  
19  import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
20  import io.github.tonywasher.joceanus.oceanus.decimal.OceanusMoney;
21  import io.github.tonywasher.joceanus.metis.field.MetisFieldRequired;
22  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseBasicDataType;
23  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseCash;
24  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseCashCategory;
25  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseCashInfo;
26  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseCashInfoSet;
27  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseDepositInfoSet;
28  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWisePayee;
29  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWisePayee.MoneyWisePayeeList;
30  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransCategory;
31  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransCategory.MoneyWiseTransCategoryList;
32  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseAccountInfoClass;
33  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseCurrency;
34  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseTransCategoryClass;
35  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataInfoClass;
36  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataItem;
37  import io.github.tonywasher.joceanus.prometheus.validate.PrometheusValidateInfoSet;
38  
39  import java.util.Currency;
40  import java.util.Iterator;
41  
42  /**
43   * Validate CashInfoSet.
44   */
45  public class MoneyWiseValidateCashInfoSet
46          extends PrometheusValidateInfoSet<MoneyWiseCashInfo> {
47      /**
48       * ClosedPayee Error string.
49       */
50      private static final String ERROR_PAYEECLOSED = "AutoPayee is closed for non-closed autoCash";
51  
52      @Override
53      public MoneyWiseCash getOwner() {
54          return (MoneyWiseCash) super.getOwner();
55      }
56  
57      @Override
58      public MoneyWiseCashInfoSet getInfoSet() {
59          return (MoneyWiseCashInfoSet) super.getInfoSet();
60      }
61  
62      @Override
63      public MetisFieldRequired isClassRequired(final PrometheusDataInfoClass pClass) {
64          /* Access details about the Cash */
65          final MoneyWiseCash myCash = getOwner();
66          final MoneyWiseCashCategory myCategory = myCash.getCategory();
67  
68          /* If we have no Category, no class is allowed */
69          if (myCategory == null) {
70              return MetisFieldRequired.NOTALLOWED;
71          }
72  
73          /* Switch on class */
74          switch ((MoneyWiseAccountInfoClass) pClass) {
75              /* Allowed set */
76              case NOTES:
77                  return MetisFieldRequired.CANEXIST;
78  
79              case OPENINGBALANCE:
80                  return myCash.isAutoExpense()
81                          ? MetisFieldRequired.NOTALLOWED
82                          : MetisFieldRequired.CANEXIST;
83  
84              case AUTOPAYEE:
85              case AUTOEXPENSE:
86                  return myCash.isAutoExpense()
87                          ? MetisFieldRequired.MUSTEXIST
88                          : MetisFieldRequired.NOTALLOWED;
89  
90              /* Disallowed Set */
91              case SORTCODE:
92              case ACCOUNT:
93              case REFERENCE:
94              case WEBSITE:
95              case CUSTOMERNO:
96              case USERID:
97              case PASSWORD:
98              case MATURITY:
99              case SYMBOL:
100             case REGION:
101             case UNDERLYINGSTOCK:
102             case OPTIONPRICE:
103             default:
104                 return MetisFieldRequired.NOTALLOWED;
105         }
106     }
107 
108     @Override
109     public void validateClass(final MoneyWiseCashInfo pInfo,
110                               final PrometheusDataInfoClass pClass) {
111         /* Switch on class */
112         switch ((MoneyWiseAccountInfoClass) pClass) {
113             case OPENINGBALANCE:
114                 validateOpeningBalance(pInfo);
115                 break;
116             case AUTOEXPENSE:
117                 validateAutoExpense(pInfo);
118                 break;
119             case AUTOPAYEE:
120                 validateAutoPayee(pInfo);
121                 break;
122             case NOTES:
123                 validateNotes(pInfo);
124                 break;
125             default:
126                 break;
127         }
128     }
129 
130     /**
131      * Validate the opening balance.
132      *
133      * @param pInfo the info
134      */
135     private void validateOpeningBalance(final MoneyWiseCashInfo pInfo) {
136         final OceanusMoney myBalance = pInfo.getValue(OceanusMoney.class);
137         if (!myBalance.getCurrency().equals(getOwner().getCurrency())) {
138             getOwner().addError(MoneyWiseDepositInfoSet.ERROR_CURRENCY, MoneyWiseCashInfoSet.getFieldForClass(MoneyWiseAccountInfoClass.OPENINGBALANCE));
139         }
140     }
141 
142     /**
143      * Validate the autoExpense info.
144      *
145      * @param pInfo the info
146      */
147     private void validateAutoExpense(final MoneyWiseCashInfo pInfo) {
148         final MoneyWiseTransCategory myExpense = pInfo.getEventCategory();
149         final MoneyWiseTransCategoryClass myCatClass = myExpense.getCategoryTypeClass();
150         if (!myCatClass.isExpense() || myCatClass.canParentCategory()) {
151             getOwner().addError(MoneyWiseCashInfoSet.ERROR_AUTOEXP, MoneyWiseCashInfoSet.getFieldForClass(MoneyWiseAccountInfoClass.AUTOEXPENSE));
152         }
153     }
154 
155     /**
156      * Validate the autoPayee info.
157      *
158      * @param pInfo the info
159      */
160     private void validateAutoPayee(final MoneyWiseCashInfo pInfo) {
161         final MoneyWisePayee myPayee = pInfo.getPayee();
162         if (myPayee.isClosed() && !getOwner().isClosed()) {
163             getOwner().addError(ERROR_PAYEECLOSED, MoneyWiseCashInfoSet.getFieldForClass(MoneyWiseAccountInfoClass.AUTOPAYEE));
164         }
165     }
166 
167     /**
168      * Validate the Notes info.
169      *
170      * @param pInfo the info
171      */
172     private void validateNotes(final MoneyWiseCashInfo pInfo) {
173         final char[] myArray = pInfo.getValue(char[].class);
174         if (myArray.length > MoneyWiseAccountInfoClass.NOTES.getMaximumLength()) {
175             getOwner().addError(PrometheusDataItem.ERROR_LENGTH, MoneyWiseCashInfoSet.getFieldForClass(MoneyWiseAccountInfoClass.NOTES));
176         }
177     }
178 
179     @Override
180     protected void setDefault(final PrometheusDataInfoClass pClass) throws OceanusException {
181         /* Switch on the class */
182         switch ((MoneyWiseAccountInfoClass) pClass) {
183             case AUTOEXPENSE:
184                 getInfoSet().setValue(pClass, getDefaultAutoExpense());
185                 break;
186             case AUTOPAYEE:
187                 getInfoSet().setValue(pClass, getDefaultAutoPayee());
188                 break;
189             default:
190                 break;
191         }
192     }
193 
194     /**
195      * Obtain default expense for autoExpense cash.
196      *
197      * @return the default expense
198      */
199     private MoneyWiseTransCategory getDefaultAutoExpense() {
200         /* Access the category list */
201         final MoneyWiseTransCategoryList myCategories
202                 = getEditSet().getDataList(MoneyWiseBasicDataType.TRANSCATEGORY, MoneyWiseTransCategoryList.class);
203 
204         /* loop through the categories */
205         final Iterator<MoneyWiseTransCategory> myIterator = myCategories.iterator();
206         while (myIterator.hasNext()) {
207             final MoneyWiseTransCategory myCategory = myIterator.next();
208 
209             /* Ignore deleted categories */
210             if (myCategory.isDeleted()) {
211                 continue;
212             }
213 
214             /* Ignore categories that are the wrong class */
215             final MoneyWiseTransCategoryClass myCatClass = myCategory.getCategoryTypeClass();
216             if (myCatClass.isExpense() && !myCatClass.canParentCategory()) {
217                 return myCategory;
218             }
219         }
220 
221         /* Return no category */
222         return null;
223     }
224 
225     /**
226      * Obtain default payee for autoExpense cash.
227      *
228      * @return the default payee
229      */
230     private MoneyWisePayee getDefaultAutoPayee() {
231         /* Access the payee list */
232         final MoneyWisePayeeList myPayees
233                 = getEditSet().getDataList(MoneyWiseBasicDataType.PAYEE, MoneyWisePayeeList.class);
234 
235         /* loop through the payees */
236         final Iterator<MoneyWisePayee> myIterator = myPayees.iterator();
237         while (myIterator.hasNext()) {
238             final MoneyWisePayee myPayee = myIterator.next();
239 
240             /* Ignore deleted and closed payees */
241             if (!myPayee.isDeleted() && Boolean.TRUE.equals(!myPayee.isClosed())) {
242                 return myPayee;
243             }
244         }
245 
246         /* Return no payee */
247         return null;
248     }
249 
250     @Override
251     protected void autoCorrect(final PrometheusDataInfoClass pClass) throws OceanusException {
252         /* If the info is Opening balance */
253         if (MoneyWiseAccountInfoClass.OPENINGBALANCE.equals(pClass)) {
254             /* Access the value */
255             final MoneyWiseCash myOwner = getOwner();
256             OceanusMoney myOpening = myOwner.getOpeningBalance();
257             final MoneyWiseCurrency myAssetCurrency = myOwner.getAssetCurrency();
258             final Currency myCurrency = myAssetCurrency.getCurrency();
259 
260             /* If we need to change currency */
261             if (!myCurrency.equals(myOpening.getCurrency())) {
262                 myOpening = myOpening.changeCurrency(myCurrency);
263                 getInfoSet().setValue(pClass, myOpening);
264             }
265         }
266     }
267 }