taxtank-core 2.0.67 → 2.0.68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/taxtank-core.mjs +108 -30
- package/fesm2022/taxtank-core.mjs.map +1 -1
- package/index.d.ts +21 -10
- package/package.json +1 -1
|
@@ -17,12 +17,12 @@ import uniqBy from 'lodash/uniqBy';
|
|
|
17
17
|
import first from 'lodash/first';
|
|
18
18
|
import last from 'lodash/last';
|
|
19
19
|
import orderBy from 'lodash/orderBy';
|
|
20
|
+
import round from 'lodash/round';
|
|
20
21
|
import uniq from 'lodash/uniq';
|
|
21
22
|
import moment from 'moment';
|
|
22
23
|
import { DateRange as DateRange$1 } from 'moment-range';
|
|
23
24
|
import * as i3 from 'taxtank-core/common';
|
|
24
25
|
import { UserRolesEnum as UserRolesEnum$1, MixpanelService as MixpanelService$1 } from 'taxtank-core/common';
|
|
25
|
-
import round from 'lodash/round';
|
|
26
26
|
import range from 'lodash/range';
|
|
27
27
|
import { Validators, FormGroup, FormArray, UntypedFormControl, UntypedFormArray, UntypedFormGroup, FormControl } from '@angular/forms';
|
|
28
28
|
import compact from 'lodash/compact';
|
|
@@ -2469,6 +2469,22 @@ class PropertyCollection extends Collection {
|
|
|
2469
2469
|
}
|
|
2470
2470
|
return propertiesByCategory;
|
|
2471
2471
|
}
|
|
2472
|
+
getEquityPositionByProperty(bankAccounts) {
|
|
2473
|
+
const loanAccounts = bankAccounts.getOwn().getLoanAndOffsetAccounts();
|
|
2474
|
+
const equityPositionByProperty = new Dictionary([]);
|
|
2475
|
+
this.items.forEach(property => {
|
|
2476
|
+
equityPositionByProperty.add(property.id, property.getEquityPosition(loanAccounts.getByPropertyId(property.id)));
|
|
2477
|
+
});
|
|
2478
|
+
return equityPositionByProperty;
|
|
2479
|
+
}
|
|
2480
|
+
getLvrByProperty(bankAccounts) {
|
|
2481
|
+
const loanAccounts = bankAccounts.getOwn().getLoanAndOffsetAccounts();
|
|
2482
|
+
const lvrByProperty = new Dictionary([]);
|
|
2483
|
+
this.items.forEach(property => {
|
|
2484
|
+
lvrByProperty.add(property.id, property.getLvr(loanAccounts.getByPropertyId(property.id)));
|
|
2485
|
+
});
|
|
2486
|
+
return lvrByProperty;
|
|
2487
|
+
}
|
|
2472
2488
|
}
|
|
2473
2489
|
|
|
2474
2490
|
class PropertyCategoryMovementCollection extends Collection {
|
|
@@ -6171,6 +6187,12 @@ class Property extends Property$1 {
|
|
|
6171
6187
|
getGrowth() {
|
|
6172
6188
|
return this.valuation.marketValue - this.purchasePrice;
|
|
6173
6189
|
}
|
|
6190
|
+
getEquityPosition(bankAccounts) {
|
|
6191
|
+
return this.marketValue - Math.abs(bankAccounts.getLoanValue(this));
|
|
6192
|
+
}
|
|
6193
|
+
getLvr(bankAccounts) {
|
|
6194
|
+
return bankAccounts.getActiveLoanAccountsByProperties([this.id]).propertiesBalanceAmount / this.marketValue * 100;
|
|
6195
|
+
}
|
|
6174
6196
|
}
|
|
6175
6197
|
__decorate([
|
|
6176
6198
|
Type(() => Number)
|
|
@@ -9477,6 +9499,9 @@ class BankAccountCollection extends Collection {
|
|
|
9477
9499
|
getActiveLoanAccountsByProperties(ids) {
|
|
9478
9500
|
return this.getActive().getLoanAccounts().getByPropertiesIds(ids);
|
|
9479
9501
|
}
|
|
9502
|
+
getLoanValue(property) {
|
|
9503
|
+
return this.items.reduce((propertyAmount, bankAccount) => propertyAmount + bankAccount.getPropertyBalanceAmount(property.id), 0);
|
|
9504
|
+
}
|
|
9480
9505
|
}
|
|
9481
9506
|
|
|
9482
9507
|
/**
|
|
@@ -9756,6 +9781,20 @@ class FinancialGoalCollection extends Collection {
|
|
|
9756
9781
|
getActive() {
|
|
9757
9782
|
return this.filterBy('status', [FinancialGoalStatusEnum.ACTIVE, FinancialGoalStatusEnum.PAUSE]);
|
|
9758
9783
|
}
|
|
9784
|
+
getPropertiesByGoal(properties) {
|
|
9785
|
+
const propertiesByGoal = new CollectionDictionary(new PropertyCollection());
|
|
9786
|
+
this.items.forEach(goal => {
|
|
9787
|
+
propertiesByGoal.add(goal.id, properties.filterBy('id', goal.properties));
|
|
9788
|
+
});
|
|
9789
|
+
return propertiesByGoal;
|
|
9790
|
+
}
|
|
9791
|
+
getBankAccountsByGoal(bankAccounts) {
|
|
9792
|
+
const bankAccountsByGoal = new CollectionDictionary(new BankAccountCollection());
|
|
9793
|
+
this.items.forEach(goal => {
|
|
9794
|
+
bankAccountsByGoal.add(goal.id, bankAccounts.filterBy('id', goal.bankAccount));
|
|
9795
|
+
});
|
|
9796
|
+
return bankAccountsByGoal;
|
|
9797
|
+
}
|
|
9759
9798
|
}
|
|
9760
9799
|
|
|
9761
9800
|
/**
|
|
@@ -10803,6 +10842,12 @@ class Dictionary {
|
|
|
10803
10842
|
get(key) {
|
|
10804
10843
|
return this.items[key] !== undefined ? this.items[key] : null;
|
|
10805
10844
|
}
|
|
10845
|
+
sum(keys) {
|
|
10846
|
+
return round(keys.reduce((sum, key) => sum + (+this.get(key)), 0), 2);
|
|
10847
|
+
}
|
|
10848
|
+
avg(keys) {
|
|
10849
|
+
return round(this.sum(keys) / keys.length, 2);
|
|
10850
|
+
}
|
|
10806
10851
|
merge(dictionary) {
|
|
10807
10852
|
Object.assign(this.items, dictionary.items);
|
|
10808
10853
|
return this;
|
|
@@ -11591,6 +11636,9 @@ class FinancialGoal extends AbstractModel {
|
|
|
11591
11636
|
}
|
|
11592
11637
|
return payments;
|
|
11593
11638
|
}
|
|
11639
|
+
get propertyIds() {
|
|
11640
|
+
return this.properties.map(property => property.id);
|
|
11641
|
+
}
|
|
11594
11642
|
}
|
|
11595
11643
|
__decorate([
|
|
11596
11644
|
Type(() => Date)
|
|
@@ -21049,6 +21097,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
|
|
|
21049
21097
|
* Logic here works like collections methods but for several entities
|
|
21050
21098
|
*/
|
|
21051
21099
|
class PropertyCalculationService {
|
|
21100
|
+
constructor() {
|
|
21101
|
+
this.propertyService = inject(PropertyService);
|
|
21102
|
+
this.bankAccountService = inject(BankAccountService);
|
|
21103
|
+
}
|
|
21052
21104
|
getTaxPosition(transactions, depreciations) {
|
|
21053
21105
|
// @TODO hack: math abs added because we have mismatching of real values signs
|
|
21054
21106
|
return transactions.grossClaimAmount - Math.abs(depreciations.claimAmount);
|
|
@@ -21085,18 +21137,8 @@ class PropertyCalculationService {
|
|
|
21085
21137
|
return properties.items.reduce((totalAmount, property) => totalAmount + bankAccounts.items
|
|
21086
21138
|
.reduce((propertyAmount, bankAccount) => propertyAmount + bankAccount.getPropertyBalanceAmount(property.id), 0), 0);
|
|
21087
21139
|
}
|
|
21088
|
-
/**
|
|
21089
|
-
* LVR
|
|
21090
|
-
*/
|
|
21091
|
-
getLvr(properties, bankAccounts) {
|
|
21092
|
-
// Math abs is required for correct percentage calculation
|
|
21093
|
-
return bankAccounts.getActiveLoanAccountsByProperties(properties.getIds()).propertiesBalanceAmount / properties.marketValue;
|
|
21094
|
-
}
|
|
21095
21140
|
getLvr$(properties$, bankAccounts$) {
|
|
21096
|
-
return combineLatest([
|
|
21097
|
-
properties$,
|
|
21098
|
-
bankAccounts$
|
|
21099
|
-
]).pipe(map(([properties, bankAccounts]) => this.getLvr(properties, bankAccounts)));
|
|
21141
|
+
return combineLatest([properties$, bankAccounts$]).pipe(map(([properties, bankAccounts]) => this.getLvr(properties, bankAccounts)));
|
|
21100
21142
|
}
|
|
21101
21143
|
getLvrCommencement(properties, loans, bankAccounts) {
|
|
21102
21144
|
// Math abs is required for correct percentage calculation
|
|
@@ -21124,6 +21166,14 @@ class PropertyCalculationService {
|
|
|
21124
21166
|
loans$
|
|
21125
21167
|
]).pipe(map(([properties, bankAccounts, loans]) => this.getLvrGrowth(properties, bankAccounts, loans)));
|
|
21126
21168
|
}
|
|
21169
|
+
getEquityPosition$(propertyIds) {
|
|
21170
|
+
return combineLatest([this.propertyService.getBy('id', propertyIds), this.bankAccountService.getActive()])
|
|
21171
|
+
.pipe(map(([properties, bankAccounts]) => this.getEquityPosition(properties, bankAccounts.getOwn().getLoanAndOffsetAccounts().getByPropertiesIds(propertyIds))));
|
|
21172
|
+
}
|
|
21173
|
+
getLVR$(propertyIds) {
|
|
21174
|
+
return combineLatest([this.propertyService.getBy('id', propertyIds), this.bankAccountService.getActive()])
|
|
21175
|
+
.pipe(map(([properties, bankAccounts]) => this.getLvr(properties, bankAccounts.getOwn().getLoanAndOffsetAccounts().getByPropertiesIds(propertyIds))));
|
|
21176
|
+
}
|
|
21127
21177
|
/**
|
|
21128
21178
|
* Equity position = Market value - current loan value
|
|
21129
21179
|
*/
|
|
@@ -21131,6 +21181,13 @@ class PropertyCalculationService {
|
|
|
21131
21181
|
// Math abs is required for correct percentage calculation
|
|
21132
21182
|
return properties.marketValue - Math.abs(this.getLoanValue(properties, bankAccounts));
|
|
21133
21183
|
}
|
|
21184
|
+
getLvr(properties, bankAccounts) {
|
|
21185
|
+
if (!properties.marketValue) {
|
|
21186
|
+
return 0;
|
|
21187
|
+
}
|
|
21188
|
+
// Math abs is required for correct percentage calculation
|
|
21189
|
+
return bankAccounts.getActiveLoanAccountsByProperties(properties.getIds()).propertiesBalanceAmount / properties.marketValue;
|
|
21190
|
+
}
|
|
21134
21191
|
/**
|
|
21135
21192
|
* Purchase Equity = Purchase price - initial loan value
|
|
21136
21193
|
*/
|
|
@@ -23262,7 +23319,7 @@ function greaterThanValidator(value) {
|
|
|
23262
23319
|
/**
|
|
23263
23320
|
* Validator that enforces the current control's value to be >= another control's value.
|
|
23264
23321
|
*/
|
|
23265
|
-
function greaterThanControlValidator(controlName) {
|
|
23322
|
+
function greaterThanControlValidator(controlName, alias) {
|
|
23266
23323
|
return (control) => {
|
|
23267
23324
|
// skip validation until control is attached to a parent FormGroup
|
|
23268
23325
|
if (!control?.parent) {
|
|
@@ -23271,7 +23328,7 @@ function greaterThanControlValidator(controlName) {
|
|
|
23271
23328
|
const group = control.parent;
|
|
23272
23329
|
const fieldToCompare = group.get(controlName);
|
|
23273
23330
|
const isLessThan = Number(fieldToCompare.value) > Number(control.value);
|
|
23274
|
-
return isLessThan ? { greaterThanControl:
|
|
23331
|
+
return isLessThan ? { greaterThanControl: `The value should be greater than ${alias}` } : null;
|
|
23275
23332
|
};
|
|
23276
23333
|
}
|
|
23277
23334
|
|
|
@@ -23457,9 +23514,25 @@ class LoanForm extends AbstractForm {
|
|
|
23457
23514
|
}
|
|
23458
23515
|
}
|
|
23459
23516
|
|
|
23517
|
+
/**
|
|
23518
|
+
* Validator that enforces the current control's value to be >= another control's value.
|
|
23519
|
+
*/
|
|
23520
|
+
function lessThanControlValidator(controlName, alias) {
|
|
23521
|
+
return (control) => {
|
|
23522
|
+
// skip validation until control is attached to a parent FormGroup
|
|
23523
|
+
if (!control?.parent) {
|
|
23524
|
+
return null;
|
|
23525
|
+
}
|
|
23526
|
+
const group = control.parent;
|
|
23527
|
+
const fieldToCompare = group.get(controlName);
|
|
23528
|
+
const isLessThan = Number(fieldToCompare.value) > Number(control.value);
|
|
23529
|
+
return isLessThan ? null : { lessThanControl: `The value should be less than ${alias}` };
|
|
23530
|
+
};
|
|
23531
|
+
}
|
|
23532
|
+
|
|
23460
23533
|
const END_DATE_VALIDATION_ERROR = 'Target date must be more than start date';
|
|
23461
23534
|
class FinancialGoalForm extends AbstractForm {
|
|
23462
|
-
constructor(goal
|
|
23535
|
+
constructor(goal, equityByProperty, lvrByProperty) {
|
|
23463
23536
|
super({
|
|
23464
23537
|
type: new FormControl({ value: goal.type ?? FinancialGoalTypeEnum.DEBIT, disabled: !!goal.id }, Validators.required),
|
|
23465
23538
|
name: new FormControl(goal.name, Validators.required),
|
|
@@ -23467,10 +23540,11 @@ class FinancialGoalForm extends AbstractForm {
|
|
|
23467
23540
|
conditionalValidator(() => !this.isPropertyType(), Validators.required),
|
|
23468
23541
|
]),
|
|
23469
23542
|
targetValue: new FormControl(goal.targetValue, [
|
|
23470
|
-
|
|
23471
|
-
|
|
23543
|
+
Validators.required,
|
|
23544
|
+
conditionalValidator(() => this.isLvrType(), lessThanControlValidator('initialValue', 'Start Value')),
|
|
23545
|
+
conditionalValidator(() => !this.isLvrType(), greaterThanControlValidator('initialValue', 'Start Value')),
|
|
23472
23546
|
]),
|
|
23473
|
-
initialValue: new FormControl({ value: goal.initialValue, disabled:
|
|
23547
|
+
initialValue: new FormControl({ value: goal.initialValue, disabled: true }, Validators.required),
|
|
23474
23548
|
startDate: new FormControl({ value: goal.startDate, disabled: true }),
|
|
23475
23549
|
endDate: new FormControl(goal.endDate, [Validators.required, minDateValidator(goal.startDate, END_DATE_VALIDATION_ERROR)]),
|
|
23476
23550
|
paymentFrequency: new FormControl(goal.paymentFrequency, [
|
|
@@ -23482,10 +23556,12 @@ class FinancialGoalForm extends AbstractForm {
|
|
|
23482
23556
|
inCalendar: new FormControl(goal.inCalendar),
|
|
23483
23557
|
file: new FormControl(goal.file),
|
|
23484
23558
|
description: new FormControl(goal.description),
|
|
23485
|
-
properties: new FormControl(goal.properties, [
|
|
23559
|
+
properties: new FormControl({ value: goal.properties, disabled: !!goal.id }, [
|
|
23486
23560
|
conditionalValidator(() => this.isPropertyType(), Validators.required),
|
|
23487
23561
|
]),
|
|
23488
23562
|
}, goal);
|
|
23563
|
+
this.equityByProperty = equityByProperty;
|
|
23564
|
+
this.lvrByProperty = lvrByProperty;
|
|
23489
23565
|
this.includeDisabledFields = true;
|
|
23490
23566
|
this.bankAccountTypes = [];
|
|
23491
23567
|
this.bankAccountTypes = this.getBankAccountTypes(goal.type);
|
|
@@ -23496,17 +23572,15 @@ class FinancialGoalForm extends AbstractForm {
|
|
|
23496
23572
|
this.listenBankAccountChanges();
|
|
23497
23573
|
this.listenPaymentChanges();
|
|
23498
23574
|
}
|
|
23499
|
-
isPropertyType() {
|
|
23500
|
-
return [FinancialGoalTypeEnum.PROPERTY_EQUITY, FinancialGoalTypeEnum.PROPERTY_LVR].includes(this.value.type);
|
|
23501
|
-
}
|
|
23502
23575
|
listenTypeChanges() {
|
|
23503
23576
|
this.get('type').valueChanges.subscribe((type) => {
|
|
23504
23577
|
this.get('bankAccount').setValue(null, { onlySelf: true });
|
|
23505
|
-
this.get('properties').setValue([], { onlySelf: true });
|
|
23578
|
+
this.get('properties').setValue([], { onlySelf: true, emitEvent: false });
|
|
23579
|
+
this.get('initialValue').setValue(null, { onlySelf: true, emitEvent: false });
|
|
23506
23580
|
if (this.isPropertyType()) {
|
|
23507
|
-
this.get('inCalendar').setValue(false, { onlySelf: true });
|
|
23508
|
-
this.get('paymentFrequency').setValue(false, { onlySelf: true });
|
|
23509
|
-
this.get('paymentAmount').setValue(false, { onlySelf: true });
|
|
23581
|
+
this.get('inCalendar').setValue(false, { onlySelf: true, emitEvent: false });
|
|
23582
|
+
this.get('paymentFrequency').setValue(false, { onlySelf: true, emitEvent: false });
|
|
23583
|
+
this.get('paymentAmount').setValue(false, { onlySelf: true, emitEvent: false });
|
|
23510
23584
|
}
|
|
23511
23585
|
this.bankAccountTypes = this.getBankAccountTypes(type);
|
|
23512
23586
|
});
|
|
@@ -23531,11 +23605,9 @@ class FinancialGoalForm extends AbstractForm {
|
|
|
23531
23605
|
this.get('endDate').setValue(this.calculateEndDate(), { emitEvent: false });
|
|
23532
23606
|
});
|
|
23533
23607
|
}
|
|
23534
|
-
/**
|
|
23535
|
-
* keeps updated initialValue when bankAccount updated. only for add form
|
|
23536
|
-
*/
|
|
23537
23608
|
listenBankAccountChanges() {
|
|
23538
|
-
this.get('bankAccount').valueChanges
|
|
23609
|
+
this.get('bankAccount').valueChanges
|
|
23610
|
+
.pipe(filter((bankAccount) => !!bankAccount))
|
|
23539
23611
|
.subscribe(bankAccount => {
|
|
23540
23612
|
this.get('initialValue').setValue(bankAccount.currentBalance);
|
|
23541
23613
|
});
|
|
@@ -23583,6 +23655,12 @@ class FinancialGoalForm extends AbstractForm {
|
|
|
23583
23655
|
return [];
|
|
23584
23656
|
}
|
|
23585
23657
|
}
|
|
23658
|
+
isPropertyType() {
|
|
23659
|
+
return [FinancialGoalTypeEnum.PROPERTY_EQUITY, FinancialGoalTypeEnum.PROPERTY_LVR].includes(this.value.type);
|
|
23660
|
+
}
|
|
23661
|
+
isLvrType() {
|
|
23662
|
+
return this.value.type === FinancialGoalTypeEnum.PROPERTY_LVR;
|
|
23663
|
+
}
|
|
23586
23664
|
}
|
|
23587
23665
|
|
|
23588
23666
|
class FirmForm extends AbstractForm {
|