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.statics;
18
19 import io.github.tonywasher.joceanus.moneywise.exc.MoneyWiseDataException;
20 import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
21 import io.github.tonywasher.joceanus.prometheus.data.PrometheusStaticDataClass;
22
23 /**
24 * Enumeration of Security Type Classes.
25 */
26 public enum MoneyWiseSecurityClass
27 implements PrometheusStaticDataClass {
28 /**
29 * Shares.
30 * <p>
31 * This is a share security and represents stock held in a company.
32 */
33 SHARES(1, 0),
34
35 /**
36 * Growth Unit Trust or OEIC.
37 * <p>
38 * This is a UnitTrust account and represents a mutual fund that reinvests income.
39 */
40 GROWTHUNITTRUST(2, 1),
41
42 /**
43 * Income Unit Trust or OEIC.
44 * <p>
45 * This is a UnitTrust account and represents a mutual fund that provides income.
46 */
47 INCOMEUNITTRUST(3, 2),
48
49 /**
50 * Life Bond.
51 * <p>
52 * This is a LifeBond account, which is a specialised form of an {@link #GROWTHUNITTRUST}
53 * security. It simply differs in tax treatment.
54 */
55 LIFEBOND(4, 3),
56
57 /**
58 * Endowment.
59 * <p>
60 * This is a Endowment account, which is a specialised form of an {@link #GROWTHUNITTRUST}
61 * security. It simply differs in tax treatment.
62 */
63 ENDOWMENT(5, 4),
64
65 /**
66 * Property.
67 * <p>
68 * This is a Property account, which represents an owned property.
69 */
70 PROPERTY(6, 5),
71
72 /**
73 * Vehicle.
74 * <p>
75 * This is a Vehicle account, which represents a road vehicle.
76 */
77 VEHICLE(7, 6),
78
79 /**
80 * Defined Contribution Pension Pot.
81 * <p>
82 * This is a defined contribution PensionPot. TaxFree contributions can be made to this Pot via
83 * an Income:Pension transaction. It should have a single unit valued at the size of the
84 * PensionPot.
85 */
86 DEFINEDCONTRIBUTION(8, 7),
87
88 /**
89 * DefinedBenefit PensionPot.
90 * <p>
91 * This is a defined Benefit Pension Pot. TaxFree contributions can be made to this Pot via an
92 * Income:Pension transaction. It should have a single unit valued at the annual income value.
93 * Its valuation is the annual income multiplied by 20.
94 */
95 DEFINEDBENEFIT(9, 8),
96
97 /**
98 * StatePension PensionPot.
99 * <p>
100 * This is a state Pension Pot. It should have a single unit valued at the weekly income value.
101 * Its valuation is the weekly income multiplied by 52*20. It is a singular Security.
102 */
103 STATEPENSION(10, 9),
104
105 /**
106 * StockOption.
107 * <p>
108 * This is stockOption. It relates to an option to buy a particular stock at a particular price
109 * at a later date.
110 */
111 STOCKOPTION(11, 10),
112
113 /**
114 * Generic Asset Account.
115 * <p>
116 * This is a generic asset account and represents items whose value is determined by the product
117 * of the number units held and the most recent unit price.
118 */
119 ASSET(12, 11);
120
121 /**
122 * Number of Pension Years for valuation.
123 */
124 private static final int PENSION_YEARS = 20;
125
126 /**
127 * Number of Pension Weeks for valuation.
128 */
129 private static final int PENSION_WEEKS = 52;
130
131 /**
132 * The String name.
133 */
134 private String theName;
135
136 /**
137 * Class Id.
138 */
139 private final int theId;
140
141 /**
142 * Class Order.
143 */
144 private final int theOrder;
145
146 /**
147 * Constructor.
148 *
149 * @param uId the Id
150 * @param uOrder the default order.
151 */
152 MoneyWiseSecurityClass(final int uId,
153 final int uOrder) {
154 theId = uId;
155 theOrder = uOrder;
156 }
157
158 @Override
159 public int getClassId() {
160 return theId;
161 }
162
163 @Override
164 public int getOrder() {
165 return theOrder;
166 }
167
168 @Override
169 public String toString() {
170 /* If we have not yet loaded the name */
171 if (theName == null) {
172 /* Load the name */
173 theName = MoneyWiseStaticResource.getKeyForSecurityType(this).getValue();
174 }
175
176 /* return the name */
177 return theName;
178 }
179
180 /**
181 * get value from id.
182 *
183 * @param id the id value
184 * @return the corresponding enum object
185 * @throws OceanusException on error
186 */
187 public static MoneyWiseSecurityClass fromId(final int id) throws OceanusException {
188 for (MoneyWiseSecurityClass myClass : values()) {
189 if (myClass.getClassId() == id) {
190 return myClass;
191 }
192 }
193 throw new MoneyWiseDataException("Invalid ClassId for " + MoneyWiseStaticDataType.SECURITYTYPE.toString() + ":" + id);
194 }
195
196 /**
197 * Determine whether the SecurityType is a pension.
198 *
199 * @return <code>true</code> if the security type is a pension, <code>false</code> otherwise.
200 */
201 public boolean isPension() {
202 return switch (this) {
203 case DEFINEDBENEFIT, DEFINEDCONTRIBUTION, STATEPENSION -> true;
204 default -> false;
205 };
206 }
207
208 /**
209 * Determine whether the SecurityType is a dividend provider.
210 *
211 * @return <code>true</code> if the security type is a dividend provider, <code>false</code>
212 * otherwise.
213 */
214 public boolean isDividend() {
215 return switch (this) {
216 case SHARES, INCOMEUNITTRUST, GROWTHUNITTRUST -> true;
217 default -> false;
218 };
219 }
220
221 /**
222 * Determine whether the SecurityType is shares.
223 *
224 * @return <code>true</code> if the security type is shares, <code>false</code> otherwise.
225 */
226 public boolean isShares() {
227 return this == SHARES;
228 }
229
230 /**
231 * Determine whether the SecurityType is option.
232 *
233 * @return <code>true</code> if the security type is option, <code>false</code> otherwise.
234 */
235 public boolean isOption() {
236 return this == STOCKOPTION;
237 }
238
239 /**
240 * Determine whether the SecurityType needs a symbol.
241 *
242 * @return <code>true</code> if the security type needs a symbol, <code>false</code> otherwise.
243 */
244 public boolean needsSymbol() {
245 return switch (this) {
246 case SHARES, GROWTHUNITTRUST, INCOMEUNITTRUST, LIFEBOND -> true;
247 default -> false;
248 };
249 }
250
251 /**
252 * Determine whether the SecurityType needs a region.
253 *
254 * @return <code>true</code> if the security type needs a region, <code>false</code> otherwise.
255 */
256 public boolean needsRegion() {
257 return switch (this) {
258 case INCOMEUNITTRUST, GROWTHUNITTRUST, LIFEBOND -> true;
259 default -> false;
260 };
261 }
262
263 /**
264 * Determine whether the SecurityType needs market as a parent.
265 *
266 * @return <code>true</code> if the security type needs market as a parent, <code>false</code>
267 * otherwise.
268 */
269 public boolean needsMarketParent() {
270 return switch (this) {
271 case ASSET, PROPERTY, VEHICLE, ENDOWMENT -> true;
272 default -> false;
273 };
274 }
275
276 /**
277 * Determine whether the SecurityType can be tax free.
278 *
279 * @return <code>true</code> if the security type can be tax free, <code>false</code> otherwise.
280 */
281 public boolean canTaxFree() {
282 return switch (this) {
283 case SHARES, INCOMEUNITTRUST, GROWTHUNITTRUST, PROPERTY -> true;
284 default -> false;
285 };
286 }
287
288 /**
289 * Determine whether the SecurityType is subject to Capital Gains.
290 *
291 * @return <code>true</code> if the security type is subject to Capital Gains,
292 * <code>false</code> otherwise.
293 */
294 public boolean isCapitalGains() {
295 return switch (this) {
296 case SHARES, INCOMEUNITTRUST, GROWTHUNITTRUST, PROPERTY -> true;
297 default -> false;
298 };
299 }
300
301 /**
302 * Determine whether the SecurityType is subject to Residential Gains.
303 *
304 * @return <code>true</code> if the security type is subject to Residential Gains,
305 * <code>false</code> otherwise.
306 */
307 public boolean isResidentialGains() {
308 return this == PROPERTY;
309 }
310
311 /**
312 * Determine whether the SecurityType is subject to Chargeable Gains.
313 *
314 * @return <code>true</code> if the security type is subject to Chargeable Gains,
315 * <code>false</code> otherwise.
316 */
317 public boolean isChargeableGains() {
318 return this == LIFEBOND;
319 }
320
321 /**
322 * Determine whether the SecurityType is Capital.
323 *
324 * @return <code>true</code> if the security type is Capital, <code>false</code> otherwise.
325 */
326 public boolean isCapital() {
327 return switch (this) {
328 case SHARES, LIFEBOND, INCOMEUNITTRUST, GROWTHUNITTRUST -> true;
329 default -> false;
330 };
331 }
332
333 /**
334 * Determine whether the SecurityType is UnitTrust.
335 *
336 * @return <code>true</code> if the security type is Capital, <code>false</code> otherwise.
337 */
338 public boolean isUnitTrust() {
339 return switch (this) {
340 case INCOMEUNITTRUST, GROWTHUNITTRUST -> true;
341 default -> false;
342 };
343 }
344
345 /**
346 * Is this a statePension?
347 *
348 * @return <code>true</code> if the SecurityType is statePension, <code>false</code> otherwise.
349 */
350 public boolean isStatePension() {
351 return this == STATEPENSION;
352 }
353
354 /**
355 * Is this a singular security?.
356 *
357 * @return <code>true</code> if the SecurityType is singular, <code>false</code> otherwise.
358 */
359 public boolean isSingular() {
360 return isStatePension();
361 }
362
363 /**
364 * Is this an autoUnits?
365 *
366 * @return <code>true</code> if the SecurityType is an autoUnits, <code>false</code> otherwise.
367 */
368 public boolean isAutoUnits() {
369 return switch (this) {
370 case ENDOWMENT, STATEPENSION, DEFINEDCONTRIBUTION, DEFINEDBENEFIT -> true;
371 default -> false;
372 };
373 }
374
375 /**
376 * Obtain autoUnits.
377 *
378 * @return the number of units for this security if active.
379 */
380 public int getAutoUnits() {
381 return switch (this) {
382 case ENDOWMENT, DEFINEDCONTRIBUTION -> 1;
383 case STATEPENSION -> PENSION_YEARS * PENSION_WEEKS;
384 case DEFINEDBENEFIT -> PENSION_YEARS;
385 default -> 0;
386 };
387 }
388 }