hl-core 0.0.10-beta.4 → 0.0.10-beta.41

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 (53) hide show
  1. package/README.md +0 -2
  2. package/api/base.api.ts +338 -191
  3. package/api/interceptors.ts +3 -5
  4. package/components/Complex/TextBlock.vue +2 -0
  5. package/components/Dialog/Dialog.vue +7 -1
  6. package/components/Dialog/FamilyDialog.vue +2 -0
  7. package/components/Form/DigitalDocument.vue +52 -0
  8. package/components/Form/DynamicForm.vue +1 -0
  9. package/components/Form/FormData.vue +1 -0
  10. package/components/Form/ManagerAttachment.vue +48 -10
  11. package/components/Form/ProductConditionsBlock.vue +12 -6
  12. package/components/Input/Datepicker.vue +5 -0
  13. package/components/Input/DynamicInput.vue +2 -0
  14. package/components/Input/FormInput.vue +7 -0
  15. package/components/Input/OtpInput.vue +25 -0
  16. package/components/Input/PanelInput.vue +1 -0
  17. package/components/Input/RoundedInput.vue +4 -0
  18. package/components/Input/RoundedSelect.vue +4 -0
  19. package/components/Input/SwitchInput.vue +2 -0
  20. package/components/Input/TextAreaField.vue +71 -0
  21. package/components/Input/TextInput.vue +2 -0
  22. package/components/Layout/Drawer.vue +2 -0
  23. package/components/Menu/MenuNav.vue +1 -1
  24. package/components/Pages/Anketa.vue +168 -169
  25. package/components/Pages/Auth.vue +2 -0
  26. package/components/Pages/ContragentForm.vue +2 -1
  27. package/components/Pages/Documents.vue +432 -59
  28. package/components/Pages/MemberForm.vue +334 -160
  29. package/components/Pages/ProductConditions.vue +838 -226
  30. package/components/Panel/PanelHandler.vue +280 -121
  31. package/components/Transitions/Animation.vue +2 -0
  32. package/components/Utilities/Chip.vue +3 -1
  33. package/components/Utilities/JsonViewer.vue +1 -2
  34. package/composables/classes.ts +143 -49
  35. package/composables/constants.ts +44 -0
  36. package/composables/fields.ts +6 -4
  37. package/composables/index.ts +298 -7
  38. package/composables/styles.ts +8 -24
  39. package/configs/pwa.ts +1 -7
  40. package/layouts/clear.vue +1 -1
  41. package/layouts/default.vue +1 -1
  42. package/layouts/full.vue +1 -1
  43. package/locales/ru.json +80 -19
  44. package/nuxt.config.ts +10 -13
  45. package/package.json +12 -12
  46. package/plugins/head.ts +2 -1
  47. package/store/data.store.ts +802 -531
  48. package/store/member.store.ts +18 -6
  49. package/store/rules.ts +22 -2
  50. package/types/enum.ts +33 -2
  51. package/types/env.d.ts +2 -2
  52. package/types/form.ts +71 -74
  53. package/types/index.ts +924 -873
@@ -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,56 +190,18 @@
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')" />
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="getFile('view')"
203
+ />
204
+ </base-animation>
104
205
  <base-btn :disabled="documentLoading" :loading="documentLoading" text="Скачать" @click="getFile('download')" />
105
206
  <base-animation>
106
207
  <base-btn v-if="canDeleteFiles" :disabled="documentLoading" :loading="documentLoading" text="Удалить" @click="deletionDialog = true" />
@@ -108,6 +209,47 @@
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,19 +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';
269
+ import type { Base, FileActions } from '../../types';
126
270
 
127
271
  export default defineComponent({
128
272
  setup() {
273
+ type DigitalDocNames = 'Удостоверение личности' | 'Паспорт' | 'Вид на жительство иностранного гражданина';
274
+ type DigitalDocTypes = 'IdentityCard' | 'Passport' | 'Vnzh';
275
+
276
+ const route = useRoute();
129
277
  const dataStore = useDataStore();
130
278
  const formStore = useFormStore();
131
279
  const currentDocument = ref<DocumentItem>(new DocumentItem());
132
280
  const documentLoading = ref<boolean>(false);
133
281
  const deletionDialog = ref<boolean>(false);
282
+ const isPanelOpen = ref<boolean>(false);
283
+ const isDigitalDocOpen = ref<boolean>(false);
134
284
  const isDisabled = computed(() => !dataStore.isTask());
135
285
  const contractDict = computed(() => dataStore.dicFileTypeList.find(i => i.nameRu === 'Договор страхования' || i.nameRu === 'Договор'));
136
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
+ ];
137
309
  const signedContract = reactive<{
138
310
  processInstanceId: string | number;
139
311
  fileTypeId: string | number | null;
@@ -171,12 +343,10 @@ export default defineComponent({
171
343
  }),
172
344
  );
173
345
  const showContract = computed(
174
- () =>
175
- formStore.applicationData &&
176
- (formStore.applicationData.statusCode === 'Completed' || formStore.applicationData.statusCode === 'PreparationDossierForm' || dataStore.isActuary()),
346
+ () => formStore.applicationData && (dataStore.isAdmin() || dataStore.isSupport() || (dataStore.isActuary() && formStore.applicationData.statusCode === 'ActuaryForm')),
177
347
  );
178
348
  const noDocuments = computed(() => {
179
- if (dataStore.isPension) return !showContract.value;
349
+ if (dataStore.isPension && (!formStore.signedDocumentList || !formStore.signedDocumentList.length)) return !showContract.value;
180
350
  return !formStore.signedDocumentList || !formStore.signedDocumentList.length;
181
351
  });
182
352
  const isUnderwriterDocuments = computed(
@@ -189,16 +359,34 @@ export default defineComponent({
189
359
  const canDeleteFiles = computed(() => {
190
360
  const baseCondition = dataStore.isTask() && dataStore.isInitiator() && dataStore.isProcessEditable(formStore.applicationData.statusCode);
191
361
  if (dataStore.isBaiterek || dataStore.isBolashak || dataStore.isLiferenta || dataStore.isKazyna || dataStore.isAmulet || dataStore.isGons) {
192
- 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';
193
372
  }
194
- if (dataStore.isPension) return baseCondition;
195
373
  return false;
196
374
  });
197
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
+
198
383
  const openPanel = async (document: DocumentItem) => {
199
384
  dataStore.rightPanel.title = document.fileTypeName!;
200
385
  currentDocument.value = document;
201
386
  dataStore.rightPanel.open = true;
387
+ isDigitalDocOpen.value = false;
388
+ isPanelOpen.value = true;
389
+ dataStore.panelAction = null;
202
390
  };
203
391
 
204
392
  const onFileChange = async (event: InputEvent) => {
@@ -208,7 +396,7 @@ export default defineComponent({
208
396
  if (files[0].size >= 20_000_000) {
209
397
  return dataStore.showToaster('error', dataStore.t('toaster.fileOnlyBelow20mb'), 6000);
210
398
  }
211
- if (files[0].type !== 'application/pdf') {
399
+ if (files[0].type !== constants.fileTypes.pdf) {
212
400
  return dataStore.showToaster('error', dataStore.t('toaster.onlyPDF'), 6000);
213
401
  }
214
402
  signedContract.fileName = files[0].name;
@@ -263,6 +451,17 @@ export default defineComponent({
263
451
  }
264
452
  };
265
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
+
266
465
  watch(
267
466
  () => document_list.value,
268
467
  () => {
@@ -293,18 +492,143 @@ export default defineComponent({
293
492
  const data = {
294
493
  id: currentDocument.value.id,
295
494
  processInstanceId: currentDocument.value.processInstanceId,
495
+ iin: currentDocument.value.iin ?? '',
296
496
  };
297
497
  await dataStore.deleteFile(data);
298
498
  deletionDialog.value = false;
299
499
  dataStore.rightPanel.open = false;
300
500
  dataStore.panelAction = null;
301
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;
302
624
  }
303
625
  };
304
626
 
305
627
  const onInit = async () => {
306
628
  await dataStore.getDicFileTypeList();
307
629
  await dataStore.getSignedDocList(formStore.applicationData.processInstanceId);
630
+ if (hasDigitalDocuments.value) getDigitalDocs();
631
+ if (processCode === 25) jointMembers.value.push(slaveInsuredForm.value as Member);
308
632
  };
309
633
 
310
634
  onInit();
@@ -315,30 +639,79 @@ export default defineComponent({
315
639
 
316
640
  return {
317
641
  // State
642
+ otpCode,
318
643
  formStore,
319
- documentLoading,
644
+ currentIin,
645
+ processCode,
646
+ isPanelOpen,
647
+ jointMembers,
320
648
  DocumentItem,
649
+ documentType,
650
+ documentItems,
321
651
  signedContract,
322
652
  deletionDialog,
323
- processCode,
653
+ currentDocument,
654
+ documentLoading,
655
+ isDigitalDocOpen,
324
656
  underDocumentsList,
325
657
 
326
658
  // Computed
327
659
  isDisabled,
660
+ requiredSign,
328
661
  showContract,
329
662
  noDocuments,
330
663
  canDeleteFiles,
664
+ insuredFiltered,
665
+ policyholderForm,
666
+ slaveInsuredForm,
667
+ beneficiaryFiltered,
668
+ hasDigitalDocuments,
669
+ documentListFiltered,
670
+ isDigitalDocDisabled,
331
671
  isUnderwriterDocuments,
332
672
 
333
673
  // Functions
674
+ getCode,
334
675
  getFile,
335
676
  openPanel,
336
677
  deleteFile,
678
+ getDigitalDocument,
337
679
  onFileChange,
338
680
  onUnderFiles,
681
+ openDigitalDocPanel,
339
682
  uploadUnderFiles,
340
683
  onClearUnderFiles,
684
+ uploadAdditionalFile,
685
+ memberHasDocumentsToSign,
341
686
  };
342
687
  },
343
688
  });
344
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>