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

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