@stamhoofd/backend 2.110.0 → 2.112.0

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 (51) hide show
  1. package/LICENSE.md +32 -0
  2. package/package.json +15 -12
  3. package/src/boot.ts +1 -0
  4. package/src/email-recipient-loaders/documents.ts +66 -0
  5. package/src/endpoints/auth/PatchUserEndpoint.test.ts +56 -0
  6. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.test.ts +701 -4
  7. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +21 -10
  8. package/src/endpoints/global/registration/PatchUserMembersEndpoint.test.ts +661 -4
  9. package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +17 -6
  10. package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +291 -8
  11. package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +22 -0
  12. package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplatesEndpoint.ts +16 -18
  13. package/src/endpoints/organization/dashboard/invoices/GetInvoicesCountEndpoint.ts +43 -0
  14. package/src/endpoints/organization/dashboard/invoices/GetInvoicesEndpoint.ts +219 -0
  15. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +8 -8
  16. package/src/endpoints/organization/dashboard/payments/PatchBalanceItemsEndpoint.ts +2 -2
  17. package/src/endpoints/organization/shared/GetUitpasNumberDetailsEndpoint.ts +72 -0
  18. package/src/endpoints/organization/webshops/RetrieveUitpasSocialTariffPriceEndpoint.ts +3 -2
  19. package/src/excel-loaders/members.ts +27 -27
  20. package/src/helpers/AdminPermissionChecker.ts +30 -10
  21. package/src/helpers/AuthenticatedStructures.ts +24 -5
  22. package/src/helpers/StripeHelper.ts +11 -1
  23. package/src/helpers/StripePayoutChecker.ts +7 -0
  24. package/src/helpers/UitpasTokenRepository.ts +7 -5
  25. package/src/helpers/passthroughFetch.ts +24 -0
  26. package/src/helpers/updateMemberDetailsUitpasNumber.ts +149 -0
  27. package/src/seeds/data/default-email-templates.sql +2 -1
  28. package/src/seeds/wip/1769088653-uitpas-status.ts +129 -0
  29. package/src/services/InvoiceService.ts +114 -0
  30. package/src/services/uitpas/PassholderEndpoints.ts +190 -0
  31. package/src/services/uitpas/UitpasService.ts +37 -12
  32. package/src/services/uitpas/checkUitpasNumbers.ts +16 -140
  33. package/src/services/uitpas/handleUitpasResponse.ts +89 -0
  34. package/src/sql-filters/invoiced-balance-items.ts +20 -0
  35. package/src/sql-filters/invoices.ts +122 -0
  36. package/src/sql-filters/payments.ts +11 -1
  37. package/src/sql-sorters/invoices.ts +83 -0
  38. package/src/sql-sorters/payments.ts +33 -0
  39. package/tests/e2e/bundle-discounts.test.ts +8 -8
  40. package/tests/e2e/tests-disable-net-connect.test.ts +5 -0
  41. package/tests/helpers/StripeMocker.ts +5 -5
  42. package/tests/helpers/UitpasApiMocker.ts +175 -0
  43. package/tests/helpers/index.ts +1 -0
  44. package/tests/helpers/resetNock.ts +7 -0
  45. package/tests/init/index.ts +1 -0
  46. package/tests/init/initPayconiq.ts +2 -2
  47. package/tests/init/initStripe.ts +1 -1
  48. package/tests/init/initUitpasApi.ts +14 -0
  49. package/tests/jest.global.setup.ts +6 -4
  50. package/tests/jest.setup.ts +12 -6
  51. package/LICENSE +0 -665
@@ -1,11 +1,12 @@
1
1
  import { Database } from '@simonbackx/simple-database';
2
2
  import { PatchableArray, PatchMap } from '@simonbackx/simple-encoding';
3
3
  import { Endpoint, Request } from '@simonbackx/simple-endpoints';
4
- import { GroupFactory, MemberFactory, OrganizationFactory, Platform, RegistrationFactory, Token, UserFactory } from '@stamhoofd/models';
5
- import { MemberDetails, MemberWithRegistrationsBlob, OrganizationMetaData, OrganizationRecordsConfiguration, Parent, PatchAnswers, PermissionLevel, RecordCategory, RecordSettings, RecordTextAnswer, TranslatedString } from '@stamhoofd/structures';
4
+ import { GroupFactory, Member, MemberFactory, OrganizationFactory, Platform, RegistrationFactory, Token, UserFactory } from '@stamhoofd/models';
5
+ import { MemberDetails, MemberWithRegistrationsBlob, OrganizationMetaData, OrganizationRecordsConfiguration, Parent, PatchAnswers, PermissionLevel, RecordCategory, RecordSettings, RecordTextAnswer, TranslatedString, UitpasNumberDetails, UitpasSocialTariff, UitpasSocialTariffStatus } from '@stamhoofd/structures';
6
6
  import { STExpect, TestUtils } from '@stamhoofd/test-utils';
7
- import { testServer } from '../../../../tests/helpers/TestServer';
8
- import { PatchUserMembersEndpoint } from './PatchUserMembersEndpoint';
7
+ import { testServer } from '../../../../tests/helpers/TestServer.js';
8
+ import { initUitpasApi } from '../../../../tests/init/index.js';
9
+ import { PatchUserMembersEndpoint } from './PatchUserMembersEndpoint.js';
9
10
 
10
11
  const baseUrl = `/members`;
11
12
  const endpoint = new PatchUserMembersEndpoint();
@@ -440,4 +441,660 @@ describe('Endpoint.PatchUserMembersEndpoint', () => {
440
441
  await expect(testServer.test(endpoint, request)).rejects.toThrow(STExpect.errorWithCode('permission_denied'));
441
442
  });
442
443
  });
444
+
445
+ describe('Uitpas number', () => {
446
+ describe('PUT', () => {
447
+ test('Should not set socialTariff from request', async () => {
448
+ initUitpasApi();
449
+
450
+ const user = await new UserFactory({ }).create();
451
+
452
+ const token = await Token.createToken(user);
453
+
454
+ const organization = await new OrganizationFactory({}).create();
455
+
456
+ // patch uitpas number
457
+ const arr: Body = new PatchableArray();
458
+
459
+ const member = MemberWithRegistrationsBlob.create({
460
+ details: MemberDetails.create({
461
+ firstName,
462
+ lastName,
463
+ uitpasNumberDetails: UitpasNumberDetails.create({
464
+ // active number
465
+ uitpasNumber: '0900011354819',
466
+ socialTariff: UitpasSocialTariff.create({
467
+ status: UitpasSocialTariffStatus.None,
468
+ endDate: new Date(2050, 0, 1),
469
+ updatedAt: new Date(2040, 0, 1),
470
+ }),
471
+ }),
472
+ }),
473
+ });
474
+
475
+ arr.addPut(member);
476
+
477
+ const request = Request.buildJson('PATCH', baseUrl, organization.getApiHost(), arr);
478
+ request.headers.authorization = 'Bearer ' + token.accessToken;
479
+
480
+ const result = await testServer.test(endpoint, request);
481
+
482
+ expect(result.status).toBe(200);
483
+ expect(result.body.members.length).toBe(1);
484
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.status).toBe(UitpasSocialTariffStatus.Active);
485
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.endDate?.getTime()).not.toBe(new Date(2050, 0, 1).getTime());
486
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.updatedAt?.getTime()).not.toBe(new Date(2040, 0, 1).getTime());
487
+ });
488
+ });
489
+
490
+ describe('PATCH', () => {
491
+ test('Should update socialTariff if uitpasNumber changes', async () => {
492
+ initUitpasApi();
493
+
494
+ const organization = await new OrganizationFactory({ }).create();
495
+
496
+ const user = await new UserFactory({ }).create();
497
+
498
+ const token = await Token.createToken(user);
499
+
500
+ // create member
501
+ const member = await new MemberFactory({
502
+ firstName,
503
+ lastName,
504
+ birthDay,
505
+ generateData: false,
506
+ // Give user access to this member
507
+ user,
508
+ details: MemberDetails.create({
509
+ uitpasNumberDetails: UitpasNumberDetails.create({
510
+ // expired
511
+ uitpasNumber: '0900000095902',
512
+ socialTariff: UitpasSocialTariff.create({
513
+ status: UitpasSocialTariffStatus.None,
514
+ updatedAt: new Date(2030, 0, 1),
515
+ }),
516
+ }),
517
+ }),
518
+ }).create();
519
+
520
+ // patch uitpas number
521
+ const arr: Body = new PatchableArray();
522
+
523
+ arr.addPatch(MemberWithRegistrationsBlob.patch({
524
+ id: member.id,
525
+ details: MemberDetails.patch({
526
+ uitpasNumberDetails: UitpasNumberDetails.patch({
527
+ // active
528
+ uitpasNumber: '0900011354819',
529
+ }),
530
+ }),
531
+ }));
532
+
533
+ const request = Request.buildJson('PATCH', baseUrl, organization.getApiHost(), arr);
534
+ request.headers.authorization = 'Bearer ' + token.accessToken;
535
+
536
+ const result = await testServer.test(endpoint, request);
537
+
538
+ expect(result.status).toBe(200);
539
+ expect(result.body.members.length).toBe(1);
540
+ expect(result.body.members[0].details.uitpasNumberDetails?.uitpasNumber).toEqual('0900011354819');
541
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.status).toEqual(UitpasSocialTariffStatus.Active);
542
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.updatedAt.getTime()).not.toEqual(new Date(2030, 0, 1).getTime());
543
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.endDate).toBeDate();
544
+ });
545
+
546
+ test('Should throw if invalid uitpas number', async () => {
547
+ initUitpasApi();
548
+
549
+ const organization = await new OrganizationFactory({ }).create();
550
+
551
+ const user = await new UserFactory({ }).create();
552
+
553
+ const token = await Token.createToken(user);
554
+
555
+ // create member
556
+ const member = await new MemberFactory({
557
+ firstName,
558
+ lastName,
559
+ birthDay,
560
+ generateData: false,
561
+ // Give user access to this member
562
+ user,
563
+ details: MemberDetails.create({
564
+ uitpasNumberDetails: UitpasNumberDetails.create({
565
+ // expired
566
+ uitpasNumber: '0900000095902',
567
+ socialTariff: UitpasSocialTariff.create({
568
+ status: UitpasSocialTariffStatus.None,
569
+ updatedAt: new Date(2030, 0, 1),
570
+ }),
571
+ }),
572
+ }),
573
+ }).create();
574
+
575
+ // patch uitpas number
576
+ const arr: Body = new PatchableArray();
577
+
578
+ arr.addPatch(MemberWithRegistrationsBlob.patch({
579
+ id: member.id,
580
+ details: MemberDetails.patch({
581
+ uitpasNumberDetails: UitpasNumberDetails.patch({
582
+ // invalid (too short)
583
+ uitpasNumber: '094',
584
+ }),
585
+ }),
586
+ }));
587
+
588
+ const request = Request.buildJson('PATCH', baseUrl, organization.getApiHost(), arr);
589
+ request.headers.authorization = 'Bearer ' + token.accessToken;
590
+
591
+ await expect(testServer.test(endpoint, request))
592
+ .rejects
593
+ .toThrow(STExpect.errorWithCode('invalid_uitpas_number'));
594
+ });
595
+
596
+ describe('unknown uitpas number', () => {
597
+ test('Should throw if number changed', async () => {
598
+ initUitpasApi();
599
+
600
+ const organization = await new OrganizationFactory({ }).create();
601
+
602
+ const user = await new UserFactory({ }).create();
603
+
604
+ const token = await Token.createToken(user);
605
+
606
+ // create member
607
+ const member = await new MemberFactory({
608
+ firstName,
609
+ lastName,
610
+ birthDay,
611
+ generateData: false,
612
+ // Give user access to this member
613
+ user,
614
+ details: MemberDetails.create({
615
+ uitpasNumberDetails: UitpasNumberDetails.create({
616
+ // expired
617
+ uitpasNumber: '0900000095902',
618
+ socialTariff: UitpasSocialTariff.create({
619
+ status: UitpasSocialTariffStatus.None,
620
+ updatedAt: new Date(2030, 0, 1),
621
+ }),
622
+ }),
623
+ }),
624
+ }).create();
625
+
626
+ // patch uitpas number
627
+ const arr: Body = new PatchableArray();
628
+
629
+ arr.addPatch(MemberWithRegistrationsBlob.patch({
630
+ id: member.id,
631
+ details: MemberDetails.patch({
632
+ uitpasNumberDetails: UitpasNumberDetails.patch({
633
+ // unknown number
634
+ uitpasNumber: '0900000095999',
635
+ }),
636
+ }),
637
+ }));
638
+
639
+ const request = Request.buildJson('PATCH', baseUrl, organization.getApiHost(), arr);
640
+ request.headers.authorization = 'Bearer ' + token.accessToken;
641
+
642
+ await expect(testServer.test(endpoint, request))
643
+ .rejects
644
+ .toThrow(STExpect.errorWithCode('https://api.publiq.be/probs/uitpas/pass-not-found'));
645
+ });
646
+
647
+ test('Should throw and set status to unknown if number did not change', async () => {
648
+ initUitpasApi();
649
+
650
+ const organization = await new OrganizationFactory({ }).create();
651
+
652
+ const user = await new UserFactory({ }).create();
653
+
654
+ const token = await Token.createToken(user);
655
+
656
+ // create member
657
+ const member = await new MemberFactory({
658
+ firstName,
659
+ lastName,
660
+ birthDay,
661
+ generateData: false,
662
+ // Give user access to this member
663
+ user,
664
+ details: MemberDetails.create({
665
+ uitpasNumberDetails: UitpasNumberDetails.create({
666
+ // unknown number
667
+ uitpasNumber: '0900000095999',
668
+ socialTariff: UitpasSocialTariff.create({
669
+ status: UitpasSocialTariffStatus.None,
670
+ updatedAt: new Date(2030, 0, 1),
671
+ }),
672
+ }),
673
+ }),
674
+ }).create();
675
+
676
+ // patch uitpas number
677
+ const arr: Body = new PatchableArray();
678
+
679
+ arr.addPatch(MemberWithRegistrationsBlob.patch({
680
+ id: member.id,
681
+ details: MemberDetails.patch({
682
+ uitpasNumberDetails: UitpasNumberDetails.patch({
683
+ // same unknown number
684
+ uitpasNumber: '0900000095999',
685
+ }),
686
+ }),
687
+ }));
688
+
689
+ const request = Request.buildJson('PATCH', baseUrl, organization.getApiHost(), arr);
690
+ request.headers.authorization = 'Bearer ' + token.accessToken;
691
+
692
+ await expect(testServer.test(endpoint, request))
693
+ .rejects
694
+ .toThrow(STExpect.errorWithCode('https://api.publiq.be/probs/uitpas/pass-not-found'));
695
+
696
+ const updatedMember = await Member.getByID(member.id);
697
+ expect(updatedMember!.details.uitpasNumberDetails?.uitpasNumber).toEqual('0900000095999');
698
+ expect(updatedMember!.details.uitpasNumberDetails?.socialTariff?.status).toEqual(UitpasSocialTariffStatus.Unknown);
699
+ expect(updatedMember!.details.uitpasNumberDetails?.socialTariff?.updatedAt.getTime()).not.toEqual(new Date(2030, 0, 1).getTime());
700
+ expect(updatedMember!.details.uitpasNumberDetails?.socialTariff?.endDate).toBeNull();
701
+ });
702
+ });
703
+
704
+ describe('Should not set socialTariff from request', () => {
705
+ test('Only patch social tariff', async () => {
706
+ initUitpasApi();
707
+
708
+ const organization = await new OrganizationFactory({ }).create();
709
+
710
+ const user = await new UserFactory({ }).create();
711
+
712
+ const token = await Token.createToken(user);
713
+
714
+ // create member
715
+ const member = await new MemberFactory({
716
+ firstName,
717
+ lastName,
718
+ birthDay,
719
+ generateData: false,
720
+ // Give user access to this member
721
+ user,
722
+ details: MemberDetails.create({
723
+ uitpasNumberDetails: UitpasNumberDetails.create({
724
+ uitpasNumber: '0900000095902',
725
+ socialTariff: UitpasSocialTariff.create({
726
+ status: UitpasSocialTariffStatus.None,
727
+ updatedAt: new Date(2000, 0, 1),
728
+ }),
729
+ }),
730
+ }),
731
+ }).create();
732
+
733
+ // patch uitpas number
734
+ const arr: Body = new PatchableArray();
735
+
736
+ arr.addPatch(MemberWithRegistrationsBlob.patch({
737
+ id: member.id,
738
+ details: MemberDetails.patch({
739
+ uitpasNumberDetails: UitpasNumberDetails.patch({
740
+ socialTariff: UitpasSocialTariff.create({
741
+ status: UitpasSocialTariffStatus.Active,
742
+ endDate: new Date(2050, 0, 1),
743
+ updatedAt: new Date(2040, 0, 1),
744
+ }),
745
+ }),
746
+ }),
747
+ }));
748
+
749
+ const request = Request.buildJson('PATCH', baseUrl, organization.getApiHost(), arr);
750
+ request.headers.authorization = 'Bearer ' + token.accessToken;
751
+
752
+ const result = await testServer.test(endpoint, request);
753
+
754
+ expect(result.status).toBe(200);
755
+ expect(result.body.members.length).toBe(1);
756
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.status).toEqual(UitpasSocialTariffStatus.None);
757
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.updatedAt.getTime()).toEqual(new Date(2000, 0, 1).getTime());
758
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.endDate).toBeNull();
759
+ });
760
+
761
+ test('New uitpas number', async () => {
762
+ initUitpasApi();
763
+
764
+ const organization = await new OrganizationFactory({ }).create();
765
+
766
+ const user = await new UserFactory({ }).create();
767
+
768
+ const token = await Token.createToken(user);
769
+
770
+ // create member
771
+ const member = await new MemberFactory({
772
+ firstName,
773
+ lastName,
774
+ birthDay,
775
+ generateData: false,
776
+ // Give user access to this member
777
+ user,
778
+ details: MemberDetails.create({
779
+ uitpasNumberDetails: UitpasNumberDetails.create({
780
+ socialTariff: UitpasSocialTariff.create({
781
+ status: UitpasSocialTariffStatus.None,
782
+ updatedAt: new Date(2000, 0, 1),
783
+ }),
784
+ }),
785
+ }),
786
+ }).create();
787
+
788
+ // patch uitpas number
789
+ const arr: Body = new PatchableArray();
790
+
791
+ arr.addPatch(MemberWithRegistrationsBlob.patch({
792
+ id: member.id,
793
+ details: MemberDetails.patch({
794
+ uitpasNumberDetails: UitpasNumberDetails.patch({
795
+ // expired
796
+ uitpasNumber: '0900000031618',
797
+ socialTariff: UitpasSocialTariff.create({
798
+ status: UitpasSocialTariffStatus.Active,
799
+ endDate: new Date(2050, 0, 1),
800
+ updatedAt: new Date(2040, 0, 1),
801
+ }),
802
+ }),
803
+ }),
804
+ }));
805
+
806
+ const request = Request.buildJson('PATCH', baseUrl, organization.getApiHost(), arr);
807
+ request.headers.authorization = 'Bearer ' + token.accessToken;
808
+
809
+ const result = await testServer.test(endpoint, request);
810
+
811
+ expect(result.status).toBe(200);
812
+ expect(result.body.members.length).toBe(1);
813
+ expect(result.body.members[0].details.uitpasNumberDetails?.uitpasNumber).toEqual('0900000031618');
814
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.status).toEqual(UitpasSocialTariffStatus.Expired);
815
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.updatedAt.getTime()).not.toEqual(new Date(2040, 0, 1).getTime());
816
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.endDate?.getTime()).not.toEqual(new Date(2050, 0, 1).getTime());
817
+ });
818
+
819
+ test('Same uitpas number', async () => {
820
+ initUitpasApi();
821
+
822
+ const organization = await new OrganizationFactory({ }).create();
823
+
824
+ const user = await new UserFactory({ }).create();
825
+
826
+ const token = await Token.createToken(user);
827
+
828
+ // create member
829
+ const member = await new MemberFactory({
830
+ firstName,
831
+ lastName,
832
+ birthDay,
833
+ generateData: false,
834
+ // Give user access to this member
835
+ user,
836
+ details: MemberDetails.create({
837
+ uitpasNumberDetails: UitpasNumberDetails.create({
838
+ // expired
839
+ uitpasNumber: '0900000031618',
840
+ socialTariff: UitpasSocialTariff.create({
841
+ status: UitpasSocialTariffStatus.None,
842
+ updatedAt: new Date(2000, 0, 1),
843
+ }),
844
+ }),
845
+ }),
846
+ }).create();
847
+
848
+ // patch uitpas number
849
+ const arr: Body = new PatchableArray();
850
+
851
+ arr.addPatch(MemberWithRegistrationsBlob.patch({
852
+ id: member.id,
853
+ details: MemberDetails.patch({
854
+ uitpasNumberDetails: UitpasNumberDetails.patch({
855
+ // expired
856
+ uitpasNumber: '0900000031618',
857
+ socialTariff: UitpasSocialTariff.create({
858
+ status: UitpasSocialTariffStatus.Active,
859
+ endDate: new Date(2050, 0, 1),
860
+ updatedAt: new Date(2040, 0, 1),
861
+ }),
862
+ }),
863
+ }),
864
+ }));
865
+
866
+ const request = Request.buildJson('PATCH', baseUrl, organization.getApiHost(), arr);
867
+ request.headers.authorization = 'Bearer ' + token.accessToken;
868
+
869
+ const result = await testServer.test(endpoint, request);
870
+
871
+ expect(result.status).toBe(200);
872
+ expect(result.body.members.length).toBe(1);
873
+ expect(result.body.members[0].details.uitpasNumberDetails?.uitpasNumber).toEqual('0900000031618');
874
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.status).toEqual(UitpasSocialTariffStatus.Expired);
875
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.updatedAt.getTime()).not.toEqual(new Date(2000, 0, 1).getTime());
876
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.updatedAt.getTime()).not.toEqual(new Date(2040, 0, 1).getTime());
877
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.endDate?.getTime()).not.toEqual(new Date(2050, 0, 1).getTime());
878
+ });
879
+ });
880
+
881
+ test('Should not fail if uitpas api is down and number did not change', async () => {
882
+ const mocker = initUitpasApi();
883
+ mocker.forceFailure();
884
+
885
+ const organization = await new OrganizationFactory({ }).create();
886
+
887
+ const user = await new UserFactory({ }).create();
888
+
889
+ const token = await Token.createToken(user);
890
+
891
+ // create member
892
+ const member = await new MemberFactory({
893
+ firstName,
894
+ lastName,
895
+ birthDay,
896
+ generateData: false,
897
+ // Give user access to this member
898
+ user,
899
+ details: MemberDetails.create({
900
+ uitpasNumberDetails: UitpasNumberDetails.create({
901
+ // active
902
+ uitpasNumber: '0900011354819',
903
+ socialTariff: UitpasSocialTariff.create({
904
+ status: UitpasSocialTariffStatus.Active,
905
+ updatedAt: new Date(2000, 0, 1),
906
+ endDate: new Date(2050, 0, 1),
907
+ }),
908
+ }),
909
+ }),
910
+ }).create();
911
+
912
+ // patch uitpas number
913
+ const arr: Body = new PatchableArray();
914
+
915
+ arr.addPatch(MemberWithRegistrationsBlob.patch({
916
+ id: member.id,
917
+ details: MemberDetails.patch({
918
+ uitpasNumberDetails: UitpasNumberDetails.patch({
919
+ // same number
920
+ uitpasNumber: '0900011354819',
921
+ }),
922
+ }),
923
+ }));
924
+
925
+ const request = Request.buildJson('PATCH', baseUrl, organization.getApiHost(), arr);
926
+ request.headers.authorization = 'Bearer ' + token.accessToken;
927
+
928
+ const result = await testServer.test(endpoint, request);
929
+
930
+ expect(result.status).toBe(200);
931
+ expect(result.body.members.length).toBe(1);
932
+ expect(result.body.members[0].details.uitpasNumberDetails?.uitpasNumber).toEqual('0900011354819');
933
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.status).toEqual(UitpasSocialTariffStatus.Active);
934
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.updatedAt.getTime()).toEqual(new Date(2000, 0, 1).getTime());
935
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.endDate?.getTime()).toEqual(new Date(2050, 0, 1).getTime());
936
+ });
937
+
938
+ test('Should remove memberDetails if member details null', async () => {
939
+ const organization = await new OrganizationFactory({ }).create();
940
+
941
+ const user = await new UserFactory({ }).create();
942
+
943
+ const token = await Token.createToken(user);
944
+
945
+ // create member
946
+ const member = await new MemberFactory({
947
+ firstName,
948
+ lastName,
949
+ birthDay,
950
+ generateData: false,
951
+ // Give user access to this member
952
+ user,
953
+ details: MemberDetails.create({
954
+ uitpasNumberDetails: UitpasNumberDetails.create({
955
+ // expired
956
+ uitpasNumber: '0900000095902',
957
+ socialTariff: UitpasSocialTariff.create({
958
+ status: UitpasSocialTariffStatus.None,
959
+ updatedAt: new Date(2030, 0, 1),
960
+ }),
961
+ }),
962
+ }),
963
+ }).create();
964
+
965
+ // patch uitpas number
966
+ const arr: Body = new PatchableArray();
967
+
968
+ arr.addPatch(MemberWithRegistrationsBlob.patch({
969
+ id: member.id,
970
+ details: MemberDetails.patch({
971
+ uitpasNumberDetails: null,
972
+ }),
973
+ }));
974
+
975
+ const request = Request.buildJson('PATCH', baseUrl, organization.getApiHost(), arr);
976
+ request.headers.authorization = 'Bearer ' + token.accessToken;
977
+
978
+ const result = await testServer.test(endpoint, request);
979
+
980
+ expect(result.status).toBe(200);
981
+ expect(result.body.members.length).toBe(1);
982
+ expect(result.body.members[0].details.uitpasNumberDetails).toBeNull();
983
+ });
984
+
985
+ test('Should update social tariff if uitpas review changed', async () => {
986
+ initUitpasApi();
987
+ const organization = await new OrganizationFactory({ }).create();
988
+
989
+ const user = await new UserFactory({ }).create();
990
+
991
+ const token = await Token.createToken(user);
992
+
993
+ // create member
994
+ const member = await new MemberFactory({
995
+ firstName,
996
+ lastName,
997
+ birthDay,
998
+ generateData: false,
999
+ // Give user access to this member
1000
+ user,
1001
+ details: MemberDetails.create({
1002
+ uitpasNumberDetails: UitpasNumberDetails.create({
1003
+ // expired (but active on last check)
1004
+ uitpasNumber: '0900000031618',
1005
+ socialTariff: UitpasSocialTariff.create({
1006
+ status: UitpasSocialTariffStatus.Active,
1007
+ updatedAt: new Date(2020, 0, 1),
1008
+ endDate: new Date(2050, 0, 1),
1009
+ }),
1010
+ }),
1011
+ }),
1012
+ }).create();
1013
+
1014
+ // set uitpas review
1015
+ member.details.reviewTimes.markReviewed('uitpasNumber', new Date(2020, 0, 1));
1016
+ await member.save();
1017
+
1018
+ // patch uitpas number review
1019
+ const arr: Body = new PatchableArray();
1020
+
1021
+ const timesClone = member.details.reviewTimes.clone();
1022
+ timesClone.markReviewed('uitpasNumber', new Date(2020, 0, 2));
1023
+
1024
+ arr.addPatch(MemberWithRegistrationsBlob.patch({
1025
+ id: member.id,
1026
+ details: MemberDetails.patch({
1027
+ reviewTimes: timesClone,
1028
+ }),
1029
+ }));
1030
+
1031
+ const request = Request.buildJson('PATCH', baseUrl, organization.getApiHost(), arr);
1032
+ request.headers.authorization = 'Bearer ' + token.accessToken;
1033
+
1034
+ const result = await testServer.test(endpoint, request);
1035
+
1036
+ expect(result.status).toBe(200);
1037
+ expect(result.body.members.length).toBe(1);
1038
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.status).toEqual(UitpasSocialTariffStatus.Expired);
1039
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.updatedAt.getTime()).not.toEqual(new Date(2020, 0, 1).getTime());
1040
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.endDate?.getTime()).not.toEqual(new Date(2050, 0, 1).getTime());
1041
+ });
1042
+
1043
+ test('Should update social tariff if uitpas review patched with same date', async () => {
1044
+ initUitpasApi();
1045
+ const organization = await new OrganizationFactory({ }).create();
1046
+
1047
+ const user = await new UserFactory({ }).create();
1048
+
1049
+ const token = await Token.createToken(user);
1050
+
1051
+ // create member
1052
+ const member = await new MemberFactory({
1053
+ firstName,
1054
+ lastName,
1055
+ birthDay,
1056
+ generateData: false,
1057
+ // Give user access to this member
1058
+ user,
1059
+ details: MemberDetails.create({
1060
+ uitpasNumberDetails: UitpasNumberDetails.create({
1061
+ // expired (but active on last check)
1062
+ uitpasNumber: '0900000031618',
1063
+ socialTariff: UitpasSocialTariff.create({
1064
+ status: UitpasSocialTariffStatus.Active,
1065
+ updatedAt: new Date(2020, 0, 1),
1066
+ endDate: new Date(2050, 0, 1),
1067
+ }),
1068
+ }),
1069
+ }),
1070
+ }).create();
1071
+
1072
+ // set uitpas review
1073
+ member.details.reviewTimes.markReviewed('uitpasNumber', new Date(2020, 0, 1));
1074
+ await member.save();
1075
+
1076
+ // patch uitpas number review
1077
+ const arr: Body = new PatchableArray();
1078
+
1079
+ const timesClone = member.details.reviewTimes.clone();
1080
+ timesClone.markReviewed('uitpasNumber', new Date(2020, 0, 1));
1081
+
1082
+ arr.addPatch(MemberWithRegistrationsBlob.patch({
1083
+ id: member.id,
1084
+ details: MemberDetails.patch({
1085
+ reviewTimes: timesClone,
1086
+ }),
1087
+ }));
1088
+
1089
+ const request = Request.buildJson('PATCH', baseUrl, organization.getApiHost(), arr);
1090
+ request.headers.authorization = 'Bearer ' + token.accessToken;
1091
+
1092
+ const result = await testServer.test(endpoint, request);
1093
+
1094
+ expect(result.status).toBe(200);
1095
+ expect(result.body.members.length).toBe(1);
1096
+ expect(result.body.members[0].details.uitpasNumberDetails?.socialTariff?.status).toEqual(UitpasSocialTariffStatus.Active);
1097
+ });
1098
+ });
1099
+ });
443
1100
  });