taxtank-core 0.28.1 → 0.28.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/bundles/taxtank-core.umd.js +343 -245
  2. package/bundles/taxtank-core.umd.js.map +1 -1
  3. package/esm2015/lib/collections/vehicle/vehicle-logbook.collection.js +2 -2
  4. package/esm2015/lib/db/Models/sole/sole-business-loss.js +1 -1
  5. package/esm2015/lib/forms/sole/sole-business.form.js +11 -2
  6. package/esm2015/lib/forms/sole/sole-details.form.js +3 -2
  7. package/esm2015/lib/interceptors/basiq-client-id.interceptor.js +31 -0
  8. package/esm2015/lib/interceptors/basiq-token.interceptor.js +35 -0
  9. package/esm2015/lib/interceptors/interceptors.module.js +15 -4
  10. package/esm2015/lib/models/endpoint/endpoints.const.js +3 -1
  11. package/esm2015/lib/models/event/app-event-type.enum.js +21 -19
  12. package/esm2015/lib/models/vehicle/vehicle-logbook.js +4 -4
  13. package/esm2015/lib/services/http/sole/sole-depreciation-method/sole-depreciation-method.service.js +12 -1
  14. package/esm2015/lib/services/http/sole/sole-details/sole-details.service.js +10 -4
  15. package/esm2015/lib/services/http/user/user.service.js +12 -1
  16. package/esm2015/lib/validators/min-date/min-date.validator.js +6 -2
  17. package/esm2015/lib/validators/required-length.validator.js +12 -0
  18. package/fesm2015/taxtank-core.js +316 -226
  19. package/fesm2015/taxtank-core.js.map +1 -1
  20. package/lib/db/Models/sole/sole-business-loss.d.ts +2 -3
  21. package/lib/forms/sole/sole-business.form.d.ts +1 -0
  22. package/lib/interceptors/basiq-client-id.interceptor.d.ts +15 -0
  23. package/lib/interceptors/{basiq.interceptor.d.ts → basiq-token.interceptor.d.ts} +3 -3
  24. package/lib/models/event/app-event-type.enum.d.ts +20 -18
  25. package/lib/models/vehicle/vehicle-logbook.d.ts +2 -2
  26. package/lib/services/http/sole/sole-depreciation-method/sole-depreciation-method.service.d.ts +4 -1
  27. package/lib/services/http/sole/sole-details/sole-details.service.d.ts +3 -1
  28. package/lib/services/http/user/user.service.d.ts +4 -0
  29. package/lib/validators/required-length.validator.d.ts +5 -0
  30. package/package.json +1 -1
  31. package/esm2015/lib/interceptors/basiq.interceptor.js +0 -35
@@ -4,7 +4,7 @@ import * as i1$1 from '@angular/common';
4
4
  import { CommonModule, DatePipe } from '@angular/common';
5
5
  import * as i1 from '@angular/common/http';
6
6
  import { HttpParams, HttpErrorResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
7
- import { ReplaySubject, Subject, BehaviorSubject, throwError, combineLatest, forkJoin, Observable, of, from } from 'rxjs';
7
+ import { ReplaySubject, Subject, BehaviorSubject, throwError, Observable, combineLatest, forkJoin, of, from } from 'rxjs';
8
8
  import { map, filter, catchError, take, switchMap, finalize, mergeMap, skip, distinctUntilChanged } from 'rxjs/operators';
9
9
  import { plainToClass, classToPlain, Type, Exclude, Transform, Expose } from 'class-transformer';
10
10
  import { JwtHelperService } from '@auth0/angular-jwt';
@@ -20,12 +20,12 @@ import uniqBy from 'lodash/uniqBy';
20
20
  import concat from 'lodash/concat';
21
21
  import { throwError as throwError$1 } from 'rxjs/internal/observable/throwError';
22
22
  import cloneDeep$1 from 'lodash/cloneDeep';
23
+ import { EventSourcePolyfill } from 'event-source-polyfill/src/eventsource.min.js';
23
24
  import compact from 'lodash/compact';
24
25
  import { Validators, FormGroup, FormControl, FormArray } from '@angular/forms';
25
26
  import isEqual from 'lodash/isEqual';
26
27
  import fromPairs from 'lodash/fromPairs';
27
28
  import _ from 'lodash';
28
- import { EventSourcePolyfill } from 'event-source-polyfill/src/eventsource.min.js';
29
29
  import * as i1$2 from '@angular/router';
30
30
  import { NavigationEnd } from '@angular/router';
31
31
  import clone from 'lodash/clone';
@@ -240,24 +240,26 @@ var AppEventTypeEnum;
240
240
  AppEventTypeEnum[AppEventTypeEnum["SERVICE_SUBSCRIPTION_UPDATED"] = 40] = "SERVICE_SUBSCRIPTION_UPDATED";
241
241
  AppEventTypeEnum[AppEventTypeEnum["SOLE_BUSINESS_CREATED"] = 41] = "SOLE_BUSINESS_CREATED";
242
242
  AppEventTypeEnum[AppEventTypeEnum["SOLE_DEPRECIATION_METHOD_UPDATED"] = 42] = "SOLE_DEPRECIATION_METHOD_UPDATED";
243
- AppEventTypeEnum[AppEventTypeEnum["TAX_REVIEW_UPDATED"] = 43] = "TAX_REVIEW_UPDATED";
244
- AppEventTypeEnum[AppEventTypeEnum["TRANSACTION_CREATED"] = 44] = "TRANSACTION_CREATED";
245
- AppEventTypeEnum[AppEventTypeEnum["TRANSACTION_DELETED"] = 45] = "TRANSACTION_DELETED";
246
- AppEventTypeEnum[AppEventTypeEnum["TRANSACTION_UPDATED"] = 46] = "TRANSACTION_UPDATED";
247
- AppEventTypeEnum[AppEventTypeEnum["TRANSACTION_UPDATED_WITH_RECEIPT"] = 47] = "TRANSACTION_UPDATED_WITH_RECEIPT";
248
- AppEventTypeEnum[AppEventTypeEnum["TRANSACTION_UPDATED_WITH_DELETED_RECEIPT"] = 48] = "TRANSACTION_UPDATED_WITH_DELETED_RECEIPT";
249
- AppEventTypeEnum[AppEventTypeEnum["TRANSACTION_RECEIPT_CREATED"] = 49] = "TRANSACTION_RECEIPT_CREATED";
250
- AppEventTypeEnum[AppEventTypeEnum["TRANSACTION_RECEIPT_DELETED"] = 50] = "TRANSACTION_RECEIPT_DELETED";
251
- AppEventTypeEnum[AppEventTypeEnum["TRANSACTIONS_CREATED"] = 51] = "TRANSACTIONS_CREATED";
252
- AppEventTypeEnum[AppEventTypeEnum["USER_UPDATED"] = 52] = "USER_UPDATED";
253
- AppEventTypeEnum[AppEventTypeEnum["VEHICLE_CLAIM_UPDATED"] = 53] = "VEHICLE_CLAIM_UPDATED";
254
- AppEventTypeEnum[AppEventTypeEnum["VEHICLE_CLAIM_CREATED"] = 54] = "VEHICLE_CLAIM_CREATED";
255
- AppEventTypeEnum[AppEventTypeEnum["VEHICLE_CLAIM_DETAILS_UPDATED"] = 55] = "VEHICLE_CLAIM_DETAILS_UPDATED";
256
- AppEventTypeEnum[AppEventTypeEnum["VEHICLE_CLAIM_DETAILS_CREATED"] = 56] = "VEHICLE_CLAIM_DETAILS_CREATED";
257
- AppEventTypeEnum[AppEventTypeEnum["VEHICLE_LOGBOOK_CREATED"] = 57] = "VEHICLE_LOGBOOK_CREATED";
258
- AppEventTypeEnum[AppEventTypeEnum["VEHICLE_LOGBOOK_UPDATED"] = 58] = "VEHICLE_LOGBOOK_UPDATED";
259
- AppEventTypeEnum[AppEventTypeEnum["VEHICLE_LOGBOOK_DELETED"] = 59] = "VEHICLE_LOGBOOK_DELETED";
260
- AppEventTypeEnum[AppEventTypeEnum["VEHICLE_LOGBOOK_BEST_PERIOD_UPDATED"] = 60] = "VEHICLE_LOGBOOK_BEST_PERIOD_UPDATED";
243
+ AppEventTypeEnum[AppEventTypeEnum["SOLE_DETAILS_CREATED"] = 43] = "SOLE_DETAILS_CREATED";
244
+ AppEventTypeEnum[AppEventTypeEnum["SOLE_DETAILS_UPDATED"] = 44] = "SOLE_DETAILS_UPDATED";
245
+ AppEventTypeEnum[AppEventTypeEnum["TAX_REVIEW_UPDATED"] = 45] = "TAX_REVIEW_UPDATED";
246
+ AppEventTypeEnum[AppEventTypeEnum["TRANSACTION_CREATED"] = 46] = "TRANSACTION_CREATED";
247
+ AppEventTypeEnum[AppEventTypeEnum["TRANSACTION_DELETED"] = 47] = "TRANSACTION_DELETED";
248
+ AppEventTypeEnum[AppEventTypeEnum["TRANSACTION_UPDATED"] = 48] = "TRANSACTION_UPDATED";
249
+ AppEventTypeEnum[AppEventTypeEnum["TRANSACTION_UPDATED_WITH_RECEIPT"] = 49] = "TRANSACTION_UPDATED_WITH_RECEIPT";
250
+ AppEventTypeEnum[AppEventTypeEnum["TRANSACTION_UPDATED_WITH_DELETED_RECEIPT"] = 50] = "TRANSACTION_UPDATED_WITH_DELETED_RECEIPT";
251
+ AppEventTypeEnum[AppEventTypeEnum["TRANSACTION_RECEIPT_CREATED"] = 51] = "TRANSACTION_RECEIPT_CREATED";
252
+ AppEventTypeEnum[AppEventTypeEnum["TRANSACTION_RECEIPT_DELETED"] = 52] = "TRANSACTION_RECEIPT_DELETED";
253
+ AppEventTypeEnum[AppEventTypeEnum["TRANSACTIONS_CREATED"] = 53] = "TRANSACTIONS_CREATED";
254
+ AppEventTypeEnum[AppEventTypeEnum["USER_UPDATED"] = 54] = "USER_UPDATED";
255
+ AppEventTypeEnum[AppEventTypeEnum["VEHICLE_CLAIM_UPDATED"] = 55] = "VEHICLE_CLAIM_UPDATED";
256
+ AppEventTypeEnum[AppEventTypeEnum["VEHICLE_CLAIM_CREATED"] = 56] = "VEHICLE_CLAIM_CREATED";
257
+ AppEventTypeEnum[AppEventTypeEnum["VEHICLE_CLAIM_DETAILS_UPDATED"] = 57] = "VEHICLE_CLAIM_DETAILS_UPDATED";
258
+ AppEventTypeEnum[AppEventTypeEnum["VEHICLE_CLAIM_DETAILS_CREATED"] = 58] = "VEHICLE_CLAIM_DETAILS_CREATED";
259
+ AppEventTypeEnum[AppEventTypeEnum["VEHICLE_LOGBOOK_CREATED"] = 59] = "VEHICLE_LOGBOOK_CREATED";
260
+ AppEventTypeEnum[AppEventTypeEnum["VEHICLE_LOGBOOK_UPDATED"] = 60] = "VEHICLE_LOGBOOK_UPDATED";
261
+ AppEventTypeEnum[AppEventTypeEnum["VEHICLE_LOGBOOK_DELETED"] = 61] = "VEHICLE_LOGBOOK_DELETED";
262
+ AppEventTypeEnum[AppEventTypeEnum["VEHICLE_LOGBOOK_BEST_PERIOD_UPDATED"] = 62] = "VEHICLE_LOGBOOK_BEST_PERIOD_UPDATED";
261
263
  })(AppEventTypeEnum || (AppEventTypeEnum = {}));
262
264
 
263
265
  class EventDispatcherService {
@@ -587,6 +589,7 @@ const ENDPOINTS = {
587
589
  BANK_TRANSACTIONS_IMPORT_POST: new Endpoint('POST', '\\/bank-transactions\\/\\d+\\/import'),
588
590
  BASIQ_ACCOUNTS_GET: new Endpoint('GET', '\\/basiq\\/accounts'),
589
591
  BASIQ_TOKEN_GET: new Endpoint('GET', '\\/basiq\\/tokens'),
592
+ BORROWING_EXPENSES_GET: new Endpoint('GET', '\\/borrowing-expenses'),
590
593
  CHARTS_INCOME_GET: new Endpoint('GET', '\\/charts\\/\\incomes'),
591
594
  CHARTS_EXPENSES_GET: new Endpoint('GET', '\\/charts\\/\\expenses'),
592
595
  CHART_ACCOUNTS_GET: new Endpoint('GET', '\\/chart-accounts'),
@@ -684,6 +687,7 @@ const ENDPOINTS = {
684
687
  SOLE_BUSINESSES_GET: new Endpoint('GET', '\\/sole-businesses'),
685
688
  SOLE_BUSINESSES_POST: new Endpoint('POST', '\\/sole-businesses'),
686
689
  SOLE_BUSINESSES_PUT: new Endpoint('PUT', '\\/sole-businesses\\/\\d+'),
690
+ BUSINESS_ACTIVITIES_GET: new Endpoint('GET', '\\/sole-business-activities'),
687
691
  SOLE_DEPRECIATION_METHODS_GET: new Endpoint('GET', '\\/sole-depreciation-methods'),
688
692
  SOLE_DEPRECIATION_METHODS_PUT: new Endpoint('PUT', '\\/sole-depreciation-methods\\/\\d+'),
689
693
  SOLE_INVOICES_GET: new Endpoint('GET', '\\/sole-invoices'),
@@ -2607,14 +2611,14 @@ class VehicleLogbook extends VehicleLogbook$1 {
2607
2611
  * Get logbook period date range from logbook date and weeksInPeriod duration
2608
2612
  */
2609
2613
  getPeriod() {
2610
- return moment.rangeFromInterval('weeks', VehicleLogbook.bestPeriodWeeks, this.date);
2614
+ return moment.rangeFromInterval('milliseconds', VehicleLogbook.bestPeriodDuration, this.date);
2611
2615
  }
2612
2616
  }
2613
2617
  /**
2614
- * Logbook period duration in weeks.
2618
+ * Logbook period duration in milliseconds.
2615
2619
  * https://taxtank.atlassian.net/wiki/spaces/TAXTANK/pages/211517441/Logbook+Vehicle
2616
2620
  */
2617
- VehicleLogbook.bestPeriodWeeks = 12;
2621
+ VehicleLogbook.bestPeriodDuration = 12 * 7 * 24 * 3600 * 1000;
2618
2622
  __decorate([
2619
2623
  Type(() => Date)
2620
2624
  ], VehicleLogbook.prototype, "date", void 0);
@@ -4732,7 +4736,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImpo
4732
4736
  /**
4733
4737
  * Interceptor which adds user's basiq token to any http request to basiq api
4734
4738
  */
4735
- class BasiqInterceptor {
4739
+ class BasiqTokenInterceptor {
4736
4740
  constructor(basiqTokenService) {
4737
4741
  this.basiqTokenService = basiqTokenService;
4738
4742
  }
@@ -4753,12 +4757,239 @@ class BasiqInterceptor {
4753
4757
  });
4754
4758
  }
4755
4759
  }
4756
- BasiqInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: BasiqInterceptor, deps: [{ token: BasiqTokenService }], target: i0.ɵɵFactoryTarget.Injectable });
4757
- BasiqInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: BasiqInterceptor });
4758
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: BasiqInterceptor, decorators: [{
4760
+ BasiqTokenInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: BasiqTokenInterceptor, deps: [{ token: BasiqTokenService }], target: i0.ɵɵFactoryTarget.Injectable });
4761
+ BasiqTokenInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: BasiqTokenInterceptor });
4762
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: BasiqTokenInterceptor, decorators: [{
4759
4763
  type: Injectable
4760
4764
  }], ctorParameters: function () { return [{ type: BasiqTokenService }]; } });
4761
4765
 
4766
+ /**
4767
+ * server sent events service
4768
+ * https://symfony.com/doc/current/mercure.html
4769
+ */
4770
+ class SseService {
4771
+ constructor(zone, jwtService, environment) {
4772
+ this.zone = zone;
4773
+ this.jwtService = jwtService;
4774
+ this.environment = environment;
4775
+ }
4776
+ /**
4777
+ * list to url for server events
4778
+ */
4779
+ on(topic) {
4780
+ const url = new URL(this.environment.mercureUrl);
4781
+ url.searchParams.append('topic', `${this.environment.apiV2}/users/${this.jwtService.decodeToken().username}/${topic}`);
4782
+ // tslint:disable-next-line:typedef
4783
+ return new Observable((observer) => {
4784
+ const es = new EventSourcePolyfill(url, {
4785
+ headers: {
4786
+ Authorization: 'Bearer ' + this.jwtService.getToken(),
4787
+ }
4788
+ });
4789
+ es.onmessage = (event) => {
4790
+ this.zone.run(() => observer.next(event));
4791
+ };
4792
+ })
4793
+ .pipe(map((messageEvent) => {
4794
+ return JSON.parse(messageEvent.data);
4795
+ }));
4796
+ }
4797
+ }
4798
+ SseService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: SseService, deps: [{ token: i0.NgZone }, { token: JwtService }, { token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable });
4799
+ SseService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: SseService, providedIn: 'root' });
4800
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: SseService, decorators: [{
4801
+ type: Injectable,
4802
+ args: [{
4803
+ providedIn: 'root'
4804
+ }]
4805
+ }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: JwtService }, { type: undefined, decorators: [{
4806
+ type: Inject,
4807
+ args: ['environment']
4808
+ }] }]; } });
4809
+
4810
+ /**
4811
+ * Service to work with user
4812
+ */
4813
+ class UserService {
4814
+ constructor(http, jwtService, eventDispatcherService, sseService, environment) {
4815
+ this.http = http;
4816
+ this.jwtService = jwtService;
4817
+ this.eventDispatcherService = eventDispatcherService;
4818
+ this.sseService = sseService;
4819
+ this.environment = environment;
4820
+ this.cacheSubject = new ReplaySubject(1);
4821
+ this.listenEvents();
4822
+ }
4823
+ listenEvents() {
4824
+ this.listenServiceSubscriptionUpdated();
4825
+ }
4826
+ get() {
4827
+ if (!this.cache) {
4828
+ this.fetch().subscribe(() => { }, (error) => {
4829
+ // force logout user (clear localStorage) when get current user return error
4830
+ if (error.status === 500) {
4831
+ this.eventDispatcherService.dispatch(new AppEvent(AppEventTypeEnum.CURRENT_USER_GET_FAILED, null));
4832
+ }
4833
+ });
4834
+ }
4835
+ return this.cacheSubject.asObservable();
4836
+ }
4837
+ /**
4838
+ * Get current user
4839
+ */
4840
+ fetch() {
4841
+ return this.http.get(`${this.environment.apiV2}/users/current`)
4842
+ .pipe(map((userBase) => {
4843
+ const user = plainToClass(User, userBase);
4844
+ localStorage.setItem('userId', user.id.toString());
4845
+ // @TODO remove
4846
+ localStorage.setItem('financialYear', user.financialYear.toString());
4847
+ this.cache = user;
4848
+ this.cacheSubject.next(this.cache);
4849
+ return user;
4850
+ }));
4851
+ }
4852
+ /**
4853
+ * Register new user
4854
+ */
4855
+ register(data) {
4856
+ return this.http.post(`${this.environment.apiV2}/users/registration`, data);
4857
+ }
4858
+ /**
4859
+ * Update user
4860
+ */
4861
+ update(user) {
4862
+ return this.http.put(`${this.environment.apiV2}/users/${user.id}`, user)
4863
+ .pipe(map((userBase) => {
4864
+ this.cache = plainToClass(User, userBase);
4865
+ this.eventDispatcherService.dispatch(new AppEvent(AppEventTypeEnum.USER_UPDATED, null));
4866
+ this.cacheSubject.next(this.cache);
4867
+ }));
4868
+ }
4869
+ /**
4870
+ * Change user password
4871
+ */
4872
+ changePassword(currentPassword, newPassword) {
4873
+ return this.http.put(`${this.environment.apiV2}/users/password/change`, { currentPassword, newPassword });
4874
+ }
4875
+ /**
4876
+ * Recovery user password
4877
+ */
4878
+ recoveryPassword(email) {
4879
+ return this.http.put(`${this.environment.apiV2}/users/password/recovery`, { email });
4880
+ }
4881
+ /**
4882
+ * Reset user password
4883
+ */
4884
+ resetPassword(newPassword, resetToken) {
4885
+ return this.http.put(`${this.environment.apiV2}/users/password/reset`, { newPassword, resetToken });
4886
+ }
4887
+ resendConfirmationEmail(email) {
4888
+ return this.http.post(`${this.environment.apiV2}/users/confirmation/resend`, { email });
4889
+ }
4890
+ /**
4891
+ * Confirm registered user
4892
+ */
4893
+ confirm(verificationCode) {
4894
+ return this.http.post(`${this.environment.apiV2}/users/confirmation`, { verificationCode });
4895
+ }
4896
+ /**
4897
+ * Search existing user
4898
+ */
4899
+ search(email) {
4900
+ return this.http.get(`${this.environment.apiV2}/users/search?email=${email}`)
4901
+ .pipe(map((userBase) => {
4902
+ return plainToClass(User, userBase);
4903
+ }));
4904
+ }
4905
+ /**
4906
+ * Finish onboarding process
4907
+ */
4908
+ finishOnboarding(user) {
4909
+ return this.http.put(`${this.environment.apiV2}/users/status`, user)
4910
+ .pipe(map(() => {
4911
+ this.cache = user;
4912
+ this.cacheSubject.next(this.cache);
4913
+ }));
4914
+ }
4915
+ /**
4916
+ * Update user photo
4917
+ */
4918
+ updatePhoto(photo) {
4919
+ return this.http.post(`${this.environment.apiV2}/users/photo?_method=PUT`, photo)
4920
+ .pipe(map((photoUrl) => {
4921
+ this.cache = plainToClass(User, Object.assign(this.cache, { photo: photoUrl }));
4922
+ this.cacheSubject.next(this.cache);
4923
+ }));
4924
+ }
4925
+ switchFinancialYear(year) {
4926
+ return this.http.get(`${this.environment.apiV2}/financial-year/switch`, { params: new HttpParams({ fromString: `financialYear=${year}` }) }).pipe(map(() => {
4927
+ localStorage.setItem('financialYear', year.toString());
4928
+ window.location.reload();
4929
+ }));
4930
+ }
4931
+ /**
4932
+ * clear service cache
4933
+ */
4934
+ resetCache() {
4935
+ this.fetch().subscribe();
4936
+ }
4937
+ /**
4938
+ * Create basiq (if not exist yet) to provide access to basiq api
4939
+ */
4940
+ createBasiq() {
4941
+ return this.http.post(`${this.environment.apiV2}/basiq/user`, {})
4942
+ .pipe(map((basiqId) => {
4943
+ this.cache = plainToClass(User, Object.assign(this.cache, { basiqId }));
4944
+ this.cacheSubject.next(this.cache);
4945
+ return basiqId;
4946
+ }));
4947
+ }
4948
+ /**
4949
+ * Update cache when user's service subscription is updated
4950
+ */
4951
+ listenServiceSubscriptionUpdated() {
4952
+ this.eventDispatcherService.on(AppEventTypeEnum.SERVICE_SUBSCRIPTION_UPDATED).subscribe(() => this.resetCache());
4953
+ }
4954
+ }
4955
+ UserService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: UserService, deps: [{ token: i1.HttpClient }, { token: JwtService }, { token: EventDispatcherService }, { token: SseService }, { token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable });
4956
+ UserService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: UserService, providedIn: 'root' });
4957
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: UserService, decorators: [{
4958
+ type: Injectable,
4959
+ args: [{
4960
+ providedIn: 'root'
4961
+ }]
4962
+ }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: JwtService }, { type: EventDispatcherService }, { type: SseService }, { type: undefined, decorators: [{
4963
+ type: Inject,
4964
+ args: ['environment']
4965
+ }] }]; } });
4966
+
4967
+ /**
4968
+ * Interceptor which check if client's basiq id exist and request it if not
4969
+ */
4970
+ class BasiqClientIdInterceptor {
4971
+ constructor(userService) {
4972
+ this.userService = userService;
4973
+ }
4974
+ intercept(request, next) {
4975
+ // Check if 'client id' URL segment contains null instead of id
4976
+ if (!request.url.startsWith(`${BasiqService.basiqApiUrl}/users/null`)) {
4977
+ return next.handle(request);
4978
+ }
4979
+ return this.userService.createBasiq().pipe(mergeMap((basiqClientId) => next.handle(this.addId(request, basiqClientId))));
4980
+ }
4981
+ addId(request, basiqClientId) {
4982
+ return request.clone({
4983
+ url: request.url.replace('null', basiqClientId)
4984
+ });
4985
+ }
4986
+ }
4987
+ BasiqClientIdInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: BasiqClientIdInterceptor, deps: [{ token: UserService }], target: i0.ɵɵFactoryTarget.Injectable });
4988
+ BasiqClientIdInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: BasiqClientIdInterceptor });
4989
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: BasiqClientIdInterceptor, decorators: [{
4990
+ type: Injectable
4991
+ }], ctorParameters: function () { return [{ type: UserService }]; } });
4992
+
4762
4993
  class InterceptorsModule {
4763
4994
  }
4764
4995
  InterceptorsModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: InterceptorsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
@@ -4792,7 +5023,12 @@ InterceptorsModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", vers
4792
5023
  },
4793
5024
  {
4794
5025
  provide: HTTP_INTERCEPTORS,
4795
- useClass: BasiqInterceptor,
5026
+ useClass: BasiqTokenInterceptor,
5027
+ multi: true
5028
+ },
5029
+ {
5030
+ provide: HTTP_INTERCEPTORS,
5031
+ useClass: BasiqClientIdInterceptor,
4796
5032
  multi: true
4797
5033
  }
4798
5034
  ] });
@@ -4828,7 +5064,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImpo
4828
5064
  },
4829
5065
  {
4830
5066
  provide: HTTP_INTERCEPTORS,
4831
- useClass: BasiqInterceptor,
5067
+ useClass: BasiqTokenInterceptor,
5068
+ multi: true
5069
+ },
5070
+ {
5071
+ provide: HTTP_INTERCEPTORS,
5072
+ useClass: BasiqClientIdInterceptor,
4832
5073
  multi: true
4833
5074
  }
4834
5075
  ]
@@ -4899,7 +5140,7 @@ class VehicleLogbookCollection extends Collection {
4899
5140
  if (this.items.length < 2) {
4900
5141
  return false;
4901
5142
  }
4902
- return VehicleLogbook.bestPeriodWeeks < (this.last.date.getTime() - this.first.date.getTime());
5143
+ return VehicleLogbook.bestPeriodDuration < (this.last.date.getTime() - this.first.date.getTime());
4903
5144
  }
4904
5145
  /**
4905
5146
  * Get collection of non-personal logbooks (work-related, sole-related).
@@ -8974,6 +9215,10 @@ class SoleDepreciationMethodService {
8974
9215
  this.toastService = toastService;
8975
9216
  this.cacheSubject = new ReplaySubject(1);
8976
9217
  this.url = 'sole-depreciation-methods';
9218
+ this.listenEvents();
9219
+ }
9220
+ listenEvents() {
9221
+ this.listenSoleDetailsChanges();
8977
9222
  }
8978
9223
  get() {
8979
9224
  if (!this.cache) {
@@ -9000,6 +9245,13 @@ class SoleDepreciationMethodService {
9000
9245
  return throwError$1(error);
9001
9246
  }));
9002
9247
  }
9248
+ listenSoleDetailsChanges() {
9249
+ this.eventDispatcherService.on([AppEventTypeEnum.SOLE_DETAILS_CREATED, AppEventTypeEnum.SOLE_DETAILS_UPDATED])
9250
+ .subscribe(() => {
9251
+ this.cache = null;
9252
+ this.get().subscribe();
9253
+ });
9254
+ }
9003
9255
  }
9004
9256
  SoleDepreciationMethodService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: SoleDepreciationMethodService, deps: [{ token: i1.HttpClient }, { token: 'environment' }, { token: EventDispatcherService }, { token: ToastService }], target: i0.ɵɵFactoryTarget.Injectable });
9005
9257
  SoleDepreciationMethodService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: SoleDepreciationMethodService, providedIn: 'root' });
@@ -9017,9 +9269,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImpo
9017
9269
  * @TODO TT-1777 Alex: extend from rest service when it refactored
9018
9270
  */
9019
9271
  class SoleDetailsService {
9020
- constructor(http, environment) {
9272
+ constructor(http, environment, eventDispatcherService) {
9021
9273
  this.http = http;
9022
9274
  this.environment = environment;
9275
+ this.eventDispatcherService = eventDispatcherService;
9023
9276
  this.cacheSubject = new ReplaySubject(1);
9024
9277
  }
9025
9278
  get() {
@@ -9042,6 +9295,7 @@ class SoleDetailsService {
9042
9295
  return this.http.post(`${this.environment.apiV2}/sole-details`, soleDetails).pipe(map((soleDetailsBase) => {
9043
9296
  this.cache = plainToClass(SoleDetails, soleDetailsBase);
9044
9297
  this.cacheSubject.next(this.cache);
9298
+ this.eventDispatcherService.dispatch(new AppEvent(AppEventTypeEnum.SOLE_DETAILS_CREATED, soleDetails));
9045
9299
  return this.cache;
9046
9300
  }));
9047
9301
  }
@@ -9049,11 +9303,12 @@ class SoleDetailsService {
9049
9303
  return this.http.put(`${this.environment.apiV2}/sole-details/${soleDetails.id}`, soleDetails).pipe(map((soleDetailsBase) => {
9050
9304
  this.cache = plainToClass(SoleDetails, soleDetailsBase);
9051
9305
  this.cacheSubject.next(this.cache);
9306
+ this.eventDispatcherService.dispatch(new AppEvent(AppEventTypeEnum.SOLE_DETAILS_UPDATED, soleDetails));
9052
9307
  return this.cache;
9053
9308
  }));
9054
9309
  }
9055
9310
  }
9056
- SoleDetailsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: SoleDetailsService, deps: [{ token: i1.HttpClient }, { token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable });
9311
+ SoleDetailsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: SoleDetailsService, deps: [{ token: i1.HttpClient }, { token: 'environment' }, { token: EventDispatcherService }], target: i0.ɵɵFactoryTarget.Injectable });
9057
9312
  SoleDetailsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: SoleDetailsService, providedIn: 'root' });
9058
9313
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: SoleDetailsService, decorators: [{
9059
9314
  type: Injectable,
@@ -9063,7 +9318,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImpo
9063
9318
  }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: undefined, decorators: [{
9064
9319
  type: Inject,
9065
9320
  args: ['environment']
9066
- }] }]; } });
9321
+ }] }, { type: EventDispatcherService }]; } });
9067
9322
 
9068
9323
  class SoleInvoiceService extends RestService {
9069
9324
  constructor() {
@@ -11042,50 +11297,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImpo
11042
11297
  }]
11043
11298
  }] });
11044
11299
 
11045
- /**
11046
- * server sent events service
11047
- * https://symfony.com/doc/current/mercure.html
11048
- */
11049
- class SseService {
11050
- constructor(zone, jwtService, environment) {
11051
- this.zone = zone;
11052
- this.jwtService = jwtService;
11053
- this.environment = environment;
11054
- }
11055
- /**
11056
- * list to url for server events
11057
- */
11058
- on(topic) {
11059
- const url = new URL(this.environment.mercureUrl);
11060
- url.searchParams.append('topic', `${this.environment.apiV2}/users/${this.jwtService.decodeToken().username}/${topic}`);
11061
- // tslint:disable-next-line:typedef
11062
- return new Observable((observer) => {
11063
- const es = new EventSourcePolyfill(url, {
11064
- headers: {
11065
- Authorization: 'Bearer ' + this.jwtService.getToken(),
11066
- }
11067
- });
11068
- es.onmessage = (event) => {
11069
- this.zone.run(() => observer.next(event));
11070
- };
11071
- })
11072
- .pipe(map((messageEvent) => {
11073
- return JSON.parse(messageEvent.data);
11074
- }));
11075
- }
11076
- }
11077
- SseService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: SseService, deps: [{ token: i0.NgZone }, { token: JwtService }, { token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable });
11078
- SseService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: SseService, providedIn: 'root' });
11079
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: SseService, decorators: [{
11080
- type: Injectable,
11081
- args: [{
11082
- providedIn: 'root'
11083
- }]
11084
- }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: JwtService }, { type: undefined, decorators: [{
11085
- type: Inject,
11086
- args: ['environment']
11087
- }] }]; } });
11088
-
11089
11300
  /**
11090
11301
  * Service for work with chats
11091
11302
  */
@@ -13570,152 +13781,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImpo
13570
13781
  }]
13571
13782
  }] });
13572
13783
 
13573
- /**
13574
- * Service to work with user
13575
- */
13576
- class UserService {
13577
- constructor(http, jwtService, eventDispatcherService, sseService, environment) {
13578
- this.http = http;
13579
- this.jwtService = jwtService;
13580
- this.eventDispatcherService = eventDispatcherService;
13581
- this.sseService = sseService;
13582
- this.environment = environment;
13583
- this.cacheSubject = new ReplaySubject(1);
13584
- this.listenEvents();
13585
- }
13586
- listenEvents() {
13587
- this.listenServiceSubscriptionUpdated();
13588
- }
13589
- get() {
13590
- if (!this.cache) {
13591
- this.fetch().subscribe(() => { }, (error) => {
13592
- // force logout user (clear localStorage) when get current user return error
13593
- if (error.status === 500) {
13594
- this.eventDispatcherService.dispatch(new AppEvent(AppEventTypeEnum.CURRENT_USER_GET_FAILED, null));
13595
- }
13596
- });
13597
- }
13598
- return this.cacheSubject.asObservable();
13599
- }
13600
- /**
13601
- * Get current user
13602
- */
13603
- fetch() {
13604
- return this.http.get(`${this.environment.apiV2}/users/current`)
13605
- .pipe(map((userBase) => {
13606
- const user = plainToClass(User, userBase);
13607
- localStorage.setItem('userId', user.id.toString());
13608
- // @TODO remove
13609
- localStorage.setItem('financialYear', user.financialYear.toString());
13610
- this.cache = user;
13611
- this.cacheSubject.next(this.cache);
13612
- return user;
13613
- }));
13614
- }
13615
- /**
13616
- * Register new user
13617
- */
13618
- register(data) {
13619
- return this.http.post(`${this.environment.apiV2}/users/registration`, data);
13620
- }
13621
- /**
13622
- * Update user
13623
- */
13624
- update(user) {
13625
- return this.http.put(`${this.environment.apiV2}/users/${user.id}`, user)
13626
- .pipe(map((userBase) => {
13627
- this.cache = plainToClass(User, userBase);
13628
- this.eventDispatcherService.dispatch(new AppEvent(AppEventTypeEnum.USER_UPDATED, null));
13629
- this.cacheSubject.next(this.cache);
13630
- }));
13631
- }
13632
- /**
13633
- * Change user password
13634
- */
13635
- changePassword(currentPassword, newPassword) {
13636
- return this.http.put(`${this.environment.apiV2}/users/password/change`, { currentPassword, newPassword });
13637
- }
13638
- /**
13639
- * Recovery user password
13640
- */
13641
- recoveryPassword(email) {
13642
- return this.http.put(`${this.environment.apiV2}/users/password/recovery`, { email });
13643
- }
13644
- /**
13645
- * Reset user password
13646
- */
13647
- resetPassword(newPassword, resetToken) {
13648
- return this.http.put(`${this.environment.apiV2}/users/password/reset`, { newPassword, resetToken });
13649
- }
13650
- resendConfirmationEmail(email) {
13651
- return this.http.post(`${this.environment.apiV2}/users/confirmation/resend`, { email });
13652
- }
13653
- /**
13654
- * Confirm registered user
13655
- */
13656
- confirm(verificationCode) {
13657
- return this.http.post(`${this.environment.apiV2}/users/confirmation`, { verificationCode });
13658
- }
13659
- /**
13660
- * Search existing user
13661
- */
13662
- search(email) {
13663
- return this.http.get(`${this.environment.apiV2}/users/search?email=${email}`)
13664
- .pipe(map((userBase) => {
13665
- return plainToClass(User, userBase);
13666
- }));
13667
- }
13668
- /**
13669
- * Finish onboarding process
13670
- */
13671
- finishOnboarding(user) {
13672
- return this.http.put(`${this.environment.apiV2}/users/status`, user)
13673
- .pipe(map(() => {
13674
- this.cache = user;
13675
- this.cacheSubject.next(this.cache);
13676
- }));
13677
- }
13678
- /**
13679
- * Update user photo
13680
- */
13681
- updatePhoto(photo) {
13682
- return this.http.post(`${this.environment.apiV2}/users/photo?_method=PUT`, photo)
13683
- .pipe(map((photoUrl) => {
13684
- this.cache = plainToClass(User, Object.assign(this.cache, { photo: photoUrl }));
13685
- this.cacheSubject.next(this.cache);
13686
- }));
13687
- }
13688
- switchFinancialYear(year) {
13689
- return this.http.get(`${this.environment.apiV2}/financial-year/switch`, { params: new HttpParams({ fromString: `financialYear=${year}` }) }).pipe(map(() => {
13690
- localStorage.setItem('financialYear', year.toString());
13691
- window.location.reload();
13692
- }));
13693
- }
13694
- /**
13695
- * clear service cache
13696
- */
13697
- resetCache() {
13698
- this.fetch().subscribe();
13699
- }
13700
- /**
13701
- * Update cache when user's service subscription is updated
13702
- */
13703
- listenServiceSubscriptionUpdated() {
13704
- this.eventDispatcherService.on(AppEventTypeEnum.SERVICE_SUBSCRIPTION_UPDATED).subscribe(() => this.resetCache());
13705
- }
13706
- }
13707
- UserService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: UserService, deps: [{ token: i1.HttpClient }, { token: JwtService }, { token: EventDispatcherService }, { token: SseService }, { token: 'environment' }], target: i0.ɵɵFactoryTarget.Injectable });
13708
- UserService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: UserService, providedIn: 'root' });
13709
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: UserService, decorators: [{
13710
- type: Injectable,
13711
- args: [{
13712
- providedIn: 'root'
13713
- }]
13714
- }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: JwtService }, { type: EventDispatcherService }, { type: SseService }, { type: undefined, decorators: [{
13715
- type: Inject,
13716
- args: ['environment']
13717
- }] }]; } });
13718
-
13719
13784
  /**
13720
13785
  * Service to work with XLSX (generate, download, e.t.c.)
13721
13786
  */
@@ -14198,7 +14263,11 @@ var MessagesEnum;
14198
14263
  */
14199
14264
  function minDateValidator(date, message = MessagesEnum.INVALID_DATE.replace('$1', new DatePipe('en-US').transform(date))) {
14200
14265
  return (control) => {
14201
- if (!control.value || (control.value >= date)) {
14266
+ if (!control.value) {
14267
+ return null;
14268
+ }
14269
+ // form control value can be as a Moment object - we wrap it in "new Date()" to work with it like with JS Date
14270
+ if (new Date(control.value) >= new Date(date)) {
14202
14271
  return null;
14203
14272
  }
14204
14273
  return { minDate: message };
@@ -14297,7 +14366,7 @@ class SoleBusinessForm extends AbstractForm {
14297
14366
  name: new FormControl(business.name, Validators.required),
14298
14367
  activity: new FormControl(business.activity, Validators.required),
14299
14368
  description: new FormControl(business.description),
14300
- website: new FormControl(business.website),
14369
+ website: new FormControl(business.website)
14301
14370
  }, business);
14302
14371
  // User have to create income source with new business.
14303
14372
  // Income source is not able for edit business
@@ -14314,11 +14383,20 @@ class SoleBusinessForm extends AbstractForm {
14314
14383
  })
14315
14384
  ])
14316
14385
  }));
14386
+ this.addControl('losses', new FormArray([
14387
+ new FormGroup({
14388
+ financialYear: new FormControl(new FinancialYear().year),
14389
+ openBalance: new FormControl(null, Validators.required)
14390
+ })
14391
+ ]));
14317
14392
  }
14318
14393
  }
14319
14394
  get forecastFormGroup() {
14320
14395
  return this.get('incomeSource').get('soleForecasts').at(0);
14321
14396
  }
14397
+ get lossFormGroup() {
14398
+ return this.get('losses').at(0);
14399
+ }
14322
14400
  }
14323
14401
 
14324
14402
  /**
@@ -14406,10 +14484,22 @@ class SoleDepreciationMethodForm extends AbstractForm {
14406
14484
  }
14407
14485
  }
14408
14486
 
14487
+ /**
14488
+ * Validator check if entered strong length is equal to passed length parameter
14489
+ */
14490
+ function requiredLengthValidator(length) {
14491
+ return (control) => {
14492
+ if (control.value && control.value.length !== length) {
14493
+ return { requiredLength: length };
14494
+ }
14495
+ return null;
14496
+ };
14497
+ }
14498
+
14409
14499
  class SoleDetailsForm extends AbstractForm {
14410
14500
  constructor(soleDetails) {
14411
14501
  super({
14412
- abn: new FormControl(soleDetails.abn, [Validators.required, Validators.minLength(11), Validators.maxLength(11)]),
14502
+ abn: new FormControl(soleDetails.abn, [Validators.required, requiredLengthValidator(11)]),
14413
14503
  isGST: new FormControl(soleDetails.isGST || false)
14414
14504
  }, soleDetails);
14415
14505
  }