hl-core 0.0.10-beta.3 → 0.0.10-beta.31

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 (52) hide show
  1. package/README.md +0 -2
  2. package/api/base.api.ts +300 -190
  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 +17 -8
  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/TextInput.vue +2 -0
  21. package/components/Layout/Drawer.vue +2 -0
  22. package/components/Pages/Anketa.vue +166 -167
  23. package/components/Pages/Auth.vue +2 -0
  24. package/components/Pages/ContragentForm.vue +2 -1
  25. package/components/Pages/Documents.vue +429 -59
  26. package/components/Pages/MemberForm.vue +327 -159
  27. package/components/Pages/ProductConditions.vue +681 -150
  28. package/components/Panel/PanelHandler.vue +261 -114
  29. package/components/Transitions/Animation.vue +2 -0
  30. package/components/Utilities/Chip.vue +3 -1
  31. package/components/Utilities/JsonViewer.vue +1 -2
  32. package/composables/classes.ts +133 -42
  33. package/composables/constants.ts +41 -0
  34. package/composables/fields.ts +6 -4
  35. package/composables/index.ts +246 -7
  36. package/composables/styles.ts +8 -24
  37. package/configs/pwa.ts +1 -7
  38. package/layouts/clear.vue +1 -1
  39. package/layouts/default.vue +1 -1
  40. package/layouts/full.vue +1 -1
  41. package/locales/ru.json +44 -14
  42. package/nuxt.config.ts +10 -13
  43. package/package.json +13 -12
  44. package/plugins/head.ts +2 -1
  45. package/store/data.store.ts +670 -480
  46. package/store/member.store.ts +18 -6
  47. package/store/rules.ts +21 -2
  48. package/tsconfig.json +3 -0
  49. package/types/enum.ts +20 -2
  50. package/types/env.d.ts +2 -2
  51. package/types/form.ts +71 -74
  52. package/types/index.ts +916 -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,31 @@ 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() && currentDocument.value.signed === true && currentDocument.value.signedType === 2;
366
+ if (formStore.applicationData.statusCode === 'AttachAppContractForm')
367
+ return canDeleteInPension && (currentDocument.value.fileTypeCode === '5' || currentDocument.value.fileTypeCode === '19');
368
+ if (formStore.applicationData.statusCode === 'ContractSignedFrom') return canDeleteInPension && currentDocument.value.fileTypeCode === '6';
193
369
  }
194
- if (dataStore.isPension) return baseCondition;
195
370
  return false;
196
371
  });
197
372
 
373
+ const policyholderForm = computed(() => formStore.policyholderForm as Base.Document.Digital);
374
+ const insuredFiltered = computed(() => formStore.insuredForm.filter(i => i.iin !== formStore.policyholderForm.iin) as Base.Document.Digital[]);
375
+ const beneficiaryFiltered = computed(() => formStore.beneficiaryForm.filter(i => i.iin !== formStore.policyholderForm.iin) as Base.Document.Digital[]);
376
+ const slaveInsuredForm = computed(() => formStore.slaveInsuredForm as Base.Document.Digital);
377
+ const documentListFiltered = computed(() => formStore.signedDocumentList.filter(i => !['1', '2', '4'].includes(String(i.fileTypeCode))));
378
+ const jointMembers = ref<Member[]>([formStore.insuredForm[0]]);
379
+
198
380
  const openPanel = async (document: DocumentItem) => {
199
381
  dataStore.rightPanel.title = document.fileTypeName!;
200
382
  currentDocument.value = document;
201
383
  dataStore.rightPanel.open = true;
384
+ isDigitalDocOpen.value = false;
385
+ isPanelOpen.value = true;
386
+ dataStore.panelAction = null;
202
387
  };
203
388
 
204
389
  const onFileChange = async (event: InputEvent) => {
@@ -208,7 +393,7 @@ export default defineComponent({
208
393
  if (files[0].size >= 20_000_000) {
209
394
  return dataStore.showToaster('error', dataStore.t('toaster.fileOnlyBelow20mb'), 6000);
210
395
  }
211
- if (files[0].type !== 'application/pdf') {
396
+ if (files[0].type !== constants.fileTypes.pdf) {
212
397
  return dataStore.showToaster('error', dataStore.t('toaster.onlyPDF'), 6000);
213
398
  }
214
399
  signedContract.fileName = files[0].name;
@@ -263,6 +448,17 @@ export default defineComponent({
263
448
  }
264
449
  };
265
450
 
451
+ const openDigitalDocPanel = async (iin: string, title: string) => {
452
+ isPanelOpen.value = false;
453
+ isDigitalDocOpen.value = true;
454
+ dataStore.panelAction = null;
455
+ dataStore.rightPanel.open = true;
456
+ dataStore.rightPanel.title = `Получить ЦД ${title}`;
457
+ documentType.value = null;
458
+ otpCode.value = '';
459
+ currentIin.value = iin;
460
+ };
461
+
266
462
  watch(
267
463
  () => document_list.value,
268
464
  () => {
@@ -293,18 +489,143 @@ export default defineComponent({
293
489
  const data = {
294
490
  id: currentDocument.value.id,
295
491
  processInstanceId: currentDocument.value.processInstanceId,
492
+ iin: currentDocument.value.iin ?? '',
296
493
  };
297
494
  await dataStore.deleteFile(data);
298
495
  deletionDialog.value = false;
299
496
  dataStore.rightPanel.open = false;
300
497
  dataStore.panelAction = null;
301
498
  await dataStore.getSignedDocList(formStore.applicationData.processInstanceId);
499
+ if (hasDigitalDocuments.value && (currentDocument.value.fileTypeCode === '1' || currentDocument.value.fileTypeCode === '2' || currentDocument.value.fileTypeCode === '4')) {
500
+ getDigitalDocs();
501
+ }
502
+ }
503
+ };
504
+
505
+ const getCode = async () => {
506
+ if (!documentType.value) {
507
+ dataStore.showToaster('error', 'Выберите тип документа', 3000);
508
+ return;
509
+ }
510
+ documentLoading.value = true;
511
+ const response = await dataStore.getOnlineAccess(currentIin.value, String(documentType.value));
512
+ if (response) {
513
+ dataStore.showToaster('success', dataStore.t('toaster.successOtp'), 3000);
514
+ }
515
+ documentLoading.value = false;
516
+ };
517
+
518
+ const getDigitalDocument = async () => {
519
+ if (!documentType.value) {
520
+ dataStore.showToaster('error', 'Выберите тип документа', 3000);
521
+ return;
522
+ }
523
+ if (!otpCode.value) {
524
+ dataStore.showToaster('error', 'Введите код подтверждения', 3000);
525
+ return;
526
+ }
527
+ documentLoading.value = true;
528
+ const response = await dataStore.getDigitalDocuments(currentIin.value, String(formStore.applicationData.processInstanceId), otpCode.value);
529
+ if (response) {
530
+ await dataStore.getSignedDocList(formStore.applicationData.processInstanceId);
531
+ getDigitalDocs();
532
+ isDigitalDocOpen.value = false;
533
+ dataStore.panelAction = null;
534
+ dataStore.rightPanel.open = false;
535
+ documentType.value = null;
536
+ otpCode.value = '';
537
+ }
538
+ documentLoading.value = false;
539
+ };
540
+
541
+ const findCommonDocs = (members: Base.Document.Digital[]) => {
542
+ let commonDocs: IDocument[] = [];
543
+ for (let member of members) {
544
+ const matchingDoc = formStore.signedDocumentList.find(
545
+ doc => doc.iin === String(member.iin).replaceAll('-', '') && (doc.fileTypeCode === '1' || doc.fileTypeCode === '2' || doc.fileTypeCode === '4'),
546
+ );
547
+ if (matchingDoc) commonDocs.push(matchingDoc);
548
+ }
549
+ return commonDocs;
550
+ };
551
+
552
+ const setDigitalDocuments = (members: Base.Document.Digital[]) => {
553
+ const commonDocs = findCommonDocs(members);
554
+ if (commonDocs.length !== 0) {
555
+ for (let member of members) {
556
+ const matchingDoc = commonDocs.find(doc => doc.iin === String(member.iin).replaceAll('-', ''));
557
+ if (matchingDoc) member.digitalDocument = matchingDoc;
558
+ }
559
+ }
560
+ };
561
+
562
+ const clearDigitalDocuments = (members: Base.Document.Digital[]) => {
563
+ for (let member of members) member.digitalDocument = null;
564
+ };
565
+
566
+ const getDigitalDocs = () => {
567
+ if (route.params.taskId !== '0') {
568
+ clearDigitalDocuments([formStore.policyholderForm as Base.Document.Digital]);
569
+ setDigitalDocuments([formStore.policyholderForm as Base.Document.Digital]);
570
+ if (insuredFiltered.value.length !== 0) {
571
+ clearDigitalDocuments(insuredFiltered.value);
572
+ setDigitalDocuments(insuredFiltered.value);
573
+ }
574
+ if (beneficiaryFiltered.value.length !== 0) {
575
+ clearDigitalDocuments(beneficiaryFiltered.value);
576
+ setDigitalDocuments(beneficiaryFiltered.value);
577
+ }
578
+ }
579
+ };
580
+
581
+ const memberHasDocumentsToSign = (iin: string | null) => {
582
+ if (!iin) return false;
583
+ // TODO reformat logic
584
+ return (
585
+ formStore.signedDocumentList.filter(i => formStore.requiredDocuments.find(j => j.code === i.fileTypeCode) && i.iin === iin.replaceAll('-', '')).length !==
586
+ formStore.requiredDocuments.filter(i => i.iin === iin.replaceAll('-', '')).length
587
+ );
588
+ };
589
+
590
+ const uploadAdditionalFile = async (event: InputEvent, code: string, iin?: string | null) => {
591
+ if (event.target) {
592
+ const files = (event.target as HTMLInputElement).files;
593
+ if (files && files.length && files[0]) {
594
+ if (files[0].type !== constants.fileTypes.pdf && files[0].type !== constants.fileTypes.docx && files[0].type !== constants.fileTypes.doc) {
595
+ return dataStore.showToaster('error', dataStore.t('toaster.onlyWithFormat', { format: 'PDF, Word' }), 6000);
596
+ }
597
+ if (files[0].size >= 10_000_000) {
598
+ return dataStore.showToaster('error', dataStore.t('toaster.fileOnlyBelow10mb'), 6000);
599
+ }
600
+ const file = Object.assign(files[0]);
601
+ const formData = new FormData();
602
+ const information: any = [];
603
+ const uuidV4 = uuid.v4();
604
+ formData.append('file', file);
605
+ const ext = file.name.substring(file.name.lastIndexOf('.'));
606
+ const selectedDocument = dataStore.dicFileTypeList.find((i: Value) => i.code === code);
607
+ information.push({
608
+ identifier: `${uuidV4}${ext}`,
609
+ iin: iin ? iin.replaceAll('-', '') : null,
610
+ processInstanceId: formStore.applicationData.processInstanceId,
611
+ fileTypeCode: selectedDocument ? selectedDocument.code : null,
612
+ fileTypeId: selectedDocument ? selectedDocument.id : null,
613
+ fileName: file.name,
614
+ });
615
+ formData.append('fileData', JSON.stringify(information));
616
+ dataStore.isLoading = true;
617
+ await dataStore.uploadFiles(formData, false);
618
+ await dataStore.getSignedDocList(formStore.applicationData.processInstanceId);
619
+ }
620
+ dataStore.isLoading = false;
302
621
  }
303
622
  };
304
623
 
305
624
  const onInit = async () => {
306
625
  await dataStore.getDicFileTypeList();
307
626
  await dataStore.getSignedDocList(formStore.applicationData.processInstanceId);
627
+ if (hasDigitalDocuments.value) getDigitalDocs();
628
+ if (processCode === 25) jointMembers.value.push(slaveInsuredForm.value as Member);
308
629
  };
309
630
 
310
631
  onInit();
@@ -315,30 +636,79 @@ export default defineComponent({
315
636
 
316
637
  return {
317
638
  // State
639
+ otpCode,
318
640
  formStore,
319
- documentLoading,
641
+ currentIin,
642
+ processCode,
643
+ isPanelOpen,
644
+ jointMembers,
320
645
  DocumentItem,
646
+ documentType,
647
+ documentItems,
321
648
  signedContract,
322
649
  deletionDialog,
323
- processCode,
650
+ currentDocument,
651
+ documentLoading,
652
+ isDigitalDocOpen,
324
653
  underDocumentsList,
325
654
 
326
655
  // Computed
327
656
  isDisabled,
657
+ requiredSign,
328
658
  showContract,
329
659
  noDocuments,
330
660
  canDeleteFiles,
661
+ insuredFiltered,
662
+ policyholderForm,
663
+ slaveInsuredForm,
664
+ beneficiaryFiltered,
665
+ hasDigitalDocuments,
666
+ documentListFiltered,
667
+ isDigitalDocDisabled,
331
668
  isUnderwriterDocuments,
332
669
 
333
670
  // Functions
671
+ getCode,
334
672
  getFile,
335
673
  openPanel,
336
674
  deleteFile,
675
+ getDigitalDocument,
337
676
  onFileChange,
338
677
  onUnderFiles,
678
+ openDigitalDocPanel,
339
679
  uploadUnderFiles,
340
680
  onClearUnderFiles,
681
+ uploadAdditionalFile,
682
+ memberHasDocumentsToSign,
341
683
  };
342
684
  },
343
685
  });
344
686
  </script>
687
+
688
+ <style>
689
+ .document-type-select .v-field {
690
+ border: none !important;
691
+ border-radius: 4px;
692
+ height: 56px;
693
+ }
694
+ .digital-document-otp .base-otp-input .v-otp-input__content {
695
+ gap: 8px;
696
+ padding-right: 0px !important;
697
+ padding-left: 0px !important;
698
+ }
699
+ .digital-doc-info .v-expansion-panel-text__wrapper {
700
+ padding: 8px 14px !important;
701
+ }
702
+ .digital-doc-info .v-expansion-panel-title {
703
+ max-height: 40px !important;
704
+ min-height: 39px !important;
705
+ padding: 0px 14px !important;
706
+ color: #464f60 !important;
707
+ }
708
+ .document-type-select .v-field-label--floating {
709
+ top: 5px !important;
710
+ }
711
+ .document-type-select .v-field__input {
712
+ padding-top: 21px;
713
+ }
714
+ </style>