taxtank-core 0.10.5 → 0.10.6

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.
Files changed (27) hide show
  1. package/bundles/taxtank-core.umd.js +1185 -979
  2. package/bundles/taxtank-core.umd.js.map +1 -1
  3. package/esm2015/lib/collections/collection-dictionary.js +6 -6
  4. package/esm2015/lib/collections/collection.js +8 -1
  5. package/esm2015/lib/collections/report/property/property-report-item-depreciation.collection.js +22 -0
  6. package/esm2015/lib/collections/report/property/property-report-item-transaction.collection.js +22 -0
  7. package/esm2015/lib/collections/report/property/property-report-item.collection.js +13 -0
  8. package/esm2015/lib/models/depreciation/depreciation.js +3 -3
  9. package/esm2015/lib/models/report/property/property-report-item-depreciation.js +19 -0
  10. package/esm2015/lib/models/report/property/property-report-item-transaction.js +12 -0
  11. package/esm2015/lib/models/report/property/property-report-item.js +27 -0
  12. package/esm2015/lib/services/report/property/property-transaction-report.service.js +76 -0
  13. package/esm2015/public-api.js +7 -1
  14. package/fesm2015/taxtank-core.js +1000 -830
  15. package/fesm2015/taxtank-core.js.map +1 -1
  16. package/lib/collections/collection-dictionary.d.ts +1 -1
  17. package/lib/collections/collection.d.ts +4 -0
  18. package/lib/collections/report/property/property-report-item-depreciation.collection.d.ts +12 -0
  19. package/lib/collections/report/property/property-report-item-transaction.collection.d.ts +12 -0
  20. package/lib/collections/report/property/property-report-item.collection.d.ts +9 -0
  21. package/lib/models/depreciation/depreciation.d.ts +1 -1
  22. package/lib/models/report/property/property-report-item-depreciation.d.ts +10 -0
  23. package/lib/models/report/property/property-report-item-transaction.d.ts +10 -0
  24. package/lib/models/report/property/property-report-item.d.ts +22 -0
  25. package/lib/services/report/property/property-transaction-report.service.d.ts +42 -0
  26. package/package.json +1 -1
  27. package/public-api.d.ts +6 -0
@@ -747,7 +747,7 @@ class CollectionDictionary {
747
747
  * @param path Path to the property to be grouped (Examples: 'transaction', 'property.category')
748
748
  * @param prop Optional: Field to group by (Default 'id', Examples: 'id', 'amount', 'date')
749
749
  */
750
- constructor(collection, path = '', prop = 'id') {
750
+ constructor(collection, path = 'id') {
751
751
  /**
752
752
  * List of grouped collections
753
753
  */
@@ -758,10 +758,10 @@ class CollectionDictionary {
758
758
  return;
759
759
  }
760
760
  // Check if the first collection item has property by path
761
- if (!has(collection.items[0], path) && path) {
761
+ if (!has(collection.items[0], path)) {
762
762
  return;
763
763
  }
764
- this.groupItems(collection, path, prop);
764
+ this.groupItems(collection, path);
765
765
  }
766
766
  /**
767
767
  * List of collections keys
@@ -799,12 +799,12 @@ class CollectionDictionary {
799
799
  /**
800
800
  * Group collection items by passed path into items object
801
801
  */
802
- groupItems(collection, path, prop) {
802
+ groupItems(collection, path) {
803
803
  // Create empty initial object for groups
804
804
  const obj = {};
805
805
  // Group collection items
806
806
  collection.items.forEach((item) => {
807
- let key = get(item, `${path ? path + '.' : ''}${prop}`);
807
+ let key = get(item, path);
808
808
  // if object does not have property for grouping it will be grouped as 'other'
809
809
  if (key === undefined) {
810
810
  key = 'other';
@@ -821,6 +821,47 @@ class CollectionDictionary {
821
821
  }
822
822
  }
823
823
 
824
+ // replace array element with the new one (only arrays of objects)
825
+ function replace(array, item, matchField = 'id') {
826
+ const index = array.findIndex((i) => i[matchField] === item[matchField]);
827
+ array.splice(index, 1, item);
828
+ }
829
+
830
+ // sort array of objects by field
831
+ function sort(array, field = 'id', isDesc = true) {
832
+ array.sort((a, b) => {
833
+ if (a[field] > b[field]) {
834
+ return !isDesc ? 1 : -1;
835
+ }
836
+ if (a[field] < b[field]) {
837
+ return !isDesc ? -1 : 1;
838
+ }
839
+ return 0;
840
+ });
841
+ }
842
+
843
+ // sort array of objects by field
844
+ function sortDeep(array, fieldsQueue = ['id'], isDesc = true) {
845
+ array.sort((a, b) => {
846
+ const aValue = getValue(a, fieldsQueue);
847
+ const bValue = getValue(b, fieldsQueue);
848
+ if (aValue > bValue) {
849
+ return !isDesc ? 1 : -1;
850
+ }
851
+ if (aValue < bValue) {
852
+ return !isDesc ? -1 : 1;
853
+ }
854
+ return 0;
855
+ });
856
+ }
857
+ function getValue(obj, fields) {
858
+ let value = obj;
859
+ fields.forEach((field) => {
860
+ value = value[field];
861
+ });
862
+ return value;
863
+ }
864
+
824
865
  const DEFAULT_INDEX = 'other';
825
866
  /**
826
867
  * Base collection class. Contains common properties and methods for all collections
@@ -892,6 +933,12 @@ class Collection {
892
933
  filter(callback) {
893
934
  return new Collection(this.items.filter(callback));
894
935
  }
936
+ /**
937
+ * Sort collection items by provided field
938
+ */
939
+ sortBy(filed = 'id', isDesc = true) {
940
+ sort(this.items, filed, isDesc);
941
+ }
895
942
  get first() {
896
943
  return first(this.items);
897
944
  }
@@ -3703,8 +3750,8 @@ class Depreciation extends Depreciation$1 {
3703
3750
  /**
3704
3751
  * Create a new transaction from current depreciation
3705
3752
  */
3706
- toTransaction() {
3707
- return plainToClass(Transaction, Object.assign({}, this, { amount: this.currentYearForecast.amount }));
3753
+ toTransaction(params = {}) {
3754
+ return plainToClass(Transaction, Object.assign(params, this, { amount: this.currentYearForecast.amount }));
3708
3755
  }
3709
3756
  get claimAmount() {
3710
3757
  var _a;
@@ -3816,6 +3863,111 @@ class DepreciationReportItemCollection extends DepreciationCollection {
3816
3863
  }
3817
3864
  }
3818
3865
 
3866
+ /**
3867
+ * Base collection to work with property report items
3868
+ */
3869
+ class PropertyReportItemCollection extends Collection {
3870
+ getIncomes() {
3871
+ return this.create(this.items.filter((item) => item.isIncome()));
3872
+ }
3873
+ getExpenses() {
3874
+ return this.create(this.items.filter((item) => item.isExpense()));
3875
+ }
3876
+ }
3877
+
3878
+ /**
3879
+ * Class with property transactions report entities
3880
+ */
3881
+ class PropertyReportItem {
3882
+ constructor(property, chartAccounts) {
3883
+ this.chartAccounts = chartAccounts;
3884
+ this.propertyId = property.id;
3885
+ this.claimPercent = property.claimPercent;
3886
+ this.sharePercent = property.sharePercent;
3887
+ this.subCode = chartAccounts.taxReturnItem.subCode;
3888
+ this.description = chartAccounts.name;
3889
+ }
3890
+ get claimAmount() {
3891
+ return +(this.amount * (this.claimPercent / 100)).toFixed(2);
3892
+ }
3893
+ get shareClaimAmount() {
3894
+ return this.claimAmount * (this.sharePercent / 100);
3895
+ }
3896
+ isIncome() {
3897
+ return CHART_ACCOUNTS_CATEGORIES.income.includes(this.chartAccounts.category);
3898
+ }
3899
+ isExpense() {
3900
+ return CHART_ACCOUNTS_CATEGORIES.expense.includes(this.chartAccounts.category);
3901
+ }
3902
+ }
3903
+
3904
+ /**
3905
+ * Class with transaction-based property transactions report entities
3906
+ */
3907
+ class PropertyReportItemTransaction extends PropertyReportItem {
3908
+ constructor(transactions, property, chartAccounts) {
3909
+ super(property, chartAccounts);
3910
+ this.amount = Math.abs(transactions.amount);
3911
+ this.description = chartAccounts.name;
3912
+ }
3913
+ }
3914
+
3915
+ /**
3916
+ * Collection to work with transaction-based property report items
3917
+ */
3918
+ class PropertyReportItemTransactionCollection extends PropertyReportItemCollection {
3919
+ constructor(transactions, properties, chartAccounts) {
3920
+ super();
3921
+ this.setItems(transactions, properties, chartAccounts);
3922
+ }
3923
+ setItems(transactions, properties, chartAccounts) {
3924
+ this.items = [];
3925
+ properties.items.forEach((property) => {
3926
+ const transactionsDictionary = new CollectionDictionary(transactions.getByPropertiesIds([property.id]), 'chartAccounts.id');
3927
+ transactionsDictionary.keys.map((chartAccountId) => {
3928
+ this.items.push(new PropertyReportItemTransaction(transactionsDictionary.get(chartAccountId), property, chartAccounts.getById(+chartAccountId)));
3929
+ });
3930
+ });
3931
+ }
3932
+ }
3933
+
3934
+ /**
3935
+ * Const with labels based on depreciation type
3936
+ */
3937
+ const DEPRECIATION_TYPE_LABELS = {
3938
+ 1: 'Plant & Equipment',
3939
+ 2: 'Building & Improvements'
3940
+ };
3941
+ /**
3942
+ * Class with depreciation-based property transactions report entities
3943
+ */
3944
+ class PropertyReportItemDepreciation extends PropertyReportItem {
3945
+ constructor(depreciations, property, chartAccounts) {
3946
+ super(property, chartAccounts);
3947
+ this.amount = Math.abs(depreciations.getCurrentYearForecastAmount());
3948
+ this.description = DEPRECIATION_TYPE_LABELS[depreciations.first.type];
3949
+ }
3950
+ }
3951
+
3952
+ /**
3953
+ * Collection to work with depreciation-based property report items
3954
+ */
3955
+ class PropertyReportItemDepreciationCollection extends PropertyReportItemCollection {
3956
+ constructor(depreciations, properties, chartAccounts) {
3957
+ super();
3958
+ this.setItems(depreciations, properties, chartAccounts);
3959
+ }
3960
+ setItems(depreciations, properties, chartAccounts) {
3961
+ this.items = [];
3962
+ properties.items.forEach((property) => {
3963
+ const depreciationsByType = new CollectionDictionary(depreciations, 'type');
3964
+ depreciationsByType.keys.map((type) => {
3965
+ this.items.push(new PropertyReportItemDepreciation(depreciationsByType.get(type), property, chartAccounts.getById(depreciationsByType.get(type).first.chartAccounts.id)));
3966
+ });
3967
+ });
3968
+ }
3969
+ }
3970
+
3819
3971
  class ServicePriceCollection extends Collection {
3820
3972
  get work() {
3821
3973
  return this.items.filter((price) => price.product.isWork())[0];
@@ -6451,47 +6603,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImpo
6451
6603
  args: ['environment']
6452
6604
  }] }]; } });
6453
6605
 
6454
- // replace array element with the new one (only arrays of objects)
6455
- function replace(array, item, matchField = 'id') {
6456
- const index = array.findIndex((i) => i[matchField] === item[matchField]);
6457
- array.splice(index, 1, item);
6458
- }
6459
-
6460
- // sort array of objects by field
6461
- function sort(array, field = 'id', isDesc = true) {
6462
- array.sort((a, b) => {
6463
- if (a[field] > b[field]) {
6464
- return !isDesc ? 1 : -1;
6465
- }
6466
- if (a[field] < b[field]) {
6467
- return !isDesc ? -1 : 1;
6468
- }
6469
- return 0;
6470
- });
6471
- }
6472
-
6473
- // sort array of objects by field
6474
- function sortDeep(array, fieldsQueue = ['id'], isDesc = true) {
6475
- array.sort((a, b) => {
6476
- const aValue = getValue(a, fieldsQueue);
6477
- const bValue = getValue(b, fieldsQueue);
6478
- if (aValue > bValue) {
6479
- return !isDesc ? 1 : -1;
6480
- }
6481
- if (aValue < bValue) {
6482
- return !isDesc ? -1 : 1;
6483
- }
6484
- return 0;
6485
- });
6486
- }
6487
- function getValue(obj, fields) {
6488
- let value = obj;
6489
- fields.forEach((field) => {
6490
- value = value[field];
6491
- });
6492
- return value;
6493
- }
6494
-
6495
6606
  class EventDispatcherService {
6496
6607
  constructor() {
6497
6608
  this.eventSubject = new Subject();
@@ -9005,136 +9116,71 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImpo
9005
9116
  args: ['environment']
9006
9117
  }] }]; } });
9007
9118
 
9119
+ function enumToList(data) {
9120
+ const list = [];
9121
+ for (const key in data) {
9122
+ if (Number(key) >= 0) {
9123
+ list.push({
9124
+ label: data[key],
9125
+ value: Number(key)
9126
+ });
9127
+ }
9128
+ }
9129
+ return list;
9130
+ }
9131
+
9132
+ var MessagesEnum;
9133
+ (function (MessagesEnum) {
9134
+ MessagesEnum["DELETED_MESSAGE"] = "Transaction deleted";
9135
+ MessagesEnum["UPDATED_MESSAGE"] = "Transaction updated";
9136
+ MessagesEnum["CREATED_MESSAGE"] = "Transaction(s) created";
9137
+ })(MessagesEnum || (MessagesEnum = {}));
9138
+
9008
9139
  /**
9009
- * Service with calculations methods for properties related with other entities.
9010
- * Logic here works like collections methods but for several entities
9140
+ * popup notifications service (toast, snackbar).
9011
9141
  */
9012
- class PropertyCalculationService {
9013
- getTaxPosition(transactions, depreciations) {
9014
- // @TODO hack: math abs added because we have mismatching of real values signs
9015
- return transactions.cashPosition - Math.abs(depreciations.claimAmount);
9142
+ class ToastService {
9143
+ constructor() {
9144
+ this.toast$ = new ReplaySubject(1);
9016
9145
  }
9017
- getTaxPosition$(transactions$, depreciations$) {
9018
- return combineLatest([
9019
- transactions$,
9020
- depreciations$
9021
- ]).pipe(map(([transactions, depreciations]) => {
9022
- return this.getTaxPosition(transactions, depreciations);
9023
- }));
9146
+ get() {
9147
+ return this.toast$.asObservable();
9024
9148
  }
9025
- taxPositionGrowth(properties, transactions, depreciations) {
9026
- const taxPosition = this.getTaxPosition(transactions, depreciations);
9027
- // check if taxPosition = 0 to avoid division by zero
9028
- if (!taxPosition) {
9029
- return 0;
9030
- }
9031
- return (taxPosition - properties.forecastedTaxPosition) / taxPosition;
9149
+ add(toast) {
9150
+ this.toast$.next(toast);
9032
9151
  }
9033
- taxPositionGrowth$(properties$, transactions$, depreciations$) {
9034
- return combineLatest([
9035
- properties$,
9036
- transactions$,
9037
- depreciations$
9038
- ]).pipe(map(([properties, transactions, depreciations]) => {
9039
- return this.taxPositionGrowth(properties, transactions, depreciations);
9152
+ success(message) {
9153
+ this.add(plainToClass(Toast, {
9154
+ type: ToastTypeEnum.SUCCESS,
9155
+ title: 'Success!',
9156
+ message,
9040
9157
  }));
9041
9158
  }
9042
- getRentalReturn(properties, transactions) {
9043
- return transactions.claimIncome / properties.marketValue;
9044
- }
9045
- getLoanAmount(properties, bankAccounts, loans) {
9046
- return properties.items.reduce((totalAmount, property) => {
9047
- return totalAmount + bankAccounts.items
9048
- .reduce((propertyAmount, bankAccount) => {
9049
- var _a;
9050
- return propertyAmount + bankAccount.getPropertyPercentage(property.id) * (((_a = loans.getByBankAccountId(bankAccount.id)) === null || _a === void 0 ? void 0 : _a.amount) || 0);
9051
- }, 0);
9052
- }, 0);
9053
- }
9054
- getLoanValue(properties, bankAccounts) {
9055
- return properties.items.reduce((totalAmount, property) => {
9056
- return totalAmount + bankAccounts.items
9057
- .reduce((propertyAmount, bankAccount) => {
9058
- return propertyAmount + bankAccount.getPropertyBalanceAmount(property.id);
9059
- }, 0);
9060
- }, 0);
9061
- }
9062
- /**
9063
- * LVR
9064
- */
9065
- getLvr(properties, bankAccounts) {
9066
- // Math abs is required for correct percentage calculation
9067
- return Math.abs(this.getLoanValue(properties, bankAccounts)) / properties.marketValue;
9068
- }
9069
- getLvr$(properties$, bankAccounts$) {
9070
- return combineLatest([
9071
- properties$,
9072
- bankAccounts$
9073
- ]).pipe(map(([properties, bankAccounts]) => {
9074
- return this.getLvr(properties, bankAccounts);
9159
+ warning(message) {
9160
+ this.add(plainToClass(Toast, {
9161
+ type: ToastTypeEnum.WARNING,
9162
+ title: 'Warning!',
9163
+ message,
9075
9164
  }));
9076
9165
  }
9077
- getLvrCommencement(properties, loans, bankAccounts) {
9078
- // Math abs is required for correct percentage calculation
9079
- return Math.abs(this.getLoanAmount(properties, bankAccounts, loans)) / properties.purchasePrice;
9166
+ error(message) {
9167
+ this.add(plainToClass(Toast, {
9168
+ type: ToastTypeEnum.ERROR,
9169
+ title: 'Error!',
9170
+ message,
9171
+ }));
9080
9172
  }
9081
- getLvrCommencement$(properties$, bankAccounts$, loans$) {
9082
- return combineLatest([
9083
- properties$,
9084
- bankAccounts$,
9085
- loans$
9086
- ]).pipe(map(([properties, bankAccounts, loans]) => {
9087
- return this.getLvrCommencement(properties, loans, bankAccounts);
9173
+ info(message) {
9174
+ this.add(plainToClass(Toast, {
9175
+ type: ToastTypeEnum.INFO,
9176
+ title: 'Information',
9177
+ message,
9088
9178
  }));
9089
9179
  }
9090
- getLvrGrowth(properties, bankAccounts, loans) {
9091
- const lvr = this.getLvr(properties, bankAccounts);
9092
- if (!lvr) {
9093
- // check if lvr = 0 to avoid division by zero
9094
- return 0;
9095
- }
9096
- return (lvr - this.getLvrCommencement(properties, loans, bankAccounts)) / lvr;
9097
- }
9098
- getLvrGrowth$(properties$, bankAccounts$, loans$) {
9099
- return combineLatest([
9100
- properties$,
9101
- bankAccounts$,
9102
- loans$
9103
- ]).pipe(map(([properties, bankAccounts, loans]) => {
9104
- return this.getLvrGrowth(properties, bankAccounts, loans);
9105
- }));
9106
- }
9107
- getEquityPosition(properties, bankAccounts) {
9108
- // Math abs is required for correct percentage calculation
9109
- return properties.marketValue - Math.abs(this.getLoanValue(properties, bankAccounts));
9110
- }
9111
- getPurchaseEquity(properties, bankAccounts, loans) {
9112
- // Math abs is required for correct percentage calculation
9113
- return properties.purchasePrice - Math.abs(this.getLoanAmount(properties, bankAccounts, loans));
9114
- }
9115
- }
9116
- PropertyCalculationService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyCalculationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
9117
- PropertyCalculationService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyCalculationService, providedIn: 'root' });
9118
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyCalculationService, decorators: [{
9119
- type: Injectable,
9120
- args: [{
9121
- providedIn: 'root'
9122
- }]
9123
- }] });
9124
-
9125
- /**
9126
- * Service for work with Property Categories
9127
- */
9128
- class PropertyCategoryService extends RestService {
9129
- constructor() {
9130
- super(...arguments);
9131
- this.modelClass = PropertyCategory;
9132
- this.url = 'properties/categories';
9133
- }
9134
9180
  }
9135
- PropertyCategoryService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyCategoryService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
9136
- PropertyCategoryService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyCategoryService, providedIn: 'root' });
9137
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyCategoryService, decorators: [{
9181
+ ToastService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: ToastService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
9182
+ ToastService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: ToastService, providedIn: 'root' });
9183
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: ToastService, decorators: [{
9138
9184
  type: Injectable,
9139
9185
  args: [{
9140
9186
  providedIn: 'root'
@@ -9142,161 +9188,667 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImpo
9142
9188
  }] });
9143
9189
 
9144
9190
  /**
9145
- * Class for work with Property Documents
9191
+ * Service for transactions business logic
9146
9192
  */
9147
- class PropertyDocumentService extends RestService {
9148
- constructor(http, eventDispatcherService, environment) {
9193
+ class TransactionService extends RestService {
9194
+ constructor(http, eventDispatcherService, environment, toastService) {
9149
9195
  super(http, eventDispatcherService, environment);
9150
9196
  this.http = http;
9151
9197
  this.eventDispatcherService = eventDispatcherService;
9152
9198
  this.environment = environment;
9153
- this.modelClass = PropertyDocument;
9154
- this.url = 'properties/documents';
9199
+ this.toastService = toastService;
9200
+ // url part for Transaction API
9201
+ this.url = 'transactions';
9202
+ this.modelClass = Transaction;
9203
+ this.transactionDeleted = new EventEmitter();
9155
9204
  this.listenEvents();
9156
9205
  }
9157
9206
  /**
9158
- * Add new Property Document
9159
- */
9160
- upload(file, propertyId) {
9161
- // create formData object with provided file
9162
- const formDataDocument = new FormData();
9163
- formDataDocument.append('file', file);
9164
- return this.http.post(`${this.environment.apiV2}/properties/${propertyId}/documents`, formDataDocument).pipe(map((documentBase) => {
9165
- const newDocument = plainToClass(PropertyDocument, documentBase);
9166
- if (this.cache) {
9167
- this.cache.push(newDocument);
9168
- this.updateCache();
9169
- }
9170
- return newDocument;
9171
- }));
9172
- }
9173
- /**
9174
- * Get documents by property id
9175
- * @param propertyId to get desired documents
9207
+ * Listen events from Event Dispatcher services
9176
9208
  */
9177
- getByPropertyId(propertyId) {
9178
- return this.get()
9179
- .pipe(map((documents) => {
9180
- return documents
9181
- .filter((document) => document.property.id === propertyId);
9182
- }));
9183
- }
9184
9209
  listenEvents() {
9185
- this.listenPropertyUpdateWithDocument();
9186
- }
9187
- listenPropertyUpdateWithDocument() {
9188
- this.eventDispatcherService.on(AppEventTypeEnum.PROPERTY_UPDATED_WITH_DOCUMENT).subscribe((property) => {
9189
- this.upload(property.documentFile, property.id).subscribe();
9190
- });
9191
- }
9192
- }
9193
- PropertyDocumentService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyDocumentService, deps: [{ token: i1.HttpClient }, { token: EventDispatcherService }, { token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable });
9194
- PropertyDocumentService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyDocumentService, providedIn: 'root' });
9195
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyDocumentService, decorators: [{
9196
- type: Injectable,
9197
- args: [{
9198
- providedIn: 'root'
9199
- }]
9200
- }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: EventDispatcherService }, { type: undefined, decorators: [{
9201
- type: Inject,
9202
- args: ['environment']
9203
- }] }]; } });
9204
-
9205
- // @TODO check and improve logic during refactoring
9206
- class PropertyShareService extends RestService {
9207
- constructor(http, eventDispatcherService, environment) {
9208
- super(http, eventDispatcherService, environment);
9209
- this.http = http;
9210
- this.eventDispatcherService = eventDispatcherService;
9211
- this.environment = environment;
9212
- // api url parameter for properties shares
9213
- this.url = 'properties/shares';
9214
- this.modelClass = PropertyShare;
9215
- this.listenEvents();
9210
+ this.listenDepreciationChange();
9211
+ this.listenPropertyShareUpdate();
9216
9212
  }
9217
9213
  /**
9218
- * Listen to Event Dispatcher events
9214
+ * get list of all user's TaxTank transactions
9219
9215
  */
9220
- listenEvents() {
9221
- this.listenUserUpdated();
9216
+ get() {
9217
+ if (!this.cache) {
9218
+ // set cache as default empty array to avoid multiple backend requests
9219
+ this.cache = [];
9220
+ this.fetch()
9221
+ .subscribe((transactions) => {
9222
+ this.cache = transactions;
9223
+ this.updateCache();
9224
+ });
9225
+ }
9226
+ return this.cacheSubject.asObservable().pipe(
9227
+ // assign child transactions (fees) to parent transactions
9228
+ map((transactions) => {
9229
+ transactions.forEach((transaction) => {
9230
+ transaction.transactions = transactions
9231
+ // get list of child transactions
9232
+ .filter((t) => t.parentTransaction && t.parentTransaction.id === transaction.id);
9233
+ });
9234
+ sort(transactions, 'date', false);
9235
+ return transactions;
9236
+ }));
9222
9237
  }
9223
9238
  /**
9224
- * Updated loan
9239
+ * Add single new transaction
9240
+ * @param model New Transaction instance for saving
9225
9241
  */
9226
- update(propertyShare) {
9227
- return this.http.put(`${this.environment.apiV2}/${this.url}/${propertyShare.id}`, propertyShare)
9228
- .pipe(map((updatedPropertyShareBase) => {
9229
- const updatedPropertyShare = plainToClass(PropertyShare, updatedPropertyShareBase);
9230
- // if loan type is NOT vehicle - fire EventDispatcher event
9231
- this.eventDispatcherService.dispatch(new AppEvent(AppEventTypeEnum.PROPERTY_SHARE_UPDATED, null));
9232
- replace(this.cache, updatedPropertyShare);
9233
- this.updateCache();
9234
- return updatedPropertyShare;
9242
+ add(model) {
9243
+ // we don't have POST API endpoint for single transaction
9244
+ return this.addBatch([model])
9245
+ .pipe(map((newTransactions) => {
9246
+ // @TODO alex
9247
+ this.eventDispatcherService.dispatch(new AppEvent(AppEventTypeEnum.TRANSACTION_CREATED, newTransactions[0]));
9248
+ return newTransactions[0];
9235
9249
  }));
9236
9250
  }
9237
9251
  /**
9238
- * Re-invite property share
9239
- * @param share user to share property
9252
+ * get transactions related with property
9240
9253
  */
9241
- reinvite(share) {
9242
- return this.http.post(`${this.environment.apiV2}/${this.url}/${share.id}/reinvite`, {});
9243
- }
9244
- getIncoming() {
9254
+ getByPropertyId(propertyId) {
9245
9255
  return this.get()
9246
- .pipe(map((propertyShares) => {
9247
- const propertySharesIncoming = [];
9248
- propertyShares.forEach((propertyShare) => {
9256
+ .pipe(map((transactions) => {
9257
+ return transactions.filter((transaction) => {
9249
9258
  var _a;
9250
- if (((_a = propertyShare.user) === null || _a === void 0 ? void 0 : _a.isLoggedIn()) && propertyShare.isPending() && propertyShare.property.user.id !== +localStorage.getItem('userId')) {
9251
- propertySharesIncoming.push(propertyShare);
9252
- }
9259
+ return ((_a = transaction.property) === null || _a === void 0 ? void 0 : _a.id) === propertyId;
9253
9260
  });
9254
- return propertySharesIncoming;
9255
9261
  }));
9256
9262
  }
9257
9263
  /**
9258
- * Get outcoming property shares list
9264
+ * get list of transactions with tank type 'Work'
9259
9265
  */
9260
- getOutcoming() {
9261
- return this.get().pipe(map((propertyShares) => {
9262
- return this.filterOutcoming(propertyShares);
9266
+ getWorkTransactions() {
9267
+ return this.get()
9268
+ .pipe(map((transactions) => {
9269
+ return transactions.filter((transaction) => transaction.isWorkTank());
9263
9270
  }));
9264
9271
  }
9265
9272
  /**
9266
- * Filter outcoming property shares
9273
+ * get list of taxable transactions with tank type 'Work'
9267
9274
  */
9268
- filterOutcoming(propertyShares) {
9269
- const propertySharesOutcoming = [];
9270
- propertyShares.forEach((propertyShare) => {
9271
- var _a;
9272
- if (!((_a = propertyShare.user) === null || _a === void 0 ? void 0 : _a.isLoggedIn())) {
9273
- propertySharesOutcoming.push(propertyShare);
9274
- }
9275
- });
9276
- return propertySharesOutcoming;
9277
- }
9278
- getByPropertyId(propertyId) {
9279
- return this.get()
9280
- .pipe(map((propertyShares) => {
9281
- return propertyShares.filter((propertyShare) => propertyShare.property.id === propertyId);
9275
+ getTaxableWorkTransactions() {
9276
+ return this.getWorkTransactions()
9277
+ .pipe(map((transactions) => {
9278
+ return transactions.filter((transaction) => !!transaction.chartAccounts.taxReturnItem);
9282
9279
  }));
9283
9280
  }
9284
9281
  /**
9285
- * Listen to User updated event
9282
+ * add multiple transactions
9283
+ * @param transactions List of new Transaction instances for saving
9286
9284
  */
9287
- listenUserUpdated() {
9288
- this.eventDispatcherService.on(AppEventTypeEnum.USER_UPDATED)
9289
- .subscribe(() => {
9290
- this.fetch().subscribe((propertyShares) => {
9291
- this.cache = propertyShares;
9292
- this.updateCache();
9285
+ addBatch(transactions) {
9286
+ transactions = _.cloneDeep(transactions);
9287
+ return this.http.post(`${this.environment.apiV2}/${this.url}`, transactions)
9288
+ .pipe(map((response) => {
9289
+ const addedTransactions = response.map((item) => plainToClass(Transaction, item));
9290
+ transactions.forEach((transaction, index) => {
9291
+ // @TODO backend: need to upload file in the same backend endpoint with transaction add/update
9292
+ // check if passed receipt and upload file
9293
+ if (transaction.file) {
9294
+ transaction.id = response[index].id;
9295
+ addedTransactions[index].file = transaction.file;
9296
+ this.uploadReceipt(addedTransactions[index]);
9297
+ }
9298
+ // @TODO Viktor: implement API for saving of nested transactions
9299
+ // add child transactions if exist
9300
+ if (transaction.transactions.length) {
9301
+ transaction.transactions.forEach((childTransaction) => {
9302
+ childTransaction.parentTransaction = plainToClass(Transaction, { id: addedTransactions[index].id });
9303
+ });
9304
+ this.addBatch(transaction.transactions).subscribe();
9305
+ }
9306
+ // add transfer transaction to cache
9307
+ if (transaction.operation === TransactionOperationEnum.TRANSFER) {
9308
+ addedTransactions.push(addedTransactions[0].transfer);
9309
+ }
9293
9310
  });
9294
- });
9311
+ if (this.cache) {
9312
+ this.cache.push(...addedTransactions);
9313
+ this.updateCache();
9314
+ }
9315
+ this.eventDispatcherService.dispatch(new AppEvent(AppEventTypeEnum.TRANSACTIONS_CREATED, addedTransactions));
9316
+ this.toastService.success(MessagesEnum.CREATED_MESSAGE);
9317
+ return addedTransactions;
9318
+ }));
9295
9319
  }
9296
- }
9297
- PropertyShareService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyShareService, deps: [{ token: i1.HttpClient }, { token: EventDispatcherService }, { token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable });
9298
- PropertyShareService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyShareService, providedIn: 'root' });
9299
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyShareService, decorators: [{
9320
+ /**
9321
+ * update existing transaction
9322
+ * @param transaction Transaction instance for updating
9323
+ */
9324
+ update(transaction) {
9325
+ return this.http.put(`${this.environment.apiV2}/${this.url}/${transaction.id}`, transaction)
9326
+ .pipe(map((response) => {
9327
+ const updatedTransaction = plainToClass(Transaction, response);
9328
+ // @TODO need to upload file in the same backend endpoint with transaction add/update
9329
+ // check if passed new receipt and upload file
9330
+ if (transaction.file) {
9331
+ updatedTransaction.file = transaction.file;
9332
+ this.uploadReceipt(updatedTransaction);
9333
+ }
9334
+ // @TODO Viktor: implement API for saving of nested transactions
9335
+ if (transaction.transactions.length) {
9336
+ // add parent transaction to child transactions
9337
+ transaction.transactions.forEach((childTransaction) => {
9338
+ childTransaction.parentTransaction = plainToClass(Transaction, { id: updatedTransaction.id });
9339
+ });
9340
+ // separate child transactions by id existing to define add or update action.
9341
+ const childTransactionsToUpdate = transaction.transactions.filter((t) => t.id);
9342
+ const childTransactionsToAdd = transaction.transactions.filter((t) => !t.id);
9343
+ // update child transactions
9344
+ if (childTransactionsToUpdate.length) {
9345
+ this.updateBatch(childTransactionsToUpdate).subscribe();
9346
+ }
9347
+ // add child transactions
9348
+ if (childTransactionsToAdd.length) {
9349
+ this.addBatch(childTransactionsToAdd).subscribe();
9350
+ }
9351
+ }
9352
+ this.toastService.success(MessagesEnum.UPDATED_MESSAGE);
9353
+ replace(this.cache, updatedTransaction);
9354
+ this.updateCache();
9355
+ return updatedTransaction;
9356
+ }));
9357
+ }
9358
+ /**
9359
+ * update multiple transactions
9360
+ * @param transactions list of transactions for updating
9361
+ */
9362
+ updateBatch(transactions) {
9363
+ return this.http.put(`${this.environment.apiV2}/${this.url}`, transactions)
9364
+ .pipe(map((response) => {
9365
+ const updatedTransactions = response.map((item) => plainToClass(Transaction, item));
9366
+ updatedTransactions.forEach((updatedTransaction) => {
9367
+ replace(this.cache, updatedTransaction);
9368
+ });
9369
+ this.updateCache();
9370
+ return updatedTransactions;
9371
+ }));
9372
+ }
9373
+ /**
9374
+ * delete transaction and related transactions
9375
+ * @param model
9376
+ */
9377
+ delete(model) {
9378
+ return this.http.delete(`${this.environment.apiV2}/${this.url}/${model.id}`)
9379
+ .pipe(map(() => {
9380
+ this.cache = this.cache.filter((transaction) => {
9381
+ var _a;
9382
+ // when delete transfer we delete actually 2 transactions
9383
+ if (model.isTransfer) {
9384
+ const ids = [model.id];
9385
+ // get id of related transfer transaction
9386
+ if (model.transfer) {
9387
+ // just take id if we delete source transaction
9388
+ ids.push(model.transfer.id);
9389
+ }
9390
+ else {
9391
+ // find source transaction id if we delete destination transaction
9392
+ ids.push(this.cache.find((t) => t.transfer.id === model.id).id);
9393
+ }
9394
+ return !ids.includes(transaction.id);
9395
+ }
9396
+ return transaction.id !== model.id && ((_a = transaction.parentTransaction) === null || _a === void 0 ? void 0 : _a.id) !== model.id;
9397
+ });
9398
+ this.eventDispatcherService.dispatch(new AppEvent(AppEventTypeEnum.TRANSACTION_DELETED, model));
9399
+ this.toastService.success(MessagesEnum.DELETED_MESSAGE);
9400
+ this.updateCache();
9401
+ this.transactionDeleted.emit(model);
9402
+ }));
9403
+ }
9404
+ /**
9405
+ * upload transaction receipt image
9406
+ * @param transaction Еhe transaction for which the receipt will be imported
9407
+ */
9408
+ uploadReceipt(transaction) {
9409
+ const formData = new FormData();
9410
+ formData.append('file', transaction.file);
9411
+ transaction.receipt = null;
9412
+ this.http.post(`${this.environment.apiV2}/${this.url}/${transaction.id}/receipts`, formData)
9413
+ .subscribe((receiptResponse) => {
9414
+ // we don't need to keep file after save
9415
+ transaction.file = null;
9416
+ transaction.receipt = plainToClass(TransactionReceipt, receiptResponse);
9417
+ replace(this.cache, transaction);
9418
+ this.updateCache();
9419
+ });
9420
+ }
9421
+ /**
9422
+ * calculate gross income amount based on transaction amount and taxes (fees)
9423
+ * @param transaction Transaction instance for calculation
9424
+ */
9425
+ calculateGrossAmount(transaction) {
9426
+ let amount = transaction.amount || 0;
9427
+ // gross income amount includes amount of fees for property tank and tax for work tank
9428
+ if (transaction.isPropertyTank()) {
9429
+ amount += transaction.transactions.reduce((sum, item) => sum + item.amount, 0);
9430
+ }
9431
+ else {
9432
+ // @TODO Alex: fix logic after TT-641 ready
9433
+ amount += (transaction.tax || 0);
9434
+ }
9435
+ return amount;
9436
+ }
9437
+ /**
9438
+ * get label for transaction tax field depended of selected chart account.
9439
+ * tax type depends of chart account heading or category.
9440
+ */
9441
+ getTaxLabel(chartAccounts) {
9442
+ var _a, _b;
9443
+ // get simple array of ids from enum with taxable chart accounts headings
9444
+ const taxableCAHeadingsIds = enumToList(ChartAccountsHeadingTaxableEnum)
9445
+ .map((item) => item.value);
9446
+ // get simple array of ids from enum with tax deductible chart accounts headings
9447
+ const deductibleCAHeadingsIds = enumToList(ChartAccountsHeadingTaxDeductibleEnum)
9448
+ .map((item) => item.value);
9449
+ // check if one of ids arrays includes current chart accounts heading id and set tax label
9450
+ // otherwise label is empty for this class
9451
+ switch (true) {
9452
+ case taxableCAHeadingsIds.includes((_a = chartAccounts.heading) === null || _a === void 0 ? void 0 : _a.id):
9453
+ return ChartAccountsTaxLabelsEnum.TAX_PAID;
9454
+ case deductibleCAHeadingsIds.includes((_b = chartAccounts.heading) === null || _b === void 0 ? void 0 : _b.id):
9455
+ return ChartAccountsTaxLabelsEnum.TAX_DEDUCTED;
9456
+ case CHART_ACCOUNTS_CATEGORIES.workIncome.includes(chartAccounts.category):
9457
+ return ChartAccountsTaxLabelsEnum.TAX_WITHHELD;
9458
+ default:
9459
+ return null;
9460
+ }
9461
+ }
9462
+ /**
9463
+ * Get transactions related to Vehicle category
9464
+ */
9465
+ getVehicleTransactions() {
9466
+ return this.get().pipe(map((transactions) => {
9467
+ return transactions.filter((transaction) => transaction.isVehicleTransaction());
9468
+ }));
9469
+ }
9470
+ /**
9471
+ * Listen to EventDispatcherService event related to Depreciation changing
9472
+ */
9473
+ listenDepreciationChange() {
9474
+ this.eventDispatcherService.on(AppEventTypeEnum.DEPRECIATION_DELETED).subscribe(() => {
9475
+ this.fetch()
9476
+ .subscribe((transactions) => {
9477
+ this.cache = transactions;
9478
+ this.updateCache();
9479
+ });
9480
+ });
9481
+ }
9482
+ /**
9483
+ * Listen to EventDispatcherService event related to Property Share changing
9484
+ */
9485
+ listenPropertyShareUpdate() {
9486
+ this.eventDispatcherService.on(AppEventTypeEnum.PROPERTY_SHARE_UPDATED).subscribe(() => this.resetCache());
9487
+ }
9488
+ }
9489
+ TransactionService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TransactionService, deps: [{ token: i1.HttpClient }, { token: EventDispatcherService }, { token: 'environment' }, { token: ToastService }], target: i0.ɵɵFactoryTarget.Injectable });
9490
+ TransactionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TransactionService, providedIn: 'root' });
9491
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TransactionService, decorators: [{
9492
+ type: Injectable,
9493
+ args: [{
9494
+ providedIn: 'root'
9495
+ }]
9496
+ }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: EventDispatcherService }, { type: undefined, decorators: [{
9497
+ type: Inject,
9498
+ args: ['environment']
9499
+ }] }, { type: ToastService }]; } });
9500
+
9501
+ /**
9502
+ * Service to handle Property transactions report items data (get income / expense report items, e.t.c.)
9503
+ */
9504
+ class PropertyTransactionReportService {
9505
+ constructor(propertyService, transactionService, depreciationService, chartAccountsService) {
9506
+ this.propertyService = propertyService;
9507
+ this.transactionService = transactionService;
9508
+ this.depreciationService = depreciationService;
9509
+ this.chartAccountsService = chartAccountsService;
9510
+ }
9511
+ /**
9512
+ * Get collection of report items based on transactions & depreciations
9513
+ */
9514
+ get() {
9515
+ return combineLatest([
9516
+ this.propertyService.get(),
9517
+ this.getTransactions(),
9518
+ this.getDepreciations(),
9519
+ this.chartAccountsService.getChartAccounts()
9520
+ ]).pipe(map(([properties, transactions, depreciations, chartAccounts]) => {
9521
+ return new CollectionDictionary(this.create(transactions, depreciations, new PropertyCollection(properties), new Collection(chartAccounts)), 'propertyId');
9522
+ }));
9523
+ }
9524
+ create(transactions, depreciations, properties, chartAccounts) {
9525
+ return new PropertyReportItemCollection([
9526
+ ...new PropertyReportItemTransactionCollection(transactions, properties, chartAccounts).items,
9527
+ ...new PropertyReportItemDepreciationCollection(depreciations, properties, chartAccounts).items,
9528
+ ]);
9529
+ }
9530
+ /**
9531
+ * Get collection of property transactions
9532
+ */
9533
+ getTransactions() {
9534
+ return this.transactionService.get().pipe(map((transactions) => {
9535
+ return new TransactionCollection(transactions)
9536
+ .getByChartAccountsCategories(CHART_ACCOUNTS_CATEGORIES.property);
9537
+ }));
9538
+ }
9539
+ /**
9540
+ * Get list of asset & capital property depreciations
9541
+ */
9542
+ getDepreciations() {
9543
+ return this.depreciationService.get().pipe(map((depreciations) => {
9544
+ return new DepreciationCollection(depreciations)
9545
+ .getByChartAccountsCategories(CHART_ACCOUNTS_CATEGORIES.property)
9546
+ // we don't need borrowing expenses for this report
9547
+ .getWithoutBorrowingExpenses();
9548
+ }));
9549
+ }
9550
+ }
9551
+ PropertyTransactionReportService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyTransactionReportService, deps: [{ token: PropertyService }, { token: TransactionService }, { token: DepreciationService }, { token: ChartAccountsService }], target: i0.ɵɵFactoryTarget.Injectable });
9552
+ PropertyTransactionReportService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyTransactionReportService, providedIn: 'root' });
9553
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyTransactionReportService, decorators: [{
9554
+ type: Injectable,
9555
+ args: [{
9556
+ providedIn: 'root'
9557
+ }]
9558
+ }], ctorParameters: function () { return [{ type: PropertyService }, { type: TransactionService }, { type: DepreciationService }, { type: ChartAccountsService }]; } });
9559
+
9560
+ /**
9561
+ * Service with calculations methods for properties related with other entities.
9562
+ * Logic here works like collections methods but for several entities
9563
+ */
9564
+ class PropertyCalculationService {
9565
+ getTaxPosition(transactions, depreciations) {
9566
+ // @TODO hack: math abs added because we have mismatching of real values signs
9567
+ return transactions.cashPosition - Math.abs(depreciations.claimAmount);
9568
+ }
9569
+ getTaxPosition$(transactions$, depreciations$) {
9570
+ return combineLatest([
9571
+ transactions$,
9572
+ depreciations$
9573
+ ]).pipe(map(([transactions, depreciations]) => {
9574
+ return this.getTaxPosition(transactions, depreciations);
9575
+ }));
9576
+ }
9577
+ taxPositionGrowth(properties, transactions, depreciations) {
9578
+ const taxPosition = this.getTaxPosition(transactions, depreciations);
9579
+ // check if taxPosition = 0 to avoid division by zero
9580
+ if (!taxPosition) {
9581
+ return 0;
9582
+ }
9583
+ return (taxPosition - properties.forecastedTaxPosition) / taxPosition;
9584
+ }
9585
+ taxPositionGrowth$(properties$, transactions$, depreciations$) {
9586
+ return combineLatest([
9587
+ properties$,
9588
+ transactions$,
9589
+ depreciations$
9590
+ ]).pipe(map(([properties, transactions, depreciations]) => {
9591
+ return this.taxPositionGrowth(properties, transactions, depreciations);
9592
+ }));
9593
+ }
9594
+ getRentalReturn(properties, transactions) {
9595
+ return transactions.claimIncome / properties.marketValue;
9596
+ }
9597
+ getLoanAmount(properties, bankAccounts, loans) {
9598
+ return properties.items.reduce((totalAmount, property) => {
9599
+ return totalAmount + bankAccounts.items
9600
+ .reduce((propertyAmount, bankAccount) => {
9601
+ var _a;
9602
+ return propertyAmount + bankAccount.getPropertyPercentage(property.id) * (((_a = loans.getByBankAccountId(bankAccount.id)) === null || _a === void 0 ? void 0 : _a.amount) || 0);
9603
+ }, 0);
9604
+ }, 0);
9605
+ }
9606
+ getLoanValue(properties, bankAccounts) {
9607
+ return properties.items.reduce((totalAmount, property) => {
9608
+ return totalAmount + bankAccounts.items
9609
+ .reduce((propertyAmount, bankAccount) => {
9610
+ return propertyAmount + bankAccount.getPropertyBalanceAmount(property.id);
9611
+ }, 0);
9612
+ }, 0);
9613
+ }
9614
+ /**
9615
+ * LVR
9616
+ */
9617
+ getLvr(properties, bankAccounts) {
9618
+ // Math abs is required for correct percentage calculation
9619
+ return Math.abs(this.getLoanValue(properties, bankAccounts)) / properties.marketValue;
9620
+ }
9621
+ getLvr$(properties$, bankAccounts$) {
9622
+ return combineLatest([
9623
+ properties$,
9624
+ bankAccounts$
9625
+ ]).pipe(map(([properties, bankAccounts]) => {
9626
+ return this.getLvr(properties, bankAccounts);
9627
+ }));
9628
+ }
9629
+ getLvrCommencement(properties, loans, bankAccounts) {
9630
+ // Math abs is required for correct percentage calculation
9631
+ return Math.abs(this.getLoanAmount(properties, bankAccounts, loans)) / properties.purchasePrice;
9632
+ }
9633
+ getLvrCommencement$(properties$, bankAccounts$, loans$) {
9634
+ return combineLatest([
9635
+ properties$,
9636
+ bankAccounts$,
9637
+ loans$
9638
+ ]).pipe(map(([properties, bankAccounts, loans]) => {
9639
+ return this.getLvrCommencement(properties, loans, bankAccounts);
9640
+ }));
9641
+ }
9642
+ getLvrGrowth(properties, bankAccounts, loans) {
9643
+ const lvr = this.getLvr(properties, bankAccounts);
9644
+ if (!lvr) {
9645
+ // check if lvr = 0 to avoid division by zero
9646
+ return 0;
9647
+ }
9648
+ return (lvr - this.getLvrCommencement(properties, loans, bankAccounts)) / lvr;
9649
+ }
9650
+ getLvrGrowth$(properties$, bankAccounts$, loans$) {
9651
+ return combineLatest([
9652
+ properties$,
9653
+ bankAccounts$,
9654
+ loans$
9655
+ ]).pipe(map(([properties, bankAccounts, loans]) => {
9656
+ return this.getLvrGrowth(properties, bankAccounts, loans);
9657
+ }));
9658
+ }
9659
+ getEquityPosition(properties, bankAccounts) {
9660
+ // Math abs is required for correct percentage calculation
9661
+ return properties.marketValue - Math.abs(this.getLoanValue(properties, bankAccounts));
9662
+ }
9663
+ getPurchaseEquity(properties, bankAccounts, loans) {
9664
+ // Math abs is required for correct percentage calculation
9665
+ return properties.purchasePrice - Math.abs(this.getLoanAmount(properties, bankAccounts, loans));
9666
+ }
9667
+ }
9668
+ PropertyCalculationService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyCalculationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
9669
+ PropertyCalculationService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyCalculationService, providedIn: 'root' });
9670
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyCalculationService, decorators: [{
9671
+ type: Injectable,
9672
+ args: [{
9673
+ providedIn: 'root'
9674
+ }]
9675
+ }] });
9676
+
9677
+ /**
9678
+ * Service for work with Property Categories
9679
+ */
9680
+ class PropertyCategoryService extends RestService {
9681
+ constructor() {
9682
+ super(...arguments);
9683
+ this.modelClass = PropertyCategory;
9684
+ this.url = 'properties/categories';
9685
+ }
9686
+ }
9687
+ PropertyCategoryService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyCategoryService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
9688
+ PropertyCategoryService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyCategoryService, providedIn: 'root' });
9689
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyCategoryService, decorators: [{
9690
+ type: Injectable,
9691
+ args: [{
9692
+ providedIn: 'root'
9693
+ }]
9694
+ }] });
9695
+
9696
+ /**
9697
+ * Class for work with Property Documents
9698
+ */
9699
+ class PropertyDocumentService extends RestService {
9700
+ constructor(http, eventDispatcherService, environment) {
9701
+ super(http, eventDispatcherService, environment);
9702
+ this.http = http;
9703
+ this.eventDispatcherService = eventDispatcherService;
9704
+ this.environment = environment;
9705
+ this.modelClass = PropertyDocument;
9706
+ this.url = 'properties/documents';
9707
+ this.listenEvents();
9708
+ }
9709
+ /**
9710
+ * Add new Property Document
9711
+ */
9712
+ upload(file, propertyId) {
9713
+ // create formData object with provided file
9714
+ const formDataDocument = new FormData();
9715
+ formDataDocument.append('file', file);
9716
+ return this.http.post(`${this.environment.apiV2}/properties/${propertyId}/documents`, formDataDocument).pipe(map((documentBase) => {
9717
+ const newDocument = plainToClass(PropertyDocument, documentBase);
9718
+ if (this.cache) {
9719
+ this.cache.push(newDocument);
9720
+ this.updateCache();
9721
+ }
9722
+ return newDocument;
9723
+ }));
9724
+ }
9725
+ /**
9726
+ * Get documents by property id
9727
+ * @param propertyId to get desired documents
9728
+ */
9729
+ getByPropertyId(propertyId) {
9730
+ return this.get()
9731
+ .pipe(map((documents) => {
9732
+ return documents
9733
+ .filter((document) => document.property.id === propertyId);
9734
+ }));
9735
+ }
9736
+ listenEvents() {
9737
+ this.listenPropertyUpdateWithDocument();
9738
+ }
9739
+ listenPropertyUpdateWithDocument() {
9740
+ this.eventDispatcherService.on(AppEventTypeEnum.PROPERTY_UPDATED_WITH_DOCUMENT).subscribe((property) => {
9741
+ this.upload(property.documentFile, property.id).subscribe();
9742
+ });
9743
+ }
9744
+ }
9745
+ PropertyDocumentService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyDocumentService, deps: [{ token: i1.HttpClient }, { token: EventDispatcherService }, { token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable });
9746
+ PropertyDocumentService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyDocumentService, providedIn: 'root' });
9747
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyDocumentService, decorators: [{
9748
+ type: Injectable,
9749
+ args: [{
9750
+ providedIn: 'root'
9751
+ }]
9752
+ }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: EventDispatcherService }, { type: undefined, decorators: [{
9753
+ type: Inject,
9754
+ args: ['environment']
9755
+ }] }]; } });
9756
+
9757
+ // @TODO check and improve logic during refactoring
9758
+ class PropertyShareService extends RestService {
9759
+ constructor(http, eventDispatcherService, environment) {
9760
+ super(http, eventDispatcherService, environment);
9761
+ this.http = http;
9762
+ this.eventDispatcherService = eventDispatcherService;
9763
+ this.environment = environment;
9764
+ // api url parameter for properties shares
9765
+ this.url = 'properties/shares';
9766
+ this.modelClass = PropertyShare;
9767
+ this.listenEvents();
9768
+ }
9769
+ /**
9770
+ * Listen to Event Dispatcher events
9771
+ */
9772
+ listenEvents() {
9773
+ this.listenUserUpdated();
9774
+ }
9775
+ /**
9776
+ * Updated loan
9777
+ */
9778
+ update(propertyShare) {
9779
+ return this.http.put(`${this.environment.apiV2}/${this.url}/${propertyShare.id}`, propertyShare)
9780
+ .pipe(map((updatedPropertyShareBase) => {
9781
+ const updatedPropertyShare = plainToClass(PropertyShare, updatedPropertyShareBase);
9782
+ // if loan type is NOT vehicle - fire EventDispatcher event
9783
+ this.eventDispatcherService.dispatch(new AppEvent(AppEventTypeEnum.PROPERTY_SHARE_UPDATED, null));
9784
+ replace(this.cache, updatedPropertyShare);
9785
+ this.updateCache();
9786
+ return updatedPropertyShare;
9787
+ }));
9788
+ }
9789
+ /**
9790
+ * Re-invite property share
9791
+ * @param share user to share property
9792
+ */
9793
+ reinvite(share) {
9794
+ return this.http.post(`${this.environment.apiV2}/${this.url}/${share.id}/reinvite`, {});
9795
+ }
9796
+ getIncoming() {
9797
+ return this.get()
9798
+ .pipe(map((propertyShares) => {
9799
+ const propertySharesIncoming = [];
9800
+ propertyShares.forEach((propertyShare) => {
9801
+ var _a;
9802
+ if (((_a = propertyShare.user) === null || _a === void 0 ? void 0 : _a.isLoggedIn()) && propertyShare.isPending() && propertyShare.property.user.id !== +localStorage.getItem('userId')) {
9803
+ propertySharesIncoming.push(propertyShare);
9804
+ }
9805
+ });
9806
+ return propertySharesIncoming;
9807
+ }));
9808
+ }
9809
+ /**
9810
+ * Get outcoming property shares list
9811
+ */
9812
+ getOutcoming() {
9813
+ return this.get().pipe(map((propertyShares) => {
9814
+ return this.filterOutcoming(propertyShares);
9815
+ }));
9816
+ }
9817
+ /**
9818
+ * Filter outcoming property shares
9819
+ */
9820
+ filterOutcoming(propertyShares) {
9821
+ const propertySharesOutcoming = [];
9822
+ propertyShares.forEach((propertyShare) => {
9823
+ var _a;
9824
+ if (!((_a = propertyShare.user) === null || _a === void 0 ? void 0 : _a.isLoggedIn())) {
9825
+ propertySharesOutcoming.push(propertyShare);
9826
+ }
9827
+ });
9828
+ return propertySharesOutcoming;
9829
+ }
9830
+ getByPropertyId(propertyId) {
9831
+ return this.get()
9832
+ .pipe(map((propertyShares) => {
9833
+ return propertyShares.filter((propertyShare) => propertyShare.property.id === propertyId);
9834
+ }));
9835
+ }
9836
+ /**
9837
+ * Listen to User updated event
9838
+ */
9839
+ listenUserUpdated() {
9840
+ this.eventDispatcherService.on(AppEventTypeEnum.USER_UPDATED)
9841
+ .subscribe(() => {
9842
+ this.fetch().subscribe((propertyShares) => {
9843
+ this.cache = propertyShares;
9844
+ this.updateCache();
9845
+ });
9846
+ });
9847
+ }
9848
+ }
9849
+ PropertyShareService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyShareService, deps: [{ token: i1.HttpClient }, { token: EventDispatcherService }, { token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable });
9850
+ PropertyShareService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyShareService, providedIn: 'root' });
9851
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: PropertyShareService, decorators: [{
9300
9852
  type: Injectable,
9301
9853
  args: [{
9302
9854
  providedIn: 'root'
@@ -9489,615 +10041,233 @@ class SubscriptionService {
9489
10041
  */
9490
10042
  billingRedirect(returnUrl) {
9491
10043
  this.http.get(`${this.environment.apiV2}/stripe/billing-portal-session`, {
9492
- params: { returnUrl }
9493
- }).subscribe((response) => {
9494
- window.location.replace(response.url);
9495
- });
9496
- }
9497
- getPayments() {
9498
- if (!this._servicePayments) {
9499
- this.http.get(`${this.environment.apiV2}/service-payments`).subscribe((response) => {
9500
- this._servicePayments = response.map((item) => plainToClass(ServicePayment, item));
9501
- this.servicePaymentsSubject.next(this._servicePayments);
9502
- });
9503
- }
9504
- return this.servicePaymentsSubject.asObservable();
9505
- }
9506
- /**
9507
- * Get difference between current subscription and selected new subscription
9508
- */
9509
- getProrationCost(items) {
9510
- return this.http.post(`${this.environment.apiV2}/subscriptions/proration-cost`, items).pipe(map((prorationCost) => {
9511
- return prorationCost;
9512
- }));
9513
- }
9514
- /**
9515
- * Change subscription plan
9516
- */
9517
- changeSubscription(items) {
9518
- return this.http.put(`${this.environment.apiV2}/subscriptions/items`, items);
9519
- }
9520
- listenSubscriptions() {
9521
- this.sseService.on(`serviceSubscriptions`)
9522
- .pipe(map((event) => plainToClass(ServiceSubscription, event)))
9523
- .subscribe((subscription) => {
9524
- this.getSubscription(true).subscribe();
9525
- this.subscriptionChangeSubject.next(subscription);
9526
- this.eventDispatcherService.dispatch(new AppEvent(AppEventTypeEnum.SERVICE_SUBSCRIPTION_UPDATED, null));
9527
- });
9528
- }
9529
- }
9530
- SubscriptionService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: SubscriptionService, deps: [{ token: i1.HttpClient }, { token: EventDispatcherService }, { token: SseService }, { token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable });
9531
- SubscriptionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: SubscriptionService, providedIn: 'root' });
9532
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: SubscriptionService, decorators: [{
9533
- type: Injectable,
9534
- args: [{
9535
- providedIn: 'root'
9536
- }]
9537
- }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: EventDispatcherService }, { type: SseService }, { type: undefined, decorators: [{
9538
- type: Inject,
9539
- args: ['environment']
9540
- }] }]; } });
9541
-
9542
- /**
9543
- * Service to work with tax review
9544
- */
9545
- class TaxReviewService extends RestService {
9546
- constructor(http, eventDispatcherService, environment) {
9547
- super(http, eventDispatcherService, environment);
9548
- this.http = http;
9549
- this.eventDispatcherService = eventDispatcherService;
9550
- this.environment = environment;
9551
- this.url = 'tax-reviews';
9552
- this.modelClass = TaxReview;
9553
- this.listenEvents();
9554
- }
9555
- /**
9556
- * Listen events from SSE and Event Dispatcher services
9557
- */
9558
- listenEvents() {
9559
- this.listenFirmChanges();
9560
- this.listenClientTransfer();
9561
- }
9562
- /**
9563
- * Add new Tax Review (request from client to firm)
9564
- * @param finYear
9565
- */
9566
- request(finYear) {
9567
- return this.http.post(`${this.environment.apiV2}/${this.url}?financialYear=${finYear}`, {})
9568
- .pipe(map((newTaxReview) => {
9569
- const taxReview = plainToClass(TaxReview, newTaxReview);
9570
- const tempCache = _.cloneDeep(this.cache);
9571
- tempCache.push(taxReview);
9572
- this.cache = tempCache;
9573
- this.updateCache();
9574
- return taxReview;
9575
- }));
9576
- }
9577
- /**
9578
- * Update tax review
9579
- * @param taxReview to be updated
9580
- */
9581
- update(taxReview) {
9582
- return this.http.put(`${this.environment.apiV2}/${this.url}/${taxReview.id}`, taxReview)
9583
- .pipe(map((updatedTaxReview) => {
9584
- const updatedInstance = plainToClass(TaxReview, updatedTaxReview);
9585
- this.eventDispatcherService.dispatch(new AppEvent(AppEventTypeEnum.TAX_REVIEW_UPDATED, updatedInstance));
9586
- const tempCache = _.cloneDeep(this.cache);
9587
- replace(tempCache, updatedInstance);
9588
- this.cache = tempCache;
9589
- this.updateCache();
9590
- return updatedInstance;
9591
- }));
9592
- }
9593
- /**
9594
- * Clear cache when user reject firm
9595
- */
9596
- listenFirmChanges() {
9597
- this.eventDispatcherService.on([AppEventTypeEnum.CLIENT_MOVEMENT_CLOSED, AppEventTypeEnum.CLIENT_INVITE_ACCEPTED])
9598
- .subscribe(() => {
9599
- this.cache = [];
9600
- this.updateCache();
9601
- });
9602
- }
9603
- /**
9604
- * Update firm for all transferred clients
9605
- * @private
9606
- */
9607
- listenClientTransfer() {
9608
- this.eventDispatcherService.on(AppEventTypeEnum.CLIENT_TRANSFER_TO_OTHER_EMPLOYEE)
9609
- .subscribe((transferredClients) => {
9610
- const tempCache = _.cloneDeep(this.cache);
9611
- transferredClients.forEach((transferredClient) => {
9612
- const taxReviewIndex = tempCache.findIndex((taxReview) => taxReview.id === transferredClient.id);
9613
- // @TODO vik
9614
- // tempCache[taxReviewIndex].employee = transferredClient.accountant;
9615
- });
9616
- this.cache = tempCache;
9617
- this.updateCache();
9618
- });
9619
- }
9620
- }
9621
- TaxReviewService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TaxReviewService, deps: [{ token: i1.HttpClient }, { token: EventDispatcherService }, { token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable });
9622
- TaxReviewService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TaxReviewService, providedIn: 'root' });
9623
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TaxReviewService, decorators: [{
9624
- type: Injectable,
9625
- args: [{
9626
- providedIn: 'root'
9627
- }]
9628
- }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: EventDispatcherService }, { type: undefined, decorators: [{
9629
- type: Inject,
9630
- args: ['environment']
9631
- }] }]; } });
9632
-
9633
- /**
9634
- * Service to work with tax review history
9635
- */
9636
- class TaxReviewHistoryService extends RestService {
9637
- constructor(http, eventDispatcherService, environment) {
9638
- super(http, eventDispatcherService, environment);
9639
- this.http = http;
9640
- this.eventDispatcherService = eventDispatcherService;
9641
- this.environment = environment;
9642
- this.url = 'tax-reviews/history';
9643
- this.modelClass = TaxReview;
9644
- // subscribe on tax review updating
9645
- eventDispatcherService.on(AppEventTypeEnum.TAX_REVIEW_UPDATED).subscribe((taxReview) => {
9646
- const tempCache = _.cloneDeep(this.cache);
9647
- // insert element at the beginning of the array
9648
- tempCache.unshift(taxReview);
9649
- this.cache = tempCache;
9650
- this.updateCache();
9651
- });
9652
- }
9653
- }
9654
- TaxReviewHistoryService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TaxReviewHistoryService, deps: [{ token: i1.HttpClient }, { token: EventDispatcherService }, { token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable });
9655
- TaxReviewHistoryService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TaxReviewHistoryService, providedIn: 'root' });
9656
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TaxReviewHistoryService, decorators: [{
9657
- type: Injectable,
9658
- args: [{
9659
- providedIn: 'root'
9660
- }]
9661
- }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: EventDispatcherService }, { type: undefined, decorators: [{
9662
- type: Inject,
9663
- args: ['environment']
9664
- }] }]; } });
9665
-
9666
- /**
9667
- * Service to work with tax summary logic
9668
- */
9669
- class TaxSummaryService {
9670
- constructor(http, eventDispatcherService, environment) {
9671
- this.http = http;
9672
- this.eventDispatcherService = eventDispatcherService;
9673
- this.environment = environment;
9674
- this.taxSummaryActualsSubject = new ReplaySubject(1);
9675
- this.taxSummaryForecastsSubject = new ReplaySubject(1);
9676
- this.listenEvents();
9677
- }
9678
- listenEvents() {
9679
- this.listenToIncomeSourceForecastsEvents();
9680
- }
9681
- /**
9682
- * Get actual tax summary items
9683
- */
9684
- getActuals() {
9685
- this.http.get(`${this.environment.apiV2}/tax-summary/${TaxSummaryTypeEnum.ACTUALS}`, {})
9686
- .subscribe((response) => {
9687
- const taxSummary = plainToClass(TaxSummary, response);
9688
- this.taxSummaryActualsSubject.next(taxSummary);
9689
- return taxSummary;
10044
+ params: { returnUrl }
10045
+ }).subscribe((response) => {
10046
+ window.location.replace(response.url);
9690
10047
  });
9691
- return this.taxSummaryActualsSubject.asObservable();
10048
+ }
10049
+ getPayments() {
10050
+ if (!this._servicePayments) {
10051
+ this.http.get(`${this.environment.apiV2}/service-payments`).subscribe((response) => {
10052
+ this._servicePayments = response.map((item) => plainToClass(ServicePayment, item));
10053
+ this.servicePaymentsSubject.next(this._servicePayments);
10054
+ });
10055
+ }
10056
+ return this.servicePaymentsSubject.asObservable();
9692
10057
  }
9693
10058
  /**
9694
- * Get forecast tax summary items
10059
+ * Get difference between current subscription and selected new subscription
9695
10060
  */
9696
- getForecast() {
9697
- this.http.get(`${this.environment.apiV2}/tax-summary/${TaxSummaryTypeEnum.FORECASTS}`, {})
9698
- .subscribe((response) => {
9699
- const taxSummary = plainToClass(TaxSummary, response);
9700
- this.taxSummaryForecastsSubject.next(taxSummary);
9701
- return taxSummary;
9702
- });
9703
- return this.taxSummaryForecastsSubject.asObservable();
10061
+ getProrationCost(items) {
10062
+ return this.http.post(`${this.environment.apiV2}/subscriptions/proration-cost`, items).pipe(map((prorationCost) => {
10063
+ return prorationCost;
10064
+ }));
9704
10065
  }
9705
10066
  /**
9706
- * Listen to EventDispatcherService events related to Income source forecasts
10067
+ * Change subscription plan
9707
10068
  */
9708
- listenToIncomeSourceForecastsEvents() {
9709
- this.eventDispatcherService
9710
- .on([AppEventTypeEnum.INCOME_SOURCES_FORECASTS_CREATED, AppEventTypeEnum.INCOME_SOURCES_FORECASTS_UPDATED])
9711
- .subscribe(() => {
9712
- this.getForecast().subscribe();
10069
+ changeSubscription(items) {
10070
+ return this.http.put(`${this.environment.apiV2}/subscriptions/items`, items);
10071
+ }
10072
+ listenSubscriptions() {
10073
+ this.sseService.on(`serviceSubscriptions`)
10074
+ .pipe(map((event) => plainToClass(ServiceSubscription, event)))
10075
+ .subscribe((subscription) => {
10076
+ this.getSubscription(true).subscribe();
10077
+ this.subscriptionChangeSubject.next(subscription);
10078
+ this.eventDispatcherService.dispatch(new AppEvent(AppEventTypeEnum.SERVICE_SUBSCRIPTION_UPDATED, null));
9713
10079
  });
9714
10080
  }
9715
10081
  }
9716
- TaxSummaryService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TaxSummaryService, deps: [{ token: i1.HttpClient }, { token: EventDispatcherService }, { token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable });
9717
- TaxSummaryService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TaxSummaryService, providedIn: 'root' });
9718
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TaxSummaryService, decorators: [{
10082
+ SubscriptionService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: SubscriptionService, deps: [{ token: i1.HttpClient }, { token: EventDispatcherService }, { token: SseService }, { token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable });
10083
+ SubscriptionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: SubscriptionService, providedIn: 'root' });
10084
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: SubscriptionService, decorators: [{
9719
10085
  type: Injectable,
9720
10086
  args: [{
9721
10087
  providedIn: 'root'
9722
10088
  }]
9723
- }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: EventDispatcherService }, { type: undefined, decorators: [{
10089
+ }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: EventDispatcherService }, { type: SseService }, { type: undefined, decorators: [{
9724
10090
  type: Inject,
9725
10091
  args: ['environment']
9726
10092
  }] }]; } });
9727
10093
 
9728
10094
  /**
9729
- * popup notifications service (toast, snackbar).
9730
- */
9731
- class ToastService {
9732
- constructor() {
9733
- this.toast$ = new ReplaySubject(1);
9734
- }
9735
- get() {
9736
- return this.toast$.asObservable();
9737
- }
9738
- add(toast) {
9739
- this.toast$.next(toast);
9740
- }
9741
- success(message) {
9742
- this.add(plainToClass(Toast, {
9743
- type: ToastTypeEnum.SUCCESS,
9744
- title: 'Success!',
9745
- message,
9746
- }));
9747
- }
9748
- warning(message) {
9749
- this.add(plainToClass(Toast, {
9750
- type: ToastTypeEnum.WARNING,
9751
- title: 'Warning!',
9752
- message,
9753
- }));
9754
- }
9755
- error(message) {
9756
- this.add(plainToClass(Toast, {
9757
- type: ToastTypeEnum.ERROR,
9758
- title: 'Error!',
9759
- message,
9760
- }));
9761
- }
9762
- info(message) {
9763
- this.add(plainToClass(Toast, {
9764
- type: ToastTypeEnum.INFO,
9765
- title: 'Information',
9766
- message,
9767
- }));
9768
- }
9769
- }
9770
- ToastService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: ToastService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
9771
- ToastService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: ToastService, providedIn: 'root' });
9772
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: ToastService, decorators: [{
9773
- type: Injectable,
9774
- args: [{
9775
- providedIn: 'root'
9776
- }]
9777
- }] });
9778
-
9779
- function enumToList(data) {
9780
- const list = [];
9781
- for (const key in data) {
9782
- if (Number(key) >= 0) {
9783
- list.push({
9784
- label: data[key],
9785
- value: Number(key)
9786
- });
9787
- }
9788
- }
9789
- return list;
9790
- }
9791
-
9792
- var MessagesEnum;
9793
- (function (MessagesEnum) {
9794
- MessagesEnum["DELETED_MESSAGE"] = "Transaction deleted";
9795
- MessagesEnum["UPDATED_MESSAGE"] = "Transaction updated";
9796
- MessagesEnum["CREATED_MESSAGE"] = "Transaction(s) created";
9797
- })(MessagesEnum || (MessagesEnum = {}));
9798
-
9799
- /**
9800
- * Service for transactions business logic
10095
+ * Service to work with tax review
9801
10096
  */
9802
- class TransactionService extends RestService {
9803
- constructor(http, eventDispatcherService, environment, toastService) {
10097
+ class TaxReviewService extends RestService {
10098
+ constructor(http, eventDispatcherService, environment) {
9804
10099
  super(http, eventDispatcherService, environment);
9805
10100
  this.http = http;
9806
10101
  this.eventDispatcherService = eventDispatcherService;
9807
10102
  this.environment = environment;
9808
- this.toastService = toastService;
9809
- // url part for Transaction API
9810
- this.url = 'transactions';
9811
- this.modelClass = Transaction;
9812
- this.transactionDeleted = new EventEmitter();
10103
+ this.url = 'tax-reviews';
10104
+ this.modelClass = TaxReview;
9813
10105
  this.listenEvents();
9814
10106
  }
9815
10107
  /**
9816
- * Listen events from Event Dispatcher services
10108
+ * Listen events from SSE and Event Dispatcher services
9817
10109
  */
9818
10110
  listenEvents() {
9819
- this.listenDepreciationChange();
9820
- this.listenPropertyShareUpdate();
9821
- }
9822
- /**
9823
- * get list of all user's TaxTank transactions
9824
- */
9825
- get() {
9826
- if (!this.cache) {
9827
- // set cache as default empty array to avoid multiple backend requests
9828
- this.cache = [];
9829
- this.fetch()
9830
- .subscribe((transactions) => {
9831
- this.cache = transactions;
9832
- this.updateCache();
9833
- });
9834
- }
9835
- return this.cacheSubject.asObservable().pipe(
9836
- // assign child transactions (fees) to parent transactions
9837
- map((transactions) => {
9838
- transactions.forEach((transaction) => {
9839
- transaction.transactions = transactions
9840
- // get list of child transactions
9841
- .filter((t) => t.parentTransaction && t.parentTransaction.id === transaction.id);
9842
- });
9843
- sort(transactions, 'date', false);
9844
- return transactions;
9845
- }));
9846
- }
9847
- /**
9848
- * Add single new transaction
9849
- * @param model New Transaction instance for saving
9850
- */
9851
- add(model) {
9852
- // we don't have POST API endpoint for single transaction
9853
- return this.addBatch([model])
9854
- .pipe(map((newTransactions) => {
9855
- // @TODO alex
9856
- this.eventDispatcherService.dispatch(new AppEvent(AppEventTypeEnum.TRANSACTION_CREATED, newTransactions[0]));
9857
- return newTransactions[0];
9858
- }));
9859
- }
9860
- /**
9861
- * get transactions related with property
9862
- */
9863
- getByPropertyId(propertyId) {
9864
- return this.get()
9865
- .pipe(map((transactions) => {
9866
- return transactions.filter((transaction) => {
9867
- var _a;
9868
- return ((_a = transaction.property) === null || _a === void 0 ? void 0 : _a.id) === propertyId;
9869
- });
9870
- }));
9871
- }
9872
- /**
9873
- * get list of transactions with tank type 'Work'
9874
- */
9875
- getWorkTransactions() {
9876
- return this.get()
9877
- .pipe(map((transactions) => {
9878
- return transactions.filter((transaction) => transaction.isWorkTank());
9879
- }));
9880
- }
9881
- /**
9882
- * get list of taxable transactions with tank type 'Work'
9883
- */
9884
- getTaxableWorkTransactions() {
9885
- return this.getWorkTransactions()
9886
- .pipe(map((transactions) => {
9887
- return transactions.filter((transaction) => !!transaction.chartAccounts.taxReturnItem);
9888
- }));
10111
+ this.listenFirmChanges();
10112
+ this.listenClientTransfer();
9889
10113
  }
9890
10114
  /**
9891
- * add multiple transactions
9892
- * @param transactions List of new Transaction instances for saving
10115
+ * Add new Tax Review (request from client to firm)
10116
+ * @param finYear
9893
10117
  */
9894
- addBatch(transactions) {
9895
- transactions = _.cloneDeep(transactions);
9896
- return this.http.post(`${this.environment.apiV2}/${this.url}`, transactions)
9897
- .pipe(map((response) => {
9898
- const addedTransactions = response.map((item) => plainToClass(Transaction, item));
9899
- transactions.forEach((transaction, index) => {
9900
- // @TODO backend: need to upload file in the same backend endpoint with transaction add/update
9901
- // check if passed receipt and upload file
9902
- if (transaction.file) {
9903
- transaction.id = response[index].id;
9904
- addedTransactions[index].file = transaction.file;
9905
- this.uploadReceipt(addedTransactions[index]);
9906
- }
9907
- // @TODO Viktor: implement API for saving of nested transactions
9908
- // add child transactions if exist
9909
- if (transaction.transactions.length) {
9910
- transaction.transactions.forEach((childTransaction) => {
9911
- childTransaction.parentTransaction = plainToClass(Transaction, { id: addedTransactions[index].id });
9912
- });
9913
- this.addBatch(transaction.transactions).subscribe();
9914
- }
9915
- // add transfer transaction to cache
9916
- if (transaction.operation === TransactionOperationEnum.TRANSFER) {
9917
- addedTransactions.push(addedTransactions[0].transfer);
9918
- }
9919
- });
9920
- if (this.cache) {
9921
- this.cache.push(...addedTransactions);
9922
- this.updateCache();
9923
- }
9924
- this.eventDispatcherService.dispatch(new AppEvent(AppEventTypeEnum.TRANSACTIONS_CREATED, addedTransactions));
9925
- this.toastService.success(MessagesEnum.CREATED_MESSAGE);
9926
- return addedTransactions;
10118
+ request(finYear) {
10119
+ return this.http.post(`${this.environment.apiV2}/${this.url}?financialYear=${finYear}`, {})
10120
+ .pipe(map((newTaxReview) => {
10121
+ const taxReview = plainToClass(TaxReview, newTaxReview);
10122
+ const tempCache = _.cloneDeep(this.cache);
10123
+ tempCache.push(taxReview);
10124
+ this.cache = tempCache;
10125
+ this.updateCache();
10126
+ return taxReview;
9927
10127
  }));
9928
10128
  }
9929
10129
  /**
9930
- * update existing transaction
9931
- * @param transaction Transaction instance for updating
10130
+ * Update tax review
10131
+ * @param taxReview to be updated
9932
10132
  */
9933
- update(transaction) {
9934
- return this.http.put(`${this.environment.apiV2}/${this.url}/${transaction.id}`, transaction)
9935
- .pipe(map((response) => {
9936
- const updatedTransaction = plainToClass(Transaction, response);
9937
- // @TODO need to upload file in the same backend endpoint with transaction add/update
9938
- // check if passed new receipt and upload file
9939
- if (transaction.file) {
9940
- updatedTransaction.file = transaction.file;
9941
- this.uploadReceipt(updatedTransaction);
9942
- }
9943
- // @TODO Viktor: implement API for saving of nested transactions
9944
- if (transaction.transactions.length) {
9945
- // add parent transaction to child transactions
9946
- transaction.transactions.forEach((childTransaction) => {
9947
- childTransaction.parentTransaction = plainToClass(Transaction, { id: updatedTransaction.id });
9948
- });
9949
- // separate child transactions by id existing to define add or update action.
9950
- const childTransactionsToUpdate = transaction.transactions.filter((t) => t.id);
9951
- const childTransactionsToAdd = transaction.transactions.filter((t) => !t.id);
9952
- // update child transactions
9953
- if (childTransactionsToUpdate.length) {
9954
- this.updateBatch(childTransactionsToUpdate).subscribe();
9955
- }
9956
- // add child transactions
9957
- if (childTransactionsToAdd.length) {
9958
- this.addBatch(childTransactionsToAdd).subscribe();
9959
- }
9960
- }
9961
- this.toastService.success(MessagesEnum.UPDATED_MESSAGE);
9962
- replace(this.cache, updatedTransaction);
10133
+ update(taxReview) {
10134
+ return this.http.put(`${this.environment.apiV2}/${this.url}/${taxReview.id}`, taxReview)
10135
+ .pipe(map((updatedTaxReview) => {
10136
+ const updatedInstance = plainToClass(TaxReview, updatedTaxReview);
10137
+ this.eventDispatcherService.dispatch(new AppEvent(AppEventTypeEnum.TAX_REVIEW_UPDATED, updatedInstance));
10138
+ const tempCache = _.cloneDeep(this.cache);
10139
+ replace(tempCache, updatedInstance);
10140
+ this.cache = tempCache;
9963
10141
  this.updateCache();
9964
- return updatedTransaction;
10142
+ return updatedInstance;
9965
10143
  }));
9966
10144
  }
9967
10145
  /**
9968
- * update multiple transactions
9969
- * @param transactions list of transactions for updating
10146
+ * Clear cache when user reject firm
9970
10147
  */
9971
- updateBatch(transactions) {
9972
- return this.http.put(`${this.environment.apiV2}/${this.url}`, transactions)
9973
- .pipe(map((response) => {
9974
- const updatedTransactions = response.map((item) => plainToClass(Transaction, item));
9975
- updatedTransactions.forEach((updatedTransaction) => {
9976
- replace(this.cache, updatedTransaction);
9977
- });
10148
+ listenFirmChanges() {
10149
+ this.eventDispatcherService.on([AppEventTypeEnum.CLIENT_MOVEMENT_CLOSED, AppEventTypeEnum.CLIENT_INVITE_ACCEPTED])
10150
+ .subscribe(() => {
10151
+ this.cache = [];
9978
10152
  this.updateCache();
9979
- return updatedTransactions;
9980
- }));
10153
+ });
9981
10154
  }
9982
10155
  /**
9983
- * delete transaction and related transactions
9984
- * @param model
10156
+ * Update firm for all transferred clients
10157
+ * @private
9985
10158
  */
9986
- delete(model) {
9987
- return this.http.delete(`${this.environment.apiV2}/${this.url}/${model.id}`)
9988
- .pipe(map(() => {
9989
- this.cache = this.cache.filter((transaction) => {
9990
- var _a;
9991
- // when delete transfer we delete actually 2 transactions
9992
- if (model.isTransfer) {
9993
- const ids = [model.id];
9994
- // get id of related transfer transaction
9995
- if (model.transfer) {
9996
- // just take id if we delete source transaction
9997
- ids.push(model.transfer.id);
9998
- }
9999
- else {
10000
- // find source transaction id if we delete destination transaction
10001
- ids.push(this.cache.find((t) => t.transfer.id === model.id).id);
10002
- }
10003
- return !ids.includes(transaction.id);
10004
- }
10005
- return transaction.id !== model.id && ((_a = transaction.parentTransaction) === null || _a === void 0 ? void 0 : _a.id) !== model.id;
10159
+ listenClientTransfer() {
10160
+ this.eventDispatcherService.on(AppEventTypeEnum.CLIENT_TRANSFER_TO_OTHER_EMPLOYEE)
10161
+ .subscribe((transferredClients) => {
10162
+ const tempCache = _.cloneDeep(this.cache);
10163
+ transferredClients.forEach((transferredClient) => {
10164
+ const taxReviewIndex = tempCache.findIndex((taxReview) => taxReview.id === transferredClient.id);
10165
+ // @TODO vik
10166
+ // tempCache[taxReviewIndex].employee = transferredClient.accountant;
10006
10167
  });
10007
- this.eventDispatcherService.dispatch(new AppEvent(AppEventTypeEnum.TRANSACTION_DELETED, model));
10008
- this.toastService.success(MessagesEnum.DELETED_MESSAGE);
10168
+ this.cache = tempCache;
10009
10169
  this.updateCache();
10010
- this.transactionDeleted.emit(model);
10011
- }));
10170
+ });
10012
10171
  }
10013
- /**
10014
- * upload transaction receipt image
10015
- * @param transaction Еhe transaction for which the receipt will be imported
10016
- */
10017
- uploadReceipt(transaction) {
10018
- const formData = new FormData();
10019
- formData.append('file', transaction.file);
10020
- transaction.receipt = null;
10021
- this.http.post(`${this.environment.apiV2}/${this.url}/${transaction.id}/receipts`, formData)
10022
- .subscribe((receiptResponse) => {
10023
- // we don't need to keep file after save
10024
- transaction.file = null;
10025
- transaction.receipt = plainToClass(TransactionReceipt, receiptResponse);
10026
- replace(this.cache, transaction);
10172
+ }
10173
+ TaxReviewService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TaxReviewService, deps: [{ token: i1.HttpClient }, { token: EventDispatcherService }, { token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable });
10174
+ TaxReviewService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TaxReviewService, providedIn: 'root' });
10175
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TaxReviewService, decorators: [{
10176
+ type: Injectable,
10177
+ args: [{
10178
+ providedIn: 'root'
10179
+ }]
10180
+ }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: EventDispatcherService }, { type: undefined, decorators: [{
10181
+ type: Inject,
10182
+ args: ['environment']
10183
+ }] }]; } });
10184
+
10185
+ /**
10186
+ * Service to work with tax review history
10187
+ */
10188
+ class TaxReviewHistoryService extends RestService {
10189
+ constructor(http, eventDispatcherService, environment) {
10190
+ super(http, eventDispatcherService, environment);
10191
+ this.http = http;
10192
+ this.eventDispatcherService = eventDispatcherService;
10193
+ this.environment = environment;
10194
+ this.url = 'tax-reviews/history';
10195
+ this.modelClass = TaxReview;
10196
+ // subscribe on tax review updating
10197
+ eventDispatcherService.on(AppEventTypeEnum.TAX_REVIEW_UPDATED).subscribe((taxReview) => {
10198
+ const tempCache = _.cloneDeep(this.cache);
10199
+ // insert element at the beginning of the array
10200
+ tempCache.unshift(taxReview);
10201
+ this.cache = tempCache;
10027
10202
  this.updateCache();
10028
10203
  });
10029
10204
  }
10030
- /**
10031
- * calculate gross income amount based on transaction amount and taxes (fees)
10032
- * @param transaction Transaction instance for calculation
10033
- */
10034
- calculateGrossAmount(transaction) {
10035
- let amount = transaction.amount || 0;
10036
- // gross income amount includes amount of fees for property tank and tax for work tank
10037
- if (transaction.isPropertyTank()) {
10038
- amount += transaction.transactions.reduce((sum, item) => sum + item.amount, 0);
10039
- }
10040
- else {
10041
- // @TODO Alex: fix logic after TT-641 ready
10042
- amount += (transaction.tax || 0);
10043
- }
10044
- return amount;
10205
+ }
10206
+ TaxReviewHistoryService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TaxReviewHistoryService, deps: [{ token: i1.HttpClient }, { token: EventDispatcherService }, { token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable });
10207
+ TaxReviewHistoryService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TaxReviewHistoryService, providedIn: 'root' });
10208
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TaxReviewHistoryService, decorators: [{
10209
+ type: Injectable,
10210
+ args: [{
10211
+ providedIn: 'root'
10212
+ }]
10213
+ }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: EventDispatcherService }, { type: undefined, decorators: [{
10214
+ type: Inject,
10215
+ args: ['environment']
10216
+ }] }]; } });
10217
+
10218
+ /**
10219
+ * Service to work with tax summary logic
10220
+ */
10221
+ class TaxSummaryService {
10222
+ constructor(http, eventDispatcherService, environment) {
10223
+ this.http = http;
10224
+ this.eventDispatcherService = eventDispatcherService;
10225
+ this.environment = environment;
10226
+ this.taxSummaryActualsSubject = new ReplaySubject(1);
10227
+ this.taxSummaryForecastsSubject = new ReplaySubject(1);
10228
+ this.listenEvents();
10045
10229
  }
10046
- /**
10047
- * get label for transaction tax field depended of selected chart account.
10048
- * tax type depends of chart account heading or category.
10049
- */
10050
- getTaxLabel(chartAccounts) {
10051
- var _a, _b;
10052
- // get simple array of ids from enum with taxable chart accounts headings
10053
- const taxableCAHeadingsIds = enumToList(ChartAccountsHeadingTaxableEnum)
10054
- .map((item) => item.value);
10055
- // get simple array of ids from enum with tax deductible chart accounts headings
10056
- const deductibleCAHeadingsIds = enumToList(ChartAccountsHeadingTaxDeductibleEnum)
10057
- .map((item) => item.value);
10058
- // check if one of ids arrays includes current chart accounts heading id and set tax label
10059
- // otherwise label is empty for this class
10060
- switch (true) {
10061
- case taxableCAHeadingsIds.includes((_a = chartAccounts.heading) === null || _a === void 0 ? void 0 : _a.id):
10062
- return ChartAccountsTaxLabelsEnum.TAX_PAID;
10063
- case deductibleCAHeadingsIds.includes((_b = chartAccounts.heading) === null || _b === void 0 ? void 0 : _b.id):
10064
- return ChartAccountsTaxLabelsEnum.TAX_DEDUCTED;
10065
- case CHART_ACCOUNTS_CATEGORIES.workIncome.includes(chartAccounts.category):
10066
- return ChartAccountsTaxLabelsEnum.TAX_WITHHELD;
10067
- default:
10068
- return null;
10069
- }
10230
+ listenEvents() {
10231
+ this.listenToIncomeSourceForecastsEvents();
10070
10232
  }
10071
10233
  /**
10072
- * Get transactions related to Vehicle category
10234
+ * Get actual tax summary items
10073
10235
  */
10074
- getVehicleTransactions() {
10075
- return this.get().pipe(map((transactions) => {
10076
- return transactions.filter((transaction) => transaction.isVehicleTransaction());
10077
- }));
10236
+ getActuals() {
10237
+ this.http.get(`${this.environment.apiV2}/tax-summary/${TaxSummaryTypeEnum.ACTUALS}`, {})
10238
+ .subscribe((response) => {
10239
+ const taxSummary = plainToClass(TaxSummary, response);
10240
+ this.taxSummaryActualsSubject.next(taxSummary);
10241
+ return taxSummary;
10242
+ });
10243
+ return this.taxSummaryActualsSubject.asObservable();
10078
10244
  }
10079
10245
  /**
10080
- * Listen to EventDispatcherService event related to Depreciation changing
10246
+ * Get forecast tax summary items
10081
10247
  */
10082
- listenDepreciationChange() {
10083
- this.eventDispatcherService.on(AppEventTypeEnum.DEPRECIATION_DELETED).subscribe(() => {
10084
- this.fetch()
10085
- .subscribe((transactions) => {
10086
- this.cache = transactions;
10087
- this.updateCache();
10088
- });
10248
+ getForecast() {
10249
+ this.http.get(`${this.environment.apiV2}/tax-summary/${TaxSummaryTypeEnum.FORECASTS}`, {})
10250
+ .subscribe((response) => {
10251
+ const taxSummary = plainToClass(TaxSummary, response);
10252
+ this.taxSummaryForecastsSubject.next(taxSummary);
10253
+ return taxSummary;
10089
10254
  });
10255
+ return this.taxSummaryForecastsSubject.asObservable();
10090
10256
  }
10091
10257
  /**
10092
- * Listen to EventDispatcherService event related to Property Share changing
10258
+ * Listen to EventDispatcherService events related to Income source forecasts
10093
10259
  */
10094
- listenPropertyShareUpdate() {
10095
- this.eventDispatcherService.on(AppEventTypeEnum.PROPERTY_SHARE_UPDATED).subscribe(() => this.resetCache());
10260
+ listenToIncomeSourceForecastsEvents() {
10261
+ this.eventDispatcherService
10262
+ .on([AppEventTypeEnum.INCOME_SOURCES_FORECASTS_CREATED, AppEventTypeEnum.INCOME_SOURCES_FORECASTS_UPDATED])
10263
+ .subscribe(() => {
10264
+ this.getForecast().subscribe();
10265
+ });
10096
10266
  }
10097
10267
  }
10098
- TransactionService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TransactionService, deps: [{ token: i1.HttpClient }, { token: EventDispatcherService }, { token: 'environment' }, { token: ToastService }], target: i0.ɵɵFactoryTarget.Injectable });
10099
- TransactionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TransactionService, providedIn: 'root' });
10100
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TransactionService, decorators: [{
10268
+ TaxSummaryService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TaxSummaryService, deps: [{ token: i1.HttpClient }, { token: EventDispatcherService }, { token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable });
10269
+ TaxSummaryService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TaxSummaryService, providedIn: 'root' });
10270
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: TaxSummaryService, decorators: [{
10101
10271
  type: Injectable,
10102
10272
  args: [{
10103
10273
  providedIn: 'root'
@@ -10105,7 +10275,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImpo
10105
10275
  }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: EventDispatcherService }, { type: undefined, decorators: [{
10106
10276
  type: Inject,
10107
10277
  args: ['environment']
10108
- }] }, { type: ToastService }]; } });
10278
+ }] }]; } });
10109
10279
 
10110
10280
  // @TODO Don't look at the commented code. Will be refactored/removed during TT-1503
10111
10281
  /**
@@ -10888,5 +11058,5 @@ class ResetPasswordForm extends AbstractForm {
10888
11058
  * Generated bundle index. Do not edit.
10889
11059
  */
10890
11060
 
10891
- export { AbstractForm, Address, AddressService, AddressTypeEnum, AlphabetColorsEnum, AppEvent, AppEventTypeEnum, AssetEntityTypeEnum, AssetTypeEnum, AssetsService, AuthService, BANK_ACCOUNT_TYPES, Bank, BankAccount, BankAccountCalculationService, BankAccountChartData, BankAccountCollection, BankAccountProperty, BankAccountService, BankAccountStatusEnum, BankAccountTypeEnum, BankConnection, BankConnectionService, BankConnectionStatusEnum, BankService, BankTransaction, BankTransactionCalculationService, BankTransactionChartData, BankTransactionCollection, BankTransactionService, BankTransactionSummaryFieldsEnum, BankTransactionTypeEnum, BasiqConfig, BasiqJob, BasiqService, BasiqToken, BorrowingExpense, BorrowingExpenseLoan, BorrowingExpenseService, CAPITAL_COSTS_ITEMS, CHART_ACCOUNTS_CATEGORIES, CalculationFormItem, CalculationFormTypeEnum, ChartAccounts, ChartAccountsCategoryEnum, ChartAccountsDepreciation, ChartAccountsDepreciationService, ChartAccountsEtpEnum, ChartAccountsHeading, ChartAccountsHeadingTaxDeductibleEnum, ChartAccountsHeadingTaxableEnum, ChartAccountsHeadingVehicleListEnum, ChartAccountsListEnum, ChartAccountsMetadata, ChartAccountsMetadataListEnum, ChartAccountsMetadataTypeEnum, ChartAccountsService, ChartAccountsTaxLabelsEnum, ChartAccountsTypeEnum, ChartData, ChartSerie, Chat, ChatService, ChatStatusEnum, ChatViewTypeEnum, ClientCollection, ClientDetails, ClientDetailsMedicareExemptionEnum, ClientDetailsWorkDepreciationCalculationEnum, ClientDetailsWorkingHolidayMakerEnum, ClientInvite, ClientInviteService, ClientInviteStatusEnum, ClientInviteTypeEnum, ClientMovement, ClientMovementCollection, ClientMovementService, ClientPortfolioChartData, ClientPortfolioReport, ClientPortfolioReportCollection, ClientPortfolioReportService, Collection, CollectionDictionary, CorelogicService, CorelogicSuggestion, Country, DEFAULT_VEHICLE_EXPENSE, DEPRECIATION_GROUPS, DOCUMENT_FILE_TYPES, Depreciation, DepreciationCalculationEnum, DepreciationCalculationPercentEnum, DepreciationCapitalProject, DepreciationCapitalProjectService, DepreciationCollection, DepreciationForecast, DepreciationForecastCollection, DepreciationGroup, DepreciationGroupEnum, DepreciationGroupItem, DepreciationLvpAssetTypeEnum, DepreciationLvpReportItem, DepreciationLvpReportItemCollection, DepreciationReceipt, DepreciationReportItem, DepreciationReportItemCollection, DepreciationService, DepreciationTypeEnum, DepreciationWriteOffAmountEnum, Document, DocumentApiUrlPrefixEnum, DocumentFolder, DocumentFolderService, ENDPOINTS, EmployeeCollection, EmployeeDetails, EmployeeInvite, EmployeeInviteService, EmployeeService, Endpoint, EquityPositionChartService, EventDispatcherService, ExportFormatEnum, FinancialYear, Firm, FirmService, FirmTypeEnum, HeaderTitleService, IconsFileEnum, IncomeAmountTypeEnum, IncomePosition, IncomeSource, IncomeSourceChartData, IncomeSourceCollection, IncomeSourceForecast, IncomeSourceForecastService, IncomeSourceService, IncomeSourceType, IncomeSourceTypeEnum, IncomeSourceTypeListOtherEnum, IncomeSourceTypeListSalaryEnum, IncomeSourceTypeListWorkEnum, InterceptorsModule, IntercomService, InviteStatusEnum, JwtService, KompassifyService, Loan, LoanBankTypeEnum, LoanCollection, LoanFrequencyEnum, LoanInterestTypeEnum, LoanMaxNumberOfPaymentsEnum, LoanPayment, LoanPayout, LoanPayoutTypeEnum, LoanRepaymentFrequencyEnum, LoanRepaymentTypeEnum, LoanService, LoanTypeEnum, LoanVehicleTypeEnum, LogbookCollection, LogbookPeriod, LoginForm, MODULE_URL_LIST, MONTHS, Message, MessageCollection, MessageDocument, MessageDocumentCollection, MessageDocumentService, MessageService, MonthNameShortEnum, MonthNumberEnum, MyAccountHistory, MyAccountHistoryInitiatedByEnum, MyAccountHistoryStatusEnum, MyAccountHistoryTypeEnum, Notification, Occupation, OccupationService, PasswordForm, PdfService, Phone, PhoneTypeEnum, PreloaderService, Property, PropertyCalculationService, PropertyCategory, PropertyCategoryMovement, PropertyCategoryMovementService, PropertyCategoryService, PropertyCollection, PropertyDepreciationCalculationEnum, PropertyDocument, PropertyDocumentService, PropertyEquityChartData, PropertyEquityChartItem, PropertyForecast, PropertySale, PropertySaleService, PropertySaleTaxExemptionMetadata, PropertyService, PropertyShare, PropertyShareAccessEnum, PropertyShareService, PropertyShareStatusEnum, PropertySubscription, PropertyValuation, RegisterClientForm, RegisterFirmForm, RegistrationInvite, RegistrationInviteStatusEnum, ReportItem, ReportItemCollection, ReportItemDetails, ResetPasswordForm, SUBSCRIPTION_DESCRIPTION, SUBSCRIPTION_TITLE, SalaryForecast, SalaryForecastFrequencyEnum, SalaryForecastService, ServiceNotificationService, ServiceNotificationStatusEnum, ServiceNotificationTypeEnum, ServicePayment, ServicePaymentStatusEnum, ServicePrice, ServicePriceCollection, ServicePriceRecurringIntervalEnum, ServicePriceTypeEnum, ServiceProduct, ServiceSubscription, ServiceSubscriptionCollection, ServiceSubscriptionItem, ServiceSubscriptionStatusEnum, ShareFilterOptionsEnum, SoleForecast, SoleForecastService, SpareDocumentSpareTypeEnum, SseService, SubscriptionService, SubscriptionTypeEnum, TYPE_LOAN, TankTypeEnum, TaxCalculationMedicareExemptionEnum, TaxCalculationTypeEnum, TaxExemption, TaxExemptionEnum, TaxExemptionMetadata, TaxExemptionMetadataEnum, TaxExemptionService, TaxReturnCategoryListEnum, TaxReturnCategorySectionEnum, TaxReview, TaxReviewCollection, TaxReviewHistoryService, TaxReviewService, TaxReviewStatusEnum, TaxSummary, TaxSummaryListEnum, TaxSummarySection, TaxSummarySectionEnum, TaxSummaryService, TaxSummaryTaxSummaryEnum, TaxSummaryTypeEnum, TicketFeedbackEnum, TicketStatusEnum, TicketTypesEnum, Toast, ToastService, ToastTypeEnum, Transaction, TransactionAllocation, TransactionAllocationCollection, TransactionAllocationService, TransactionBase, TransactionCalculationService, TransactionCollection, TransactionMetadata, TransactionOperationEnum, TransactionReceipt, TransactionService, TransactionSourceEnum, TransactionTypeEnum, TtCoreModule, USER_ROLES, USER_WORK_POSITION, User, UserEventSetting, UserEventSettingCollection, UserEventSettingFieldEnum, UserEventSettingService, UserEventStatusEnum, UserEventType, UserEventTypeCategory, UserEventTypeClientTypeEnum, UserEventTypeEmployeeTypeEnum, UserEventTypeFrequencyEnum, UserEventTypeService, UserEventTypeUserTypeEnum, UserMedicareExemptionEnum, UserRolesEnum, UserService, UserStatusEnum, UserSwitcherService, UserTitleEnum, UserToRegister, UserWorkDepreciationCalculationEnum, UserWorkingHolidayMakerEnum, Vehicle, VehicleClaim, VehicleClaimMethodEnum, VehicleLogbook, VehicleLogbookPurposeEnum, VehicleService, WORK_TANK_LOGBOOK_PURPOSE_OPTIONS, XlsxService, cloneDeep, compare, compareMatOptions, createDate, displayMatOptions, enumToList, getDocIcon, replace, roundTo, sort, sortDeep, taxReviewFilterPredicate };
11061
+ export { AbstractForm, Address, AddressService, AddressTypeEnum, AlphabetColorsEnum, AppEvent, AppEventTypeEnum, AssetEntityTypeEnum, AssetTypeEnum, AssetsService, AuthService, BANK_ACCOUNT_TYPES, Bank, BankAccount, BankAccountCalculationService, BankAccountChartData, BankAccountCollection, BankAccountProperty, BankAccountService, BankAccountStatusEnum, BankAccountTypeEnum, BankConnection, BankConnectionService, BankConnectionStatusEnum, BankService, BankTransaction, BankTransactionCalculationService, BankTransactionChartData, BankTransactionCollection, BankTransactionService, BankTransactionSummaryFieldsEnum, BankTransactionTypeEnum, BasiqConfig, BasiqJob, BasiqService, BasiqToken, BorrowingExpense, BorrowingExpenseLoan, BorrowingExpenseService, CAPITAL_COSTS_ITEMS, CHART_ACCOUNTS_CATEGORIES, CalculationFormItem, CalculationFormTypeEnum, ChartAccounts, ChartAccountsCategoryEnum, ChartAccountsDepreciation, ChartAccountsDepreciationService, ChartAccountsEtpEnum, ChartAccountsHeading, ChartAccountsHeadingTaxDeductibleEnum, ChartAccountsHeadingTaxableEnum, ChartAccountsHeadingVehicleListEnum, ChartAccountsListEnum, ChartAccountsMetadata, ChartAccountsMetadataListEnum, ChartAccountsMetadataTypeEnum, ChartAccountsService, ChartAccountsTaxLabelsEnum, ChartAccountsTypeEnum, ChartData, ChartSerie, Chat, ChatService, ChatStatusEnum, ChatViewTypeEnum, ClientCollection, ClientDetails, ClientDetailsMedicareExemptionEnum, ClientDetailsWorkDepreciationCalculationEnum, ClientDetailsWorkingHolidayMakerEnum, ClientInvite, ClientInviteService, ClientInviteStatusEnum, ClientInviteTypeEnum, ClientMovement, ClientMovementCollection, ClientMovementService, ClientPortfolioChartData, ClientPortfolioReport, ClientPortfolioReportCollection, ClientPortfolioReportService, Collection, CollectionDictionary, CorelogicService, CorelogicSuggestion, Country, DEFAULT_VEHICLE_EXPENSE, DEPRECIATION_GROUPS, DOCUMENT_FILE_TYPES, Depreciation, DepreciationCalculationEnum, DepreciationCalculationPercentEnum, DepreciationCapitalProject, DepreciationCapitalProjectService, DepreciationCollection, DepreciationForecast, DepreciationForecastCollection, DepreciationGroup, DepreciationGroupEnum, DepreciationGroupItem, DepreciationLvpAssetTypeEnum, DepreciationLvpReportItem, DepreciationLvpReportItemCollection, DepreciationReceipt, DepreciationReportItem, DepreciationReportItemCollection, DepreciationService, DepreciationTypeEnum, DepreciationWriteOffAmountEnum, Document, DocumentApiUrlPrefixEnum, DocumentFolder, DocumentFolderService, ENDPOINTS, EmployeeCollection, EmployeeDetails, EmployeeInvite, EmployeeInviteService, EmployeeService, Endpoint, EquityPositionChartService, EventDispatcherService, ExportFormatEnum, FinancialYear, Firm, FirmService, FirmTypeEnum, HeaderTitleService, IconsFileEnum, IncomeAmountTypeEnum, IncomePosition, IncomeSource, IncomeSourceChartData, IncomeSourceCollection, IncomeSourceForecast, IncomeSourceForecastService, IncomeSourceService, IncomeSourceType, IncomeSourceTypeEnum, IncomeSourceTypeListOtherEnum, IncomeSourceTypeListSalaryEnum, IncomeSourceTypeListWorkEnum, InterceptorsModule, IntercomService, InviteStatusEnum, JwtService, KompassifyService, Loan, LoanBankTypeEnum, LoanCollection, LoanFrequencyEnum, LoanInterestTypeEnum, LoanMaxNumberOfPaymentsEnum, LoanPayment, LoanPayout, LoanPayoutTypeEnum, LoanRepaymentFrequencyEnum, LoanRepaymentTypeEnum, LoanService, LoanTypeEnum, LoanVehicleTypeEnum, LogbookCollection, LogbookPeriod, LoginForm, MODULE_URL_LIST, MONTHS, Message, MessageCollection, MessageDocument, MessageDocumentCollection, MessageDocumentService, MessageService, MonthNameShortEnum, MonthNumberEnum, MyAccountHistory, MyAccountHistoryInitiatedByEnum, MyAccountHistoryStatusEnum, MyAccountHistoryTypeEnum, Notification, Occupation, OccupationService, PasswordForm, PdfService, Phone, PhoneTypeEnum, PreloaderService, Property, PropertyCalculationService, PropertyCategory, PropertyCategoryMovement, PropertyCategoryMovementService, PropertyCategoryService, PropertyCollection, PropertyDepreciationCalculationEnum, PropertyDocument, PropertyDocumentService, PropertyEquityChartData, PropertyEquityChartItem, PropertyForecast, PropertyReportItem, PropertyReportItemCollection, PropertyReportItemDepreciationCollection, PropertyReportItemTransaction, PropertyReportItemTransactionCollection, PropertySale, PropertySaleService, PropertySaleTaxExemptionMetadata, PropertyService, PropertyShare, PropertyShareAccessEnum, PropertyShareService, PropertyShareStatusEnum, PropertySubscription, PropertyTransactionReportService, PropertyValuation, RegisterClientForm, RegisterFirmForm, RegistrationInvite, RegistrationInviteStatusEnum, ReportItem, ReportItemCollection, ReportItemDetails, ResetPasswordForm, SUBSCRIPTION_DESCRIPTION, SUBSCRIPTION_TITLE, SalaryForecast, SalaryForecastFrequencyEnum, SalaryForecastService, ServiceNotificationService, ServiceNotificationStatusEnum, ServiceNotificationTypeEnum, ServicePayment, ServicePaymentStatusEnum, ServicePrice, ServicePriceCollection, ServicePriceRecurringIntervalEnum, ServicePriceTypeEnum, ServiceProduct, ServiceSubscription, ServiceSubscriptionCollection, ServiceSubscriptionItem, ServiceSubscriptionStatusEnum, ShareFilterOptionsEnum, SoleForecast, SoleForecastService, SpareDocumentSpareTypeEnum, SseService, SubscriptionService, SubscriptionTypeEnum, TYPE_LOAN, TankTypeEnum, TaxCalculationMedicareExemptionEnum, TaxCalculationTypeEnum, TaxExemption, TaxExemptionEnum, TaxExemptionMetadata, TaxExemptionMetadataEnum, TaxExemptionService, TaxReturnCategoryListEnum, TaxReturnCategorySectionEnum, TaxReview, TaxReviewCollection, TaxReviewHistoryService, TaxReviewService, TaxReviewStatusEnum, TaxSummary, TaxSummaryListEnum, TaxSummarySection, TaxSummarySectionEnum, TaxSummaryService, TaxSummaryTaxSummaryEnum, TaxSummaryTypeEnum, TicketFeedbackEnum, TicketStatusEnum, TicketTypesEnum, Toast, ToastService, ToastTypeEnum, Transaction, TransactionAllocation, TransactionAllocationCollection, TransactionAllocationService, TransactionBase, TransactionCalculationService, TransactionCollection, TransactionMetadata, TransactionOperationEnum, TransactionReceipt, TransactionService, TransactionSourceEnum, TransactionTypeEnum, TtCoreModule, USER_ROLES, USER_WORK_POSITION, User, UserEventSetting, UserEventSettingCollection, UserEventSettingFieldEnum, UserEventSettingService, UserEventStatusEnum, UserEventType, UserEventTypeCategory, UserEventTypeClientTypeEnum, UserEventTypeEmployeeTypeEnum, UserEventTypeFrequencyEnum, UserEventTypeService, UserEventTypeUserTypeEnum, UserMedicareExemptionEnum, UserRolesEnum, UserService, UserStatusEnum, UserSwitcherService, UserTitleEnum, UserToRegister, UserWorkDepreciationCalculationEnum, UserWorkingHolidayMakerEnum, Vehicle, VehicleClaim, VehicleClaimMethodEnum, VehicleLogbook, VehicleLogbookPurposeEnum, VehicleService, WORK_TANK_LOGBOOK_PURPOSE_OPTIONS, XlsxService, cloneDeep, compare, compareMatOptions, createDate, displayMatOptions, enumToList, getDocIcon, replace, roundTo, sort, sortDeep, taxReviewFilterPredicate };
10892
11062
  //# sourceMappingURL=taxtank-core.js.map