hl-core 0.0.7-beta.19 → 0.0.7-beta.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/api/index.ts CHANGED
@@ -496,7 +496,7 @@ export class ApiClass {
496
496
  });
497
497
  }
498
498
 
499
- async getContragentFromGBDFL(data: any) {
499
+ async getContragentFromGBDFL(data: { iin: string; phoneNumber: string }): Promise<GBDFLResponse> {
500
500
  return this.axiosCall({
501
501
  method: Methods.POST,
502
502
  url: '/externalservices/api/ExternalServices/GetGbdflToken',
@@ -504,6 +504,14 @@ export class ApiClass {
504
504
  });
505
505
  }
506
506
 
507
+ async getFamilyInfo(data: { iin: string; phoneNumber: string }): Promise<FamilyInfoGKB> {
508
+ return this.axiosCall({
509
+ method: Methods.POST,
510
+ url: '/externalservices/api/ExternalServices/GetFamilyInfoToken',
511
+ data: data,
512
+ });
513
+ }
514
+
507
515
  async getProcessTariff(code: number | string = 5) {
508
516
  return this.axiosCall({ url: `/arm/api/Dictionary/ProcessTariff/${code}` });
509
517
  }
@@ -27,9 +27,9 @@ export default function (axios: AxiosInstance) {
27
27
  dataStore.sendToParent(constants.postActions.Error401, 401);
28
28
  }
29
29
  }
30
- if (error.response.status === 500) {
30
+ if (error.response.status >= 500) {
31
31
  if (router.currentRoute.value.name !== 'Auth') {
32
- router.push({ name: '500', query: { stack: error.stack } });
32
+ dataStore.showToaster('error', error.stack, 5000);
33
33
  }
34
34
  }
35
35
  return Promise.reject(error);
@@ -9,10 +9,6 @@
9
9
  <slot v-if="!subtitle" name="subtitle"></slot>
10
10
  {{ subtitle }}
11
11
  </v-card-subtitle>
12
- <v-card-text>
13
- <slot v-if="text" name="content"></slot>
14
- {{ text }}
15
- </v-card-text>
16
12
  <v-card-actions class="gap-[16px]">
17
13
  <base-btn v-if="actions === 'default'" class="!w-fit px-6" size="sm" :text="$t('confirm.yes')" :btn="$libStyles.blueBtn" @click="$emit('yes')"></base-btn>
18
14
  <base-btn v-if="actions === 'default'" class="!w-fit px-6" size="sm" :text="$t('confirm.no')" :btn="$libStyles.blueBtn" @click="$emit('no')" />
@@ -37,10 +33,6 @@ export default defineComponent({
37
33
  type: String,
38
34
  default: '',
39
35
  },
40
- text: {
41
- type: String,
42
- default: '',
43
- },
44
36
  actions: {
45
37
  type: String,
46
38
  default: 'default',
@@ -0,0 +1,39 @@
1
+ <template>
2
+ <v-list lines="two" v-if="formStore.birthInfos && formStore.birthInfos.length" class="w-full !py-0">
3
+ <v-list-item @click="$emit('reset')" :append-icon="selected && Object.keys(selected).length === 0 ? `mdi-radiobox-marked ${$libStyles.greenText}` : 'mdi-radiobox-blank text-[#636363]'">
4
+ <v-list-item-title :class="[$libStyles.greenText, $libStyles.textTitle]">{{ $t('form.notChosen') }}</v-list-item-title>
5
+ </v-list-item>
6
+ <v-list-item
7
+ v-for="familyMember of formStore.birthInfos"
8
+ :key="familyMember.childIIN"
9
+ @click="$emit('selectFamilyMember', familyMember)"
10
+ :append-icon="familyMember && selected && selected.childIIN === familyMember.childIIN ? `mdi-radiobox-marked ${$libStyles.greenText}` : 'mdi-radiobox-blank text-[#636363]'"
11
+ >
12
+ <v-list-item-title :class="[$libStyles.greenText, $libStyles.textTitle]">{{
13
+ `${familyMember.childSurName} ${familyMember.childName} ${familyMember.childPatronymic ? familyMember.childPatronymic : ''}`
14
+ }}</v-list-item-title>
15
+ <v-list-item-subtitle :class="[$libStyles.textSimple]"
16
+ ><span>{{ `${$t('form.iin')}:` }}</span
17
+ >{{ ` ${$reformatIin(familyMember.childIIN!)}` }}</v-list-item-subtitle
18
+ >
19
+ </v-list-item>
20
+ </v-list>
21
+ <base-list-empty class="w-full" v-else></base-list-empty>
22
+ </template>
23
+
24
+ <script lang="ts">
25
+ export default defineComponent({
26
+ props: {
27
+ selected: {
28
+ type: Object as PropType<BirthInfoGKB>,
29
+ },
30
+ },
31
+ emits: ['selectFamilyMember', 'reset'],
32
+ setup() {
33
+ const formStore = useFormStore();
34
+ return {
35
+ formStore,
36
+ };
37
+ },
38
+ });
39
+ </script>
@@ -84,7 +84,7 @@ export default defineComponent({
84
84
  const memberStore = useMemberStore();
85
85
  const multipleMembers = ['insuredForm', 'beneficiaryForm', 'beneficialOwnerForm'];
86
86
  const isMultiple = ref(multipleMembers.includes(props.whichForm));
87
- const member = formStore[props.whichForm as keyof typeof formStore];
87
+ const member: Member = formStore[props.whichForm as MemberKeys];
88
88
 
89
89
  const getMemberInfo = (memberData: Member) => {
90
90
  return {
@@ -8,7 +8,7 @@
8
8
  :maska="$maska.iin"
9
9
  :readonly="isDisabled || isIinPhoneDisabled"
10
10
  :clearable="!isDisabled"
11
- append-inner-icon="mdi mdi-magnify"
11
+ :append-inner-icon="showSaveButton ? 'mdi mdi-magnify' : ''"
12
12
  @append="searchMember"
13
13
  :rules="$rules.required.concat($rules.iinRight)"
14
14
  ></base-form-input>
@@ -21,7 +21,7 @@
21
21
  :append-inner-icon="otpCondition ? 'mdi mdi-phone-message' : ''"
22
22
  @append="sendOtp(false)"
23
23
  @keyup.enter.prevent="otpCondition ? sendOtp(false) : null"
24
- :rules="$rules.required.concat($rules.phoneFormat)"
24
+ :rules="phoneRule"
25
25
  ></base-form-input>
26
26
  <base-fade-transition>
27
27
  <base-form-input
@@ -63,13 +63,7 @@
63
63
  :maska="$maska.date"
64
64
  append-inner-icon="mdi mdi-calendar-blank-outline"
65
65
  ></base-form-input>
66
- <base-form-input
67
- v-model="member.age"
68
- :label="$t('form.age')"
69
- :readonly="isDisabled || isFromGBD"
70
- :clearable="!isDisabled"
71
- :rules="$rules.required.concat($rules.numbers)"
72
- ></base-form-input>
66
+ <base-form-input v-model="member.age" :label="$t('form.age')" :readonly="isDisabled || isFromGBD" :clearable="!isDisabled" :rules="ageRule"></base-form-input>
73
67
  <base-panel-input
74
68
  v-model="member.gender"
75
69
  :value="member.gender.nameRu"
@@ -475,8 +469,9 @@
475
469
  </Teleport>
476
470
  <Teleport v-if="isSearchOpen" to="#panel-actions">
477
471
  <div :class="[$libStyles.flexColNav]">
478
- <base-btn v-if="$dataStore.controls.hasGBDFL" :loading="isButtonLoading" :text="$t('buttons.fromGBDFL')" @click="getContragentFromGBDFL"></base-btn>
479
- <base-btn v-if="$dataStore.controls.hasInsis" :loading="isButtonLoading" :text="$t('buttons.fromInsis')" @click="getContragent"></base-btn>
472
+ <base-btn v-if="hasGBDFL" :loading="isButtonLoading" :text="$t('buttons.fromGBDFL')" @click="getContragentFromGBDFL"></base-btn>
473
+ <base-btn v-if="hasInsis" :loading="isButtonLoading" :text="$t('buttons.fromInsis')" @click="getContragent"></base-btn>
474
+ <base-btn v-if="hasGKB" :loading="isButtonLoading" :text="$t('buttons.fromGKB')" @click="getFamilyInfo"></base-btn>
480
475
  </div>
481
476
  </Teleport>
482
477
  <Teleport v-if="isDocumentOpen" to="#panel-actions">
@@ -485,6 +480,11 @@
485
480
  <base-btn :disabled="documentLoading" :loading="documentLoading" text="Скачать" @click="getFile('download')"></base-btn>
486
481
  </div>
487
482
  </Teleport>
483
+ <base-dialog v-model="familyDialog" :title="$t('dialog.familyMember')" actions="familyDialog">
484
+ <template #actions>
485
+ <base-family-dialog :selected="selectedFamilyMember" @selectFamilyMember="selectFamilyMember" @reset="closeFamilyDialog(true)"></base-family-dialog>
486
+ </template>
487
+ </base-dialog>
488
488
  </section>
489
489
  </template>
490
490
 
@@ -502,8 +502,9 @@ export default {
502
502
  const formStore = useFormStore();
503
503
  const memberStore = useMemberStore();
504
504
  const getMember = (whichForm: LocationQueryValue | LocationQueryValue[], whichIndex?: LocationQueryValue | LocationQueryValue[]) =>
505
- memberStore.getMemberFromStore(whichForm as keyof typeof formStore, Number((whichIndex ? whichIndex : '0') as string))!;
505
+ memberStore.getMemberFromStore(whichForm as MemberKeys, Number((whichIndex ? whichIndex : '0') as string))!;
506
506
  const member = ref(getMember(route.query.tab, route.query.i));
507
+ const selectedFamilyMember = ref<BirthInfoGKB>({});
507
508
  const isPanelOpen = ref<boolean>(false);
508
509
  const memberDocument = ref<DocumentItem>();
509
510
  const isButtonLoading = ref<boolean>(false);
@@ -512,6 +513,7 @@ export default {
512
513
  const isSearchOpen = ref<boolean>(false);
513
514
  const isDocumentOpen = ref<boolean>(false);
514
515
  const isPanelLoading = ref<boolean>(false);
516
+ const familyDialog = ref<boolean>(false);
515
517
  const panelValue = ref<Value>(new Value());
516
518
  const panelList = ref<Value[]>([]);
517
519
  const currentPanel = ref<keyof typeof member.value>();
@@ -543,6 +545,67 @@ export default {
543
545
  return generalCondition && perMemberCondtion();
544
546
  });
545
547
 
548
+ const hasGBDFL = computed(() => dataStore.controls.hasGBDFL && !hasGKB.value);
549
+ const hasInsis = computed(() => dataStore.controls.hasInsis);
550
+ const hasGKB = computed(() => {
551
+ const byProductCondition = dataStore.isGons || dataStore.isBolashak;
552
+ const perMemberCondition = () => {
553
+ switch (whichForm.value) {
554
+ case formStore.beneficiaryFormKey:
555
+ return member.value.id === 0;
556
+ case formStore.policyholderFormKey:
557
+ case formStore.insuredFormKey:
558
+ case formStore.beneficialOwnerFormKey:
559
+ case formStore.policyholdersRepresentativeFormKey:
560
+ return false;
561
+ default:
562
+ return false;
563
+ }
564
+ };
565
+ return dataStore.controls.hasGKB && !!dataStore.isTask() && byProductCondition && perMemberCondition();
566
+ });
567
+
568
+ const ageRule = computed(() => {
569
+ const baseAgeRule = dataStore.rules.required.concat(dataStore.rules.numbers);
570
+ const byMemberAndProductRule = () => {
571
+ switch (whichForm.value) {
572
+ case formStore.policyholderFormKey: {
573
+ if (dataStore.isGons || dataStore.isBolashak) {
574
+ return dataStore.rules.policyholderAgeLimit;
575
+ } else {
576
+ return [];
577
+ }
578
+ }
579
+ case formStore.beneficiaryFormKey: {
580
+ if (dataStore.isGons || dataStore.isBolashak) {
581
+ return dataStore.rules.beneficiaryAgeLimit;
582
+ } else {
583
+ return [];
584
+ }
585
+ }
586
+ default:
587
+ return [];
588
+ }
589
+ };
590
+ return baseAgeRule.concat(byMemberAndProductRule());
591
+ });
592
+
593
+ const phoneRule = computed(() => {
594
+ const basePhoneRule = dataStore.rules.required.concat(dataStore.rules.phoneFormat);
595
+ const byMemberAndProductRule = () => {
596
+ switch (whichForm.value) {
597
+ case formStore.beneficiaryFormKey: {
598
+ if (dataStore.isGons || dataStore.isBolashak) {
599
+ return [];
600
+ }
601
+ }
602
+ default:
603
+ return basePhoneRule;
604
+ }
605
+ };
606
+ return byMemberAndProductRule();
607
+ });
608
+
546
609
  const getOtpConditionByMember = () => {
547
610
  switch (whichForm.value) {
548
611
  case formStore.policyholderFormKey:
@@ -668,37 +731,86 @@ export default {
668
731
  }
669
732
  };
670
733
 
734
+ const getFamilyInfo = async () => {
735
+ if (formStore.birthInfos.length === 0) {
736
+ isButtonLoading.value = true;
737
+ await dataStore.getFamilyInfo(formStore.policyholderForm.iin, formStore.policyholderForm.phoneNumber);
738
+ if (formStore.birthInfos.length !== 0) {
739
+ familyDialog.value = true;
740
+ }
741
+ } else {
742
+ familyDialog.value = true;
743
+ }
744
+ isButtonLoading.value = false;
745
+ };
746
+
747
+ const closeFamilyDialog = (resetMember = false) => {
748
+ if (resetMember === true) {
749
+ member.value.resetMember();
750
+ }
751
+ familyDialog.value = false;
752
+ selectedFamilyMember.value = {};
753
+ isButtonLoading.value = false;
754
+ dataStore.panel.open = false;
755
+ isSearchOpen.value = false;
756
+ };
757
+
758
+ const selectFamilyMember = (familyMember: BirthInfoGKB) => {
759
+ if (selectedFamilyMember.value && selectedFamilyMember.value.childIIN === familyMember.childIIN) {
760
+ selectedFamilyMember.value = {};
761
+ } else {
762
+ selectedFamilyMember.value = familyMember;
763
+ member.value.iin = reformatIin(selectedFamilyMember.value.childIIN!);
764
+ member.value.firstName = selectedFamilyMember.value.childName!;
765
+ member.value.lastName = selectedFamilyMember.value.childSurName!;
766
+ member.value.middleName = selectedFamilyMember.value.childPatronymic ?? '';
767
+ member.value.birthDate = reformatDate(selectedFamilyMember.value.childBirthDate!);
768
+ }
769
+ familyDialog.value = false;
770
+ isButtonLoading.value = false;
771
+ dataStore.panel.open = false;
772
+ isSearchOpen.value = false;
773
+ };
774
+
671
775
  const getContragentFromGBDFL = async () => {
672
776
  if (member.value.hasAgreement === false) {
673
777
  dataStore.showToaster('error', dataStore.t('toaster.needAgreement'), 3000);
778
+ dataStore.panel.open = false;
779
+ isSearchOpen.value = false;
674
780
  return;
675
781
  }
676
782
  if (!member.value.iin || member.value.iin.length !== useMask().iin.length || !member.value.phoneNumber || member.value.phoneNumber.length !== useMask().phone.length) {
677
783
  dataStore.showToaster('error', dataStore.t('toaster.errorFormField').replace('{text}', 'Номер телефона, ИИН'), 5000);
784
+ dataStore.panel.open = false;
785
+ isSearchOpen.value = false;
678
786
  return;
679
787
  }
680
788
  isButtonLoading.value = true;
681
789
  await dataStore.getContragentFromGBDFL(member.value.iin, member.value.phoneNumber, whichForm.value, whichIndex.value ? Number(whichIndex.value) : null);
682
790
  member.value.gotFromInsis = true;
683
- isSearchOpen.value = false;
684
- dataStore.panel.open = false;
685
791
  isButtonLoading.value = false;
792
+ dataStore.panel.open = false;
793
+ isSearchOpen.value = false;
686
794
  };
687
795
 
688
796
  const getContragent = async () => {
689
797
  if (member.value.hasAgreement === false) {
690
798
  dataStore.showToaster('error', dataStore.t('toaster.needAgreement'), 3000);
799
+ dataStore.panel.open = false;
800
+ isSearchOpen.value = false;
691
801
  return;
692
802
  }
693
803
  if (!member.value.iin || member.value.iin.length !== useMask().iin.length) {
694
804
  dataStore.showToaster('error', dataStore.t('toaster.errorFormField').replace('{text}', 'ИИН'), 5000);
805
+ dataStore.panel.open = false;
806
+ isSearchOpen.value = false;
695
807
  return;
696
808
  }
697
809
  isButtonLoading.value = true;
698
810
  await dataStore.getContragent(member.value, whichForm.value, whichIndex.value, false);
699
- isSearchOpen.value = false;
700
- dataStore.panel.open = false;
701
811
  isButtonLoading.value = false;
812
+ dataStore.panel.open = false;
813
+ isSearchOpen.value = false;
702
814
  };
703
815
 
704
816
  const validateESBD = async (docTypeNumber: number) => {
@@ -756,15 +868,15 @@ export default {
756
868
  await uploadFile(formStore.applicationData.processInstanceId);
757
869
  }
758
870
  }
759
- const memberFromApplicaiton = memberStore.getMemberFromApplication(whichForm.value as keyof typeof formStore, whichIndex.value ? Number(whichIndex.value) : undefined);
760
- const isSaved = await dataStore.saveMember(member.value, memberStore.getMemberCode(whichForm.value as keyof typeof formStore), memberFromApplicaiton);
871
+ const memberFromApplicaiton = memberStore.getMemberFromApplication(whichForm.value as MemberKeys, whichIndex.value ? Number(whichIndex.value) : undefined);
872
+ const isSaved = await dataStore.saveMember(member.value, memberStore.getMemberCode(whichForm.value as MemberKeys), memberFromApplicaiton);
761
873
  if (!isSaved) return false;
762
874
  if (whichForm.value === formStore.policyholderFormKey && isInsured === true) {
763
875
  formStore.insuredForm[0] = formStore.policyholderForm;
764
876
  const isInsuredSaved = await dataStore.saveMember(
765
877
  member.value,
766
- memberStore.getMemberCode(formStore.insuredFormKey as keyof typeof formStore),
767
- memberStore.getMemberFromApplication(formStore.insuredFormKey as keyof typeof formStore, formStore.insuredFormIndex),
878
+ memberStore.getMemberCode(formStore.insuredFormKey as MemberKeys),
879
+ memberStore.getMemberFromApplication(formStore.insuredFormKey as MemberKeys, formStore.insuredFormIndex),
768
880
  );
769
881
  if (!isInsuredSaved) return false;
770
882
  }
@@ -789,11 +901,23 @@ export default {
789
901
  vForm.value.scrollTo({ top: 0, behavior: 'smooth' });
790
902
  };
791
903
 
792
- const submitForm = async () => {
904
+ const validateAgreement = () => {
905
+ if (dataStore.isGons || dataStore.isBolashak) {
906
+ if (whichForm.value === formStore.beneficiaryFormKey) {
907
+ // TODO уточнить
908
+ return true;
909
+ }
910
+ }
793
911
  if (member.value.hasAgreement === false) {
794
912
  dataStore.showToaster('error', dataStore.t('toaster.needAgreement'));
795
- return;
913
+ return false;
796
914
  }
915
+ return true;
916
+ };
917
+
918
+ const submitForm = async () => {
919
+ const agreementValidated = validateAgreement();
920
+ if (!agreementValidated) return;
797
921
  await vForm.value.validate().then(async (v: { valid: Boolean; errors: any }) => {
798
922
  if (v.valid) {
799
923
  isSubmittingForm.value = true;
@@ -844,7 +968,7 @@ export default {
844
968
  };
845
969
 
846
970
  const checkOtp = async () => {
847
- if (!member.value.otpCode || member.value.iin?.length !== useMask().iin.length || member.value.phoneNumber?.length !== useMask().phone.length ) {
971
+ if (!member.value.otpCode || member.value.iin?.length !== useMask().iin.length || member.value.phoneNumber?.length !== useMask().phone.length) {
848
972
  dataStore.showToaster('error', dataStore.t('toaster.errorFormField').replace('{text}', dataStore.t('form.otpCode')), 3000);
849
973
  return;
850
974
  }
@@ -967,6 +1091,8 @@ export default {
967
1091
  searchQuery,
968
1092
  Value,
969
1093
  memberDocument,
1094
+ familyDialog,
1095
+ selectedFamilyMember,
970
1096
 
971
1097
  // Computed
972
1098
  whichForm,
@@ -978,6 +1104,12 @@ export default {
978
1104
  isIinPhoneDisabled,
979
1105
  isFromGBD,
980
1106
  showSaveButton,
1107
+ hasGBDFL,
1108
+ hasInsis,
1109
+ hasGKB,
1110
+ // Rules
1111
+ ageRule,
1112
+ phoneRule,
981
1113
 
982
1114
  // Functions
983
1115
  searchMember,
@@ -987,10 +1119,13 @@ export default {
987
1119
  submitForm,
988
1120
  checkOtp,
989
1121
  sendOtp,
1122
+ getFamilyInfo,
990
1123
  getContragentFromGBDFL,
991
1124
  getContragent,
992
1125
  attachFile,
993
1126
  getFile,
1127
+ selectFamilyMember,
1128
+ closeFamilyDialog,
994
1129
  };
995
1130
  },
996
1131
  };
@@ -20,6 +20,7 @@
20
20
  <base-menu-nav-item
21
21
  :menu-item="item"
22
22
  :selected="!!selected.title && !!item.title && selected.title === item.title"
23
+ :disabled="typeof item.disabled === 'boolean' ? item.disabled : false"
23
24
  @click.left="pickItem(item)"
24
25
  @click.middle="openTab(item)"
25
26
  >
@@ -1,6 +1,12 @@
1
1
  <template>
2
2
  <div
3
- :class="[selected ? $libStyles.blueBg : $libStyles.blueBgLight, selected ? $libStyles.whiteText : $libStyles.blackText, $libStyles.rounded, $libStyles.textSimple]"
3
+ :class="[
4
+ selected ? $libStyles.blueBg : $libStyles.blueBgLight,
5
+ selected ? $libStyles.whiteText : $libStyles.blackText,
6
+ $libStyles.rounded,
7
+ $libStyles.textSimple,
8
+ disabled ? 'cursor-not-allowed opacity-50' : '',
9
+ ]"
4
10
  class="h-[60px] flex items-center justify-between hover:bg-[#A0B3D8] hover:!text-white pl-4 cursor-pointer transition-all"
5
11
  >
6
12
  <span>{{ menuItem.title }}</span>
@@ -22,6 +28,10 @@ export default defineComponent({
22
28
  type: Boolean,
23
29
  default: false,
24
30
  },
31
+ disabled: {
32
+ type: Boolean,
33
+ default: false,
34
+ },
25
35
  },
26
36
  });
27
37
  </script>
@@ -218,7 +218,7 @@ class Person {
218
218
  this.registrationDate = new Date(Date.now() - new Date().getTimezoneOffset() * 60 * 1000).toISOString().slice(0, -1);
219
219
  }
220
220
 
221
- resetPerson(clearIinAndPhone = true) {
221
+ resetPerson(clearIinAndPhone: boolean = true) {
222
222
  this.id = 0;
223
223
  this.type = 1;
224
224
  if (clearIinAndPhone === true) {
@@ -553,7 +553,7 @@ export class Member extends Person {
553
553
  this.hasAgreement = null;
554
554
  }
555
555
 
556
- resetForm(clearIinAndPhone = true) {
556
+ resetMember(clearIinAndPhone: boolean = true) {
557
557
  super.resetPerson(clearIinAndPhone);
558
558
  this.job = null;
559
559
  this.jobPosition = null;
@@ -771,6 +771,8 @@ export class DataStoreClass {
771
771
  onAuth: boolean;
772
772
  // Подтягивание с ГБДФЛ
773
773
  hasGBDFL: boolean;
774
+ // Подтягивание с ГКБ
775
+ hasGKB: boolean;
774
776
  // Подтягивание с ИНСИС
775
777
  hasInsis: boolean;
776
778
  // Калькулятор без ввода данных
@@ -872,6 +874,7 @@ export class DataStoreClass {
872
874
  this.controls = {
873
875
  onAuth: false,
874
876
  hasGBDFL: true,
877
+ hasGKB: false,
875
878
  hasInsis: false,
876
879
  hasCalculator: false,
877
880
  };
@@ -1003,7 +1006,7 @@ export class DataStoreClass {
1003
1006
  }
1004
1007
 
1005
1008
  export class FormStoreClass {
1006
- birthInfos: any[];
1009
+ birthInfos: BirthInfoGKB[];
1007
1010
  SaleChanellPolicy: Value;
1008
1011
  AgentData: {
1009
1012
  agentId: null;
@@ -90,6 +90,13 @@ export const getKeyWithPattern = (obj: any, key: string) => {
90
90
  return Object.keys(obj).find(i => i.match(new RegExp(key, 'i'))) || null;
91
91
  };
92
92
 
93
+ export const getAgeByBirthDate = (rawDate: string) => {
94
+ const age = Math.abs(new Date(Date.now() - new Date(rawDate).getTime()).getUTCFullYear() - 1970);
95
+ if (new Date(rawDate) < new Date(Date.now()) && age >= 0) {
96
+ return age;
97
+ }
98
+ };
99
+
93
100
  export const getFullNameShorted = (text: string | null, fromWhichWord: number = 1) => {
94
101
  if (text) {
95
102
  const names = text.split(' ');
@@ -21,6 +21,9 @@ export class Styles {
21
21
  greenText: string = 'text-[#009C73]';
22
22
  greenTextHover: string = 'hover:text-[#009C73]';
23
23
 
24
+ // Yellow
25
+ yellowText: string = 'text-[#FAB31C]';
26
+
24
27
  // Grey
25
28
  greyBg: string = 'bg-[#B8B8B8]';
26
29
  greyText: string = 'text-[#B8B8B8]';
package/nuxt.config.ts CHANGED
@@ -10,6 +10,9 @@ export default defineNuxtConfig({
10
10
  },
11
11
 
12
12
  vite: {
13
+ build: {
14
+ minify: false,
15
+ },
13
16
  resolve: {
14
17
  alias: [
15
18
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hl-core",
3
- "version": "0.0.7-beta.19",
3
+ "version": "0.0.7-beta.20",
4
4
  "license": "MIT",
5
5
  "private": false,
6
6
  "main": "nuxt.config.ts",
@@ -12,6 +12,7 @@
12
12
  "components/",
13
13
  "plugins/",
14
14
  "pages/",
15
+ "types/",
15
16
  "nuxt.config.ts",
16
17
  "tailwind.config.js",
17
18
  ".prettierrc"
@@ -2,7 +2,7 @@ import { defineStore } from 'pinia';
2
2
  import { t } from './messages';
3
3
  import { rules } from './rules';
4
4
  import { Toast, Types, Positions, ToastOptions } from './toast';
5
- import { isValidGUID, yearEnding, jwtDecode, ErrorHandler, getKeyWithPattern, getNumber } from '../composables';
5
+ import { isValidGUID, yearEnding, jwtDecode, ErrorHandler, getKeyWithPattern, getNumber, getAgeByBirthDate } from '../composables';
6
6
  import { DataStoreClass, Contragent } from '../composables/classes';
7
7
  import { ApiClass } from '@/api';
8
8
  import { useFormStore } from './form.store';
@@ -16,7 +16,6 @@ export const useDataStore = defineStore('data', {
16
16
  toastTypes: Types,
17
17
  toastPositions: Positions,
18
18
  isValidGUID: isValidGUID,
19
- route: useRoute(),
20
19
  router: useRouter(),
21
20
  formStore: useFormStore(),
22
21
  contragent: useContragentStore(),
@@ -2098,6 +2097,45 @@ export const useDataStore = defineStore('data', {
2098
2097
  this.isLoading = false;
2099
2098
  return false;
2100
2099
  },
2100
+ async getFamilyInfo(iin, phoneNumber) {
2101
+ this.isLoading = true;
2102
+ try {
2103
+ const familyResponse = await this.api.getFamilyInfo({ iin: iin.replace(/-/g, ''), phoneNumber: formatPhone(phoneNumber) });
2104
+ if (familyResponse.status === 'PENDING') {
2105
+ this.showToaster('success', this.t('toaster.waitForClient'), 5000);
2106
+ this.isLoading = false;
2107
+ return;
2108
+ }
2109
+ if (constants.gbdErrors.find(i => i === familyResponse.status)) {
2110
+ if (familyResponse.status === 'TIMEOUT') {
2111
+ this.showToaster('success', `${familyResponse.statusName}. Отправьте запрос еще раз`, 5000);
2112
+ } else {
2113
+ this.showToaster('error', familyResponse.statusName, 5000);
2114
+ }
2115
+ this.isLoading = false;
2116
+ return;
2117
+ }
2118
+ if (familyResponse.infoList && familyResponse.infoList.birthInfos && familyResponse.infoList.birthInfos.length) {
2119
+ const filteredBirthInfos = familyResponse.infoList.birthInfos.filter(
2120
+ member => member.childBirthDate && getAgeByBirthDate(member.childBirthDate) <= 15 && typeof member.childLifeStatus === 'number' && member.childLifeStatus === 0,
2121
+ );
2122
+ if (filteredBirthInfos && filteredBirthInfos.length) {
2123
+ this.formStore.birthInfos = filteredBirthInfos;
2124
+ this.showToaster('success', this.t('toaster.pickFamilyMember'), 3000);
2125
+ } else {
2126
+ this.formStore.birthInfos = [];
2127
+ this.showToaster('error', this.t('toaster.notFound'), 3000);
2128
+ }
2129
+ } else {
2130
+ this.formStore.birthInfos = [];
2131
+ this.showToaster('error', this.t('toaster.notFound'), 3000);
2132
+ }
2133
+ } catch (err) {
2134
+ ErrorHandler(err);
2135
+ } finally {
2136
+ this.isLoading = false;
2137
+ }
2138
+ },
2101
2139
  async getContragentFromGBDFL(iin, phoneNumber, whichForm, whichIndex) {
2102
2140
  this.isLoading = true;
2103
2141
  try {
@@ -2124,12 +2162,12 @@ export const useDataStore = defineStore('data', {
2124
2162
  const { responseInfo } = parseXML(gbdResponse.content, true, 'responseInfo');
2125
2163
  if (typeof whichIndex !== 'number') {
2126
2164
  if (this.formStore[whichForm].gosPersonData !== null && this.formStore[whichForm].gosPersonData.iin !== iin.replace(/-/g, '')) {
2127
- this.formStore[whichForm].resetForm(false);
2165
+ this.formStore[whichForm].resetMember(false);
2128
2166
  }
2129
2167
  this.formStore[whichForm].gosPersonData = person;
2130
2168
  } else {
2131
2169
  if (this.formStore[whichForm][whichIndex].gosPersonData !== null && this.formStore[whichForm][whichIndex].gosPersonData.iin !== iin.replace(/-/g, '')) {
2132
- this.formStore[whichForm][whichIndex].resetForm(false);
2170
+ this.formStore[whichForm][whichIndex].resetMember(false);
2133
2171
  }
2134
2172
  this.formStore[whichForm][whichIndex].gosPersonData = person;
2135
2173
  }
@@ -7,7 +7,6 @@ import { Member } from '../composables/classes';
7
7
 
8
8
  export const useMemberStore = defineStore('members', {
9
9
  state: () => ({
10
- route: useRoute(),
11
10
  router: useRouter(),
12
11
  dataStore: useDataStore(),
13
12
  formStore: useFormStore(),
@@ -27,12 +26,12 @@ export const useMemberStore = defineStore('members', {
27
26
  }
28
27
  return true;
29
28
  },
30
- hasMemberData(whichForm: keyof typeof this.formStore, whichIndex?: number, key: string = 'id', emptyValue: any = 0) {
29
+ hasMemberData(whichForm: MemberKeys, whichIndex?: number, key: string = 'id', emptyValue: any = 0) {
31
30
  if (!this.validateInitiator(false)) return false;
32
31
  if (!this.isStatementEditible(whichForm)) return false;
33
32
  return typeof whichIndex === 'number' ? this.formStore[whichForm][whichIndex][key] != emptyValue : this.formStore[whichForm][key] != emptyValue;
34
33
  },
35
- canMemberDeleted(whichForm: keyof typeof this.formStore, whichIndex?: number) {
34
+ canMemberDeleted(whichForm: MemberKeys, whichIndex?: number) {
36
35
  if (!whichForm) return false;
37
36
  if (!this.isStatementEditible(whichForm)) return false;
38
37
  if (!this.validateInitiator(false)) return false;
@@ -46,7 +45,7 @@ export const useMemberStore = defineStore('members', {
46
45
  }
47
46
  return false;
48
47
  },
49
- getMemberFromStore(whichForm: keyof typeof this.formStore, whichIndex?: number): Member | null {
48
+ getMemberFromStore(whichForm: MemberKeys, whichIndex?: number): Member | null {
50
49
  switch (whichForm) {
51
50
  case this.formStore.policyholderFormKey:
52
51
  return this.formStore.policyholderForm;
@@ -62,7 +61,7 @@ export const useMemberStore = defineStore('members', {
62
61
  return null;
63
62
  }
64
63
  },
65
- getMemberFromApplication(whichForm: keyof typeof this.formStore, whichIndex?: number) {
64
+ getMemberFromApplication(whichForm: MemberKeys, whichIndex?: number) {
66
65
  const id = typeof whichIndex === 'number' ? this.formStore[whichForm][whichIndex].id : this.formStore[whichForm].id;
67
66
  switch (whichForm) {
68
67
  case this.formStore.policyholderFormKey:
@@ -83,7 +82,7 @@ export const useMemberStore = defineStore('members', {
83
82
  }
84
83
  }
85
84
  },
86
- getMemberClass(whichForm: keyof typeof this.formStore) {
85
+ getMemberClass(whichForm: MemberKeys) {
87
86
  if (!whichForm) return false;
88
87
  switch (whichForm) {
89
88
  case this.formStore.policyholderFormKey:
@@ -100,7 +99,7 @@ export const useMemberStore = defineStore('members', {
100
99
  return false;
101
100
  }
102
101
  },
103
- getMemberCode(whichForm: keyof typeof this.formStore) {
102
+ getMemberCode(whichForm: MemberKeys) {
104
103
  switch (whichForm) {
105
104
  case this.formStore.policyholderFormKey:
106
105
  return 'Client';
@@ -114,25 +113,23 @@ export const useMemberStore = defineStore('members', {
114
113
  return 'Spokesman';
115
114
  }
116
115
  },
117
- clearMember(whichForm: keyof typeof this.formStore, whichIndex?: number) {
116
+ clearMember(whichForm: MemberKeys, whichIndex?: number) {
118
117
  if (!whichForm) return false;
119
118
  if (!this.isStatementEditible(whichForm)) return false;
120
119
  if (!this.validateInitiator()) return false;
121
- const memberClass = this.getMemberClass(whichForm);
122
- if (!memberClass) return false;
123
120
  if (whichForm === this.formStore.policyholderFormKey || whichForm === this.formStore.policyholdersRepresentativeFormKey) {
124
- this.formStore[whichForm].resetForm();
121
+ this.formStore[whichForm].resetMember();
125
122
  }
126
123
  if (typeof whichIndex === 'number') {
127
124
  if (this.formStore[whichForm].length === 1) {
128
- this.formStore[whichForm][whichIndex] = memberClass;
125
+ this.formStore[whichForm][whichIndex].resetMember();
129
126
  } else {
130
127
  this.formStore[whichForm].splice(whichIndex, 1);
131
128
  }
132
129
  }
133
130
  return true;
134
131
  },
135
- async deleteMember(whichForm: keyof typeof this.formStore, whichIndex?: number) {
132
+ async deleteMember(taskId: string, whichForm: MemberKeys, whichIndex?: number) {
136
133
  if (!whichForm) return false;
137
134
  if (!this.isStatementEditible(whichForm)) return false;
138
135
  if (!this.validateInitiator()) return false;
@@ -147,14 +144,14 @@ export const useMemberStore = defineStore('members', {
147
144
  } else {
148
145
  if (memberData) await this.dataStore.api.deleteMember(memberCode, memberData.id as number);
149
146
  }
150
- if (memberData) await this.dataStore.getApplicationData(this.route.params.taskId, true, true, true, false);
147
+ if (memberData) await this.dataStore.getApplicationData(taskId, true, true, true, false);
151
148
  return this.clearMember(whichForm, whichIndex);
152
149
  } catch (err) {
153
150
  console.log(err);
154
151
  return ErrorHandler(err);
155
152
  }
156
153
  },
157
- addMember(whichForm: keyof typeof this.formStore) {
154
+ addMember(whichForm: MemberKeys) {
158
155
  if (!whichForm) return false;
159
156
  if (!this.isStatementEditible(whichForm)) return false;
160
157
  if (!this.validateInitiator()) return false;
package/store/messages.ts CHANGED
@@ -77,8 +77,9 @@ export const messages = {
77
77
  error: 'Произошла ошибка ',
78
78
  applicationDeleted: 'Заявка удалена',
79
79
  emptyProductConditions: 'Не заполнены данные условия продуктов и расчетов',
80
- emptyHealthAnketa: 'Не заполнены данные анкеты по здоровью',
81
- emptyCriticalAnketa: 'Не заполнены данные анкеты по критическому заболеванию застрахованного',
80
+ emptyHealthAnketa: 'Не заполнены данные анкеты по здоровью Застрахованного',
81
+ emptyHealthAnketaPolicyholder: 'Не заполнены данные анкеты по здоровью Страхователя',
82
+ emptyCriticalAnketa: 'Не заполнены данные анкеты по критическому заболеванию Застрахованного',
82
83
  successOperation: 'Операция прошла успешно',
83
84
  noAssignee: 'Нужно взять задачу в работу',
84
85
  canDoOnlyAssignee: 'Задача в работе и у вас нету доступа',
@@ -86,19 +87,24 @@ export const messages = {
86
87
  noTasksForYou: 'Список, назначенных задач на вашу роль, пустой',
87
88
  youCanNotStartApplication: 'У вас нет доступа на запуск заявки',
88
89
  hasNewApplicationState: 'Неактуальная заявка',
89
- reloadEverySeconds: 'Обновление можно делать каждые { text } секунд',
90
+ reloadEverySeconds: 'Обновление можно делать каждые {text} секунд',
90
91
  successReload: 'Обновлено',
91
- sendEverySeconds: 'СМС можно отправлять каждые { text } секунд ',
92
+ sendEverySeconds: 'СМС можно отправлять каждые {text} секунд ',
92
93
  waitForClient: 'Ожидайте подтверждения клиента',
93
94
  noSuchProduct: 'Ошибка при переходе: неправильная ссылка',
94
95
  affiliationDocumentNotUploaded: 'Не прикреплен файл в решении андеррайтингового совета',
95
96
  documentNumberWasNotFilled: 'Номер документа и дата не были заполнены',
96
- valueShouldBeHigher: `Значение должно быть больше { text } процентов`,
97
+ valueShouldBeHigher: `Значение должно быть больше {text} процентов`,
97
98
  valueShouldBeBetween: `Значение должно быть в промежутке от { floor } до { ceil } процентов`,
98
99
  needAgreement: 'Нужно получить согласие клиента',
99
100
  successOtp: 'Код подтверждения отправлен успешно',
100
101
  hasSuccessOtp: 'По клиенту уже имеется согласие',
101
102
  tokenExpire: 'Истекло время ожидания',
103
+ requiredBeneficiary: 'Необходимо указать данные выгодоприобретателя',
104
+ requiredInsured: 'Необходимо указать данные застрахованного',
105
+ needToRecalculate: 'Необходимо пересчитать условия продукта',
106
+ noUrl: 'Отсутствует ссылка',
107
+ pickFamilyMember: 'Выберите члена семьи',
102
108
  },
103
109
  buttons: {
104
110
  createStatement: 'Создать заявку',
@@ -138,6 +144,7 @@ export const messages = {
138
144
  createInvoice: 'Создать Счет на оплату',
139
145
  fromInsis: 'Информационная система INSIS',
140
146
  fromGBDFL: 'Государственная база данных физических лиц',
147
+ fromGKB: 'Государственное кредитное бюро',
141
148
  sendSMS: 'Отправить СМС',
142
149
  toPayment: 'Перейти к оплате',
143
150
  calcSum: 'Рассчитать сумму',
@@ -160,6 +167,7 @@ export const messages = {
160
167
  deleteFile: 'Вы уверены что хотите удалить файл',
161
168
  continue: 'Продолжить',
162
169
  correctSum: 'Корректна ли сумма страховой премии?',
170
+ familyMember: 'Выберите члена семьи',
163
171
  },
164
172
  sign: {
165
173
  chooseDoc: 'Выберите документы для подписание',
@@ -181,7 +189,7 @@ export const messages = {
181
189
  byHealth: 'Анкета по здоровью застрахованного',
182
190
  byCritical: 'Анкета по критической болезни Застрахованного',
183
191
  answerAllNo: 'Ответить везде Нет',
184
- pleaseAnswer: 'Пожалуйста ответьте на { text } вопросов',
192
+ pleaseAnswer: 'Пожалуйста ответьте на {text} вопросов',
185
193
  },
186
194
  questionnaireHealth: 'Анкета по здоровью Застрахованного',
187
195
  chooseAll: 'Выбрать все',
@@ -301,6 +309,8 @@ export const messages = {
301
309
  requestedSumInsuredMycar: 'Максимальная сумма не должна превышать 60 млн',
302
310
  ageMycar: 'Пороговое значение по возрасту с 21 по 65',
303
311
  noResident: 'Нерезидентам отказано',
312
+ policyholderAgeLimit: 'Возраст Застрахованного должен быть не менее 18-ти лет',
313
+ beneficiaryAgeLimit: 'На дату подписания полиса возраст Выгодоприобретателя должен быть не более 15 лет',
304
314
  },
305
315
  code: 'КЭС',
306
316
  fontSize: 'Размер шрифта',
package/store/rules.js CHANGED
@@ -148,4 +148,6 @@ export const rules = {
148
148
  }
149
149
  },
150
150
  ],
151
+ policyholderAgeLimit: [v => v >= 18 || t('rules.policyholderAgeLimit')],
152
+ beneficiaryAgeLimit: [v => v <= 15 || t('rules.beneficiaryAgeLimit')],
151
153
  };
package/types/index.ts ADDED
@@ -0,0 +1,120 @@
1
+ export {};
2
+
3
+ declare global {
4
+ type MemberKeys = keyof ReturnType<typeof useFormStore>;
5
+ type MemberFormTypes = 'policyholderForm' | 'insuredForm' | 'beneficiaryForm' | 'beneficialOwnerForm' | 'policyholdersRepresentativeForm' | 'productConditionsForm';
6
+ type PanelTypes = 'settings' | 'panel';
7
+ type FileActions = 'view' | 'download';
8
+ type InputVariants = 'solo' | 'filled' | 'outlined' | 'plain' | 'underlined';
9
+ type InputTypes =
10
+ | 'button'
11
+ | 'checkbox'
12
+ | 'color'
13
+ | 'date'
14
+ | 'datetime-local'
15
+ | 'email'
16
+ | 'file'
17
+ | 'hidden'
18
+ | 'image'
19
+ | 'month'
20
+ | 'number'
21
+ | 'password'
22
+ | 'radio'
23
+ | 'range'
24
+ | 'reset'
25
+ | 'search'
26
+ | 'submit'
27
+ | 'tel'
28
+ | 'text'
29
+ | 'time'
30
+ | 'url'
31
+ | 'week';
32
+ type TaskListItem = {
33
+ addRegNumber: string | number;
34
+ applicationTaskId: string;
35
+ dateCreated: string;
36
+ historyStatus: string;
37
+ historyStatusTitle: string;
38
+ id: string;
39
+ iin: string;
40
+ insurerIin: string;
41
+ insurerLongName: string;
42
+ isTask: boolean | number;
43
+ longName: string;
44
+ number: string;
45
+ processCode: number;
46
+ processCodeTitle: string;
47
+ status: string;
48
+ userId: string;
49
+ userName: string;
50
+ };
51
+ type TaskHistory = {
52
+ appointmentDate: string | null;
53
+ comment: string | null;
54
+ dateCreated: string;
55
+ decisionCode: string | null;
56
+ decisionNameRu: string | null;
57
+ factEndDate: string;
58
+ id: string;
59
+ number: string;
60
+ planEndDate: string;
61
+ statusCode: string;
62
+ statusTitle: string;
63
+ userFullName: string | null;
64
+ userId: string | null;
65
+ violationText: string | null;
66
+ };
67
+
68
+ type Item = {
69
+ itemCode: string;
70
+ itemId: number;
71
+ itemName: string;
72
+ };
73
+
74
+ type GBDFLResponse = {
75
+ status: string;
76
+ statusName: string;
77
+ content: string;
78
+ };
79
+
80
+ type FamilyInfoGKB = {
81
+ infoList: InfoListGKB;
82
+ status: string;
83
+ statusName: string;
84
+ content: null;
85
+ };
86
+
87
+ type InfoListGKB = {
88
+ birthInfos: BirthInfoGKB[];
89
+ };
90
+
91
+ type BirthInfoGKB = {
92
+ actDate?: string;
93
+ actNumber?: string;
94
+ childBirthDate?: string;
95
+ childIIN?: string;
96
+ childLifeStatus?: number;
97
+ childName?: string;
98
+ childPatronymic?: string;
99
+ childSurName?: string;
100
+ fatherBirthDate?: string;
101
+ fatherLifeStatus?: number;
102
+ fatherIIN?: string;
103
+ fatherName?: string;
104
+ fatherPatronymic?: string;
105
+ fatherSurName?: string;
106
+ marriageActDate?: string;
107
+ marriageActNumber?: string;
108
+ marriageActPlace?: string;
109
+ motherApplication?: number;
110
+ motherBirthDate?: string;
111
+ motherLifeStatus?: string | null;
112
+ motherIIN?: string | null;
113
+ motherName?: string | null;
114
+ motherPatronymic?: string | null;
115
+ motherSurName?: string | null;
116
+ zagsCode?: string;
117
+ zagsNameKZ?: string;
118
+ zagsNameRU?: string;
119
+ };
120
+ }