taxtank-core 2.0.95 → 2.0.97
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/taxtank-core.mjs +626 -579
- package/fesm2022/taxtank-core.mjs.map +1 -1
- package/index.d.ts +91 -53
- package/package.json +1 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Inject, Injectable, inject,
|
|
2
|
+
import { Inject, Injectable, inject, NgModule, EventEmitter, InjectionToken, Pipe } from '@angular/core';
|
|
3
3
|
import * as i1$1 from '@angular/common';
|
|
4
4
|
import { formatDate, DatePipe, CurrencyPipe, CommonModule as CommonModule$1 } from '@angular/common';
|
|
5
5
|
import * as i1 from '@angular/common/http';
|
|
6
|
-
import { HttpClient, HttpErrorResponse,
|
|
6
|
+
import { HttpClient, HttpErrorResponse, HTTP_INTERCEPTORS, HttpParams } from '@angular/common/http';
|
|
7
7
|
import { map, filter, catchError, finalize, switchMap, first as first$1, take, mergeMap, startWith, debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
|
8
|
-
import { ReplaySubject, Subject, Observable, shareReplay, of, forkJoin, throwError,
|
|
8
|
+
import { ReplaySubject, Subject, Observable, shareReplay, of, forkJoin, throwError, BehaviorSubject, combineLatest, from, merge as merge$1 } from 'rxjs';
|
|
9
9
|
import { plainToClass, Type, Transform, Exclude, Expose, classToPlain } from 'class-transformer';
|
|
10
10
|
import get from 'lodash/get';
|
|
11
11
|
import 'reflect-metadata';
|
|
@@ -32,14 +32,14 @@ import moment$1 from 'moment/moment';
|
|
|
32
32
|
import { EventSourcePolyfill } from 'event-source-polyfill/src/eventsource.min.js';
|
|
33
33
|
import clone from 'lodash/clone';
|
|
34
34
|
import merge from 'lodash/merge';
|
|
35
|
+
import mixpanel from 'mixpanel-browser';
|
|
36
|
+
import { JwtHelperService } from '@auth0/angular-jwt';
|
|
35
37
|
import * as i4 from '@angular/router';
|
|
36
38
|
import { NavigationEnd } from '@angular/router';
|
|
37
39
|
import _ from 'lodash';
|
|
38
40
|
import remove from 'lodash/remove';
|
|
39
41
|
import pick from 'lodash/pick';
|
|
40
42
|
import { checkAdBlock } from 'adblock-checker';
|
|
41
|
-
import mixpanel from 'mixpanel-browser';
|
|
42
|
-
import { JwtHelperService } from '@auth0/angular-jwt';
|
|
43
43
|
import { jsPDF } from 'jspdf';
|
|
44
44
|
import { applyPlugin } from 'jspdf-autotable';
|
|
45
45
|
import * as xlsx from '@e965/xlsx';
|
|
@@ -2359,7 +2359,7 @@ class MoneyCalendarEventCollection extends CalendarEventCollection {
|
|
|
2359
2359
|
return this.filterByRange('date', dateFrom, dateTo);
|
|
2360
2360
|
}
|
|
2361
2361
|
getByMonth(index) {
|
|
2362
|
-
return new
|
|
2362
|
+
return new MoneyCalendarEventCollection(this.items.filter(event => event.inMonth(index)));
|
|
2363
2363
|
}
|
|
2364
2364
|
}
|
|
2365
2365
|
|
|
@@ -4398,6 +4398,7 @@ const USER_ROLES = {
|
|
|
4398
4398
|
ROLE_USER_SOLE: [UserRolesEnum$1.SOLE_TANK],
|
|
4399
4399
|
ROLE_USER_HOLDING: [UserRolesEnum$1.HOLDING_TANK],
|
|
4400
4400
|
ROLE_PREVIOUS_ADMIN: [UserRolesEnum$1.SWITCH_USER],
|
|
4401
|
+
ROLE_USER_MONEY: [UserRolesEnum$1.MONEY_TANK]
|
|
4401
4402
|
};
|
|
4402
4403
|
|
|
4403
4404
|
/**
|
|
@@ -4719,10 +4720,11 @@ var ServiceProductIdEnum;
|
|
|
4719
4720
|
ServiceProductIdEnum[ServiceProductIdEnum["PROPERTIES"] = 5] = "PROPERTIES";
|
|
4720
4721
|
ServiceProductIdEnum[ServiceProductIdEnum["SOLE_TANK"] = 6] = "SOLE_TANK";
|
|
4721
4722
|
ServiceProductIdEnum[ServiceProductIdEnum["HOLDINGS_TANK"] = 7] = "HOLDINGS_TANK";
|
|
4723
|
+
ServiceProductIdEnum[ServiceProductIdEnum["MONEY_TANK"] = 8] = "MONEY_TANK";
|
|
4722
4724
|
})(ServiceProductIdEnum || (ServiceProductIdEnum = {}));
|
|
4723
4725
|
|
|
4724
4726
|
class ServiceProduct extends ServiceProduct$1 {
|
|
4725
|
-
static { this.quantity =
|
|
4727
|
+
static { this.quantity = 5; }
|
|
4726
4728
|
isProperties() {
|
|
4727
4729
|
return [ServiceProductIdEnum.PROPERTY_OLD, ServiceProductIdEnum.PROPERTIES].includes(this.id);
|
|
4728
4730
|
}
|
|
@@ -4735,6 +4737,9 @@ class ServiceProduct extends ServiceProduct$1 {
|
|
|
4735
4737
|
isHoldingsTank() {
|
|
4736
4738
|
return this.id === ServiceProductIdEnum.HOLDINGS_TANK;
|
|
4737
4739
|
}
|
|
4740
|
+
isMoneyTank() {
|
|
4741
|
+
return this.id === ServiceProductIdEnum.MONEY_TANK;
|
|
4742
|
+
}
|
|
4738
4743
|
isArchived() {
|
|
4739
4744
|
return this.status === ServiceProductStatusEnum.ARCHIVED;
|
|
4740
4745
|
}
|
|
@@ -5758,6 +5763,11 @@ var AccountSetupItemsEnum;
|
|
|
5758
5763
|
AccountSetupItemsEnum[AccountSetupItemsEnum["BANK_TRANSACTION"] = 24] = "BANK_TRANSACTION";
|
|
5759
5764
|
AccountSetupItemsEnum[AccountSetupItemsEnum["BANK_RULE"] = 27] = "BANK_RULE";
|
|
5760
5765
|
AccountSetupItemsEnum[AccountSetupItemsEnum["BANK_BORROWING_EXPENSE"] = 28] = "BANK_BORROWING_EXPENSE";
|
|
5766
|
+
// money tank
|
|
5767
|
+
AccountSetupItemsEnum[AccountSetupItemsEnum["MONEY_BANK_ACCOUNT"] = 31] = "MONEY_BANK_ACCOUNT";
|
|
5768
|
+
AccountSetupItemsEnum[AccountSetupItemsEnum["MONEY_EXPENSE_BUDGETS"] = 32] = "MONEY_EXPENSE_BUDGETS";
|
|
5769
|
+
AccountSetupItemsEnum[AccountSetupItemsEnum["MONEY_INCOME_BUDGETS"] = 33] = "MONEY_INCOME_BUDGETS";
|
|
5770
|
+
AccountSetupItemsEnum[AccountSetupItemsEnum["MONEY_GOALS"] = 34] = "MONEY_GOALS";
|
|
5761
5771
|
})(AccountSetupItemsEnum || (AccountSetupItemsEnum = {}));
|
|
5762
5772
|
|
|
5763
5773
|
class User extends User$1 {
|
|
@@ -8643,11 +8653,12 @@ class TransactionReportItem {
|
|
|
8643
8653
|
}
|
|
8644
8654
|
|
|
8645
8655
|
class BudgetRuleItem {
|
|
8646
|
-
constructor(rule, transactions, isGross = false) {
|
|
8656
|
+
constructor(rule, transactions, dateFrom, dateTo, isGross = false) {
|
|
8647
8657
|
this.rule = rule;
|
|
8648
8658
|
this.tankType = TankTypeEnum[rule.chartAccounts.tankType];
|
|
8649
8659
|
this.category = ChartAccountsCategoryEnum[rule.chartAccounts.category];
|
|
8650
8660
|
this.frequency = DailyFrequencyEnum[rule.frequency] ?? 'Once';
|
|
8661
|
+
this.isGross = isGross;
|
|
8651
8662
|
if (rule.business) {
|
|
8652
8663
|
transactions = transactions.filterBy('business.id', rule.business.id);
|
|
8653
8664
|
}
|
|
@@ -8657,9 +8668,11 @@ class BudgetRuleItem {
|
|
|
8657
8668
|
if (rule.property) {
|
|
8658
8669
|
transactions = transactions.filterBy('property.id', rule.property.id);
|
|
8659
8670
|
}
|
|
8671
|
+
this.forecast = rule.calendarEvents.filterByDate(dateFrom, dateTo).amount;
|
|
8672
|
+
this.transactions = transactions;
|
|
8660
8673
|
this.actual = transactions.sumBy(isGross ? 'grossAmount' : 'amount');
|
|
8661
|
-
this.variance = this.actual - this.
|
|
8662
|
-
this.variancePercent = round(this.actual * 100 / this.
|
|
8674
|
+
this.variance = this.actual - this.forecast;
|
|
8675
|
+
this.variancePercent = round(this.actual * 100 / this.forecast, 2);
|
|
8663
8676
|
}
|
|
8664
8677
|
getSource() {
|
|
8665
8678
|
switch (true) {
|
|
@@ -8679,6 +8692,10 @@ class BudgetRuleItem {
|
|
|
8679
8692
|
onTrack() {
|
|
8680
8693
|
return this.variance >= 0;
|
|
8681
8694
|
}
|
|
8695
|
+
getName() {
|
|
8696
|
+
const source = this.getSource();
|
|
8697
|
+
return this.rule.chartAccounts.name + (source ? ` (${source})` : '');
|
|
8698
|
+
}
|
|
8682
8699
|
}
|
|
8683
8700
|
|
|
8684
8701
|
/**
|
|
@@ -8773,13 +8790,40 @@ class TransactionReportItemCollection extends Collection {
|
|
|
8773
8790
|
}
|
|
8774
8791
|
}
|
|
8775
8792
|
|
|
8793
|
+
class BudgetCollection extends Collection {
|
|
8794
|
+
}
|
|
8795
|
+
|
|
8796
|
+
class BudgetRuleCollection extends Collection {
|
|
8797
|
+
get expenses() {
|
|
8798
|
+
return this.filter(rule => rule.chartAccounts.isExpense());
|
|
8799
|
+
}
|
|
8800
|
+
get incomes() {
|
|
8801
|
+
return this.filter(rule => rule.chartAccounts.isIncome());
|
|
8802
|
+
}
|
|
8803
|
+
filterByProperties(properties) {
|
|
8804
|
+
const propertyIds = properties.map(property => property.id);
|
|
8805
|
+
return this.filter(rule => propertyIds.includes(rule.property?.id));
|
|
8806
|
+
}
|
|
8807
|
+
get calendarEvents() {
|
|
8808
|
+
return new MoneyCalendarEventCollection(this.map(rule => rule.calendarEvents.items).flat());
|
|
8809
|
+
}
|
|
8810
|
+
getByMonth(index) {
|
|
8811
|
+
return new BudgetRuleCollection(this.items.filter(rule => rule.inMonth(index)));
|
|
8812
|
+
}
|
|
8813
|
+
getByChartAccountsName(name) {
|
|
8814
|
+
const searchQuery = name.toLowerCase().trim();
|
|
8815
|
+
return this.filter(rule => rule.chartAccounts.name.toLowerCase().includes(searchQuery));
|
|
8816
|
+
}
|
|
8817
|
+
}
|
|
8818
|
+
|
|
8776
8819
|
class BudgetRuleItemCollection extends Collection {
|
|
8777
|
-
static create(rules, transactions, isGross = false) {
|
|
8820
|
+
static create(rules, transactions, dateFrom = new FinancialYear().startDate, dateTo = new FinancialYear().endDate, isGross = false) {
|
|
8778
8821
|
const collection = new BudgetRuleItemCollection();
|
|
8779
8822
|
const transactionsByChartAccounts = transactions.groupBy('chartAccounts.id');
|
|
8780
8823
|
rules.items.forEach(rule => {
|
|
8781
|
-
collection.push(new BudgetRuleItem(rule, transactionsByChartAccounts.get(rule.chartAccounts.id), isGross));
|
|
8824
|
+
collection.push(new BudgetRuleItem(rule, transactionsByChartAccounts.get(rule.chartAccounts.id), dateFrom, dateTo, isGross));
|
|
8782
8825
|
});
|
|
8826
|
+
collection.isGross = isGross;
|
|
8783
8827
|
return collection;
|
|
8784
8828
|
}
|
|
8785
8829
|
get incomes() {
|
|
@@ -8791,12 +8835,36 @@ class BudgetRuleItemCollection extends Collection {
|
|
|
8791
8835
|
isIncome() {
|
|
8792
8836
|
return this.first.isIncome();
|
|
8793
8837
|
}
|
|
8794
|
-
get
|
|
8795
|
-
return
|
|
8838
|
+
get transactions() {
|
|
8839
|
+
return new TransactionCollection(this.map(item => item.transactions.toArray()).flat());
|
|
8840
|
+
}
|
|
8841
|
+
get rules() {
|
|
8842
|
+
return new BudgetRuleCollection(this.mapBy('rule'));
|
|
8843
|
+
}
|
|
8844
|
+
get calendarEvents() {
|
|
8845
|
+
return new MoneyCalendarEventCollection(this.map(item => item.rule.calendarEvents.toArray()).flat());
|
|
8796
8846
|
}
|
|
8797
8847
|
onTrack() {
|
|
8798
8848
|
return this.sumBy('variance') >= 0;
|
|
8799
8849
|
}
|
|
8850
|
+
/**
|
|
8851
|
+
* @TODO move to property to avoid recalculations?
|
|
8852
|
+
*/
|
|
8853
|
+
getActualByMonth(month) {
|
|
8854
|
+
return this.transactions.getByMonth(month).sumBy(this.isGross ? 'grossAmount' : 'amount');
|
|
8855
|
+
}
|
|
8856
|
+
/**
|
|
8857
|
+
* @TODO move to property to avoid recalculations?
|
|
8858
|
+
*/
|
|
8859
|
+
getForecastByMonth(month) {
|
|
8860
|
+
return this.calendarEvents.getByMonth(month).amount;
|
|
8861
|
+
}
|
|
8862
|
+
/**
|
|
8863
|
+
* @TODO move to property to avoid recalculations?
|
|
8864
|
+
*/
|
|
8865
|
+
get variancePercent() {
|
|
8866
|
+
return round(this.sumBy('actual') * 100 / this.sumBy('forecast'), 2);
|
|
8867
|
+
}
|
|
8800
8868
|
}
|
|
8801
8869
|
|
|
8802
8870
|
class SoleBusinessLossCollection extends Collection {
|
|
@@ -8923,15 +8991,10 @@ class ServicePriceCollection extends Collection {
|
|
|
8923
8991
|
// the default number of properties should be 5.
|
|
8924
8992
|
return this.annualPackage.sumBy('amount') + property.amount * (propertyQuantity - 1);
|
|
8925
8993
|
}
|
|
8926
|
-
getProperty(
|
|
8927
|
-
|
|
8928
|
-
|
|
8929
|
-
|
|
8930
|
-
}
|
|
8931
|
-
else {
|
|
8932
|
-
type = isPackage ? ServicePriceTypeEnum.MONTHLY_PACKAGE : ServicePriceTypeEnum.MONTHLY;
|
|
8933
|
-
}
|
|
8934
|
-
return this.filterBy('type', type).findBy('product.id', ServiceProductIdEnum.PROPERTIES);
|
|
8994
|
+
getProperty(isPackage) {
|
|
8995
|
+
return this
|
|
8996
|
+
.filterBy('type', isPackage ? ServicePriceTypeEnum.YEARLY_PACKAGE : ServicePriceTypeEnum.YEARLY)
|
|
8997
|
+
.findBy('product.id', ServiceProductIdEnum.PROPERTIES);
|
|
8935
8998
|
}
|
|
8936
8999
|
get products() {
|
|
8937
9000
|
return new ServiceProductCollection(this.mapBy('product'));
|
|
@@ -9429,32 +9492,6 @@ class DocumentFolderCollection extends Collection {
|
|
|
9429
9492
|
}
|
|
9430
9493
|
}
|
|
9431
9494
|
|
|
9432
|
-
class BudgetCollection extends Collection {
|
|
9433
|
-
}
|
|
9434
|
-
|
|
9435
|
-
class BudgetRuleCollection extends Collection {
|
|
9436
|
-
get expenses() {
|
|
9437
|
-
return this.filter(rule => rule.chartAccounts.isExpense());
|
|
9438
|
-
}
|
|
9439
|
-
get incomes() {
|
|
9440
|
-
return this.filter(rule => rule.chartAccounts.isIncome());
|
|
9441
|
-
}
|
|
9442
|
-
filterByProperties(properties) {
|
|
9443
|
-
const propertyIds = properties.map(property => property.id);
|
|
9444
|
-
return this.filter(rule => propertyIds.includes(rule.property?.id));
|
|
9445
|
-
}
|
|
9446
|
-
get calendarEvents() {
|
|
9447
|
-
return new MoneyCalendarEventCollection(this.map(rule => rule.calendarEvents.items).flat());
|
|
9448
|
-
}
|
|
9449
|
-
getByMonth(index) {
|
|
9450
|
-
return new BudgetRuleCollection(this.items.filter(rule => rule.inMonth(index)));
|
|
9451
|
-
}
|
|
9452
|
-
getByChartAccountsName(name) {
|
|
9453
|
-
const searchQuery = name.toLowerCase().trim();
|
|
9454
|
-
return this.filter(rule => rule.chartAccounts.name.toLowerCase().includes(searchQuery));
|
|
9455
|
-
}
|
|
9456
|
-
}
|
|
9457
|
-
|
|
9458
9495
|
class AllocationGroupCollection extends Collection {
|
|
9459
9496
|
constructor(items) {
|
|
9460
9497
|
super(items);
|
|
@@ -13301,100 +13338,469 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
|
|
|
13301
13338
|
}]
|
|
13302
13339
|
}] });
|
|
13303
13340
|
|
|
13304
|
-
|
|
13305
|
-
|
|
13306
|
-
|
|
13307
|
-
|
|
13308
|
-
|
|
13309
|
-
this.
|
|
13310
|
-
this.disabledMethods = ['postBatch', 'putBatch', 'deleteBatch'];
|
|
13341
|
+
/**
|
|
13342
|
+
* Service to work with mixpanel https://docs.mixpanel.com/docs/tracking/reference/javascript
|
|
13343
|
+
*/
|
|
13344
|
+
class MixpanelService {
|
|
13345
|
+
constructor(environment) {
|
|
13346
|
+
this.environment = environment;
|
|
13311
13347
|
}
|
|
13312
|
-
|
|
13313
|
-
|
|
13348
|
+
init() {
|
|
13349
|
+
if (!this.environment.enableMixpanel) {
|
|
13350
|
+
return;
|
|
13351
|
+
}
|
|
13352
|
+
mixpanel.init(this.environment.mixpanelToken);
|
|
13353
|
+
}
|
|
13354
|
+
identify(id) {
|
|
13355
|
+
if (!this.environment.enableMixpanel) {
|
|
13356
|
+
return;
|
|
13357
|
+
}
|
|
13358
|
+
mixpanel.identify(id);
|
|
13359
|
+
mixpanel.people.set({ 'last seen': new Date(Date.now()).toLocaleString() });
|
|
13360
|
+
}
|
|
13361
|
+
reset() {
|
|
13362
|
+
if (!this.environment.enableMixpanel) {
|
|
13363
|
+
return;
|
|
13364
|
+
}
|
|
13365
|
+
mixpanel.reset();
|
|
13366
|
+
}
|
|
13367
|
+
track(event, properties = {}) {
|
|
13368
|
+
if (!this.environment.enableMixpanel) {
|
|
13369
|
+
return;
|
|
13370
|
+
}
|
|
13371
|
+
mixpanel.track(event, properties);
|
|
13372
|
+
}
|
|
13373
|
+
trackLink(id, event, properties = {}) {
|
|
13374
|
+
if (!this.environment.enableMixpanel) {
|
|
13375
|
+
return;
|
|
13376
|
+
}
|
|
13377
|
+
mixpanel.track_links(`#${id}`, event, properties);
|
|
13378
|
+
}
|
|
13379
|
+
trackPageView() {
|
|
13380
|
+
if (!this.environment.enableMixpanel) {
|
|
13381
|
+
return;
|
|
13382
|
+
}
|
|
13383
|
+
mixpanel['track_pageview']();
|
|
13384
|
+
}
|
|
13385
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: MixpanelService, deps: [{ token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
13386
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: MixpanelService, providedIn: 'root' }); }
|
|
13314
13387
|
}
|
|
13315
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type:
|
|
13388
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: MixpanelService, decorators: [{
|
|
13316
13389
|
type: Injectable,
|
|
13317
13390
|
args: [{
|
|
13318
13391
|
providedIn: 'root'
|
|
13319
13392
|
}]
|
|
13320
|
-
}]
|
|
13393
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
13394
|
+
type: Inject,
|
|
13395
|
+
args: ['environment']
|
|
13396
|
+
}] }] });
|
|
13321
13397
|
|
|
13322
|
-
var
|
|
13323
|
-
(function (
|
|
13324
|
-
|
|
13325
|
-
|
|
13326
|
-
|
|
13327
|
-
|
|
13328
|
-
|
|
13398
|
+
var UserRolesEnum;
|
|
13399
|
+
(function (UserRolesEnum) {
|
|
13400
|
+
UserRolesEnum["FIRM_OWNER"] = "ROLE_FIRM_OWNER";
|
|
13401
|
+
UserRolesEnum["FIRM_MANAGER"] = "ROLE_FIRM_MANAGER";
|
|
13402
|
+
UserRolesEnum["FIRM_TOP_MANAGER"] = "ROLE_FIRM_TOP_MANAGER";
|
|
13403
|
+
UserRolesEnum["CLIENT"] = "ROLE_CLIENT";
|
|
13404
|
+
UserRolesEnum["EMPLOYEE"] = "ROLE_EMPLOYEE";
|
|
13405
|
+
UserRolesEnum["ACCOUNTANT"] = "ROLE_ACCOUNTANT";
|
|
13406
|
+
UserRolesEnum["ADVISOR"] = "ROLE_ADVISOR";
|
|
13407
|
+
UserRolesEnum["USER"] = "ROLE_USER";
|
|
13408
|
+
UserRolesEnum["SUBSCRIPTION"] = "ROLE_USER_SUBSCRIPTION";
|
|
13409
|
+
UserRolesEnum["WORK_TANK"] = "ROLE_USER_WORK";
|
|
13410
|
+
UserRolesEnum["PROPERTY_TANK"] = "ROLE_USER_PROPERTY";
|
|
13411
|
+
UserRolesEnum["SOLE_TANK"] = "ROLE_USER_SOLE";
|
|
13412
|
+
UserRolesEnum["HOLDING_TANK"] = "ROLE_USER_HOLDING";
|
|
13413
|
+
UserRolesEnum["MONEY_TANK"] = "ROLE_USER_MONEY";
|
|
13414
|
+
UserRolesEnum["SWITCH_USER"] = "IS_IMPERSONATOR";
|
|
13415
|
+
})(UserRolesEnum || (UserRolesEnum = {}));
|
|
13329
13416
|
|
|
13330
|
-
|
|
13417
|
+
const NAME_TOKEN = 'token';
|
|
13418
|
+
const NAME_REFRESH_TOKEN = 'refreshToken';
|
|
13419
|
+
class JwtService extends JwtHelperService {
|
|
13331
13420
|
constructor() {
|
|
13332
13421
|
super(...arguments);
|
|
13333
|
-
this.
|
|
13334
|
-
this.
|
|
13335
|
-
this.endpointUri = 'budget-rules';
|
|
13336
|
-
this.disabledMethods = ['postBatch', 'putBatch', 'deleteBatch'];
|
|
13422
|
+
this.mpService = inject(MixpanelService);
|
|
13423
|
+
this.isLoggedInSubject = new BehaviorSubject(!this.isTokenExpired());
|
|
13337
13424
|
}
|
|
13338
|
-
|
|
13339
|
-
|
|
13340
|
-
}
|
|
13341
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: BudgetRuleService, decorators: [{
|
|
13342
|
-
type: Injectable,
|
|
13343
|
-
args: [{
|
|
13344
|
-
providedIn: 'root'
|
|
13345
|
-
}]
|
|
13346
|
-
}] });
|
|
13347
|
-
|
|
13348
|
-
class FinancialGoalService extends RestService$1 {
|
|
13349
|
-
constructor() {
|
|
13350
|
-
super(...arguments);
|
|
13351
|
-
this.modelClass = FinancialGoal;
|
|
13352
|
-
this.collectionClass = FinancialGoalCollection;
|
|
13353
|
-
this.endpointUri = 'financial-goals';
|
|
13354
|
-
this.disabledMethods = ['postBatch', 'putBatch', 'deleteBatch'];
|
|
13355
|
-
this.useBackendError = true;
|
|
13425
|
+
getToken() {
|
|
13426
|
+
return localStorage[NAME_TOKEN];
|
|
13356
13427
|
}
|
|
13357
|
-
|
|
13358
|
-
return
|
|
13428
|
+
getRefreshToken() {
|
|
13429
|
+
return localStorage[NAME_REFRESH_TOKEN];
|
|
13359
13430
|
}
|
|
13360
|
-
|
|
13361
|
-
|
|
13431
|
+
saveTokens(tokens) {
|
|
13432
|
+
localStorage[NAME_TOKEN] = tokens.token;
|
|
13433
|
+
localStorage[NAME_REFRESH_TOKEN] = tokens.refreshToken;
|
|
13434
|
+
this.mpService.identify(this.decode(tokens.token).id.toString());
|
|
13435
|
+
this.isLoggedInSubject.next(true);
|
|
13362
13436
|
}
|
|
13363
|
-
|
|
13364
|
-
|
|
13437
|
+
destroyTokens() {
|
|
13438
|
+
localStorage.removeItem(NAME_TOKEN);
|
|
13439
|
+
localStorage.removeItem(NAME_REFRESH_TOKEN);
|
|
13440
|
+
localStorage.removeItem('userId');
|
|
13441
|
+
localStorage.removeItem('_switch_user');
|
|
13442
|
+
this.mpService.track('logout');
|
|
13443
|
+
this.mpService.reset();
|
|
13444
|
+
this.isLoggedInSubject.next(false);
|
|
13365
13445
|
}
|
|
13366
|
-
|
|
13367
|
-
|
|
13446
|
+
decode(token) {
|
|
13447
|
+
return super.decodeToken(token);
|
|
13448
|
+
}
|
|
13449
|
+
isClient() {
|
|
13450
|
+
return this.decode().roles.includes(UserRolesEnum.CLIENT);
|
|
13451
|
+
}
|
|
13452
|
+
isMe(userId) {
|
|
13453
|
+
return this.decode().id === userId;
|
|
13454
|
+
}
|
|
13455
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: JwtService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
13456
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: JwtService, providedIn: 'root' }); }
|
|
13368
13457
|
}
|
|
13369
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type:
|
|
13458
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: JwtService, decorators: [{
|
|
13370
13459
|
type: Injectable,
|
|
13371
13460
|
args: [{
|
|
13372
13461
|
providedIn: 'root'
|
|
13373
13462
|
}]
|
|
13374
13463
|
}] });
|
|
13375
13464
|
|
|
13376
|
-
|
|
13377
|
-
(
|
|
13378
|
-
|
|
13379
|
-
|
|
13380
|
-
|
|
13381
|
-
|
|
13382
|
-
FinancialGoalMessagesEnum["CONFIRM_COMPLETE"] = "Are you sure? Complete goals can not be made active again. Would you like to continue?";
|
|
13383
|
-
})(FinancialGoalMessagesEnum || (FinancialGoalMessagesEnum = {}));
|
|
13384
|
-
|
|
13385
|
-
/**
|
|
13386
|
-
* Service to work with depreciation chart accounts
|
|
13387
|
-
*/
|
|
13388
|
-
class ChartAccountsDepreciationService extends RestService$1 {
|
|
13389
|
-
constructor() {
|
|
13390
|
-
super(...arguments);
|
|
13391
|
-
this.endpointUri = 'chart-accounts-depreciations';
|
|
13392
|
-
this.modelClass = ChartAccountsDepreciation;
|
|
13393
|
-
this.collectionClass = Collection;
|
|
13394
|
-
this.disabledMethods = ['postBatch', 'putBatch', 'deleteBatch'];
|
|
13465
|
+
class AuthService {
|
|
13466
|
+
constructor(http, jwtService, mpService, environment) {
|
|
13467
|
+
this.http = http;
|
|
13468
|
+
this.jwtService = jwtService;
|
|
13469
|
+
this.mpService = mpService;
|
|
13470
|
+
this.environment = environment;
|
|
13395
13471
|
}
|
|
13396
|
-
|
|
13397
|
-
|
|
13472
|
+
setAuth(response) {
|
|
13473
|
+
this.jwtService.saveTokens(response);
|
|
13474
|
+
}
|
|
13475
|
+
login(username, password) {
|
|
13476
|
+
return this.http.post(`${this.environment.apiV2}/login`, { username, password }).pipe(map((response) => {
|
|
13477
|
+
if (response.token) {
|
|
13478
|
+
this.setAuth(response);
|
|
13479
|
+
}
|
|
13480
|
+
return response;
|
|
13481
|
+
}));
|
|
13482
|
+
}
|
|
13483
|
+
mfaLogin(otp) {
|
|
13484
|
+
return this.http.post(`${this.environment.apiV2}/2fa_check`, { otp }).pipe(map((response) => {
|
|
13485
|
+
this.setAuth(response);
|
|
13486
|
+
return response;
|
|
13487
|
+
}));
|
|
13488
|
+
}
|
|
13489
|
+
refresh(refreshToken) {
|
|
13490
|
+
return this.http.post(`${this.environment.apiV2}/token/refresh`, { refreshToken }).pipe(map((response) => {
|
|
13491
|
+
this.setAuth(response);
|
|
13492
|
+
return response;
|
|
13493
|
+
}));
|
|
13494
|
+
}
|
|
13495
|
+
logoutFront(url = '/login') {
|
|
13496
|
+
this.jwtService.destroyTokens();
|
|
13497
|
+
location.replace(url);
|
|
13498
|
+
}
|
|
13499
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AuthService, deps: [{ token: i1.HttpClient }, { token: JwtService }, { token: MixpanelService }, { token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
13500
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AuthService, providedIn: 'root' }); }
|
|
13501
|
+
}
|
|
13502
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AuthService, decorators: [{
|
|
13503
|
+
type: Injectable,
|
|
13504
|
+
args: [{
|
|
13505
|
+
providedIn: 'root'
|
|
13506
|
+
}]
|
|
13507
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: JwtService }, { type: MixpanelService }, { type: undefined, decorators: [{
|
|
13508
|
+
type: Inject,
|
|
13509
|
+
args: ['environment']
|
|
13510
|
+
}] }] });
|
|
13511
|
+
|
|
13512
|
+
var AuthMessagesEnum;
|
|
13513
|
+
(function (AuthMessagesEnum) {
|
|
13514
|
+
AuthMessagesEnum["ERROR_401"] = "Email or password is incorrect";
|
|
13515
|
+
})(AuthMessagesEnum || (AuthMessagesEnum = {}));
|
|
13516
|
+
|
|
13517
|
+
const MESSAGE_DEFAULT_500_ERROR = 'Unexpected error! Please try again later. You can send us via chat your questions.';
|
|
13518
|
+
/**
|
|
13519
|
+
* JWT Interceptor add jwt token to each request related with TaxTank API
|
|
13520
|
+
*/
|
|
13521
|
+
class JwtInterceptor {
|
|
13522
|
+
constructor(jwtService, authService, environment) {
|
|
13523
|
+
this.jwtService = jwtService;
|
|
13524
|
+
this.authService = authService;
|
|
13525
|
+
this.environment = environment;
|
|
13526
|
+
this.isRefreshingToken = false;
|
|
13527
|
+
this.tokenSubject = new BehaviorSubject(null);
|
|
13528
|
+
}
|
|
13529
|
+
addToken(req) {
|
|
13530
|
+
return req.clone({
|
|
13531
|
+
setHeaders: { Authorization: 'Bearer ' + this.jwtService.getToken() },
|
|
13532
|
+
withCredentials: true
|
|
13533
|
+
});
|
|
13534
|
+
}
|
|
13535
|
+
intercept(request, next) {
|
|
13536
|
+
// skip third party requests
|
|
13537
|
+
if (!request.url.includes(this.environment.apiV2)) {
|
|
13538
|
+
return next.handle(request);
|
|
13539
|
+
}
|
|
13540
|
+
// add token to every api request
|
|
13541
|
+
return next.handle(this.addToken(request)).pipe(
|
|
13542
|
+
// handle errors
|
|
13543
|
+
catchError((err) => {
|
|
13544
|
+
if (err instanceof HttpErrorResponse) {
|
|
13545
|
+
switch (err.status) {
|
|
13546
|
+
// unexpected errors
|
|
13547
|
+
case 405:
|
|
13548
|
+
case 500:
|
|
13549
|
+
this.handle500Error();
|
|
13550
|
+
break;
|
|
13551
|
+
// expected errors
|
|
13552
|
+
case 401:
|
|
13553
|
+
return this.handle401Error(request, next, err);
|
|
13554
|
+
case 400:
|
|
13555
|
+
case 403:
|
|
13556
|
+
// @TODO in most cases 404 is not an error, handle in components
|
|
13557
|
+
// case 404:
|
|
13558
|
+
this.showErrorMessages(err);
|
|
13559
|
+
break;
|
|
13560
|
+
}
|
|
13561
|
+
}
|
|
13562
|
+
return throwError(err);
|
|
13563
|
+
}));
|
|
13564
|
+
}
|
|
13565
|
+
/**
|
|
13566
|
+
* @TODO log
|
|
13567
|
+
* @TODO waiting for backend to handle errors in a better way
|
|
13568
|
+
*/
|
|
13569
|
+
handle400Error(err) {
|
|
13570
|
+
// this.snackBar.open(err.error['hydra:description'], '', {
|
|
13571
|
+
// panelClass: 'error'
|
|
13572
|
+
// });
|
|
13573
|
+
}
|
|
13574
|
+
/**
|
|
13575
|
+
* @TODO log
|
|
13576
|
+
* @TODO waiting for backend to handle errors in a better way
|
|
13577
|
+
*/
|
|
13578
|
+
handle403Error(err) {
|
|
13579
|
+
// this.snackBar.open(err.error['hydra:description'], '', {
|
|
13580
|
+
// panelClass: 'error'
|
|
13581
|
+
// });
|
|
13582
|
+
}
|
|
13583
|
+
/**
|
|
13584
|
+
* @TODO log
|
|
13585
|
+
*/
|
|
13586
|
+
handle500Error() {
|
|
13587
|
+
// this.snackBar.open(MESSAGE_DEFAULT_500_ERROR, '', {
|
|
13588
|
+
// panelClass: 'error'
|
|
13589
|
+
// });
|
|
13590
|
+
}
|
|
13591
|
+
handle401Error(req, next, err) {
|
|
13592
|
+
// skip 401 errors not from JWT (basiq login case or other)
|
|
13593
|
+
if (!err.error.message?.includes('JWT Token')) {
|
|
13594
|
+
return throwError(err);
|
|
13595
|
+
}
|
|
13596
|
+
if (req.url.includes('token/refresh') || req.url.includes('login')) {
|
|
13597
|
+
if (req.url.includes('token/refresh')) {
|
|
13598
|
+
this.authService.logoutFront();
|
|
13599
|
+
}
|
|
13600
|
+
return throwError(err);
|
|
13601
|
+
}
|
|
13602
|
+
// refreshing token, wait until it's done and retry the request
|
|
13603
|
+
if (this.isRefreshingToken) {
|
|
13604
|
+
return this.tokenSubject.pipe(filter(token => token != null), take(1), switchMap(token => next.handle(this.addToken(req))));
|
|
13605
|
+
// refresh token
|
|
13606
|
+
}
|
|
13607
|
+
// subsequent requests should wait until refresh token is ready
|
|
13608
|
+
this.isRefreshingToken = true;
|
|
13609
|
+
this.tokenSubject.next(null);
|
|
13610
|
+
return this.authService.refresh(this.jwtService.getRefreshToken()).pipe(switchMap((tokens) => {
|
|
13611
|
+
this.tokenSubject.next(tokens.token);
|
|
13612
|
+
return next.handle(this.addToken(req));
|
|
13613
|
+
}), catchError(() => {
|
|
13614
|
+
this.authService.logoutFront();
|
|
13615
|
+
return throwError(err);
|
|
13616
|
+
}), finalize(() => {
|
|
13617
|
+
this.isRefreshingToken = false;
|
|
13618
|
+
}));
|
|
13619
|
+
}
|
|
13620
|
+
/**
|
|
13621
|
+
* Handle error messages
|
|
13622
|
+
* @param errorResponse from which messages should be taken
|
|
13623
|
+
*
|
|
13624
|
+
* @TODO move to separated interceptor
|
|
13625
|
+
*/
|
|
13626
|
+
showErrorMessages(errorResponse) {
|
|
13627
|
+
if (!errorResponse.error.violations) {
|
|
13628
|
+
// this.snackBar.open('Something went wrong', '', {
|
|
13629
|
+
// panelClass: 'error'
|
|
13630
|
+
// });
|
|
13631
|
+
return;
|
|
13632
|
+
}
|
|
13633
|
+
errorResponse.error.violations.forEach((violation) => {
|
|
13634
|
+
// this.snackBar.open(violation['message'], '', {
|
|
13635
|
+
// panelClass: 'error'
|
|
13636
|
+
// });
|
|
13637
|
+
});
|
|
13638
|
+
}
|
|
13639
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: JwtInterceptor, deps: [{ token: JwtService }, { token: AuthService }, { token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
13640
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: JwtInterceptor }); }
|
|
13641
|
+
}
|
|
13642
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: JwtInterceptor, decorators: [{
|
|
13643
|
+
type: Injectable
|
|
13644
|
+
}], ctorParameters: () => [{ type: JwtService }, { type: AuthService }, { type: undefined, decorators: [{
|
|
13645
|
+
type: Inject,
|
|
13646
|
+
args: ['environment']
|
|
13647
|
+
}] }] });
|
|
13648
|
+
|
|
13649
|
+
let InterceptorsModule$1 = class InterceptorsModule {
|
|
13650
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: InterceptorsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
13651
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.10", ngImport: i0, type: InterceptorsModule }); }
|
|
13652
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: InterceptorsModule, providers: [
|
|
13653
|
+
{
|
|
13654
|
+
provide: HTTP_INTERCEPTORS,
|
|
13655
|
+
useClass: JwtInterceptor,
|
|
13656
|
+
multi: true
|
|
13657
|
+
}
|
|
13658
|
+
] }); }
|
|
13659
|
+
};
|
|
13660
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: InterceptorsModule$1, decorators: [{
|
|
13661
|
+
type: NgModule,
|
|
13662
|
+
args: [{
|
|
13663
|
+
providers: [
|
|
13664
|
+
{
|
|
13665
|
+
provide: HTTP_INTERCEPTORS,
|
|
13666
|
+
useClass: JwtInterceptor,
|
|
13667
|
+
multi: true
|
|
13668
|
+
}
|
|
13669
|
+
]
|
|
13670
|
+
}]
|
|
13671
|
+
}] });
|
|
13672
|
+
|
|
13673
|
+
/**
|
|
13674
|
+
* https://angular.io/guide/creating-libraries
|
|
13675
|
+
*/
|
|
13676
|
+
class CommonModule {
|
|
13677
|
+
static forRoot(environment) {
|
|
13678
|
+
// @TODO remove when bank model refactored (the only use case)
|
|
13679
|
+
localStorage.setItem('api_uri', environment['api_uri']);
|
|
13680
|
+
return {
|
|
13681
|
+
ngModule: CommonModule,
|
|
13682
|
+
providers: [
|
|
13683
|
+
{
|
|
13684
|
+
provide: 'environment',
|
|
13685
|
+
useValue: environment
|
|
13686
|
+
}
|
|
13687
|
+
]
|
|
13688
|
+
};
|
|
13689
|
+
}
|
|
13690
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: CommonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
13691
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.10", ngImport: i0, type: CommonModule, imports: [CommonModule$1,
|
|
13692
|
+
InterceptorsModule$1] }); }
|
|
13693
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: CommonModule, imports: [CommonModule$1,
|
|
13694
|
+
InterceptorsModule$1] }); }
|
|
13695
|
+
}
|
|
13696
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: CommonModule, decorators: [{
|
|
13697
|
+
type: NgModule,
|
|
13698
|
+
args: [{
|
|
13699
|
+
declarations: [],
|
|
13700
|
+
imports: [
|
|
13701
|
+
CommonModule$1,
|
|
13702
|
+
InterceptorsModule$1
|
|
13703
|
+
]
|
|
13704
|
+
}]
|
|
13705
|
+
}] });
|
|
13706
|
+
|
|
13707
|
+
class BudgetService extends RestService$1 {
|
|
13708
|
+
constructor() {
|
|
13709
|
+
super(...arguments);
|
|
13710
|
+
this.modelClass = Budget;
|
|
13711
|
+
this.collectionClass = BudgetCollection;
|
|
13712
|
+
this.endpointUri = 'budgets';
|
|
13713
|
+
this.disabledMethods = ['postBatch', 'putBatch', 'deleteBatch'];
|
|
13714
|
+
this.roles = [UserRolesEnum.MONEY_TANK];
|
|
13715
|
+
}
|
|
13716
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: BudgetService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
13717
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: BudgetService, providedIn: 'root' }); }
|
|
13718
|
+
}
|
|
13719
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: BudgetService, decorators: [{
|
|
13720
|
+
type: Injectable,
|
|
13721
|
+
args: [{
|
|
13722
|
+
providedIn: 'root'
|
|
13723
|
+
}]
|
|
13724
|
+
}] });
|
|
13725
|
+
|
|
13726
|
+
var BudgetMessagesEnum;
|
|
13727
|
+
(function (BudgetMessagesEnum) {
|
|
13728
|
+
BudgetMessagesEnum["CREATED"] = "Budget created";
|
|
13729
|
+
BudgetMessagesEnum["UPDATED"] = "Budget updated";
|
|
13730
|
+
BudgetMessagesEnum["DELETED"] = "Budget deleted";
|
|
13731
|
+
BudgetMessagesEnum["CONFIRM_DELETE"] = "Are you sure you want to delete budgeting?";
|
|
13732
|
+
})(BudgetMessagesEnum || (BudgetMessagesEnum = {}));
|
|
13733
|
+
|
|
13734
|
+
class BudgetRuleService extends RestService$1 {
|
|
13735
|
+
constructor() {
|
|
13736
|
+
super(...arguments);
|
|
13737
|
+
this.modelClass = BudgetRule;
|
|
13738
|
+
this.collectionClass = BudgetRuleCollection;
|
|
13739
|
+
this.endpointUri = 'budget-rules';
|
|
13740
|
+
this.disabledMethods = ['postBatch', 'putBatch', 'deleteBatch'];
|
|
13741
|
+
this.roles = [UserRolesEnum.MONEY_TANK];
|
|
13742
|
+
}
|
|
13743
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: BudgetRuleService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
13744
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: BudgetRuleService, providedIn: 'root' }); }
|
|
13745
|
+
}
|
|
13746
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: BudgetRuleService, decorators: [{
|
|
13747
|
+
type: Injectable,
|
|
13748
|
+
args: [{
|
|
13749
|
+
providedIn: 'root'
|
|
13750
|
+
}]
|
|
13751
|
+
}] });
|
|
13752
|
+
|
|
13753
|
+
class FinancialGoalService extends RestService$1 {
|
|
13754
|
+
constructor() {
|
|
13755
|
+
super(...arguments);
|
|
13756
|
+
this.modelClass = FinancialGoal;
|
|
13757
|
+
this.collectionClass = FinancialGoalCollection;
|
|
13758
|
+
this.endpointUri = 'financial-goals';
|
|
13759
|
+
this.disabledMethods = ['postBatch', 'putBatch', 'deleteBatch'];
|
|
13760
|
+
this.useBackendError = true;
|
|
13761
|
+
this.roles = [UserRolesEnum.MONEY_TANK];
|
|
13762
|
+
}
|
|
13763
|
+
pause(goal) {
|
|
13764
|
+
return this.put(Object.assign({}, goal, { status: FinancialGoalStatusEnum.PAUSE }));
|
|
13765
|
+
}
|
|
13766
|
+
resume(goal) {
|
|
13767
|
+
return this.put(Object.assign({}, goal, { status: FinancialGoalStatusEnum.ACTIVE }));
|
|
13768
|
+
}
|
|
13769
|
+
complete(goal) {
|
|
13770
|
+
return this.put(Object.assign({}, goal, { status: FinancialGoalStatusEnum.COMPLETE, finalValue: goal.bankAccount.currentBalance }));
|
|
13771
|
+
}
|
|
13772
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: FinancialGoalService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
13773
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: FinancialGoalService, providedIn: 'root' }); }
|
|
13774
|
+
}
|
|
13775
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: FinancialGoalService, decorators: [{
|
|
13776
|
+
type: Injectable,
|
|
13777
|
+
args: [{
|
|
13778
|
+
providedIn: 'root'
|
|
13779
|
+
}]
|
|
13780
|
+
}] });
|
|
13781
|
+
|
|
13782
|
+
var FinancialGoalMessagesEnum;
|
|
13783
|
+
(function (FinancialGoalMessagesEnum) {
|
|
13784
|
+
FinancialGoalMessagesEnum["CREATED"] = "Goal created!";
|
|
13785
|
+
FinancialGoalMessagesEnum["UPDATED"] = "Goal updated!";
|
|
13786
|
+
FinancialGoalMessagesEnum["CONFIRM_DELETE"] = "Are you sure you want to delete the goal?";
|
|
13787
|
+
FinancialGoalMessagesEnum["DELETED"] = "Goal deleted!";
|
|
13788
|
+
FinancialGoalMessagesEnum["CONFIRM_COMPLETE"] = "Are you sure? Complete goals can not be made active again. Would you like to continue?";
|
|
13789
|
+
})(FinancialGoalMessagesEnum || (FinancialGoalMessagesEnum = {}));
|
|
13790
|
+
|
|
13791
|
+
/**
|
|
13792
|
+
* Service to work with depreciation chart accounts
|
|
13793
|
+
*/
|
|
13794
|
+
class ChartAccountsDepreciationService extends RestService$1 {
|
|
13795
|
+
constructor() {
|
|
13796
|
+
super(...arguments);
|
|
13797
|
+
this.endpointUri = 'chart-accounts-depreciations';
|
|
13798
|
+
this.modelClass = ChartAccountsDepreciation;
|
|
13799
|
+
this.collectionClass = Collection;
|
|
13800
|
+
this.disabledMethods = ['postBatch', 'putBatch', 'deleteBatch'];
|
|
13801
|
+
}
|
|
13802
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: ChartAccountsDepreciationService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
13803
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: ChartAccountsDepreciationService, providedIn: 'root' }); }
|
|
13398
13804
|
}
|
|
13399
13805
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: ChartAccountsDepreciationService, decorators: [{
|
|
13400
13806
|
type: Injectable,
|
|
@@ -20193,30 +20599,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
|
|
|
20193
20599
|
* Checks required steps and their completion
|
|
20194
20600
|
*/
|
|
20195
20601
|
class AccountSetupService {
|
|
20196
|
-
constructor(
|
|
20197
|
-
this.setupItemService =
|
|
20198
|
-
this.propertyService =
|
|
20199
|
-
this.incomeSourceService =
|
|
20200
|
-
this.bankConnectionService =
|
|
20201
|
-
this.bankAccountsService =
|
|
20202
|
-
this.bankTransactionService =
|
|
20203
|
-
this.loanService =
|
|
20204
|
-
this.allocationRuleService =
|
|
20205
|
-
this.transactionAllocationService =
|
|
20206
|
-
this.vehicleClaimService =
|
|
20207
|
-
this.homeOfficeClaimService =
|
|
20208
|
-
this.transactionService =
|
|
20209
|
-
this.depreciationService =
|
|
20210
|
-
this.businessService =
|
|
20211
|
-
this.holdingService =
|
|
20212
|
-
this.userService =
|
|
20213
|
-
this.clientMovementService =
|
|
20214
|
-
this.clientInviteService =
|
|
20215
|
-
this.employeeService =
|
|
20216
|
-
this.employeeInviteService =
|
|
20217
|
-
this.firmService =
|
|
20218
|
-
this.sharesightDetailsService =
|
|
20219
|
-
this.propertyShareService =
|
|
20602
|
+
constructor() {
|
|
20603
|
+
this.setupItemService = inject(SetupItemService);
|
|
20604
|
+
this.propertyService = inject(PropertyService);
|
|
20605
|
+
this.incomeSourceService = inject(IncomeSourceService);
|
|
20606
|
+
this.bankConnectionService = inject(BankConnectionService);
|
|
20607
|
+
this.bankAccountsService = inject(BankAccountService);
|
|
20608
|
+
this.bankTransactionService = inject(BankTransactionService);
|
|
20609
|
+
this.loanService = inject(LoanService);
|
|
20610
|
+
this.allocationRuleService = inject(AllocationRuleService);
|
|
20611
|
+
this.transactionAllocationService = inject(TransactionAllocationService);
|
|
20612
|
+
this.vehicleClaimService = inject(VehicleClaimService);
|
|
20613
|
+
this.homeOfficeClaimService = inject(HomeOfficeClaimService);
|
|
20614
|
+
this.transactionService = inject(TransactionService);
|
|
20615
|
+
this.depreciationService = inject(DepreciationService);
|
|
20616
|
+
this.businessService = inject(SoleBusinessService);
|
|
20617
|
+
this.holdingService = inject(HoldingTradeService);
|
|
20618
|
+
this.userService = inject(UserService);
|
|
20619
|
+
this.clientMovementService = inject(ClientMovementService);
|
|
20620
|
+
this.clientInviteService = inject(ClientInviteService);
|
|
20621
|
+
this.employeeService = inject(EmployeeService);
|
|
20622
|
+
this.employeeInviteService = inject(EmployeeInviteService);
|
|
20623
|
+
this.firmService = inject(FirmService);
|
|
20624
|
+
this.sharesightDetailsService = inject(SharesightDetailsService);
|
|
20625
|
+
this.propertyShareService = inject(PropertyShareService);
|
|
20626
|
+
this.budgetRuleService = inject(BudgetRuleService);
|
|
20627
|
+
this.financialGoalService = inject(FinancialGoalService);
|
|
20220
20628
|
}
|
|
20221
20629
|
/**
|
|
20222
20630
|
* Get list of account setup items for current user/firm
|
|
@@ -20256,6 +20664,11 @@ class AccountSetupService {
|
|
|
20256
20664
|
// bankAccounts
|
|
20257
20665
|
[AccountSetupItemsEnum.BANK_CONNECTION]: this.bankConnectionService.getArray(),
|
|
20258
20666
|
[AccountSetupItemsEnum.BANK_ACCOUNT]: this.getBankAccounts(),
|
|
20667
|
+
// money tank
|
|
20668
|
+
[AccountSetupItemsEnum.MONEY_BANK_ACCOUNT]: this.getBankAccounts(),
|
|
20669
|
+
[AccountSetupItemsEnum.MONEY_EXPENSE_BUDGETS]: this.budgetRuleService.get().pipe(map(rules => rules.expenses)),
|
|
20670
|
+
[AccountSetupItemsEnum.MONEY_INCOME_BUDGETS]: this.budgetRuleService.get().pipe(map(rules => rules.incomes)),
|
|
20671
|
+
[AccountSetupItemsEnum.MONEY_GOALS]: this.financialGoalService.get(),
|
|
20259
20672
|
};
|
|
20260
20673
|
// property
|
|
20261
20674
|
if (property) {
|
|
@@ -20291,472 +20704,106 @@ class AccountSetupService {
|
|
|
20291
20704
|
* Check and update isCompleted flag for passed item
|
|
20292
20705
|
*/
|
|
20293
20706
|
setItemStatus(item, request) {
|
|
20294
|
-
return request.pipe(map((result) => {
|
|
20295
|
-
const isSkipped = !!this.user.blacklistSetupItems.find((skippedItem) => skippedItem.id === item.id);
|
|
20296
|
-
item.status = isSkipped ? AccountSetupItemStatusEnum.SKIPPED : result.length ? AccountSetupItemStatusEnum.ACHIEVED : AccountSetupItemStatusEnum.PENDING;
|
|
20297
|
-
return item;
|
|
20298
|
-
}));
|
|
20299
|
-
}
|
|
20300
|
-
getAllocations(bankAccountId) {
|
|
20301
|
-
return combineLatest([this.bankTransactionService.get(), this.transactionAllocationService.get()]).pipe(map(([bankTransactions, allocations]) => {
|
|
20302
|
-
const bankTransactionsIds = bankTransactions.filterBy('bankAccount.id', bankAccountId).getIds();
|
|
20303
|
-
return new TransactionAllocationCollection(allocations).getByBankTransactionsIds(bankTransactionsIds).toArray();
|
|
20304
|
-
}));
|
|
20305
|
-
}
|
|
20306
|
-
getTransactions(propertyId) {
|
|
20307
|
-
return this.transactionService.getByPropertyId(propertyId);
|
|
20308
|
-
}
|
|
20309
|
-
getCoOwners(propertyId) {
|
|
20310
|
-
return this.propertyShareService.getArrayBy('property.id', propertyId).pipe(map(shares => shares.slice(1)));
|
|
20311
|
-
}
|
|
20312
|
-
/**
|
|
20313
|
-
* AccountSetupItemsEnum.FIRM_CLIENTS completed when client invites sent or accepted
|
|
20314
|
-
*/
|
|
20315
|
-
getClients() {
|
|
20316
|
-
return combineLatest([this.clientMovementService.getActive(), this.clientInviteService.get()]).pipe(map(([movements, invites]) => [...movements, ...invites]));
|
|
20317
|
-
}
|
|
20318
|
-
/**
|
|
20319
|
-
* AccountSetupItemsEnum.FIRM_EMPLOYEES completed when employee invites sent or accepted
|
|
20320
|
-
*/
|
|
20321
|
-
getEmployees() {
|
|
20322
|
-
return combineLatest([this.employeeService.getArray(), this.employeeInviteService.getArray()]).pipe(map(([employees, invites]) => [...employees.slice(1), ...invites]));
|
|
20323
|
-
}
|
|
20324
|
-
/**
|
|
20325
|
-
* AccountSetupItemsEnum.FIRM_DETAILS when firm data filled
|
|
20326
|
-
*/
|
|
20327
|
-
getFirms() {
|
|
20328
|
-
return this.firmService.get().pipe(map((firm) => [firm].filter(firm => firm.address || firm.phone || firm.file || firm.shortName)));
|
|
20329
|
-
}
|
|
20330
|
-
/**
|
|
20331
|
-
* @TODO Alex: work with collection when services refactored
|
|
20332
|
-
* @TODO Vik: waiting for income sources refactoring
|
|
20333
|
-
*/
|
|
20334
|
-
getIncomeSources(isSalary) {
|
|
20335
|
-
return this.incomeSourceService.get().pipe(map((incomeSources) => {
|
|
20336
|
-
const collection = new IncomeSourceCollection(incomeSources);
|
|
20337
|
-
if (isSalary) {
|
|
20338
|
-
return collection.getSalary();
|
|
20339
|
-
}
|
|
20340
|
-
return collection.items.filter((incomeSource) => incomeSource.isOtherIncome());
|
|
20341
|
-
}));
|
|
20342
|
-
}
|
|
20343
|
-
getVehicleClaims(businessId) {
|
|
20344
|
-
return this.vehicleClaimService.getArray().pipe(map(claims => claims.filter(claim => claim.business?.id === businessId)));
|
|
20345
|
-
}
|
|
20346
|
-
getHomeOfficeClaims(businessId) {
|
|
20347
|
-
return this.homeOfficeClaimService.getArray().pipe(map(claims => claims.filter(claim => claim.business?.id === businessId)));
|
|
20348
|
-
}
|
|
20349
|
-
getBankAccounts(tankType) {
|
|
20350
|
-
return this.bankAccountsService.get().pipe(map((bankAccounts => bankAccounts.getByTankType(tankType).toArray())));
|
|
20351
|
-
}
|
|
20352
|
-
getDepreciations(tankType, id) {
|
|
20353
|
-
return this.depreciationService.get().pipe(map(depreciations => {
|
|
20354
|
-
depreciations = depreciations.getByTankType(tankType);
|
|
20355
|
-
if (tankType === TankTypeEnum.PROPERTY && id) {
|
|
20356
|
-
depreciations.filterBy('property.id', id);
|
|
20357
|
-
}
|
|
20358
|
-
if (tankType === TankTypeEnum.SOLE && id) {
|
|
20359
|
-
depreciations.filterBy('business.id', id);
|
|
20360
|
-
}
|
|
20361
|
-
return depreciations.toArray();
|
|
20362
|
-
}));
|
|
20363
|
-
}
|
|
20364
|
-
getSharesightDetails(importEnabled) {
|
|
20365
|
-
return this.sharesightDetailsService.getArray().pipe(map(details => details.filter(detail => importEnabled ? detail.importEnabled : detail.exportEnabled)));
|
|
20366
|
-
}
|
|
20367
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AccountSetupService, deps: [{ token: SetupItemService }, { token: PropertyService }, { token: IncomeSourceService }, { token: BankConnectionService }, { token: BankAccountService }, { token: BankTransactionService }, { token: LoanService }, { token: AllocationRuleService }, { token: TransactionAllocationService }, { token: VehicleClaimService }, { token: HomeOfficeClaimService }, { token: TransactionService }, { token: DepreciationService }, { token: SoleBusinessService }, { token: HoldingTradeService }, { token: UserService }, { token: ClientMovementService }, { token: ClientInviteService }, { token: EmployeeService }, { token: EmployeeInviteService }, { token: FirmService }, { token: SharesightDetailsService }, { token: PropertyShareService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
20368
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AccountSetupService, providedIn: 'root' }); }
|
|
20369
|
-
}
|
|
20370
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AccountSetupService, decorators: [{
|
|
20371
|
-
type: Injectable,
|
|
20372
|
-
args: [{
|
|
20373
|
-
providedIn: 'root'
|
|
20374
|
-
}]
|
|
20375
|
-
}], ctorParameters: () => [{ type: SetupItemService }, { type: PropertyService }, { type: IncomeSourceService }, { type: BankConnectionService }, { type: BankAccountService }, { type: BankTransactionService }, { type: LoanService }, { type: AllocationRuleService }, { type: TransactionAllocationService }, { type: VehicleClaimService }, { type: HomeOfficeClaimService }, { type: TransactionService }, { type: DepreciationService }, { type: SoleBusinessService }, { type: HoldingTradeService }, { type: UserService }, { type: ClientMovementService }, { type: ClientInviteService }, { type: EmployeeService }, { type: EmployeeInviteService }, { type: FirmService }, { type: SharesightDetailsService }, { type: PropertyShareService }] });
|
|
20376
|
-
|
|
20377
|
-
/**
|
|
20378
|
-
* service that checks adblock once we started application and saves this information
|
|
20379
|
-
* to unbound from promise of adblock-checker
|
|
20380
|
-
*/
|
|
20381
|
-
class AdblockDetectorService {
|
|
20382
|
-
constructor() {
|
|
20383
|
-
checkAdBlock().then((isDetected) => this.isDetected = isDetected);
|
|
20384
|
-
}
|
|
20385
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AdblockDetectorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
20386
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AdblockDetectorService, providedIn: 'root' }); }
|
|
20387
|
-
}
|
|
20388
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AdblockDetectorService, decorators: [{
|
|
20389
|
-
type: Injectable,
|
|
20390
|
-
args: [{
|
|
20391
|
-
providedIn: 'root'
|
|
20392
|
-
}]
|
|
20393
|
-
}], ctorParameters: () => [] });
|
|
20394
|
-
|
|
20395
|
-
/**
|
|
20396
|
-
* Service to work with mixpanel https://docs.mixpanel.com/docs/tracking/reference/javascript
|
|
20397
|
-
*/
|
|
20398
|
-
class MixpanelService {
|
|
20399
|
-
constructor(environment) {
|
|
20400
|
-
this.environment = environment;
|
|
20401
|
-
}
|
|
20402
|
-
init() {
|
|
20403
|
-
if (!this.environment.enableMixpanel) {
|
|
20404
|
-
return;
|
|
20405
|
-
}
|
|
20406
|
-
mixpanel.init(this.environment.mixpanelToken);
|
|
20407
|
-
}
|
|
20408
|
-
identify(id) {
|
|
20409
|
-
if (!this.environment.enableMixpanel) {
|
|
20410
|
-
return;
|
|
20411
|
-
}
|
|
20412
|
-
mixpanel.identify(id);
|
|
20413
|
-
mixpanel.people.set({ 'last seen': new Date(Date.now()).toLocaleString() });
|
|
20414
|
-
}
|
|
20415
|
-
reset() {
|
|
20416
|
-
if (!this.environment.enableMixpanel) {
|
|
20417
|
-
return;
|
|
20418
|
-
}
|
|
20419
|
-
mixpanel.reset();
|
|
20420
|
-
}
|
|
20421
|
-
track(event, properties = {}) {
|
|
20422
|
-
if (!this.environment.enableMixpanel) {
|
|
20423
|
-
return;
|
|
20424
|
-
}
|
|
20425
|
-
mixpanel.track(event, properties);
|
|
20426
|
-
}
|
|
20427
|
-
trackLink(id, event, properties = {}) {
|
|
20428
|
-
if (!this.environment.enableMixpanel) {
|
|
20429
|
-
return;
|
|
20430
|
-
}
|
|
20431
|
-
mixpanel.track_links(`#${id}`, event, properties);
|
|
20432
|
-
}
|
|
20433
|
-
trackPageView() {
|
|
20434
|
-
if (!this.environment.enableMixpanel) {
|
|
20435
|
-
return;
|
|
20436
|
-
}
|
|
20437
|
-
mixpanel['track_pageview']();
|
|
20438
|
-
}
|
|
20439
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: MixpanelService, deps: [{ token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
20440
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: MixpanelService, providedIn: 'root' }); }
|
|
20441
|
-
}
|
|
20442
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: MixpanelService, decorators: [{
|
|
20443
|
-
type: Injectable,
|
|
20444
|
-
args: [{
|
|
20445
|
-
providedIn: 'root'
|
|
20446
|
-
}]
|
|
20447
|
-
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
20448
|
-
type: Inject,
|
|
20449
|
-
args: ['environment']
|
|
20450
|
-
}] }] });
|
|
20451
|
-
|
|
20452
|
-
var UserRolesEnum;
|
|
20453
|
-
(function (UserRolesEnum) {
|
|
20454
|
-
UserRolesEnum["FIRM_OWNER"] = "ROLE_FIRM_OWNER";
|
|
20455
|
-
UserRolesEnum["FIRM_MANAGER"] = "ROLE_FIRM_MANAGER";
|
|
20456
|
-
UserRolesEnum["FIRM_TOP_MANAGER"] = "ROLE_FIRM_TOP_MANAGER";
|
|
20457
|
-
UserRolesEnum["CLIENT"] = "ROLE_CLIENT";
|
|
20458
|
-
UserRolesEnum["EMPLOYEE"] = "ROLE_EMPLOYEE";
|
|
20459
|
-
UserRolesEnum["ACCOUNTANT"] = "ROLE_ACCOUNTANT";
|
|
20460
|
-
UserRolesEnum["ADVISOR"] = "ROLE_ADVISOR";
|
|
20461
|
-
UserRolesEnum["USER"] = "ROLE_USER";
|
|
20462
|
-
UserRolesEnum["SUBSCRIPTION"] = "ROLE_USER_SUBSCRIPTION";
|
|
20463
|
-
UserRolesEnum["WORK_TANK"] = "ROLE_USER_WORK";
|
|
20464
|
-
UserRolesEnum["PROPERTY_TANK"] = "ROLE_USER_PROPERTY";
|
|
20465
|
-
UserRolesEnum["SOLE_TANK"] = "ROLE_USER_SOLE";
|
|
20466
|
-
UserRolesEnum["HOLDING_TANK"] = "ROLE_USER_HOLDING";
|
|
20467
|
-
UserRolesEnum["MONEY_TANK"] = "ROLE_USER_MONEY";
|
|
20468
|
-
UserRolesEnum["SWITCH_USER"] = "IS_IMPERSONATOR";
|
|
20469
|
-
})(UserRolesEnum || (UserRolesEnum = {}));
|
|
20470
|
-
|
|
20471
|
-
const NAME_TOKEN = 'token';
|
|
20472
|
-
const NAME_REFRESH_TOKEN = 'refreshToken';
|
|
20473
|
-
class JwtService extends JwtHelperService {
|
|
20474
|
-
constructor() {
|
|
20475
|
-
super(...arguments);
|
|
20476
|
-
this.mpService = inject(MixpanelService);
|
|
20477
|
-
this.isLoggedInSubject = new BehaviorSubject(!this.isTokenExpired());
|
|
20478
|
-
}
|
|
20479
|
-
getToken() {
|
|
20480
|
-
return localStorage[NAME_TOKEN];
|
|
20481
|
-
}
|
|
20482
|
-
getRefreshToken() {
|
|
20483
|
-
return localStorage[NAME_REFRESH_TOKEN];
|
|
20484
|
-
}
|
|
20485
|
-
saveTokens(tokens) {
|
|
20486
|
-
localStorage[NAME_TOKEN] = tokens.token;
|
|
20487
|
-
localStorage[NAME_REFRESH_TOKEN] = tokens.refreshToken;
|
|
20488
|
-
this.mpService.identify(this.decode(tokens.token).id.toString());
|
|
20489
|
-
this.isLoggedInSubject.next(true);
|
|
20490
|
-
}
|
|
20491
|
-
destroyTokens() {
|
|
20492
|
-
localStorage.removeItem(NAME_TOKEN);
|
|
20493
|
-
localStorage.removeItem(NAME_REFRESH_TOKEN);
|
|
20494
|
-
localStorage.removeItem('userId');
|
|
20495
|
-
localStorage.removeItem('_switch_user');
|
|
20496
|
-
this.mpService.track('logout');
|
|
20497
|
-
this.mpService.reset();
|
|
20498
|
-
this.isLoggedInSubject.next(false);
|
|
20499
|
-
}
|
|
20500
|
-
decode(token) {
|
|
20501
|
-
return super.decodeToken(token);
|
|
20502
|
-
}
|
|
20503
|
-
isClient() {
|
|
20504
|
-
return this.decode().roles.includes(UserRolesEnum.CLIENT);
|
|
20505
|
-
}
|
|
20506
|
-
isMe(userId) {
|
|
20507
|
-
return this.decode().id === userId;
|
|
20508
|
-
}
|
|
20509
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: JwtService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
20510
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: JwtService, providedIn: 'root' }); }
|
|
20511
|
-
}
|
|
20512
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: JwtService, decorators: [{
|
|
20513
|
-
type: Injectable,
|
|
20514
|
-
args: [{
|
|
20515
|
-
providedIn: 'root'
|
|
20516
|
-
}]
|
|
20517
|
-
}] });
|
|
20518
|
-
|
|
20519
|
-
class AuthService {
|
|
20520
|
-
constructor(http, jwtService, mpService, environment) {
|
|
20521
|
-
this.http = http;
|
|
20522
|
-
this.jwtService = jwtService;
|
|
20523
|
-
this.mpService = mpService;
|
|
20524
|
-
this.environment = environment;
|
|
20525
|
-
}
|
|
20526
|
-
setAuth(response) {
|
|
20527
|
-
this.jwtService.saveTokens(response);
|
|
20528
|
-
}
|
|
20529
|
-
login(username, password) {
|
|
20530
|
-
return this.http.post(`${this.environment.apiV2}/login`, { username, password }).pipe(map((response) => {
|
|
20531
|
-
if (response.token) {
|
|
20532
|
-
this.setAuth(response);
|
|
20533
|
-
}
|
|
20534
|
-
return response;
|
|
20535
|
-
}));
|
|
20536
|
-
}
|
|
20537
|
-
mfaLogin(otp) {
|
|
20538
|
-
return this.http.post(`${this.environment.apiV2}/2fa_check`, { otp }).pipe(map((response) => {
|
|
20539
|
-
this.setAuth(response);
|
|
20540
|
-
return response;
|
|
20707
|
+
return request.pipe(map((result) => {
|
|
20708
|
+
const isSkipped = !!this.user.blacklistSetupItems.find((skippedItem) => skippedItem.id === item.id);
|
|
20709
|
+
item.status = isSkipped ? AccountSetupItemStatusEnum.SKIPPED : result.length ? AccountSetupItemStatusEnum.ACHIEVED : AccountSetupItemStatusEnum.PENDING;
|
|
20710
|
+
return item;
|
|
20541
20711
|
}));
|
|
20542
20712
|
}
|
|
20543
|
-
|
|
20544
|
-
return this.
|
|
20545
|
-
|
|
20546
|
-
return
|
|
20713
|
+
getAllocations(bankAccountId) {
|
|
20714
|
+
return combineLatest([this.bankTransactionService.get(), this.transactionAllocationService.get()]).pipe(map(([bankTransactions, allocations]) => {
|
|
20715
|
+
const bankTransactionsIds = bankTransactions.filterBy('bankAccount.id', bankAccountId).getIds();
|
|
20716
|
+
return new TransactionAllocationCollection(allocations).getByBankTransactionsIds(bankTransactionsIds).toArray();
|
|
20547
20717
|
}));
|
|
20548
20718
|
}
|
|
20549
|
-
|
|
20550
|
-
this.
|
|
20551
|
-
location.replace(url);
|
|
20552
|
-
}
|
|
20553
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AuthService, deps: [{ token: i1.HttpClient }, { token: JwtService }, { token: MixpanelService }, { token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
20554
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AuthService, providedIn: 'root' }); }
|
|
20555
|
-
}
|
|
20556
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AuthService, decorators: [{
|
|
20557
|
-
type: Injectable,
|
|
20558
|
-
args: [{
|
|
20559
|
-
providedIn: 'root'
|
|
20560
|
-
}]
|
|
20561
|
-
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: JwtService }, { type: MixpanelService }, { type: undefined, decorators: [{
|
|
20562
|
-
type: Inject,
|
|
20563
|
-
args: ['environment']
|
|
20564
|
-
}] }] });
|
|
20565
|
-
|
|
20566
|
-
var AuthMessagesEnum;
|
|
20567
|
-
(function (AuthMessagesEnum) {
|
|
20568
|
-
AuthMessagesEnum["ERROR_401"] = "Email or password is incorrect";
|
|
20569
|
-
})(AuthMessagesEnum || (AuthMessagesEnum = {}));
|
|
20570
|
-
|
|
20571
|
-
const MESSAGE_DEFAULT_500_ERROR = 'Unexpected error! Please try again later. You can send us via chat your questions.';
|
|
20572
|
-
/**
|
|
20573
|
-
* JWT Interceptor add jwt token to each request related with TaxTank API
|
|
20574
|
-
*/
|
|
20575
|
-
class JwtInterceptor {
|
|
20576
|
-
constructor(jwtService, authService, environment) {
|
|
20577
|
-
this.jwtService = jwtService;
|
|
20578
|
-
this.authService = authService;
|
|
20579
|
-
this.environment = environment;
|
|
20580
|
-
this.isRefreshingToken = false;
|
|
20581
|
-
this.tokenSubject = new BehaviorSubject(null);
|
|
20719
|
+
getTransactions(propertyId) {
|
|
20720
|
+
return this.transactionService.getByPropertyId(propertyId);
|
|
20582
20721
|
}
|
|
20583
|
-
|
|
20584
|
-
return
|
|
20585
|
-
setHeaders: { Authorization: 'Bearer ' + this.jwtService.getToken() },
|
|
20586
|
-
withCredentials: true
|
|
20587
|
-
});
|
|
20722
|
+
getCoOwners(propertyId) {
|
|
20723
|
+
return this.propertyShareService.getArrayBy('property.id', propertyId).pipe(map(shares => shares.slice(1)));
|
|
20588
20724
|
}
|
|
20589
|
-
|
|
20590
|
-
|
|
20591
|
-
|
|
20592
|
-
|
|
20593
|
-
|
|
20594
|
-
// add token to every api request
|
|
20595
|
-
return next.handle(this.addToken(request)).pipe(
|
|
20596
|
-
// handle errors
|
|
20597
|
-
catchError((err) => {
|
|
20598
|
-
if (err instanceof HttpErrorResponse) {
|
|
20599
|
-
switch (err.status) {
|
|
20600
|
-
// unexpected errors
|
|
20601
|
-
case 405:
|
|
20602
|
-
case 500:
|
|
20603
|
-
this.handle500Error();
|
|
20604
|
-
break;
|
|
20605
|
-
// expected errors
|
|
20606
|
-
case 401:
|
|
20607
|
-
return this.handle401Error(request, next, err);
|
|
20608
|
-
case 400:
|
|
20609
|
-
case 403:
|
|
20610
|
-
// @TODO in most cases 404 is not an error, handle in components
|
|
20611
|
-
// case 404:
|
|
20612
|
-
this.showErrorMessages(err);
|
|
20613
|
-
break;
|
|
20614
|
-
}
|
|
20615
|
-
}
|
|
20616
|
-
return throwError(err);
|
|
20617
|
-
}));
|
|
20725
|
+
/**
|
|
20726
|
+
* AccountSetupItemsEnum.FIRM_CLIENTS completed when client invites sent or accepted
|
|
20727
|
+
*/
|
|
20728
|
+
getClients() {
|
|
20729
|
+
return combineLatest([this.clientMovementService.getActive(), this.clientInviteService.get()]).pipe(map(([movements, invites]) => [...movements, ...invites]));
|
|
20618
20730
|
}
|
|
20619
20731
|
/**
|
|
20620
|
-
*
|
|
20621
|
-
* @TODO waiting for backend to handle errors in a better way
|
|
20732
|
+
* AccountSetupItemsEnum.FIRM_EMPLOYEES completed when employee invites sent or accepted
|
|
20622
20733
|
*/
|
|
20623
|
-
|
|
20624
|
-
|
|
20625
|
-
// panelClass: 'error'
|
|
20626
|
-
// });
|
|
20734
|
+
getEmployees() {
|
|
20735
|
+
return combineLatest([this.employeeService.getArray(), this.employeeInviteService.getArray()]).pipe(map(([employees, invites]) => [...employees.slice(1), ...invites]));
|
|
20627
20736
|
}
|
|
20628
20737
|
/**
|
|
20629
|
-
*
|
|
20630
|
-
* @TODO waiting for backend to handle errors in a better way
|
|
20738
|
+
* AccountSetupItemsEnum.FIRM_DETAILS when firm data filled
|
|
20631
20739
|
*/
|
|
20632
|
-
|
|
20633
|
-
|
|
20634
|
-
// panelClass: 'error'
|
|
20635
|
-
// });
|
|
20740
|
+
getFirms() {
|
|
20741
|
+
return this.firmService.get().pipe(map((firm) => [firm].filter(firm => firm.address || firm.phone || firm.file || firm.shortName)));
|
|
20636
20742
|
}
|
|
20637
20743
|
/**
|
|
20638
|
-
* @TODO
|
|
20744
|
+
* @TODO Alex: work with collection when services refactored
|
|
20745
|
+
* @TODO Vik: waiting for income sources refactoring
|
|
20639
20746
|
*/
|
|
20640
|
-
|
|
20641
|
-
|
|
20642
|
-
|
|
20643
|
-
|
|
20747
|
+
getIncomeSources(isSalary) {
|
|
20748
|
+
return this.incomeSourceService.get().pipe(map((incomeSources) => {
|
|
20749
|
+
const collection = new IncomeSourceCollection(incomeSources);
|
|
20750
|
+
if (isSalary) {
|
|
20751
|
+
return collection.getSalary();
|
|
20752
|
+
}
|
|
20753
|
+
return collection.items.filter((incomeSource) => incomeSource.isOtherIncome());
|
|
20754
|
+
}));
|
|
20644
20755
|
}
|
|
20645
|
-
|
|
20646
|
-
|
|
20647
|
-
|
|
20648
|
-
|
|
20649
|
-
|
|
20650
|
-
|
|
20651
|
-
|
|
20652
|
-
|
|
20756
|
+
getVehicleClaims(businessId) {
|
|
20757
|
+
return this.vehicleClaimService.getArray().pipe(map(claims => claims.filter(claim => claim.business?.id === businessId)));
|
|
20758
|
+
}
|
|
20759
|
+
getHomeOfficeClaims(businessId) {
|
|
20760
|
+
return this.homeOfficeClaimService.getArray().pipe(map(claims => claims.filter(claim => claim.business?.id === businessId)));
|
|
20761
|
+
}
|
|
20762
|
+
getBankAccounts(tankType) {
|
|
20763
|
+
return this.bankAccountsService.get().pipe(map((bankAccounts => bankAccounts.getByTankType(tankType).toArray())));
|
|
20764
|
+
}
|
|
20765
|
+
getDepreciations(tankType, id) {
|
|
20766
|
+
return this.depreciationService.get().pipe(map(depreciations => {
|
|
20767
|
+
depreciations = depreciations.getByTankType(tankType);
|
|
20768
|
+
if (tankType === TankTypeEnum.PROPERTY && id) {
|
|
20769
|
+
depreciations.filterBy('property.id', id);
|
|
20653
20770
|
}
|
|
20654
|
-
|
|
20655
|
-
|
|
20656
|
-
|
|
20657
|
-
|
|
20658
|
-
return this.tokenSubject.pipe(filter(token => token != null), take(1), switchMap(token => next.handle(this.addToken(req))));
|
|
20659
|
-
// refresh token
|
|
20660
|
-
}
|
|
20661
|
-
// subsequent requests should wait until refresh token is ready
|
|
20662
|
-
this.isRefreshingToken = true;
|
|
20663
|
-
this.tokenSubject.next(null);
|
|
20664
|
-
return this.authService.refresh(this.jwtService.getRefreshToken()).pipe(switchMap((tokens) => {
|
|
20665
|
-
this.tokenSubject.next(tokens.token);
|
|
20666
|
-
return next.handle(this.addToken(req));
|
|
20667
|
-
}), catchError(() => {
|
|
20668
|
-
this.authService.logoutFront();
|
|
20669
|
-
return throwError(err);
|
|
20670
|
-
}), finalize(() => {
|
|
20671
|
-
this.isRefreshingToken = false;
|
|
20771
|
+
if (tankType === TankTypeEnum.SOLE && id) {
|
|
20772
|
+
depreciations.filterBy('business.id', id);
|
|
20773
|
+
}
|
|
20774
|
+
return depreciations.toArray();
|
|
20672
20775
|
}));
|
|
20673
20776
|
}
|
|
20674
|
-
|
|
20675
|
-
|
|
20676
|
-
* @param errorResponse from which messages should be taken
|
|
20677
|
-
*
|
|
20678
|
-
* @TODO move to separated interceptor
|
|
20679
|
-
*/
|
|
20680
|
-
showErrorMessages(errorResponse) {
|
|
20681
|
-
if (!errorResponse.error.violations) {
|
|
20682
|
-
// this.snackBar.open('Something went wrong', '', {
|
|
20683
|
-
// panelClass: 'error'
|
|
20684
|
-
// });
|
|
20685
|
-
return;
|
|
20686
|
-
}
|
|
20687
|
-
errorResponse.error.violations.forEach((violation) => {
|
|
20688
|
-
// this.snackBar.open(violation['message'], '', {
|
|
20689
|
-
// panelClass: 'error'
|
|
20690
|
-
// });
|
|
20691
|
-
});
|
|
20777
|
+
getSharesightDetails(importEnabled) {
|
|
20778
|
+
return this.sharesightDetailsService.getArray().pipe(map(details => details.filter(detail => importEnabled ? detail.importEnabled : detail.exportEnabled)));
|
|
20692
20779
|
}
|
|
20693
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type:
|
|
20694
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type:
|
|
20780
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AccountSetupService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
20781
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AccountSetupService, providedIn: 'root' }); }
|
|
20695
20782
|
}
|
|
20696
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type:
|
|
20697
|
-
type: Injectable
|
|
20698
|
-
}], ctorParameters: () => [{ type: JwtService }, { type: AuthService }, { type: undefined, decorators: [{
|
|
20699
|
-
type: Inject,
|
|
20700
|
-
args: ['environment']
|
|
20701
|
-
}] }] });
|
|
20702
|
-
|
|
20703
|
-
let InterceptorsModule$1 = class InterceptorsModule {
|
|
20704
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: InterceptorsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
20705
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.10", ngImport: i0, type: InterceptorsModule }); }
|
|
20706
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: InterceptorsModule, providers: [
|
|
20707
|
-
{
|
|
20708
|
-
provide: HTTP_INTERCEPTORS,
|
|
20709
|
-
useClass: JwtInterceptor,
|
|
20710
|
-
multi: true
|
|
20711
|
-
}
|
|
20712
|
-
] }); }
|
|
20713
|
-
};
|
|
20714
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: InterceptorsModule$1, decorators: [{
|
|
20715
|
-
type: NgModule,
|
|
20783
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AccountSetupService, decorators: [{
|
|
20784
|
+
type: Injectable,
|
|
20716
20785
|
args: [{
|
|
20717
|
-
|
|
20718
|
-
{
|
|
20719
|
-
provide: HTTP_INTERCEPTORS,
|
|
20720
|
-
useClass: JwtInterceptor,
|
|
20721
|
-
multi: true
|
|
20722
|
-
}
|
|
20723
|
-
]
|
|
20786
|
+
providedIn: 'root'
|
|
20724
20787
|
}]
|
|
20725
20788
|
}] });
|
|
20726
20789
|
|
|
20727
20790
|
/**
|
|
20728
|
-
*
|
|
20791
|
+
* service that checks adblock once we started application and saves this information
|
|
20792
|
+
* to unbound from promise of adblock-checker
|
|
20729
20793
|
*/
|
|
20730
|
-
class
|
|
20731
|
-
|
|
20732
|
-
|
|
20733
|
-
localStorage.setItem('api_uri', environment['api_uri']);
|
|
20734
|
-
return {
|
|
20735
|
-
ngModule: CommonModule,
|
|
20736
|
-
providers: [
|
|
20737
|
-
{
|
|
20738
|
-
provide: 'environment',
|
|
20739
|
-
useValue: environment
|
|
20740
|
-
}
|
|
20741
|
-
]
|
|
20742
|
-
};
|
|
20794
|
+
class AdblockDetectorService {
|
|
20795
|
+
constructor() {
|
|
20796
|
+
checkAdBlock().then((isDetected) => this.isDetected = isDetected);
|
|
20743
20797
|
}
|
|
20744
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type:
|
|
20745
|
-
static { this.ɵ
|
|
20746
|
-
InterceptorsModule$1] }); }
|
|
20747
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: CommonModule, imports: [CommonModule$1,
|
|
20748
|
-
InterceptorsModule$1] }); }
|
|
20798
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AdblockDetectorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
20799
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AdblockDetectorService, providedIn: 'root' }); }
|
|
20749
20800
|
}
|
|
20750
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type:
|
|
20751
|
-
type:
|
|
20801
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AdblockDetectorService, decorators: [{
|
|
20802
|
+
type: Injectable,
|
|
20752
20803
|
args: [{
|
|
20753
|
-
|
|
20754
|
-
imports: [
|
|
20755
|
-
CommonModule$1,
|
|
20756
|
-
InterceptorsModule$1
|
|
20757
|
-
]
|
|
20804
|
+
providedIn: 'root'
|
|
20758
20805
|
}]
|
|
20759
|
-
}] });
|
|
20806
|
+
}], ctorParameters: () => [] });
|
|
20760
20807
|
|
|
20761
20808
|
const KEY = '_switch_user';
|
|
20762
20809
|
/**
|