taxtank-core 2.0.96 → 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.
@@ -1,11 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Inject, Injectable, inject, EventEmitter, NgModule, InjectionToken, Pipe } from '@angular/core';
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, HttpParams, HTTP_INTERCEPTORS } from '@angular/common/http';
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, combineLatest, BehaviorSubject, from, merge as merge$1 } from 'rxjs';
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 CalendarEventCollection(this.items.filter(event => event.inMonth(index)));
2362
+ return new MoneyCalendarEventCollection(this.items.filter(event => event.inMonth(index)));
2363
2363
  }
2364
2364
  }
2365
2365
 
@@ -8653,11 +8653,12 @@ class TransactionReportItem {
8653
8653
  }
8654
8654
 
8655
8655
  class BudgetRuleItem {
8656
- constructor(rule, transactions, isGross = false) {
8656
+ constructor(rule, transactions, dateFrom, dateTo, isGross = false) {
8657
8657
  this.rule = rule;
8658
8658
  this.tankType = TankTypeEnum[rule.chartAccounts.tankType];
8659
8659
  this.category = ChartAccountsCategoryEnum[rule.chartAccounts.category];
8660
8660
  this.frequency = DailyFrequencyEnum[rule.frequency] ?? 'Once';
8661
+ this.isGross = isGross;
8661
8662
  if (rule.business) {
8662
8663
  transactions = transactions.filterBy('business.id', rule.business.id);
8663
8664
  }
@@ -8667,9 +8668,11 @@ class BudgetRuleItem {
8667
8668
  if (rule.property) {
8668
8669
  transactions = transactions.filterBy('property.id', rule.property.id);
8669
8670
  }
8671
+ this.forecast = rule.calendarEvents.filterByDate(dateFrom, dateTo).amount;
8672
+ this.transactions = transactions;
8670
8673
  this.actual = transactions.sumBy(isGross ? 'grossAmount' : 'amount');
8671
- this.variance = this.actual - this.rule.amount;
8672
- this.variancePercent = round(this.actual * 100 / this.rule.amount, 2);
8674
+ this.variance = this.actual - this.forecast;
8675
+ this.variancePercent = round(this.actual * 100 / this.forecast, 2);
8673
8676
  }
8674
8677
  getSource() {
8675
8678
  switch (true) {
@@ -8689,6 +8692,10 @@ class BudgetRuleItem {
8689
8692
  onTrack() {
8690
8693
  return this.variance >= 0;
8691
8694
  }
8695
+ getName() {
8696
+ const source = this.getSource();
8697
+ return this.rule.chartAccounts.name + (source ? ` (${source})` : '');
8698
+ }
8692
8699
  }
8693
8700
 
8694
8701
  /**
@@ -8783,13 +8790,40 @@ class TransactionReportItemCollection extends Collection {
8783
8790
  }
8784
8791
  }
8785
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
+
8786
8819
  class BudgetRuleItemCollection extends Collection {
8787
- static create(rules, transactions, isGross = false) {
8820
+ static create(rules, transactions, dateFrom = new FinancialYear().startDate, dateTo = new FinancialYear().endDate, isGross = false) {
8788
8821
  const collection = new BudgetRuleItemCollection();
8789
8822
  const transactionsByChartAccounts = transactions.groupBy('chartAccounts.id');
8790
8823
  rules.items.forEach(rule => {
8791
- 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));
8792
8825
  });
8826
+ collection.isGross = isGross;
8793
8827
  return collection;
8794
8828
  }
8795
8829
  get incomes() {
@@ -8801,12 +8835,36 @@ class BudgetRuleItemCollection extends Collection {
8801
8835
  isIncome() {
8802
8836
  return this.first.isIncome();
8803
8837
  }
8804
- get variancePercent() {
8805
- return round(this.sumBy('actual') * 100 / this.sumBy('rule.amount'), 2);
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());
8806
8846
  }
8807
8847
  onTrack() {
8808
8848
  return this.sumBy('variance') >= 0;
8809
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
+ }
8810
8868
  }
8811
8869
 
8812
8870
  class SoleBusinessLossCollection extends Collection {
@@ -9434,32 +9492,6 @@ class DocumentFolderCollection extends Collection {
9434
9492
  }
9435
9493
  }
9436
9494
 
9437
- class BudgetCollection extends Collection {
9438
- }
9439
-
9440
- class BudgetRuleCollection extends Collection {
9441
- get expenses() {
9442
- return this.filter(rule => rule.chartAccounts.isExpense());
9443
- }
9444
- get incomes() {
9445
- return this.filter(rule => rule.chartAccounts.isIncome());
9446
- }
9447
- filterByProperties(properties) {
9448
- const propertyIds = properties.map(property => property.id);
9449
- return this.filter(rule => propertyIds.includes(rule.property?.id));
9450
- }
9451
- get calendarEvents() {
9452
- return new MoneyCalendarEventCollection(this.map(rule => rule.calendarEvents.items).flat());
9453
- }
9454
- getByMonth(index) {
9455
- return new BudgetRuleCollection(this.items.filter(rule => rule.inMonth(index)));
9456
- }
9457
- getByChartAccountsName(name) {
9458
- const searchQuery = name.toLowerCase().trim();
9459
- return this.filter(rule => rule.chartAccounts.name.toLowerCase().includes(searchQuery));
9460
- }
9461
- }
9462
-
9463
9495
  class AllocationGroupCollection extends Collection {
9464
9496
  constructor(items) {
9465
9497
  super(items);
@@ -13306,78 +13338,447 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
13306
13338
  }]
13307
13339
  }] });
13308
13340
 
13309
- class BudgetService extends RestService$1 {
13310
- constructor() {
13311
- super(...arguments);
13312
- this.modelClass = Budget;
13313
- this.collectionClass = BudgetCollection;
13314
- this.endpointUri = 'budgets';
13315
- 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;
13316
13347
  }
13317
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: BudgetService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
13318
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: BudgetService, providedIn: 'root' }); }
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' }); }
13319
13387
  }
13320
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: BudgetService, decorators: [{
13388
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: MixpanelService, decorators: [{
13321
13389
  type: Injectable,
13322
13390
  args: [{
13323
13391
  providedIn: 'root'
13324
13392
  }]
13325
- }] });
13393
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
13394
+ type: Inject,
13395
+ args: ['environment']
13396
+ }] }] });
13326
13397
 
13327
- var BudgetMessagesEnum;
13328
- (function (BudgetMessagesEnum) {
13329
- BudgetMessagesEnum["CREATED"] = "Budget created";
13330
- BudgetMessagesEnum["UPDATED"] = "Budget updated";
13331
- BudgetMessagesEnum["DELETED"] = "Budget deleted";
13332
- BudgetMessagesEnum["CONFIRM_DELETE"] = "Are you sure you want to delete budgeting?";
13333
- })(BudgetMessagesEnum || (BudgetMessagesEnum = {}));
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 = {}));
13334
13416
 
13335
- class BudgetRuleService extends RestService$1 {
13417
+ const NAME_TOKEN = 'token';
13418
+ const NAME_REFRESH_TOKEN = 'refreshToken';
13419
+ class JwtService extends JwtHelperService {
13336
13420
  constructor() {
13337
13421
  super(...arguments);
13338
- this.modelClass = BudgetRule;
13339
- this.collectionClass = BudgetRuleCollection;
13340
- this.endpointUri = 'budget-rules';
13341
- this.disabledMethods = ['postBatch', 'putBatch', 'deleteBatch'];
13422
+ this.mpService = inject(MixpanelService);
13423
+ this.isLoggedInSubject = new BehaviorSubject(!this.isTokenExpired());
13342
13424
  }
13343
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: BudgetRuleService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
13344
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: BudgetRuleService, providedIn: 'root' }); }
13425
+ getToken() {
13426
+ return localStorage[NAME_TOKEN];
13427
+ }
13428
+ getRefreshToken() {
13429
+ return localStorage[NAME_REFRESH_TOKEN];
13430
+ }
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);
13436
+ }
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);
13445
+ }
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' }); }
13345
13457
  }
13346
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: BudgetRuleService, decorators: [{
13458
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: JwtService, decorators: [{
13347
13459
  type: Injectable,
13348
13460
  args: [{
13349
13461
  providedIn: 'root'
13350
13462
  }]
13351
13463
  }] });
13352
13464
 
13353
- class FinancialGoalService extends RestService$1 {
13354
- constructor() {
13355
- super(...arguments);
13356
- this.modelClass = FinancialGoal;
13357
- this.collectionClass = FinancialGoalCollection;
13358
- this.endpointUri = 'financial-goals';
13359
- this.disabledMethods = ['postBatch', 'putBatch', 'deleteBatch'];
13360
- this.useBackendError = true;
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;
13361
13471
  }
13362
- pause(goal) {
13363
- return this.put(Object.assign({}, goal, { status: FinancialGoalStatusEnum.PAUSE }));
13472
+ setAuth(response) {
13473
+ this.jwtService.saveTokens(response);
13364
13474
  }
13365
- resume(goal) {
13366
- return this.put(Object.assign({}, goal, { status: FinancialGoalStatusEnum.ACTIVE }));
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
+ }));
13367
13482
  }
13368
- complete(goal) {
13369
- return this.put(Object.assign({}, goal, { status: FinancialGoalStatusEnum.COMPLETE, finalValue: goal.bankAccount.currentBalance }));
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
+ }));
13370
13488
  }
13371
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: FinancialGoalService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
13372
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: FinancialGoalService, providedIn: 'root' }); }
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' }); }
13373
13501
  }
13374
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: FinancialGoalService, decorators: [{
13502
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AuthService, decorators: [{
13375
13503
  type: Injectable,
13376
13504
  args: [{
13377
13505
  providedIn: 'root'
13378
13506
  }]
13379
- }] });
13380
-
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
+
13381
13782
  var FinancialGoalMessagesEnum;
13382
13783
  (function (FinancialGoalMessagesEnum) {
13383
13784
  FinancialGoalMessagesEnum["CREATED"] = "Goal created!";
@@ -20304,471 +20705,105 @@ class AccountSetupService {
20304
20705
  */
20305
20706
  setItemStatus(item, request) {
20306
20707
  return request.pipe(map((result) => {
20307
- const isSkipped = !!this.user.blacklistSetupItems.find((skippedItem) => skippedItem.id === item.id);
20308
- item.status = isSkipped ? AccountSetupItemStatusEnum.SKIPPED : result.length ? AccountSetupItemStatusEnum.ACHIEVED : AccountSetupItemStatusEnum.PENDING;
20309
- return item;
20310
- }));
20311
- }
20312
- getAllocations(bankAccountId) {
20313
- return combineLatest([this.bankTransactionService.get(), this.transactionAllocationService.get()]).pipe(map(([bankTransactions, allocations]) => {
20314
- const bankTransactionsIds = bankTransactions.filterBy('bankAccount.id', bankAccountId).getIds();
20315
- return new TransactionAllocationCollection(allocations).getByBankTransactionsIds(bankTransactionsIds).toArray();
20316
- }));
20317
- }
20318
- getTransactions(propertyId) {
20319
- return this.transactionService.getByPropertyId(propertyId);
20320
- }
20321
- getCoOwners(propertyId) {
20322
- return this.propertyShareService.getArrayBy('property.id', propertyId).pipe(map(shares => shares.slice(1)));
20323
- }
20324
- /**
20325
- * AccountSetupItemsEnum.FIRM_CLIENTS completed when client invites sent or accepted
20326
- */
20327
- getClients() {
20328
- return combineLatest([this.clientMovementService.getActive(), this.clientInviteService.get()]).pipe(map(([movements, invites]) => [...movements, ...invites]));
20329
- }
20330
- /**
20331
- * AccountSetupItemsEnum.FIRM_EMPLOYEES completed when employee invites sent or accepted
20332
- */
20333
- getEmployees() {
20334
- return combineLatest([this.employeeService.getArray(), this.employeeInviteService.getArray()]).pipe(map(([employees, invites]) => [...employees.slice(1), ...invites]));
20335
- }
20336
- /**
20337
- * AccountSetupItemsEnum.FIRM_DETAILS when firm data filled
20338
- */
20339
- getFirms() {
20340
- return this.firmService.get().pipe(map((firm) => [firm].filter(firm => firm.address || firm.phone || firm.file || firm.shortName)));
20341
- }
20342
- /**
20343
- * @TODO Alex: work with collection when services refactored
20344
- * @TODO Vik: waiting for income sources refactoring
20345
- */
20346
- getIncomeSources(isSalary) {
20347
- return this.incomeSourceService.get().pipe(map((incomeSources) => {
20348
- const collection = new IncomeSourceCollection(incomeSources);
20349
- if (isSalary) {
20350
- return collection.getSalary();
20351
- }
20352
- return collection.items.filter((incomeSource) => incomeSource.isOtherIncome());
20353
- }));
20354
- }
20355
- getVehicleClaims(businessId) {
20356
- return this.vehicleClaimService.getArray().pipe(map(claims => claims.filter(claim => claim.business?.id === businessId)));
20357
- }
20358
- getHomeOfficeClaims(businessId) {
20359
- return this.homeOfficeClaimService.getArray().pipe(map(claims => claims.filter(claim => claim.business?.id === businessId)));
20360
- }
20361
- getBankAccounts(tankType) {
20362
- return this.bankAccountsService.get().pipe(map((bankAccounts => bankAccounts.getByTankType(tankType).toArray())));
20363
- }
20364
- getDepreciations(tankType, id) {
20365
- return this.depreciationService.get().pipe(map(depreciations => {
20366
- depreciations = depreciations.getByTankType(tankType);
20367
- if (tankType === TankTypeEnum.PROPERTY && id) {
20368
- depreciations.filterBy('property.id', id);
20369
- }
20370
- if (tankType === TankTypeEnum.SOLE && id) {
20371
- depreciations.filterBy('business.id', id);
20372
- }
20373
- return depreciations.toArray();
20374
- }));
20375
- }
20376
- getSharesightDetails(importEnabled) {
20377
- return this.sharesightDetailsService.getArray().pipe(map(details => details.filter(detail => importEnabled ? detail.importEnabled : detail.exportEnabled)));
20378
- }
20379
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AccountSetupService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
20380
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AccountSetupService, providedIn: 'root' }); }
20381
- }
20382
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AccountSetupService, decorators: [{
20383
- type: Injectable,
20384
- args: [{
20385
- providedIn: 'root'
20386
- }]
20387
- }] });
20388
-
20389
- /**
20390
- * service that checks adblock once we started application and saves this information
20391
- * to unbound from promise of adblock-checker
20392
- */
20393
- class AdblockDetectorService {
20394
- constructor() {
20395
- checkAdBlock().then((isDetected) => this.isDetected = isDetected);
20396
- }
20397
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AdblockDetectorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
20398
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AdblockDetectorService, providedIn: 'root' }); }
20399
- }
20400
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AdblockDetectorService, decorators: [{
20401
- type: Injectable,
20402
- args: [{
20403
- providedIn: 'root'
20404
- }]
20405
- }], ctorParameters: () => [] });
20406
-
20407
- /**
20408
- * Service to work with mixpanel https://docs.mixpanel.com/docs/tracking/reference/javascript
20409
- */
20410
- class MixpanelService {
20411
- constructor(environment) {
20412
- this.environment = environment;
20413
- }
20414
- init() {
20415
- if (!this.environment.enableMixpanel) {
20416
- return;
20417
- }
20418
- mixpanel.init(this.environment.mixpanelToken);
20419
- }
20420
- identify(id) {
20421
- if (!this.environment.enableMixpanel) {
20422
- return;
20423
- }
20424
- mixpanel.identify(id);
20425
- mixpanel.people.set({ 'last seen': new Date(Date.now()).toLocaleString() });
20426
- }
20427
- reset() {
20428
- if (!this.environment.enableMixpanel) {
20429
- return;
20430
- }
20431
- mixpanel.reset();
20432
- }
20433
- track(event, properties = {}) {
20434
- if (!this.environment.enableMixpanel) {
20435
- return;
20436
- }
20437
- mixpanel.track(event, properties);
20438
- }
20439
- trackLink(id, event, properties = {}) {
20440
- if (!this.environment.enableMixpanel) {
20441
- return;
20442
- }
20443
- mixpanel.track_links(`#${id}`, event, properties);
20444
- }
20445
- trackPageView() {
20446
- if (!this.environment.enableMixpanel) {
20447
- return;
20448
- }
20449
- mixpanel['track_pageview']();
20450
- }
20451
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: MixpanelService, deps: [{ token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable }); }
20452
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: MixpanelService, providedIn: 'root' }); }
20453
- }
20454
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: MixpanelService, decorators: [{
20455
- type: Injectable,
20456
- args: [{
20457
- providedIn: 'root'
20458
- }]
20459
- }], ctorParameters: () => [{ type: undefined, decorators: [{
20460
- type: Inject,
20461
- args: ['environment']
20462
- }] }] });
20463
-
20464
- var UserRolesEnum;
20465
- (function (UserRolesEnum) {
20466
- UserRolesEnum["FIRM_OWNER"] = "ROLE_FIRM_OWNER";
20467
- UserRolesEnum["FIRM_MANAGER"] = "ROLE_FIRM_MANAGER";
20468
- UserRolesEnum["FIRM_TOP_MANAGER"] = "ROLE_FIRM_TOP_MANAGER";
20469
- UserRolesEnum["CLIENT"] = "ROLE_CLIENT";
20470
- UserRolesEnum["EMPLOYEE"] = "ROLE_EMPLOYEE";
20471
- UserRolesEnum["ACCOUNTANT"] = "ROLE_ACCOUNTANT";
20472
- UserRolesEnum["ADVISOR"] = "ROLE_ADVISOR";
20473
- UserRolesEnum["USER"] = "ROLE_USER";
20474
- UserRolesEnum["SUBSCRIPTION"] = "ROLE_USER_SUBSCRIPTION";
20475
- UserRolesEnum["WORK_TANK"] = "ROLE_USER_WORK";
20476
- UserRolesEnum["PROPERTY_TANK"] = "ROLE_USER_PROPERTY";
20477
- UserRolesEnum["SOLE_TANK"] = "ROLE_USER_SOLE";
20478
- UserRolesEnum["HOLDING_TANK"] = "ROLE_USER_HOLDING";
20479
- UserRolesEnum["MONEY_TANK"] = "ROLE_USER_MONEY";
20480
- UserRolesEnum["SWITCH_USER"] = "IS_IMPERSONATOR";
20481
- })(UserRolesEnum || (UserRolesEnum = {}));
20482
-
20483
- const NAME_TOKEN = 'token';
20484
- const NAME_REFRESH_TOKEN = 'refreshToken';
20485
- class JwtService extends JwtHelperService {
20486
- constructor() {
20487
- super(...arguments);
20488
- this.mpService = inject(MixpanelService);
20489
- this.isLoggedInSubject = new BehaviorSubject(!this.isTokenExpired());
20490
- }
20491
- getToken() {
20492
- return localStorage[NAME_TOKEN];
20493
- }
20494
- getRefreshToken() {
20495
- return localStorage[NAME_REFRESH_TOKEN];
20496
- }
20497
- saveTokens(tokens) {
20498
- localStorage[NAME_TOKEN] = tokens.token;
20499
- localStorage[NAME_REFRESH_TOKEN] = tokens.refreshToken;
20500
- this.mpService.identify(this.decode(tokens.token).id.toString());
20501
- this.isLoggedInSubject.next(true);
20502
- }
20503
- destroyTokens() {
20504
- localStorage.removeItem(NAME_TOKEN);
20505
- localStorage.removeItem(NAME_REFRESH_TOKEN);
20506
- localStorage.removeItem('userId');
20507
- localStorage.removeItem('_switch_user');
20508
- this.mpService.track('logout');
20509
- this.mpService.reset();
20510
- this.isLoggedInSubject.next(false);
20511
- }
20512
- decode(token) {
20513
- return super.decodeToken(token);
20514
- }
20515
- isClient() {
20516
- return this.decode().roles.includes(UserRolesEnum.CLIENT);
20517
- }
20518
- isMe(userId) {
20519
- return this.decode().id === userId;
20520
- }
20521
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: JwtService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
20522
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: JwtService, providedIn: 'root' }); }
20523
- }
20524
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: JwtService, decorators: [{
20525
- type: Injectable,
20526
- args: [{
20527
- providedIn: 'root'
20528
- }]
20529
- }] });
20530
-
20531
- class AuthService {
20532
- constructor(http, jwtService, mpService, environment) {
20533
- this.http = http;
20534
- this.jwtService = jwtService;
20535
- this.mpService = mpService;
20536
- this.environment = environment;
20537
- }
20538
- setAuth(response) {
20539
- this.jwtService.saveTokens(response);
20540
- }
20541
- login(username, password) {
20542
- return this.http.post(`${this.environment.apiV2}/login`, { username, password }).pipe(map((response) => {
20543
- if (response.token) {
20544
- this.setAuth(response);
20545
- }
20546
- return response;
20547
- }));
20548
- }
20549
- mfaLogin(otp) {
20550
- return this.http.post(`${this.environment.apiV2}/2fa_check`, { otp }).pipe(map((response) => {
20551
- this.setAuth(response);
20552
- return response;
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;
20553
20711
  }));
20554
20712
  }
20555
- refresh(refreshToken) {
20556
- return this.http.post(`${this.environment.apiV2}/token/refresh`, { refreshToken }).pipe(map((response) => {
20557
- this.setAuth(response);
20558
- return response;
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();
20559
20717
  }));
20560
20718
  }
20561
- logoutFront(url = '/login') {
20562
- this.jwtService.destroyTokens();
20563
- location.replace(url);
20564
- }
20565
- 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 }); }
20566
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AuthService, providedIn: 'root' }); }
20567
- }
20568
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AuthService, decorators: [{
20569
- type: Injectable,
20570
- args: [{
20571
- providedIn: 'root'
20572
- }]
20573
- }], ctorParameters: () => [{ type: i1.HttpClient }, { type: JwtService }, { type: MixpanelService }, { type: undefined, decorators: [{
20574
- type: Inject,
20575
- args: ['environment']
20576
- }] }] });
20577
-
20578
- var AuthMessagesEnum;
20579
- (function (AuthMessagesEnum) {
20580
- AuthMessagesEnum["ERROR_401"] = "Email or password is incorrect";
20581
- })(AuthMessagesEnum || (AuthMessagesEnum = {}));
20582
-
20583
- const MESSAGE_DEFAULT_500_ERROR = 'Unexpected error! Please try again later. You can send us via chat your questions.';
20584
- /**
20585
- * JWT Interceptor add jwt token to each request related with TaxTank API
20586
- */
20587
- class JwtInterceptor {
20588
- constructor(jwtService, authService, environment) {
20589
- this.jwtService = jwtService;
20590
- this.authService = authService;
20591
- this.environment = environment;
20592
- this.isRefreshingToken = false;
20593
- this.tokenSubject = new BehaviorSubject(null);
20719
+ getTransactions(propertyId) {
20720
+ return this.transactionService.getByPropertyId(propertyId);
20594
20721
  }
20595
- addToken(req) {
20596
- return req.clone({
20597
- setHeaders: { Authorization: 'Bearer ' + this.jwtService.getToken() },
20598
- withCredentials: true
20599
- });
20722
+ getCoOwners(propertyId) {
20723
+ return this.propertyShareService.getArrayBy('property.id', propertyId).pipe(map(shares => shares.slice(1)));
20600
20724
  }
20601
- intercept(request, next) {
20602
- // skip third party requests
20603
- if (!request.url.includes(this.environment.apiV2)) {
20604
- return next.handle(request);
20605
- }
20606
- // add token to every api request
20607
- return next.handle(this.addToken(request)).pipe(
20608
- // handle errors
20609
- catchError((err) => {
20610
- if (err instanceof HttpErrorResponse) {
20611
- switch (err.status) {
20612
- // unexpected errors
20613
- case 405:
20614
- case 500:
20615
- this.handle500Error();
20616
- break;
20617
- // expected errors
20618
- case 401:
20619
- return this.handle401Error(request, next, err);
20620
- case 400:
20621
- case 403:
20622
- // @TODO in most cases 404 is not an error, handle in components
20623
- // case 404:
20624
- this.showErrorMessages(err);
20625
- break;
20626
- }
20627
- }
20628
- return throwError(err);
20629
- }));
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]));
20630
20730
  }
20631
20731
  /**
20632
- * @TODO log
20633
- * @TODO waiting for backend to handle errors in a better way
20732
+ * AccountSetupItemsEnum.FIRM_EMPLOYEES completed when employee invites sent or accepted
20634
20733
  */
20635
- handle400Error(err) {
20636
- // this.snackBar.open(err.error['hydra:description'], '', {
20637
- // panelClass: 'error'
20638
- // });
20734
+ getEmployees() {
20735
+ return combineLatest([this.employeeService.getArray(), this.employeeInviteService.getArray()]).pipe(map(([employees, invites]) => [...employees.slice(1), ...invites]));
20639
20736
  }
20640
20737
  /**
20641
- * @TODO log
20642
- * @TODO waiting for backend to handle errors in a better way
20738
+ * AccountSetupItemsEnum.FIRM_DETAILS when firm data filled
20643
20739
  */
20644
- handle403Error(err) {
20645
- // this.snackBar.open(err.error['hydra:description'], '', {
20646
- // panelClass: 'error'
20647
- // });
20740
+ getFirms() {
20741
+ return this.firmService.get().pipe(map((firm) => [firm].filter(firm => firm.address || firm.phone || firm.file || firm.shortName)));
20648
20742
  }
20649
20743
  /**
20650
- * @TODO log
20744
+ * @TODO Alex: work with collection when services refactored
20745
+ * @TODO Vik: waiting for income sources refactoring
20651
20746
  */
20652
- handle500Error() {
20653
- // this.snackBar.open(MESSAGE_DEFAULT_500_ERROR, '', {
20654
- // panelClass: 'error'
20655
- // });
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
+ }));
20656
20755
  }
20657
- handle401Error(req, next, err) {
20658
- // skip 401 errors not from JWT (basiq login case or other)
20659
- if (!err.error.message?.includes('JWT Token')) {
20660
- return throwError(err);
20661
- }
20662
- if (req.url.includes('token/refresh') || req.url.includes('login')) {
20663
- if (req.url.includes('token/refresh')) {
20664
- this.authService.logoutFront();
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);
20665
20770
  }
20666
- return throwError(err);
20667
- }
20668
- // refreshing token, wait until it's done and retry the request
20669
- if (this.isRefreshingToken) {
20670
- return this.tokenSubject.pipe(filter(token => token != null), take(1), switchMap(token => next.handle(this.addToken(req))));
20671
- // refresh token
20672
- }
20673
- // subsequent requests should wait until refresh token is ready
20674
- this.isRefreshingToken = true;
20675
- this.tokenSubject.next(null);
20676
- return this.authService.refresh(this.jwtService.getRefreshToken()).pipe(switchMap((tokens) => {
20677
- this.tokenSubject.next(tokens.token);
20678
- return next.handle(this.addToken(req));
20679
- }), catchError(() => {
20680
- this.authService.logoutFront();
20681
- return throwError(err);
20682
- }), finalize(() => {
20683
- this.isRefreshingToken = false;
20771
+ if (tankType === TankTypeEnum.SOLE && id) {
20772
+ depreciations.filterBy('business.id', id);
20773
+ }
20774
+ return depreciations.toArray();
20684
20775
  }));
20685
20776
  }
20686
- /**
20687
- * Handle error messages
20688
- * @param errorResponse from which messages should be taken
20689
- *
20690
- * @TODO move to separated interceptor
20691
- */
20692
- showErrorMessages(errorResponse) {
20693
- if (!errorResponse.error.violations) {
20694
- // this.snackBar.open('Something went wrong', '', {
20695
- // panelClass: 'error'
20696
- // });
20697
- return;
20698
- }
20699
- errorResponse.error.violations.forEach((violation) => {
20700
- // this.snackBar.open(violation['message'], '', {
20701
- // panelClass: 'error'
20702
- // });
20703
- });
20777
+ getSharesightDetails(importEnabled) {
20778
+ return this.sharesightDetailsService.getArray().pipe(map(details => details.filter(detail => importEnabled ? detail.importEnabled : detail.exportEnabled)));
20704
20779
  }
20705
- 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 }); }
20706
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: JwtInterceptor }); }
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' }); }
20707
20782
  }
20708
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: JwtInterceptor, decorators: [{
20709
- type: Injectable
20710
- }], ctorParameters: () => [{ type: JwtService }, { type: AuthService }, { type: undefined, decorators: [{
20711
- type: Inject,
20712
- args: ['environment']
20713
- }] }] });
20714
-
20715
- let InterceptorsModule$1 = class InterceptorsModule {
20716
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: InterceptorsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
20717
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.10", ngImport: i0, type: InterceptorsModule }); }
20718
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: InterceptorsModule, providers: [
20719
- {
20720
- provide: HTTP_INTERCEPTORS,
20721
- useClass: JwtInterceptor,
20722
- multi: true
20723
- }
20724
- ] }); }
20725
- };
20726
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: InterceptorsModule$1, decorators: [{
20727
- type: NgModule,
20783
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AccountSetupService, decorators: [{
20784
+ type: Injectable,
20728
20785
  args: [{
20729
- providers: [
20730
- {
20731
- provide: HTTP_INTERCEPTORS,
20732
- useClass: JwtInterceptor,
20733
- multi: true
20734
- }
20735
- ]
20786
+ providedIn: 'root'
20736
20787
  }]
20737
20788
  }] });
20738
20789
 
20739
20790
  /**
20740
- * https://angular.io/guide/creating-libraries
20791
+ * service that checks adblock once we started application and saves this information
20792
+ * to unbound from promise of adblock-checker
20741
20793
  */
20742
- class CommonModule {
20743
- static forRoot(environment) {
20744
- // @TODO remove when bank model refactored (the only use case)
20745
- localStorage.setItem('api_uri', environment['api_uri']);
20746
- return {
20747
- ngModule: CommonModule,
20748
- providers: [
20749
- {
20750
- provide: 'environment',
20751
- useValue: environment
20752
- }
20753
- ]
20754
- };
20794
+ class AdblockDetectorService {
20795
+ constructor() {
20796
+ checkAdBlock().then((isDetected) => this.isDetected = isDetected);
20755
20797
  }
20756
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: CommonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
20757
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.10", ngImport: i0, type: CommonModule, imports: [CommonModule$1,
20758
- InterceptorsModule$1] }); }
20759
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: CommonModule, imports: [CommonModule$1,
20760
- 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' }); }
20761
20800
  }
20762
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: CommonModule, decorators: [{
20763
- type: NgModule,
20801
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AdblockDetectorService, decorators: [{
20802
+ type: Injectable,
20764
20803
  args: [{
20765
- declarations: [],
20766
- imports: [
20767
- CommonModule$1,
20768
- InterceptorsModule$1
20769
- ]
20804
+ providedIn: 'root'
20770
20805
  }]
20771
- }] });
20806
+ }], ctorParameters: () => [] });
20772
20807
 
20773
20808
  const KEY = '_switch_user';
20774
20809
  /**
@@ -22361,13 +22396,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
22361
22396
  }] }] });
22362
22397
 
22363
22398
  const ADBLOCK_ERROR_HTML = new InjectionToken('ADBLOCK_ERROR_HTML');
22364
- const ADBLOCK_ERROR_HTML_VALUE = `
22365
- <div class="text-center">
22366
- <strong>Action needed - Your adblocker is blocking CoreLogic</strong>
22367
- To add a property in TaxTank we need to fetch data from CoreLogic — but your ad blocker is getting in the way.
22368
- Please disable your adblocker or whitelist TaxTank to continue.
22369
- <a class="btn" target="_blank" href="https://support.taxtank.com.au/en/articles/10505609-how-to-ensure-seamless-functionality-while-using-ad-blockers-with-taxtank">Learn more</a>
22370
- </div>
22399
+ const ADBLOCK_ERROR_HTML_VALUE = `
22400
+ <div class="text-center">
22401
+ <strong>Action needed - Your adblocker is blocking CoreLogic</strong>
22402
+ To add a property in TaxTank we need to fetch data from CoreLogic — but your ad blocker is getting in the way.
22403
+ Please disable your adblocker or whitelist TaxTank to continue.
22404
+ <a class="btn" target="_blank" href="https://support.taxtank.com.au/en/articles/10505609-how-to-ensure-seamless-functionality-while-using-ad-blockers-with-taxtank">Learn more</a>
22405
+ </div>
22371
22406
  `;
22372
22407
 
22373
22408
  /**