hl-core 0.0.10-beta.5 → 0.0.10-beta.51

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 (42) hide show
  1. package/README.md +0 -2
  2. package/api/base.api.ts +345 -137
  3. package/api/interceptors.ts +3 -5
  4. package/components/Dialog/Dialog.vue +5 -1
  5. package/components/Dialog/FamilyDialog.vue +15 -4
  6. package/components/Form/DigitalDocument.vue +52 -0
  7. package/components/Form/FormSource.vue +30 -0
  8. package/components/Form/ManagerAttachment.vue +60 -11
  9. package/components/Form/ProductConditionsBlock.vue +12 -6
  10. package/components/Input/Datepicker.vue +5 -0
  11. package/components/Input/FileInput.vue +1 -1
  12. package/components/Input/FormInput.vue +5 -0
  13. package/components/Input/OtpInput.vue +25 -0
  14. package/components/Input/RoundedInput.vue +2 -0
  15. package/components/Input/RoundedSelect.vue +2 -0
  16. package/components/Input/TextAreaField.vue +71 -0
  17. package/components/Menu/MenuNav.vue +1 -1
  18. package/components/Pages/Anketa.vue +207 -176
  19. package/components/Pages/ContragentForm.vue +1 -1
  20. package/components/Pages/Documents.vue +452 -64
  21. package/components/Pages/MemberForm.vue +416 -180
  22. package/components/Pages/ProductConditions.vue +1021 -243
  23. package/components/Panel/PanelHandler.vue +297 -124
  24. package/components/Utilities/Chip.vue +1 -1
  25. package/components/Utilities/JsonViewer.vue +1 -2
  26. package/composables/classes.ts +124 -20
  27. package/composables/constants.ts +46 -1
  28. package/composables/index.ts +336 -8
  29. package/composables/styles.ts +8 -24
  30. package/configs/pwa.ts +1 -7
  31. package/layouts/clear.vue +1 -1
  32. package/layouts/default.vue +1 -1
  33. package/layouts/full.vue +1 -1
  34. package/locales/ru.json +90 -19
  35. package/nuxt.config.ts +10 -12
  36. package/package.json +12 -12
  37. package/plugins/head.ts +7 -1
  38. package/store/data.store.ts +966 -575
  39. package/store/member.store.ts +17 -6
  40. package/store/rules.ts +23 -3
  41. package/types/enum.ts +42 -2
  42. package/types/index.ts +111 -56
@@ -6,6 +6,55 @@
6
6
  <base-btn v-if="underDocumentsList && underDocumentsList.length" :loading="documentLoading" text="Загрузить" size="sm" class="mt-3" @click="uploadUnderFiles" />
7
7
  </base-animation>
8
8
  </base-form-section>
9
+ <section
10
+ v-if="$dataStore.isPension && (showContract || formStore.applicationData.statusCode === 'PreparationDossierForm')"
11
+ class="w-full px-[10px] pt-[14px] flex flex-col gap-2"
12
+ >
13
+ <base-content-block v-if="showContract" :class="[$styles.textSimple]">
14
+ <h5 class="text-center font-medium mb-4">{{ $dataStore.t('labels.statements') }}</h5>
15
+ <div :class="[$styles.whiteBg, $styles.rounded]" class="p-2 h-12 flex items-center relative">
16
+ <span class="ml-2">Заявления на {{ processCode === 19 || processCode === 25 ? 'страхование' : 'возврат' }}</span>
17
+ <i
18
+ class="transition-all cursor-pointer mdi mdi-tray-arrow-down pl-2 mr-3 border-l-[1px] text-xl absolute right-0"
19
+ :class="[$styles.greenTextHover]"
20
+ @click="$dataStore.generatePDFDocument(processCode === 19 ? 'PA_Statement' : processCode === 25 ? 'PAJ_Statement' : 'PA_RefundStatement', '37')"
21
+ ></i>
22
+ </div>
23
+ </base-content-block>
24
+ <base-content-block v-if="showContract" :class="[$styles.textSimple]">
25
+ <h5 class="text-center font-medium mb-4">{{ $dataStore.t('labels.contract') }}</h5>
26
+ <div :class="[$styles.whiteBg, $styles.rounded]" class="p-2 h-12 flex items-center relative">
27
+ <span class="ml-2">Договор {{ processCode === 19 || processCode === 25 ? 'страхования' : 'возврата' }}</span>
28
+ <i
29
+ class="transition-all cursor-pointer mdi mdi-tray-arrow-down pl-2 mr-3 border-l-[1px] text-xl absolute right-0"
30
+ :class="[$styles.greenTextHover]"
31
+ @click="$dataStore.generatePDFDocument(processCode === 19 ? 'PA_Contract' : processCode === 25 ? 'PAJ_Contract' : 'PA_RefundAgreement', '38')"
32
+ ></i>
33
+ </div>
34
+ </base-content-block>
35
+ <base-content-block :class="[$styles.textSimple]" v-if="formStore.applicationData.statusCode !== 'StartForm' && showContract">
36
+ <h5 class="text-center font-medium mb-4">{{ $dataStore.t('pension.complianceFinMonitoring') }}</h5>
37
+ <div :class="[$styles.whiteBg, $styles.rounded]" class="p-2 h-12 flex items-center relative">
38
+ <span class="ml-2">{{ $dataStore.t('pension.complianceFinMonitoring') }}</span>
39
+ <i
40
+ class="transition-all cursor-pointer mdi mdi-tray-arrow-down pl-2 mr-3 border-l-[1px] text-xl absolute right-0"
41
+ :class="[$styles.greenTextHover]"
42
+ @click="$dataStore.generatePDFDocument('Compliance_FinMonitoring', '39')"
43
+ ></i>
44
+ </div>
45
+ </base-content-block>
46
+ <base-content-block :class="[$styles.textSimple]" v-if="formStore.applicationData.statusCode === 'PreparationDossierForm'">
47
+ <h5 class="text-center font-medium mb-4">{{ $dataStore.t('pension.dossierPA') }}</h5>
48
+ <div :class="[$styles.whiteBg, $styles.rounded]" class="p-2 h-12 flex items-center relative">
49
+ <span class="ml-2">{{ $dataStore.t('pension.dossierPA') }}</span>
50
+ <i
51
+ class="transition-all cursor-pointer mdi mdi-tray-arrow-down pl-2 mr-3 border-l-[1px] text-xl absolute right-0"
52
+ :class="[$styles.greenTextHover]"
53
+ @click="$dataStore.generatePDFDocument('PA_Dossier', '40', 'doc')"
54
+ ></i>
55
+ </div>
56
+ </base-content-block>
57
+ </section>
9
58
  <section class="w-full px-[10px] pt-[14px] flex flex-col gap-2" v-if="formStore.signedDocumentList && formStore.signedDocumentList.length">
10
59
  <base-content-block
11
60
  v-if="$dataStore.isInitiator() && !$dataStore.isPension && $dataStore.controls.hasChooseSign && formStore.applicationData.statusCode === 'ContractSignedFrom'"
@@ -17,7 +66,7 @@
17
66
  <base-form-input v-model="formStore.contractDate" :label="$dataStore.t('form.date')" :readonly="true" append-inner-icon="mdi mdi-calendar-blank-outline" />
18
67
  <base-file-input :readonly="isDisabled" @input.prevent="onFileChange($event)" />
19
68
  </base-content-block>
20
- <base-content-block v-for="document of formStore.signedDocumentList" :key="document.id" :class="[$styles.textSimple]">
69
+ <base-content-block v-for="document of documentListFiltered" :key="document.id" :class="[$styles.textSimple]">
21
70
  <h5 class="text-center font-medium mb-4">
22
71
  {{ document.fileTypeName }}
23
72
  </h5>
@@ -31,6 +80,105 @@
31
80
  </div>
32
81
  </base-content-block>
33
82
  </section>
83
+ <section v-if="requiredSign">
84
+ <div v-for="(member, index) in jointMembers.filter(i => memberHasDocumentsToSign(i.iin))" :key="index">
85
+ <base-form-section :title="`${member.firstName} ${member.lastName}`" class="mx-[10px] mt-[14px] d-flex">
86
+ <base-file-input
87
+ v-if="
88
+ !formStore.signedDocumentList.find(i => i.fileTypeCode === '10' && i.iin === String(member.iin).replaceAll('-', '')) &&
89
+ formStore.requiredDocuments.some(i => i.code === '10' && i.iin === String(member.iin).replaceAll('-', ''))
90
+ "
91
+ :label="$dataStore.t('form.bankStatement')"
92
+ :loading="$dataStore.isLoading"
93
+ @input="uploadAdditionalFile($event, '10', member.iin)"
94
+ />
95
+ <base-file-input
96
+ v-if="!formStore.signedDocumentList.find(i => i.fileTypeCode === '9' && i.iin === String(member.iin).replaceAll('-', '')) && member.isDisability"
97
+ label="Справка об инвалидности"
98
+ :loading="$dataStore.isLoading"
99
+ @input="uploadAdditionalFile($event, '9', member.iin)"
100
+ />
101
+ <base-file-input
102
+ v-if="
103
+ !formStore.signedDocumentList.find(i => i.fileTypeCode === '8' && i.iin === String(member.iin).replaceAll('-', '')) &&
104
+ formStore.requiredDocuments.some(i => i.code === '8' && i.iin === String(member.iin).replaceAll('-', ''))
105
+ "
106
+ :label="$dataStore.t('pension.ENPFnote')"
107
+ :loading="$dataStore.isLoading"
108
+ @input="uploadAdditionalFile($event, '8', member.iin)"
109
+ />
110
+ <base-file-input
111
+ v-if="
112
+ !formStore.signedDocumentList.find(i => i.fileTypeCode === '40' && i.iin === String(member.iin).replaceAll('-', '')) &&
113
+ formStore.requiredDocuments.some(i => i.code === '40' && i.iin === String(member.iin).replaceAll('-', ''))
114
+ "
115
+ :label="$dataStore.t('pension.dossierPA')"
116
+ :loading="$dataStore.isLoading"
117
+ @input="uploadAdditionalFile($event, '40', member.iin)"
118
+ />
119
+ <base-file-input
120
+ v-if="
121
+ !formStore.signedDocumentList.find(i => i.fileTypeCode === '50' && i.iin === String(member.iin).replaceAll('-', '')) &&
122
+ formStore.requiredDocuments.some(i => i.code === '50' && i.iin === String(member.iin).replaceAll('-', ''))
123
+ "
124
+ :label="$dataStore.t('pension.oppvPaymentCertificate')"
125
+ :loading="$dataStore.isLoading"
126
+ @input="uploadAdditionalFile($event, '50', member.iin)"
127
+ />
128
+ <base-file-input
129
+ v-if="
130
+ formStore.signedDocumentList.filter(i => i.fileTypeCode === '29' && i.iin === String(member.iin).replaceAll('-', '')).length !==
131
+ formStore.requiredDocuments.filter(i => i.code === '29' && i.iin === String(member.iin).replaceAll('-', '')).length
132
+ "
133
+ :label="$dataStore.t('pension.KSJagreement')"
134
+ :loading="$dataStore.isLoading"
135
+ @input.prevent="uploadAdditionalFile($event, '29', member.iin)"
136
+ />
137
+ </base-form-section>
138
+ </div>
139
+ </section>
140
+ <section v-if="hasDigitalDocuments">
141
+ <base-digital-document
142
+ v-if="$route.params.taskId !== '0'"
143
+ :member="policyholderForm"
144
+ :title="$dataStore.t('policyholderForm')"
145
+ :disabled="isDigitalDocDisabled"
146
+ @openDigitalDocPanel="openDigitalDocPanel($event, 'Страхователя')"
147
+ @openPanel="openPanel"
148
+ />
149
+ <base-digital-document
150
+ v-if="$route.params.taskId !== '0' && slaveInsuredForm"
151
+ :member="slaveInsuredForm"
152
+ :title="$dataStore.t('policyholderForm') + ' 2'"
153
+ :disabled="isDigitalDocDisabled"
154
+ @openDigitalDocPanel="openDigitalDocPanel($event, 'Страхователя 2')"
155
+ @openPanel="openPanel"
156
+ />
157
+ <div v-if="insuredFiltered.length !== 0">
158
+ <base-digital-document
159
+ v-for="(member, index) in insuredFiltered"
160
+ :key="index"
161
+ :member="member"
162
+ :number="index + 1"
163
+ :title="$dataStore.t('insuredForm')"
164
+ :disabled="isDigitalDocDisabled"
165
+ @openDigitalDocPanel="openDigitalDocPanel($event, 'Застрахованного')"
166
+ @openPanel="openPanel"
167
+ />
168
+ </div>
169
+ <div v-if="beneficiaryFiltered.length !== 0">
170
+ <base-digital-document
171
+ v-for="(member, index) in beneficiaryFiltered"
172
+ :key="index"
173
+ :member="member"
174
+ :number="index + 1"
175
+ :title="$dataStore.t('beneficiaryForm')"
176
+ :disabled="isDigitalDocDisabled"
177
+ @openDigitalDocPanel="openDigitalDocPanel($event, 'Выгодоприобретателя')"
178
+ @openPanel="openPanel"
179
+ />
180
+ </div>
181
+ </section>
34
182
  <div v-if="noDocuments" class="h-[calc(90vh-70px)] flex flex-col items-center justify-center gap-6">
35
183
  <svg xmlns="http://www.w3.org/2000/svg" width="125" height="131" viewBox="0 0 125 131" fill="none" class="cursor-help">
36
184
  <path
@@ -51,63 +199,66 @@
51
199
  </svg>
52
200
  <p class="text-xl" :class="[$styles.mutedText]">{{ $dataStore.t('labels.noDocuments') }}</p>
53
201
  </div>
54
- <section v-if="$dataStore.isPension && showContract" class="w-full px-[10px] pt-[14px] flex flex-col gap-2">
55
- <base-content-block :class="[$styles.textSimple]">
56
- <h5 class="text-center font-medium mb-4">{{ $dataStore.t('labels.statements') }}</h5>
57
- <div :class="[$styles.whiteBg, $styles.rounded]" class="p-2 h-12 flex items-center relative">
58
- <span class="ml-2">Заявления на {{ processCode == 19 ? 'страхование' : 'возврат' }}</span>
59
- <i
60
- class="transition-all cursor-pointer mdi mdi-paperclip pl-2 mr-3 border-l-[1px] text-xl absolute right-0"
61
- :class="[$styles.greenTextHover]"
62
- @click="$dataStore.generatePDFDocument(processCode == 19 ? 'PA_Statement' : 'PA_RefundStatement', '37')"
63
- ></i>
64
- </div>
65
- </base-content-block>
66
- <base-content-block :class="[$styles.textSimple]">
67
- <h5 class="text-center font-medium mb-4">{{ $dataStore.t('labels.contract') }}</h5>
68
- <div :class="[$styles.whiteBg, $styles.rounded]" class="p-2 h-12 flex items-center relative">
69
- <span class="ml-2">Договор {{ processCode == 19 ? 'страхования' : 'возврата' }}</span>
70
- <i
71
- class="transition-all cursor-pointer mdi mdi-paperclip pl-2 mr-3 border-l-[1px] text-xl absolute right-0"
72
- :class="[$styles.greenTextHover]"
73
- @click="$dataStore.generatePDFDocument(processCode == 19 ? 'PA_Contract' : 'PA_RefundAgreement', '38')"
74
- ></i>
75
- </div>
76
- </base-content-block>
77
- <base-content-block :class="[$styles.textSimple]" v-if="formStore.applicationData.statusCode !== 'StartForm' && processCode == 19">
78
- <h5 class="text-center font-medium mb-4">{{ $dataStore.t('pension.complianceFinMonitoring') }}</h5>
79
- <div :class="[$styles.whiteBg, $styles.rounded]" class="p-2 h-12 flex items-center relative">
80
- <span class="ml-2">{{ $dataStore.t('pension.complianceFinMonitoring') }}</span>
81
- <i
82
- class="transition-all cursor-pointer mdi mdi-paperclip pl-2 mr-3 border-l-[1px] text-xl absolute right-0"
83
- :class="[$styles.greenTextHover]"
84
- @click="$dataStore.generatePDFDocument('Compliance_FinMonitoring', '39')"
85
- ></i>
86
- </div>
87
- </base-content-block>
88
- <base-content-block :class="[$styles.textSimple]" v-if="formStore.applicationData.statusCode === 'PreparationDossierForm' && processCode == 19">
89
- <h5 class="text-center font-medium mb-4">{{ $dataStore.t('pension.dossierPA') }}</h5>
90
- <div :class="[$styles.whiteBg, $styles.rounded]" class="p-2 h-12 flex items-center relative">
91
- <span class="ml-2">{{ $dataStore.t('pension.dossierPA') }}</span>
92
- <i
93
- class="transition-all cursor-pointer mdi mdi-paperclip pl-2 mr-3 border-l-[1px] text-xl absolute right-0"
94
- :class="[$styles.greenTextHover]"
95
- @click="$dataStore.generatePDFDocument('PA_Dossier', '40', 'doc')"
96
- ></i>
97
- </div>
98
- </base-content-block>
99
- </section>
100
- <Teleport v-if="$dataStore.panelAction === null" to="#right-panel-actions">
202
+ <Teleport v-if="isPanelOpen" to="#right-panel-actions">
101
203
  <base-fade-transition>
102
204
  <div :class="[$styles.flexColNav]">
103
- <base-btn :disabled="documentLoading" :loading="documentLoading" text="Открыть" @click="getFile('view')" />
104
- <base-btn :disabled="documentLoading" :loading="documentLoading" text="Скачать" @click="getFile('download')" />
205
+ <base-animation>
206
+ <base-btn
207
+ v-if="currentDocument.fileName && currentDocument.fileName.includes('.') ? currentDocument.fileName.endsWith('.pdf') : true"
208
+ :disabled="documentLoading"
209
+ :loading="documentLoading"
210
+ text="Открыть"
211
+ @click="getDoc('view')"
212
+ />
213
+ </base-animation>
214
+ <base-btn :disabled="documentLoading" :loading="documentLoading" text="Скачать" @click="getDoc('download')" />
105
215
  <base-animation>
106
216
  <base-btn v-if="canDeleteFiles" :disabled="documentLoading" :loading="documentLoading" text="Удалить" @click="deletionDialog = true" />
107
217
  </base-animation>
108
218
  </div>
109
219
  </base-fade-transition>
110
220
  </Teleport>
221
+ <Teleport v-if="isDigitalDocOpen" to="#right-panel-actions">
222
+ <div :class="[$styles.flexColNav]">
223
+ <base-form-section class="!mt-0">
224
+ <v-expansion-panels :flat="true">
225
+ <v-expansion-panel class="digital-doc-info !rounded-[8px]">
226
+ <v-expansion-panel-title class="!text-[12px]"> Как получить цифровой документ: </v-expansion-panel-title>
227
+ <v-expansion-panel-text class="text-[12px] text-[#464f60]">
228
+ 1. Выберите тип документа.<br /><br />
229
+ 2. Через приложение eGov mobile и другие приложения: <br />
230
+ • Откройте раздел "Цифровые документы". <br />
231
+ • Выберите нужный документ и откройте доступ. <br />
232
+ • Введите 6-значный код в поле «Код подтверждения». <br />
233
+ • Нажмите "Получить документ".<br /><br />
234
+ 3. Через SMS: <br />
235
+ • Нажмите "Отправить код". <br />
236
+ • Введите полученный SMS-код. <br />
237
+ • Нажмите "Получить документ".<br /><br />
238
+ 4. При ошибке нажмите <a href="javascript:void(0);" class="text-blue-600" @click="$dataStore.updateDigitalDocumentsProfile(currentIin)">обновить профиль</a><br />
239
+ </v-expansion-panel-text>
240
+ </v-expansion-panel>
241
+ </v-expansion-panels>
242
+ </base-form-section>
243
+ <div class="p-4 d-flex flex-col gap-0.5" :class="[$styles.blueBgLight, $styles.rounded]">
244
+ <base-rounded-select v-model="documentType" class="document-type-select" :items="documentItems" :label="$dataStore.t('form.documentType')" hide-details />
245
+ <div class="digital-document-otp flex flex-col">
246
+ <base-otp-input
247
+ v-model="otpCode"
248
+ @keyup.enter.prevent="otpCode.length === useMask().otpSixDigit.length && getCode()"
249
+ @input="otpCode.length === useMask().otpSixDigit.length && getDigitalDocument()"
250
+ />
251
+ <base-animation>
252
+ <span v-if="!documentLoading" class="text-center cursor-pointer" :class="[$styles.mutedText]" @click="getCode"
253
+ >Не получили код? <span class="underline underline-offset-2">Отправить код заново</span></span
254
+ >
255
+ </base-animation>
256
+ </div>
257
+ </div>
258
+ <base-btn :disabled="documentLoading" :loading="documentLoading" :btn="$styles.greenLightBtn" text="Отправить SMS-код" @click="getCode" />
259
+ <base-btn :disabled="documentLoading" :loading="documentLoading" text="Получить документ" @click="getDigitalDocument" />
260
+ </div>
261
+ </Teleport>
111
262
  <base-dialog
112
263
  v-model="deletionDialog"
113
264
  :title="$dataStore.t('dialog.confirmDelete')"
@@ -121,20 +272,49 @@
121
272
  </template>
122
273
 
123
274
  <script lang="ts">
124
- import { DocumentItem } from '../../composables/classes';
275
+ import { DocumentItem, Value } from '../../composables/classes';
276
+ import type { IDocument, Member } from '../../composables/classes';
125
277
  import { uuid } from 'vue-uuid';
126
- import type { FileActions } from '../../types';
278
+ import type { Base, FileActions } from '../../types';
127
279
 
128
280
  export default defineComponent({
129
281
  setup() {
282
+ type DigitalDocNames = 'Удостоверение личности' | 'Паспорт' | 'Вид на жительство иностранного гражданина';
283
+ type DigitalDocTypes = 'IdentityCard' | 'Passport' | 'Vnzh';
284
+
285
+ const route = useRoute();
130
286
  const dataStore = useDataStore();
131
287
  const formStore = useFormStore();
132
288
  const currentDocument = ref<DocumentItem>(new DocumentItem());
133
289
  const documentLoading = ref<boolean>(false);
134
290
  const deletionDialog = ref<boolean>(false);
291
+ const isPanelOpen = ref<boolean>(false);
292
+ const isDigitalDocOpen = ref<boolean>(false);
135
293
  const isDisabled = computed(() => !dataStore.isTask());
136
294
  const contractDict = computed(() => dataStore.dicFileTypeList.find(i => i.nameRu === 'Договор страхования' || i.nameRu === 'Договор'));
137
295
  const processCode = formStore.applicationData.processCode;
296
+ const requiredSign = computed(
297
+ () =>
298
+ !isDisabled.value &&
299
+ dataStore.isPension &&
300
+ formStore.applicationData &&
301
+ (formStore.applicationData.statusCode === 'StartForm' ||
302
+ formStore.applicationData.statusCode === 'EditForm' ||
303
+ formStore.applicationData.statusCode === 'PreparationDossierForm'),
304
+ );
305
+ const hasDigitalDocuments = computed(() => dataStore.isEfoParent && !dataStore.isGns && !dataStore.isLifeBusiness && !!formStore.applicationData);
306
+ const isDigitalDocDisabled = computed(
307
+ () => !dataStore.isTask() || route.params.taskId === '0' || !dataStore.isInitiator() || !dataStore.isProcessEditable(formStore.applicationData.statusCode),
308
+ );
309
+ const documentType = ref<DigitalDocNames | null>(null);
310
+ const otpCode = ref<string>('');
311
+ const currentIin = ref<string>('');
312
+ const deleteFilesId = ['1', '2', '3', '4', '46'];
313
+ const documentItems: Array<{ title: DigitalDocNames; value: DigitalDocTypes }> = [
314
+ { title: 'Удостоверение личности', value: 'IdentityCard' },
315
+ { title: 'Паспорт', value: 'Passport' },
316
+ { title: 'Вид на жительство иностранного гражданина', value: 'Vnzh' },
317
+ ];
138
318
  const signedContract = reactive<{
139
319
  processInstanceId: string | number;
140
320
  fileTypeId: string | number | null;
@@ -172,12 +352,10 @@ export default defineComponent({
172
352
  }),
173
353
  );
174
354
  const showContract = computed(
175
- () =>
176
- formStore.applicationData &&
177
- (formStore.applicationData.statusCode === 'Completed' || formStore.applicationData.statusCode === 'PreparationDossierForm' || dataStore.isActuary()),
355
+ () => formStore.applicationData && (dataStore.isAdmin() || dataStore.isSupport() || (dataStore.isActuary() && formStore.applicationData.statusCode === 'ActuaryForm')),
178
356
  );
179
357
  const noDocuments = computed(() => {
180
- if (dataStore.isPension) return !showContract.value;
358
+ if (dataStore.isPension && (!formStore.signedDocumentList || !formStore.signedDocumentList.length)) return !showContract.value;
181
359
  return !formStore.signedDocumentList || !formStore.signedDocumentList.length;
182
360
  });
183
361
  const isUnderwriterDocuments = computed(
@@ -190,16 +368,34 @@ export default defineComponent({
190
368
  const canDeleteFiles = computed(() => {
191
369
  const baseCondition = dataStore.isTask() && dataStore.isInitiator() && dataStore.isProcessEditable(formStore.applicationData.statusCode);
192
370
  if (dataStore.isBaiterek || dataStore.isBolashak || dataStore.isLiferenta || dataStore.isKazyna || dataStore.isAmulet || dataStore.isGons) {
193
- return baseCondition && (currentDocument.value ? currentDocument.value.fileTypeCode === '46' : false);
371
+ return baseCondition && (currentDocument.value ? deleteFilesId.includes(String(currentDocument.value.fileTypeCode)) : false);
372
+ }
373
+ if (dataStore.isPension) {
374
+ const canDeleteInPension = dataStore.isTask() && dataStore.isInitiator();
375
+ const canDeletePaperInPension = canDeleteInPension && currentDocument.value.signed === true && currentDocument.value.signedType === 2;
376
+ if (canDeleteInPension && dataStore.isProcessEditable(formStore.applicationData.statusCode))
377
+ return formStore.requiredDocuments.some(i => i.code === currentDocument.value.fileTypeCode);
378
+ if (formStore.applicationData.statusCode === 'AttachAppContractForm')
379
+ return canDeletePaperInPension && (currentDocument.value.fileTypeCode === '5' || currentDocument.value.fileTypeCode === '19');
380
+ if (formStore.applicationData.statusCode === 'ContractSignedFrom') return canDeletePaperInPension && currentDocument.value.fileTypeCode === '6';
194
381
  }
195
- if (dataStore.isPension) return baseCondition;
196
382
  return false;
197
383
  });
198
384
 
385
+ const policyholderForm = computed(() => formStore.policyholderForm as Base.Document.Digital);
386
+ const insuredFiltered = computed(() => formStore.insuredForm.filter(i => i.iin !== formStore.policyholderForm.iin) as Base.Document.Digital[]);
387
+ const beneficiaryFiltered = computed(() => formStore.beneficiaryForm.filter(i => i.iin !== formStore.policyholderForm.iin) as Base.Document.Digital[]);
388
+ const slaveInsuredForm = computed(() => formStore.slaveInsuredForm as Base.Document.Digital);
389
+ const documentListFiltered = computed(() => formStore.signedDocumentList.filter(i => !['1', '2', '3', '4'].includes(String(i.fileTypeCode))));
390
+ const jointMembers = ref<Member[]>([formStore.insuredForm[0]]);
391
+
199
392
  const openPanel = async (document: DocumentItem) => {
200
393
  dataStore.rightPanel.title = document.fileTypeName!;
201
394
  currentDocument.value = document;
202
395
  dataStore.rightPanel.open = true;
396
+ isDigitalDocOpen.value = false;
397
+ isPanelOpen.value = true;
398
+ dataStore.panelAction = null;
203
399
  };
204
400
 
205
401
  const onFileChange = async (event: InputEvent) => {
@@ -209,7 +405,7 @@ export default defineComponent({
209
405
  if (files[0].size >= 20_000_000) {
210
406
  return dataStore.showToaster('error', dataStore.t('toaster.fileOnlyBelow20mb'), 6000);
211
407
  }
212
- if (files[0].type !== 'application/pdf') {
408
+ if (files[0].type !== constants.fileTypes.pdf) {
213
409
  return dataStore.showToaster('error', dataStore.t('toaster.onlyPDF'), 6000);
214
410
  }
215
411
  signedContract.fileName = files[0].name;
@@ -264,6 +460,17 @@ export default defineComponent({
264
460
  }
265
461
  };
266
462
 
463
+ const openDigitalDocPanel = async (iin: string, title: string) => {
464
+ isPanelOpen.value = false;
465
+ isDigitalDocOpen.value = true;
466
+ dataStore.panelAction = null;
467
+ dataStore.rightPanel.open = true;
468
+ dataStore.rightPanel.title = `Получить ЦД ${title}`;
469
+ documentType.value = null;
470
+ otpCode.value = '';
471
+ currentIin.value = iin;
472
+ };
473
+
267
474
  watch(
268
475
  () => document_list.value,
269
476
  () => {
@@ -280,11 +487,11 @@ export default defineComponent({
280
487
  },
281
488
  );
282
489
 
283
- const getFile = async (type: FileActions) => {
490
+ const getDoc = async (type: FileActions) => {
284
491
  if (currentDocument.value) {
285
492
  documentLoading.value = true;
286
493
  const fileExtension = currentDocument.value.fileName!.match(/\.([0-9a-z]+)(?:[\?#]|$)/i)![1];
287
- await dataStore.getFile(currentDocument.value, type, fileExtension);
494
+ await dataStore.getDoc(currentDocument.value, type, fileExtension);
288
495
  documentLoading.value = false;
289
496
  }
290
497
  };
@@ -294,18 +501,150 @@ export default defineComponent({
294
501
  const data = {
295
502
  id: currentDocument.value.id,
296
503
  processInstanceId: currentDocument.value.processInstanceId,
504
+ iin: currentDocument.value.iin ?? '',
297
505
  };
298
506
  await dataStore.deleteFile(data);
299
507
  deletionDialog.value = false;
300
508
  dataStore.rightPanel.open = false;
301
509
  dataStore.panelAction = null;
302
510
  await dataStore.getSignedDocList(formStore.applicationData.processInstanceId);
511
+ if (
512
+ hasDigitalDocuments.value &&
513
+ (currentDocument.value.fileTypeCode === '1' ||
514
+ currentDocument.value.fileTypeCode === '2' ||
515
+ currentDocument.value.fileTypeCode === '3' ||
516
+ currentDocument.value.fileTypeCode === '4')
517
+ ) {
518
+ getDigitalDocs();
519
+ }
520
+ }
521
+ };
522
+
523
+ const getCode = async () => {
524
+ if (!documentType.value) {
525
+ dataStore.showToaster('error', 'Выберите тип документа', 3000);
526
+ return;
527
+ }
528
+ documentLoading.value = true;
529
+ const response = await dataStore.getOnlineAccess(currentIin.value, String(documentType.value));
530
+ if (response) {
531
+ dataStore.showToaster('success', dataStore.t('toaster.successOtp'), 3000);
532
+ }
533
+ documentLoading.value = false;
534
+ };
535
+
536
+ const getDigitalDocument = async () => {
537
+ if (!documentType.value) {
538
+ dataStore.showToaster('error', 'Выберите тип документа', 3000);
539
+ return;
540
+ }
541
+ if (!otpCode.value) {
542
+ dataStore.showToaster('error', 'Введите код подтверждения', 3000);
543
+ return;
544
+ }
545
+ documentLoading.value = true;
546
+ const response = await dataStore.getDigitalDocuments(currentIin.value, String(formStore.applicationData.processInstanceId), otpCode.value);
547
+ if (response) {
548
+ await dataStore.getSignedDocList(formStore.applicationData.processInstanceId);
549
+ getDigitalDocs();
550
+ isDigitalDocOpen.value = false;
551
+ dataStore.panelAction = null;
552
+ dataStore.rightPanel.open = false;
553
+ documentType.value = null;
554
+ otpCode.value = '';
555
+ }
556
+ documentLoading.value = false;
557
+ };
558
+
559
+ const findCommonDocs = (members: Base.Document.Digital[]) => {
560
+ let commonDocs: IDocument[] = [];
561
+ for (let member of members) {
562
+ const matchingDoc = formStore.signedDocumentList.find(
563
+ doc =>
564
+ doc.iin === String(member.iin).replaceAll('-', '') && (doc.fileTypeCode === '1' || doc.fileTypeCode === '2' || doc.fileTypeCode === '3' || doc.fileTypeCode === '4'),
565
+ );
566
+ if (matchingDoc) commonDocs.push(matchingDoc);
567
+ }
568
+ return commonDocs;
569
+ };
570
+
571
+ const setDigitalDocuments = (members: Base.Document.Digital[]) => {
572
+ const commonDocs = findCommonDocs(members);
573
+ if (commonDocs.length !== 0) {
574
+ for (let member of members) {
575
+ const matchingDoc = commonDocs.find(doc => doc.iin === String(member.iin).replaceAll('-', ''));
576
+ if (matchingDoc) member.digitalDocument = matchingDoc;
577
+ }
578
+ }
579
+ };
580
+
581
+ const clearDigitalDocuments = (members: Base.Document.Digital[]) => {
582
+ for (let member of members) member.digitalDocument = null;
583
+ };
584
+
585
+ const getDigitalDocs = () => {
586
+ if (route.params.taskId !== '0') {
587
+ clearDigitalDocuments([formStore.policyholderForm as Base.Document.Digital]);
588
+ setDigitalDocuments([formStore.policyholderForm as Base.Document.Digital]);
589
+ if (insuredFiltered.value.length !== 0) {
590
+ clearDigitalDocuments(insuredFiltered.value);
591
+ setDigitalDocuments(insuredFiltered.value);
592
+ }
593
+ if (beneficiaryFiltered.value.length !== 0) {
594
+ clearDigitalDocuments(beneficiaryFiltered.value);
595
+ setDigitalDocuments(beneficiaryFiltered.value);
596
+ }
597
+ }
598
+ };
599
+
600
+ const memberHasDocumentsToSign = (iin: string | null) => {
601
+ if (!iin) return false;
602
+ // TODO reformat logic
603
+ return (
604
+ formStore.signedDocumentList.filter(i => formStore.requiredDocuments.find(j => j.code === i.fileTypeCode) && i.iin === iin.replaceAll('-', '')).length !==
605
+ formStore.requiredDocuments.filter(i => i.iin === iin.replaceAll('-', '')).length
606
+ );
607
+ };
608
+
609
+ const uploadAdditionalFile = async (event: InputEvent, code: string, iin?: string | null) => {
610
+ if (event.target) {
611
+ const files = (event.target as HTMLInputElement).files;
612
+ if (files && files.length && files[0]) {
613
+ if (files[0].type !== constants.fileTypes.pdf && files[0].type !== constants.fileTypes.docx && files[0].type !== constants.fileTypes.doc) {
614
+ return dataStore.showToaster('error', dataStore.t('toaster.onlyWithFormat', { format: 'PDF, Word' }), 6000);
615
+ }
616
+ if (files[0].size >= 10_000_000) {
617
+ return dataStore.showToaster('error', dataStore.t('toaster.fileOnlyBelow10mb'), 6000);
618
+ }
619
+ const file = Object.assign(files[0]);
620
+ const formData = new FormData();
621
+ const information: any = [];
622
+ const uuidV4 = uuid.v4();
623
+ formData.append('file', file);
624
+ const ext = file.name.substring(file.name.lastIndexOf('.'));
625
+ const selectedDocument = dataStore.dicFileTypeList.find((i: Value) => i.code === code);
626
+ information.push({
627
+ identifier: `${uuidV4}${ext}`,
628
+ iin: iin ? iin.replaceAll('-', '') : null,
629
+ processInstanceId: formStore.applicationData.processInstanceId,
630
+ fileTypeCode: selectedDocument ? selectedDocument.code : null,
631
+ fileTypeId: selectedDocument ? selectedDocument.id : null,
632
+ fileName: file.name,
633
+ });
634
+ formData.append('fileData', JSON.stringify(information));
635
+ dataStore.isLoading = true;
636
+ await dataStore.uploadFiles(formData, false);
637
+ await dataStore.getSignedDocList(formStore.applicationData.processInstanceId);
638
+ }
639
+ dataStore.isLoading = false;
303
640
  }
304
641
  };
305
642
 
306
643
  const onInit = async () => {
307
644
  await dataStore.getDicFileTypeList();
308
645
  await dataStore.getSignedDocList(formStore.applicationData.processInstanceId);
646
+ if (hasDigitalDocuments.value) getDigitalDocs();
647
+ if (processCode === 25) jointMembers.value.push(slaveInsuredForm.value as Member);
309
648
  };
310
649
 
311
650
  onInit();
@@ -316,30 +655,79 @@ export default defineComponent({
316
655
 
317
656
  return {
318
657
  // State
658
+ otpCode,
319
659
  formStore,
320
- documentLoading,
660
+ currentIin,
661
+ processCode,
662
+ isPanelOpen,
663
+ jointMembers,
321
664
  DocumentItem,
665
+ documentType,
666
+ documentItems,
322
667
  signedContract,
323
668
  deletionDialog,
324
- processCode,
669
+ currentDocument,
670
+ documentLoading,
671
+ isDigitalDocOpen,
325
672
  underDocumentsList,
326
673
 
327
674
  // Computed
328
675
  isDisabled,
676
+ requiredSign,
329
677
  showContract,
330
678
  noDocuments,
331
679
  canDeleteFiles,
680
+ insuredFiltered,
681
+ policyholderForm,
682
+ slaveInsuredForm,
683
+ beneficiaryFiltered,
684
+ hasDigitalDocuments,
685
+ documentListFiltered,
686
+ isDigitalDocDisabled,
332
687
  isUnderwriterDocuments,
333
688
 
334
689
  // Functions
335
- getFile,
690
+ getCode,
691
+ getDoc,
336
692
  openPanel,
337
693
  deleteFile,
694
+ getDigitalDocument,
338
695
  onFileChange,
339
696
  onUnderFiles,
697
+ openDigitalDocPanel,
340
698
  uploadUnderFiles,
341
699
  onClearUnderFiles,
700
+ uploadAdditionalFile,
701
+ memberHasDocumentsToSign,
342
702
  };
343
703
  },
344
704
  });
345
705
  </script>
706
+
707
+ <style>
708
+ .document-type-select .v-field {
709
+ border: none !important;
710
+ border-radius: 4px;
711
+ height: 56px;
712
+ }
713
+ .digital-document-otp .base-otp-input .v-otp-input__content {
714
+ gap: 8px;
715
+ padding-right: 0px !important;
716
+ padding-left: 0px !important;
717
+ }
718
+ .digital-doc-info .v-expansion-panel-text__wrapper {
719
+ padding: 8px 14px !important;
720
+ }
721
+ .digital-doc-info .v-expansion-panel-title {
722
+ max-height: 40px !important;
723
+ min-height: 39px !important;
724
+ padding: 0px 14px !important;
725
+ color: #464f60 !important;
726
+ }
727
+ .document-type-select .v-field-label--floating {
728
+ top: 5px !important;
729
+ }
730
+ .document-type-select .v-field__input {
731
+ padding-top: 21px;
732
+ }
733
+ </style>