hl-core 0.0.9-beta.8 → 0.0.10-beta.1

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 (72) hide show
  1. package/api/base.api.ts +1109 -0
  2. package/api/index.ts +2 -620
  3. package/api/interceptors.ts +38 -1
  4. package/components/Button/Btn.vue +1 -6
  5. package/components/Complex/MessageBlock.vue +1 -1
  6. package/components/Complex/Page.vue +1 -1
  7. package/components/Complex/TextBlock.vue +23 -0
  8. package/components/Dialog/Dialog.vue +70 -16
  9. package/components/Dialog/FamilyDialog.vue +1 -1
  10. package/components/Form/DynamicForm.vue +100 -0
  11. package/components/Form/FormBlock.vue +12 -3
  12. package/components/Form/FormData.vue +110 -0
  13. package/components/Form/FormSection.vue +3 -3
  14. package/components/Form/FormTextSection.vue +11 -3
  15. package/components/Form/FormToggle.vue +25 -5
  16. package/components/Form/ManagerAttachment.vue +177 -89
  17. package/components/Form/ProductConditionsBlock.vue +59 -6
  18. package/components/Input/Datepicker.vue +43 -7
  19. package/components/Input/DynamicInput.vue +23 -0
  20. package/components/Input/FileInput.vue +25 -5
  21. package/components/Input/FormInput.vue +7 -4
  22. package/components/Input/Monthpicker.vue +34 -0
  23. package/components/Input/PanelInput.vue +5 -1
  24. package/components/Input/RoundedSelect.vue +7 -2
  25. package/components/Input/SwitchInput.vue +64 -0
  26. package/components/Input/TextInput.vue +160 -0
  27. package/components/Layout/Drawer.vue +17 -4
  28. package/components/Layout/Header.vue +23 -2
  29. package/components/Layout/Loader.vue +2 -1
  30. package/components/Layout/SettingsPanel.vue +24 -11
  31. package/components/Menu/InfoMenu.vue +35 -0
  32. package/components/Menu/MenuNav.vue +25 -3
  33. package/components/Pages/Anketa.vue +254 -65
  34. package/components/Pages/Auth.vue +56 -9
  35. package/components/Pages/ContragentForm.vue +9 -9
  36. package/components/Pages/Documents.vue +266 -30
  37. package/components/Pages/InvoiceInfo.vue +1 -1
  38. package/components/Pages/MemberForm.vue +774 -102
  39. package/components/Pages/ProductAgreement.vue +1 -8
  40. package/components/Pages/ProductConditions.vue +1132 -180
  41. package/components/Panel/PanelHandler.vue +632 -50
  42. package/components/Panel/PanelSelectItem.vue +17 -2
  43. package/components/Panel/RightPanelCloser.vue +7 -0
  44. package/components/Transitions/Animation.vue +28 -0
  45. package/components/Utilities/JsonViewer.vue +3 -2
  46. package/components/Utilities/Qr.vue +44 -0
  47. package/composables/axios.ts +1 -0
  48. package/composables/classes.ts +501 -14
  49. package/composables/constants.ts +126 -6
  50. package/composables/fields.ts +328 -0
  51. package/composables/index.ts +355 -20
  52. package/composables/styles.ts +23 -6
  53. package/configs/pwa.ts +63 -0
  54. package/layouts/clear.vue +21 -0
  55. package/layouts/default.vue +62 -3
  56. package/layouts/full.vue +21 -0
  57. package/locales/ru.json +559 -16
  58. package/nuxt.config.ts +11 -15
  59. package/package.json +36 -39
  60. package/pages/Token.vue +0 -13
  61. package/plugins/head.ts +26 -0
  62. package/plugins/vuetifyPlugin.ts +1 -5
  63. package/store/data.store.ts +1610 -321
  64. package/store/extractStore.ts +17 -0
  65. package/store/form.store.ts +13 -1
  66. package/store/member.store.ts +1 -1
  67. package/store/rules.ts +97 -3
  68. package/store/toast.ts +1 -1
  69. package/types/enum.ts +81 -0
  70. package/types/env.d.ts +2 -0
  71. package/types/form.ts +94 -0
  72. package/types/index.ts +419 -24
@@ -17,57 +17,187 @@
17
17
  >{{ `Запрашиваемая страховая сумма: ` }} <b>{{ `${requestedSumInsured}₸` }}</b>
18
18
  </span>
19
19
  </base-content-block>
20
- <base-btn :text="$dataStore.t('confirm.yes')" @click="handleTask" />
21
- <base-btn :btn="$styles.blueLightBtn" :text="$dataStore.t('confirm.no')" @click="closePanel" />
20
+ <base-content-block v-if="$dataStore.isLifetrip" class="flex flex-col gap-3">
21
+ <span
22
+ >{{ `Стоимость на страховую сумму ${insuredAmount}:` }} <b>{{ `${price}₸` }}</b></span
23
+ >
24
+ </base-content-block>
25
+ <div class="flex flex-col gap-3" v-if="hasConditionsAction">
26
+ <base-btn :text="$dataStore.t('confirm.yes')" @click="handleTask" />
27
+ <base-btn :btn="$styles.blueLightBtn" :text="$dataStore.t('confirm.no')" @click="closePanel" />
28
+ </div>
22
29
  </div>
23
30
  </section>
24
- <section v-if="signingActions" class="relative">
25
- <div>
26
- <base-fade-transition>
27
- <div v-if="!isSendNumberOpen" :class="[$styles.flexColNav]">
28
- <div :class="[$styles.blueBgLight]" class="rounded-lg p-4">
29
- <v-expansion-panels v-if="formStore.signUrls && formStore.signUrls.length" variant="accordion" multiple>
30
- <v-expansion-panel v-for="signUrl of formStore.signUrls" :key="signUrl.iin!" class="border-[1px]" elevation="0" bg-color="#FFF">
31
- <v-expansion-panel-title class="h-[80px]" :class="$styles.textTitle">{{ `${signUrl.longName} - ${signUrl.iin}` }}</v-expansion-panel-title>
32
- <v-expansion-panel-text class="border-t-[1px]">
33
- <section class="flex flex-col gap-4 py-3" :class="$styles.textSimple">
34
- <base-btn :loading="loading" :text="$dataStore.t('sign.copyCloud')" @click="$dataStore.copyToClipboard(signUrl.uri)" />
35
- <base-btn :loading="loading" :btn="$styles.blueLightBtn" :text="$dataStore.t('sign.recipientNumber')" @click="openSmsPanel(signUrl)" />
36
- </section>
37
- </v-expansion-panel-text>
38
- </v-expansion-panel>
39
- </v-expansion-panels>
40
- <base-list-empty v-else />
31
+ <section v-if="chooseSignActions">
32
+ <div v-if="!isElectronicContract && !isPaperContract && !isScansDocuments && !isQr" :class="[$styles.flexColNav]">
33
+ <base-btn :text="$dataStore.t('buttons.sendOnPaper')" :disabled="isPaperDisabled" :loading="loading" @click="handleSignAction('paper')" />
34
+ <base-btn :text="$dataStore.t('buttons.sendElectronically')" :disabled="isElectronicDisabled" :loading="loading" @click="handleSignAction('electronic')" />
35
+ <base-btn :text="$dataStore.t('buttons.generatePrintedForms')" :disabled="isScansDisabled" :loading="loading" @click="handleSignAction('scans')" />
36
+ <base-btn v-if="!useEnv().isProduction" :text="$dataStore.t('buttons.sendEgovMob')" :disabled="isQrDisabled" :loading="loading" @click="handleSignAction('qr')" />
37
+ <base-btn
38
+ v-if="$dataStore.isPension"
39
+ :text="$dataStore.t('buttons.signWithSignature')"
40
+ :disabled="isSignatureDisabled"
41
+ :loading="loading"
42
+ @click="handleSignAction('signature')"
43
+ />
44
+ <base-btn
45
+ v-if="$dataStore.isPension && !useEnv().isProduction"
46
+ :text="$dataStore.t('buttons.signWithSignatureXML')"
47
+ :disabled="isQrXmlDisabled"
48
+ :loading="loading"
49
+ @click="handleSignAction('qrXml')"
50
+ />
51
+ </div>
52
+ <div v-if="isPaperContract" :class="[$styles.flexColNav]">
53
+ <base-btn :text="$dataStore.t('buttons.downloadContract')" :loading="$dataStore.isButtonsLoading" @click="generateDocument" />
54
+ </div>
55
+ <div v-if="isScansDocuments" :class="[$styles.flexColNav]">
56
+ <div v-if="$dataStore.isPension">
57
+ <div v-if="processCode == 19">
58
+ <div v-if="formStore.applicationData.statusCode === 'HeadManagerForm' || formStore.applicationData.statusCode === 'ContractSignedFrom'">
59
+ <base-btn :text="$dataStore.t('buttons.downloadContract')" :loading="$dataStore.isButtonsLoading" @click="$dataStore.generatePDFDocument('PA_Contract', '38')" />
60
+ <base-form-section class="mt-4 flex flex-col !gap-2" :title="$dataStore.t('clients.attachScansSignDocs')">
61
+ <base-file-input :label="$dataStore.t('labels.attachContract')" @input.prevent="onFileChangeScans($event, 'pa_contract')" @onClear="onClearFile('pa_contract')" />
62
+ </base-form-section>
63
+ </div>
64
+ <div v-else class="flex flex-col gap-2">
65
+ <base-btn :text="$dataStore.t('buttons.downloadStatement')" :loading="$dataStore.isButtonsLoading" @click="$dataStore.generatePDFDocument('PA_Statement', '37')" />
66
+ <base-btn :text="$dataStore.t('buttons.downloadAgreement')" :loading="$dataStore.isButtonsLoading" @click="$dataStore.generatePDFDocument('Agreement', '19')" />
67
+ <base-form-section class="mt-4 flex flex-col !gap-2" :title="$dataStore.t('clients.attachScansSignDocs')">
68
+ <base-file-input :label="$dataStore.t('labels.attachStatement')" @input.prevent="onFileChangeScans($event, 'pa_statement')" @onClear="onClearFile('pa_statement')" />
69
+ <base-file-input :label="$dataStore.t('labels.attachAgreement')" @input.prevent="onFileChangeScans($event, 'agreement')" @onClear="onClearFile('agreement')" />
70
+ </base-form-section>
41
71
  </div>
42
72
  </div>
43
- <div v-if="isSendNumberOpen" :class="[$styles.flexColNav]">
44
- <i
45
- class="mdi mdi-arrow-left cursor-pointer absolute text-xl left-0 top-0 rounded-br-full bg-white border-[1px] pb-3 pt-1 pl-1 pr-3"
46
- @click="isSendNumberOpen = false"
47
- ></i>
48
- <base-form-section :title="selectedClient && selectedClient.longName ? selectedClient.longName : ''">
49
- <v-form ref="vForm">
50
- <base-rounded-input
51
- v-model="phoneNumber"
52
- :maska="$maska.phone"
53
- :rules="$rules.required.concat($rules.phoneFormat)"
54
- :label="$dataStore.t('form.phoneNumber')"
55
- placeholder="+7 7"
56
- />
57
- </v-form>
58
- <base-btn :text="$dataStore.t('buttons.sendSMS')" :loading="loading" @click="submitForm"
59
- /></base-form-section>
73
+ <div v-if="processCode == 2" class="flex flex-col gap-2">
74
+ <base-btn
75
+ :text="$dataStore.t('buttons.downloadPARefundStatement')"
76
+ :loading="$dataStore.isButtonsLoading"
77
+ @click="$dataStore.generatePDFDocument('PA_RefundStatement', '41')"
78
+ />
79
+ <base-btn
80
+ :text="$dataStore.t('buttons.downloadPARefundAgreement')"
81
+ :loading="$dataStore.isButtonsLoading"
82
+ @click="$dataStore.generatePDFDocument('PA_RefundAgreement', '42')"
83
+ />
84
+
85
+ <base-form-section class="mt-4 flex flex-col !gap-2" :title="$dataStore.t('clients.attachScansSignDocs')">
86
+ <base-file-input
87
+ :label="$dataStore.t('buttons.downloadPARefundStatement')"
88
+ @input.prevent="onFileChangeScans($event, 'pa_refundstatement')"
89
+ @onClear="onClearFile('pa_refundstatement')"
90
+ />
91
+ <base-file-input
92
+ :label="$dataStore.t('buttons.downloadPARefundAgreement')"
93
+ @input.prevent="onFileChangeScans($event, 'pa_refundagreement')"
94
+ @onClear="onClearFile('pa_refundagreement')"
95
+ />
96
+ </base-form-section>
60
97
  </div>
61
- </base-fade-transition>
98
+ </div>
99
+ <div :class="[$styles.flexColNav]" v-else>
100
+ <base-btn :text="$dataStore.t('buttons.downloadStatement')" @click="downloadTemplate(constants.documentTypes.statement, 'docx')" />
101
+ <base-btn :text="$dataStore.t('buttons.downloadContract')" @click="downloadTemplate(constants.documentTypes.contract, 'doc')" />
102
+ <base-btn :text="$dataStore.t('buttons.downloadApplication')" @click="downloadTemplate(constants.documentTypes.application1, 'vnd.ms-excel')" />
103
+ <base-form-section class="mt-4 flex flex-col !gap-2" :title="$dataStore.t('clients.attachScansSignDocs')">
104
+ <base-file-input :label="$dataStore.t('labels.attachStatement')" @input.prevent="onFileChangeScans($event, 'statement')" @onClear="onClearFile('statement')" />
105
+ <base-file-input :label="$dataStore.t('labels.attachContract')" @input.prevent="onFileChangeScans($event, 'contract')" @onClear="onClearFile('contract')" />
106
+ <base-file-input :label="$dataStore.t('labels.attachApplication')" @input.prevent="onFileChangeScans($event, 'app')" @onClear="onClearFile('app')" />
107
+ <base-file-input :label="$dataStore.t('labels.attachPowerOfAttorney')" @input.prevent="onFileChangeScans($event, 'attorney')" @onClear="onClearFile('attorney')" />
108
+ </base-form-section>
109
+ </div>
110
+ <base-btn :text="$dataStore.t('buttons.sign')" :loading="$dataStore.isButtonsLoading" @click="sendFiles" />
111
+ <base-btn :text="$dataStore.t('buttons.cancel')" :btn="$styles.whiteBtn" @click="isScansDocuments = false" />
112
+ </div>
113
+ <div v-if="isQr" :class="[$styles.flexColNav]">
114
+ <base-form-section :title="''">
115
+ <base-loader v-if="isQrLoading" class="self-center m-5 opacity-70" />
116
+ <div v-if="qrUrl && !isQrLoading">
117
+ <base-qr :value="qrUrl" :size="200" class="ma-auto rounded" />
118
+ <span :class="[$styles.textSimple]" class="mt-3 text-center d-block">{{ $dataStore.t('sign.scanQrCode') }}</span>
119
+ </div>
120
+ <base-btn class="mt-10" :loading="loading" :text="$dataStore.t('sign.copyEgov')" @click="$dataStore.copyToClipboard(urlCopy)" />
121
+ <base-btn :text="$dataStore.t('buttons.cancel')" :btn="$styles.whiteBtn" @click="closeQrPanel" />
122
+ </base-form-section>
123
+ </div>
124
+ </section>
125
+ <section v-if="choosePayActions">
126
+ <div v-if="!isEpayPay && !isOfflinePay" :class="[$styles.flexColNav]">
127
+ <base-btn :text="$dataStore.t('buttons.payEpay')" :loading="loading" @click="handlePayAction('epay')" />
128
+ <base-btn :text="$dataStore.t('buttons.payOffline')" :loading="loading" @click="handlePayAction('offline')" />
129
+ </div>
130
+ <div v-if="isOfflinePay" :class="[$styles.flexColNav]">
131
+ <base-form-section class="!gap-3 p-3" :title="''">
132
+ <v-form ref="vForm">
133
+ <base-form-input v-model="email" :rules="$rules.required.concat($rules.email)" :label="$dataStore.t('form.email')" />
134
+ </v-form>
135
+ <base-panel-item class="cursor-pointer bg-white border-b-0 rounded" @click="downloadTemplate(constants.documentTypes.invoicePayment, 'pdf')">
136
+ Счет на оплату.pdf
137
+ <i class="mdi mdi-download text-2xl text-[#A0B3D8]"></i
138
+ ></base-panel-item>
139
+ </base-form-section>
140
+ <base-btn :text="$dataStore.t('buttons.send')" :loading="$dataStore.isButtonsLoading" @click="sendInvoiceToEmail" />
62
141
  </div>
63
142
  </section>
143
+ <section v-if="signingActions" class="relative">
144
+ <base-fade-transition>
145
+ <div v-if="!isSendNumberOpen" :class="[$styles.flexColNav]">
146
+ <div :class="[$styles.blueBgLight]" class="rounded-lg p-4">
147
+ <v-expansion-panels v-if="formStore.signUrls && formStore.signUrls.length" variant="accordion" multiple>
148
+ <v-expansion-panel v-for="signUrl of formStore.signUrls" :key="signUrl.iin!" class="border-[1px]" elevation="0" bg-color="#FFF">
149
+ <v-expansion-panel-title class="h-[80px]" :class="$styles.textTitle">
150
+ {{ `${signUrl.longName} - ${signUrl.iin}` }}
151
+ </v-expansion-panel-title>
152
+ <v-expansion-panel-text class="border-t-[1px]">
153
+ <section class="flex flex-col gap-4 py-3" :class="$styles.textSimple">
154
+ <base-btn :loading="loading" :text="$dataStore.t('sign.copyCloud')" @click="$dataStore.copyToClipboard(signUrl.uri)" />
155
+ <base-btn :loading="loading" :btn="$styles.blueLightBtn" :text="$dataStore.t('sign.recipientNumber')" @click="openSmsPanel(signUrl)" />
156
+ <base-btn :loading="loading" :text="$dataStore.t('sign.convertQr')" @click="convertQr(signUrl.uri)" />
157
+ </section>
158
+ </v-expansion-panel-text>
159
+ </v-expansion-panel>
160
+ </v-expansion-panels>
161
+ <base-list-empty v-else />
162
+ </div>
163
+ </div>
164
+ <div v-if="isSendNumberOpen" :class="[$styles.flexColNav]">
165
+ <i class="mdi mdi-arrow-left cursor-pointer absolute text-xl left-0 top-0 rounded-br-full bg-white border-[1px] pb-3 pt-1 pl-1 pr-3" @click="isSendNumberOpen = false"></i>
166
+ <base-form-section :title="selectedClient && selectedClient.longName ? selectedClient.longName : ''">
167
+ <v-form ref="vForm">
168
+ <base-rounded-input
169
+ v-model="phoneNumber"
170
+ :maska="$maska.phone"
171
+ :rules="$rules.required.concat($rules.phoneFormat)"
172
+ :label="$dataStore.t('form.phoneNumber')"
173
+ placeholder="+7 7"
174
+ />
175
+ </v-form>
176
+ <base-btn :text="$dataStore.t('buttons.sendSMS')" :loading="loading" @click="submitForm" />
177
+ </base-form-section>
178
+ </div>
179
+ </base-fade-transition>
180
+ <base-btn
181
+ v-if="$dataStore.isPension"
182
+ :text="$dataStore.t('buttons.cancel')"
183
+ :btn="$styles.whiteBtn"
184
+ @click="
185
+ $dataStore.panelAction = constants.actions.chooseSign;
186
+ isElectronicContract = false;
187
+ "
188
+ />
189
+ </section>
64
190
  <section v-if="payingActions" class="relative">
65
191
  <div>
66
192
  <base-fade-transition>
67
- <div v-if="!isSendNumberOpen" :class="[$styles.flexColNav]">
68
- <base-btn :loading="loading" :text="$dataStore.t('payment.copyUrl')" @click="$dataStore.copyToClipboard(formStore.epayLink)" />
69
- <base-btn :loading="loading" :btn="$styles.blueLightBtn" :text="$dataStore.t('payment.recipientNumber')" @click="openEpayPanel" />
70
- </div>
193
+ <base-form-section v-if="!isSendNumberOpen" class="!p-3 m-[10px]">
194
+ <div class="flex flex-col gap-3">
195
+ <base-btn :loading="loading" :text="$dataStore.t('payment.copyUrl')" @click="$dataStore.copyToClipboard(formStore.epayLink)" />
196
+ <base-btn :loading="loading" :text="$dataStore.t('payment.recipientNumber')" @click="openEpayPanel" />
197
+ <base-btn :loading="loading" :text="$dataStore.t('sign.convertQr')" @click="convertQr(formStore.epayLink)" />
198
+ <base-btn :loading="loading" :btn="$styles.greenBtn" :text="$dataStore.t('payment.halykLink')" @click="convertQr(formStore.epayLink, 'halyk_pay_link_template')" />
199
+ </div>
200
+ </base-form-section>
71
201
  <div v-if="isSendNumberOpen" :class="[$styles.flexColNav]">
72
202
  <i
73
203
  class="mdi mdi-arrow-left cursor-pointer absolute text-xl left-0 top-0 rounded-br-full bg-white border-[1px] pb-3 pt-1 pl-1 pr-3"
@@ -99,32 +229,60 @@
99
229
  :maska="$maska.date"
100
230
  :rules="$rules.required"
101
231
  :label="$dataStore.t('form.date')"
102
- append-inner-icon="mdi mdi-calendar-blank-outline" />
232
+ append-inner-icon="mdi mdi-calendar-blank-outline"
233
+ />
103
234
  <base-file-input v-if="!affiliationDocument" @input.prevent="onFileChange($event)" />
104
235
  <base-empty-form-field v-if="affiliationDocument" class="justify-between">
105
236
  {{ `${affiliationDocument.fileTypeName} - ${affiliationDocument.fileName}` }}
106
- <i class="cursor-pointer mdi mdi-file-document mr-6 text-[#a0b3d8] text-xl"></i></base-empty-form-field
107
- ></base-content-block>
237
+ <i class="cursor-pointer mdi mdi-file-document mr-6 text-[#a0b3d8] text-xl"></i
238
+ ></base-empty-form-field>
239
+ </base-content-block>
108
240
  </v-form>
109
241
  <base-btn :text="buttonText" :loading="loading" @click="submitForm" />
110
242
  </div>
111
243
  </section>
244
+ <v-dialog v-model="isQrDialog" width="auto">
245
+ <v-card>
246
+ <v-card-text class="!p-4">
247
+ <base-qr :value="qrUrl" class="rounded" :size="300" />
248
+ </v-card-text>
249
+ </v-card>
250
+ </v-dialog>
112
251
  </template>
113
252
 
114
253
  <script lang="ts">
115
- import { DocumentItem } from '../../composables/classes';
254
+ import { DocumentItem, Value } from '../../composables/classes';
255
+ import { HubConnectionBuilder } from '@microsoft/signalr';
256
+ import { uuid } from 'vue-uuid';
257
+
116
258
  export default defineComponent({
117
- setup() {
259
+ emits: ['task'],
260
+ setup(props, { emit }) {
118
261
  const route = useRoute();
119
262
  const dataStore = useDataStore();
120
263
  const formStore = useFormStore();
121
264
  const actionCause = ref<string>('');
122
265
  const loading = ref<boolean>(false);
266
+ const isPaperContract = ref<boolean>(false);
267
+ const isScansDocuments = ref<boolean>(false);
268
+ const isQr = ref<boolean>(false);
269
+ const isElectronicContract = ref<boolean>(true);
270
+ const qrUrl = ref<string>('');
271
+ const connection = ref<any>(null);
272
+ const isQrLoading = ref<boolean>(false);
273
+ const urlCopy = ref<string>('');
274
+ const isEpayPay = ref<boolean>(false);
275
+ const isOfflinePay = ref<boolean>(false);
276
+ const isQrDialog = ref<boolean>(false);
277
+ const email = ref<string>('');
278
+
123
279
  const vForm = ref<any>();
124
280
  const isSendNumberOpen = ref<boolean>(false);
125
281
  const phoneNumber = ref<string | null>(formStore.policyholderForm.phoneNumber ?? '');
126
282
  const selectedClient = ref<SignUrlType>();
127
283
  const documentDict = computed(() => dataStore.dicFileTypeList.find(i => i.nameRu === 'Решение АС'));
284
+ const pensionForm = formStore.applicationData?.pensionApp ?? undefined;
285
+ const consentGiven = computed(() => !!formStore.signedDocumentList.find(i => i.fileTypeCode === '43' && i.signed === true));
128
286
  const affiliationDocument = computed(() => formStore.signedDocumentList.find((file: DocumentItem) => file.fileTypeName === 'Решение АС'));
129
287
  const affiliationData = ref<{
130
288
  processInstanceId: string | number;
@@ -137,6 +295,9 @@ export default defineComponent({
137
295
  fileTypeCode: documentDict.value ? documentDict.value.code : '',
138
296
  });
139
297
  const affiliationFormData = ref(new FormData());
298
+ const scansFormData = ref(new FormData());
299
+ const scansFiles = ref<any[]>([]);
300
+ const processCode = formStore.applicationData.processCode;
140
301
 
141
302
  const openSmsPanel = (signInfo: SignUrlType) => {
142
303
  if (signInfo) {
@@ -166,6 +327,92 @@ export default defineComponent({
166
327
  }
167
328
  };
168
329
 
330
+ const onFileChangeScans = async (
331
+ event: InputEvent,
332
+ type: 'statement' | 'pa_statement' | 'pa_refundstatement' | 'contract' | 'pa_contract' | 'pa_refundagreement' | 'app' | 'attorney' | 'agreement',
333
+ ) => {
334
+ if (event.target) {
335
+ const files = (event.target as HTMLInputElement).files;
336
+ if (files && files.length) {
337
+ if (files[0].type !== 'application/pdf') {
338
+ return dataStore.showToaster('error', dataStore.t('toaster.onlyPDF'), 6000);
339
+ }
340
+ const doc = await selectedDocument(type);
341
+ const data = {
342
+ processInstanceId: formStore.applicationData.processInstanceId,
343
+ fileTypeCode: doc ? doc.code : null,
344
+ fileTypeId: doc ? doc.id : null,
345
+ fileName: files[0].name,
346
+ };
347
+ scansFiles.value.push({
348
+ file: files[0],
349
+ fileData: JSON.stringify([data]),
350
+ });
351
+ }
352
+ }
353
+ };
354
+
355
+ const onClearFile = async (
356
+ type: 'statement' | 'pa_statement' | 'pa_refundstatement' | 'contract' | 'pa_contract' | 'pa_refundagreement' | 'app' | 'attorney' | 'agreement',
357
+ ) => {
358
+ const doc = await selectedDocument(type);
359
+ const result = scansFiles.value.filter(i => JSON.parse(i.fileData)[0].fileTypeCode !== doc.code);
360
+ scansFiles.value = result;
361
+ };
362
+
363
+ const selectedDocument = (type: 'statement' | 'pa_statement' | 'pa_refundstatement' | 'contract' | 'pa_contract' | 'pa_refundagreement' | 'app' | 'attorney' | 'agreement') => {
364
+ let selectedDocument: any;
365
+ if (type === 'statement') {
366
+ selectedDocument = dataStore.dicFileTypeList.find((i: Value) => i.code === '32');
367
+ }
368
+ if (type === 'pa_statement') {
369
+ selectedDocument = dataStore.dicFileTypeList.find((i: Value) => i.code === '37');
370
+ }
371
+ if (type === 'pa_refundstatement') {
372
+ selectedDocument = dataStore.dicFileTypeList.find((i: Value) => i.code === '41');
373
+ }
374
+ if (type === 'contract') {
375
+ selectedDocument = dataStore.dicFileTypeList.find((i: Value) => i.code === '6');
376
+ }
377
+ if (type === 'pa_contract') {
378
+ selectedDocument = dataStore.dicFileTypeList.find((i: Value) => i.code === '38');
379
+ }
380
+ if (type === 'pa_refundagreement') {
381
+ selectedDocument = dataStore.dicFileTypeList.find((i: Value) => i.code === '42');
382
+ }
383
+ if (type === 'app') {
384
+ selectedDocument = dataStore.dicFileTypeList.find((i: Value) => i.code === '33');
385
+ }
386
+ if (type === 'attorney') {
387
+ selectedDocument = dataStore.dicFileTypeList.find((i: Value) => i.code === '34');
388
+ }
389
+ if (type === 'agreement') {
390
+ selectedDocument = dataStore.dicFileTypeList.find((i: Value) => i.code === '19');
391
+ }
392
+ return selectedDocument;
393
+ };
394
+
395
+ const sendFiles = async () => {
396
+ if (
397
+ dataStore.isPension
398
+ ? formStore.applicationData.statusCode === 'ContractSignedFrom'
399
+ ? scansFiles.value.length !== 1
400
+ : scansFiles.value.length !== 2
401
+ : scansFiles.value.length !== 4
402
+ ) {
403
+ dataStore.showToaster('warning', dataStore.t('toaster.notAllDocumentsAttached'));
404
+ return;
405
+ }
406
+ for (const item of scansFiles.value) {
407
+ scansFormData.value.append('file', item.file);
408
+ scansFormData.value.append('fileData', item.fileData);
409
+ await dataStore.uploadFiles(scansFormData.value);
410
+ scansFormData.value = new FormData();
411
+ }
412
+ closePanel();
413
+ dataStore.showToaster('success', dataStore.t('toaster.successOperation'));
414
+ await dataStore.handleTask(dataStore.isPension ? constants.actions.accept : constants.actions.signed, route.params.taskId as string, 'scans');
415
+ };
169
416
  const submitForm = async () => {
170
417
  await vForm.value.validate().then(async (v: { valid: Boolean; errors: any }) => {
171
418
  if (v.valid) {
@@ -198,12 +445,38 @@ export default defineComponent({
198
445
 
199
446
  const handleTask = async () => {
200
447
  loading.value = true;
201
- await dataStore.handleTask(dataStore.panelAction, route.params.taskId as string, actionCause.value);
448
+ // Пока не нужно, на всякий оставить
449
+ // if (needRecalculation.value) {
450
+ // dataStore.showToaster('info', dataStore.t('toaster.needToRecalculate'));
451
+ // loading.value = false;
452
+ // return;
453
+ // }
454
+ if (dataStore.isAML || dataStore.isCheckContract || dataStore.isCheckContragent || dataStore.isDas || dataStore.isPrePension || dataStore.isUU) {
455
+ emit('task', [dataStore.panelAction, route.params.taskId as string, actionCause.value]);
456
+ } else {
457
+ await dataStore.handleTask(dataStore.panelAction, route.params.taskId as string, actionCause.value);
458
+ }
202
459
  loading.value = false;
203
460
  };
204
461
 
462
+ const onInit = async () => {
463
+ if (dataStore.controls.hasChooseSign) {
464
+ if (dataStore.isGons || dataStore.isLifeBusiness || dataStore.isPension || dataStore.isGns) {
465
+ isElectronicContract.value = false;
466
+ }
467
+ }
468
+ if (dataStore.isPension) {
469
+ await dataStore.getSignedDocList(formStore.applicationData.processInstanceId);
470
+ }
471
+ };
472
+
473
+ onMounted(async () => {
474
+ await onInit();
475
+ });
476
+
205
477
  const buttonText = computed(() => {
206
478
  switch (dataStore.panelAction) {
479
+ case constants.actions.cancel:
207
480
  case constants.actions.reject:
208
481
  case constants.actions.rejectclient:
209
482
  return dataStore.t('buttons.rejectStatement');
@@ -219,6 +492,8 @@ export default defineComponent({
219
492
  return dataStore.t('buttons.register');
220
493
  case constants.actions.affiliate:
221
494
  return dataStore.t('buttons.send');
495
+ default:
496
+ return dataStore.t('buttons.send');
222
497
  }
223
498
  });
224
499
 
@@ -226,28 +501,296 @@ export default defineComponent({
226
501
  () => dataStore.panelAction,
227
502
  val => {
228
503
  if (!!val) {
229
- dataStore.panel.title = buttonText.value!;
504
+ dataStore.panel.title = buttonText.value;
230
505
  dataStore.panel.open = true;
231
506
  }
232
507
  },
233
508
  { immediate: true },
234
509
  );
510
+
511
+ const needRecalculation = computed(
512
+ () =>
513
+ dataStore.isGons &&
514
+ formStore.applicationData.statusCode === 'UnderwriterForm' &&
515
+ dataStore.panelAction === constants.actions.accept &&
516
+ formStore.productConditionsForm.isRecalculated === false,
517
+ );
235
518
  const sendingActions = computed(
236
- () => dataStore.panelAction === constants.actions.reject || dataStore.panelAction === constants.actions.return || dataStore.panelAction === constants.actions.rejectclient,
519
+ () =>
520
+ dataStore.panelAction === constants.actions.reject ||
521
+ dataStore.panelAction === constants.actions.cancel ||
522
+ dataStore.panelAction === constants.actions.return ||
523
+ dataStore.panelAction === constants.actions.rejectclient,
237
524
  );
238
525
  const acceptAction = computed(() => dataStore.panelAction === constants.actions.accept);
239
526
  const signingActions = computed(() => dataStore.panelAction === constants.actions.sign);
240
527
  const payingActions = computed(() => dataStore.panelAction === constants.actions.pay);
241
528
  const affiliateActions = computed(() => dataStore.panelAction === constants.actions.affiliate);
529
+ const chooseSignActions = computed(() => dataStore.controls.hasChooseSign && dataStore.panelAction === constants.actions.chooseSign);
530
+ const choosePayActions = computed(() => dataStore.controls.hasChoosePay && dataStore.panelAction === constants.actions.choosePay);
531
+
242
532
  const paymentPeriod = computed(() => formStore.productConditionsForm.paymentPeriod.nameRu);
243
533
  const insurancePremiumPerMonth = computed(() => dataStore.getNumberWithSpaces(formStore.productConditionsForm.insurancePremiumPerMonth));
244
- const requestedSumInsured = computed(() => dataStore.getNumberWithSpaces(formStore.productConditionsForm.requestedSumInsured));
534
+ const requestedSumInsured = computed(() => {
535
+ if ((dataStore.isLifeBusiness || dataStore.isGns) && formStore.productConditionsForm.requestedSumInsured === null) {
536
+ return dataStore.getNumberWithSpaces(formStore.applicationData.policyAppDto!.mainInsSum);
537
+ }
538
+ return dataStore.getNumberWithSpaces(formStore.productConditionsForm.requestedSumInsured);
539
+ });
540
+ const price = computed(() => dataStore.getNumberWithSpaces(formStore.productConditionsForm.calculatorForm.price));
541
+ const insuredAmount = computed(() => formStore.productConditionsForm.calculatorForm.amount!.nameRu! + dataStore.currency);
245
542
  const hasConditionsInfo = computed(() => {
543
+ if (dataStore.isLifetrip || dataStore.isDas || dataStore.isUU || dataStore.isPrePension) {
544
+ return false;
545
+ }
246
546
  if (dataStore.isFinCenter()) {
247
547
  return false;
248
548
  }
249
549
  return true;
250
550
  });
551
+ const hasConditionsAction = computed(() => {
552
+ if (dataStore.isPrePension) {
553
+ return false;
554
+ }
555
+ return true;
556
+ });
557
+ const isPaperDisabled = computed(() => {
558
+ if (dataStore.isGons) {
559
+ return false;
560
+ }
561
+ return true;
562
+ });
563
+ const isElectronicDisabled = computed(() => {
564
+ if (dataStore.isGons || dataStore.isLifeBusiness || dataStore.isGns || dataStore.isPension) {
565
+ return true;
566
+ }
567
+ return false;
568
+ });
569
+ const isScansDisabled = computed(() => {
570
+ if (dataStore.isGons) {
571
+ return true;
572
+ }
573
+ if ((!consentGiven.value || formStore.applicationData.statusCode === 'HeadManagerForm') && dataStore.isPension && processCode !== 2) {
574
+ return true;
575
+ }
576
+ return false;
577
+ });
578
+ const isQrDisabled = computed(() => {
579
+ if (consentGiven.value && dataStore.isPension && processCode !== 2) {
580
+ return false;
581
+ }
582
+ return true;
583
+ });
584
+ const isQrXmlDisabled = computed(() => {
585
+ if (!consentGiven.value && dataStore.isPension && processCode !== 2) {
586
+ return false;
587
+ }
588
+ if (dataStore.isLifeBusiness || dataStore.isGns) {
589
+ return false;
590
+ }
591
+ return true;
592
+ });
593
+ const isSignatureDisabled = computed(() => {
594
+ if ((!consentGiven.value || formStore.applicationData.statusCode === 'HeadManagerForm') && dataStore.isPension && processCode !== 2) {
595
+ return false;
596
+ }
597
+ return true;
598
+ });
599
+ const downloadTemplate = async (documentType: number, fileType: string) => {
600
+ await dataStore.downloadTemplate(documentType, fileType, formStore.applicationData.processInstanceId);
601
+ };
602
+
603
+ const handleSignAction = async (type: 'paper' | 'electronic' | 'scans' | 'qr' | 'qrXml' | 'signature') => {
604
+ loading.value = true;
605
+ if (type === 'electronic') {
606
+ await dataStore.signDocument();
607
+ isElectronicContract.value = true;
608
+ dataStore.panelAction = constants.actions.sign;
609
+ }
610
+ if (type === 'paper') {
611
+ isPaperContract.value = true;
612
+ }
613
+ if (type === 'scans') {
614
+ isScansDocuments.value = true;
615
+ }
616
+ if (type === 'qr') {
617
+ const result = (await dataStore.signDocument('qr')) as any;
618
+ if (result && result.data) {
619
+ const groupId = result.data[0].signatureDocumentGroupId;
620
+ await generateQR(groupId);
621
+ isQr.value = true;
622
+ }
623
+ }
624
+ if (type === 'qrXml') {
625
+ const result = (await dataStore.signDocument('qrXml')) as any;
626
+ if (result && result.data) {
627
+ const id = result.data;
628
+ await generateQR(id, 'xml');
629
+ isQr.value = true;
630
+ }
631
+ }
632
+ if (type === 'signature') {
633
+ await dataStore.signDocument('signature');
634
+ }
635
+ loading.value = false;
636
+ };
637
+
638
+ const handlePayAction = async (type: 'epay' | 'offline') => {
639
+ loading.value = true;
640
+ if (type === 'epay') {
641
+ await payEpay();
642
+ }
643
+ if (type === 'offline') {
644
+ const result = await dataStore.sendTask(route.params.taskId as string, constants.actions.payed, 'offline');
645
+ if (result) {
646
+ isOfflinePay.value = true;
647
+ }
648
+ }
649
+ loading.value = false;
650
+ };
651
+
652
+ const generateQR = async (groupId: string, type: string = 'cms') => {
653
+ const confName = type === 'cms' ? 'qrGenUrl' : 'qrXmlGenUrl';
654
+ const uuidV4 = uuid.v4();
655
+ const linkToCopy = ref<string>(`${getStrValuePerEnv(confName)}/${uuidV4}/${groupId}`);
656
+ const qrValue = `mobileSign:${linkToCopy.value}`;
657
+ qrUrl.value = qrValue;
658
+ if (dataStore.isLifeBusiness || dataStore.isGns) {
659
+ //для юр лиц
660
+ urlCopy.value = `https://egovbusiness.page.link/?link=${linkToCopy.value}?mgovSign&amp;apn=kz.mobile.mgov.business&amp;isi=1597880144&amp;ibi=kz.mobile.mgov.business`;
661
+ } else {
662
+ //для физ лиц
663
+ urlCopy.value = `https://mgovsign.page.link/?link=${linkToCopy.value}?mgovSign&amp;apn=kz.mobile.mgov&amp;isi=1476128386&amp;ibi=kz.egov.mobile`;
664
+ }
665
+
666
+ await startConnection(uuidV4, groupId);
667
+ };
668
+
669
+ const startConnection = async (uuid: string, groupId?: string) => {
670
+ connection.value = new HubConnectionBuilder()
671
+ .withUrl(`${getStrValuePerEnv('qrHubUrl')}/${uuid}`)
672
+ .withAutomaticReconnect()
673
+ .build();
674
+ try {
675
+ await connection.value.start();
676
+ console.log('SignalR connection started.');
677
+ connection.value.on('QR', async (message: any) => {
678
+ if (message === 'Opened') {
679
+ isQrLoading.value = true;
680
+ } else if (message === 'Signed') {
681
+ isQrLoading.value = false;
682
+ if (dataStore.isPension) {
683
+ dataStore.showToaster('info', dataStore.t('pension.signInProcess'));
684
+ } else {
685
+ dataStore.showToaster('success', dataStore.t('sign.successQrSigned'));
686
+ }
687
+ qrUrl.value = '';
688
+ isQr.value = false;
689
+ dataStore.panel.open = false;
690
+ dataStore.panelAction = null;
691
+ await stopConnection();
692
+ } else {
693
+ console.log('message from SignalR', message);
694
+ if (message.signed === true) {
695
+ isQrLoading.value = false;
696
+ qrUrl.value = '';
697
+ isQr.value = false;
698
+ dataStore.panel.open = false;
699
+ dataStore.panelAction = null;
700
+ if (message.signature) {
701
+ console.log('signature from SignalR', message.signature);
702
+ const data = new FormData();
703
+ data.append('processInstanceId', String(dataStore.formStore.applicationData.processInstanceId));
704
+ data.append('xmlData', message.signature);
705
+ data.append('name', 'PAEnpf_Agreement');
706
+ data.append('format', 'xml');
707
+ data.append('EdsXmlId', groupId ?? '');
708
+ await dataStore.api.uploadXml(data);
709
+ await dataStore.getSignedDocList(dataStore.formStore.applicationData.processInstanceId);
710
+ dataStore.showToaster('success', dataStore.t('pension.consentGiven'), 3000);
711
+ }
712
+ await stopConnection();
713
+ } else {
714
+ if (message.error) {
715
+ dataStore.showToaster('error', message.error, 3000);
716
+ }
717
+ }
718
+ }
719
+ });
720
+ } catch (err) {
721
+ console.error('Error starting SignalR connection:', err);
722
+ }
723
+ };
724
+
725
+ const closeQrPanel = async () => {
726
+ isQr.value = false;
727
+ isQrLoading.value = false;
728
+ await stopConnection();
729
+ };
730
+
731
+ const stopConnection = async () => {
732
+ if (connection.value) {
733
+ await connection.value.stop();
734
+ console.log('SignalR connection stopped.');
735
+ }
736
+ };
737
+
738
+ const generateDocument = async () => {
739
+ dataStore.panel.open = false;
740
+ dataStore.panelAction = null;
741
+ await dataStore.generateDocument();
742
+ };
743
+
744
+ const convertQr = async (url: string | null, template?: Api.GenerateShortLink.Templates) => {
745
+ if (url) {
746
+ const shortedUrl = await dataStore.generateShortLink(url, template);
747
+ qrUrl.value = typeof shortedUrl === 'string' && !!shortedUrl ? shortedUrl : url;
748
+ isQrDialog.value = true;
749
+ } else {
750
+ dataStore.showToaster('error', dataStore.t('toaster.noUrl'));
751
+ }
752
+ };
753
+
754
+ const sendInvoiceToEmail = async () => {
755
+ await vForm.value.validate().then(async (v: { valid: Boolean; errors: any }) => {
756
+ if (v.valid) {
757
+ await dataStore.sendInvoiceToEmail(formStore.applicationData.processInstanceId, email.value);
758
+ email.value = '';
759
+ }
760
+ });
761
+ };
762
+
763
+ const payEpay = async () => {
764
+ const invoiceData = await dataStore.getInvoiceData(formStore.applicationData.processInstanceId);
765
+ if (invoiceData === false || invoiceData.status === 3 || invoiceData.status === 0) {
766
+ if (invoiceData === false || invoiceData.status === 3) {
767
+ const created = await dataStore.createInvoice();
768
+ if (created) {
769
+ const ePayData = await dataStore.sendToEpay();
770
+ if (!ePayData) return;
771
+ formStore.epayLink = dataStore.sanitize(ePayData.link);
772
+ }
773
+ }
774
+ if (!!invoiceData && invoiceData.status === 0) {
775
+ const ePayData = await dataStore.sendToEpay();
776
+ if (!ePayData) return;
777
+ formStore.epayLink = dataStore.sanitize(ePayData.link);
778
+ }
779
+ } else {
780
+ if (invoiceData.paymentLink) {
781
+ formStore.epayLink = dataStore.sanitize(invoiceData.paymentLink);
782
+ } else {
783
+ dataStore.showToaster('error', dataStore.t('toaster.noUrl'));
784
+ }
785
+ }
786
+ if (!formStore.epayLink) {
787
+ dataStore.showToaster('error', dataStore.t('toaster.noUrl'));
788
+ return;
789
+ }
790
+ loading.value = false;
791
+ isEpayPay.value = true;
792
+ dataStore.panelAction = constants.actions.pay;
793
+ };
251
794
 
252
795
  return {
253
796
  // State
@@ -258,6 +801,18 @@ export default defineComponent({
258
801
  isSendNumberOpen,
259
802
  phoneNumber,
260
803
  selectedClient,
804
+ isPaperContract,
805
+ isScansDocuments,
806
+ isQr,
807
+ qrUrl,
808
+ scansFiles,
809
+ isQrLoading,
810
+ urlCopy,
811
+ isEpayPay,
812
+ isOfflinePay,
813
+ processCode,
814
+ isQrDialog,
815
+ email,
261
816
 
262
817
  // Functions
263
818
  closePanel,
@@ -266,6 +821,16 @@ export default defineComponent({
266
821
  openSmsPanel,
267
822
  openEpayPanel,
268
823
  onFileChange,
824
+ downloadTemplate,
825
+ onFileChangeScans,
826
+ sendFiles,
827
+ onClearFile,
828
+ closeQrPanel,
829
+ handlePayAction,
830
+ payEpay,
831
+ convertQr,
832
+ sendInvoiceToEmail,
833
+ hasConditionsAction,
269
834
 
270
835
  // Computed
271
836
  buttonText,
@@ -274,11 +839,25 @@ export default defineComponent({
274
839
  payingActions,
275
840
  acceptAction,
276
841
  affiliateActions,
842
+ chooseSignActions,
277
843
  paymentPeriod,
278
844
  insurancePremiumPerMonth,
279
845
  requestedSumInsured,
280
846
  affiliationDocument,
281
847
  hasConditionsInfo,
848
+ price,
849
+ insuredAmount,
850
+ isElectronicContract,
851
+ handleSignAction,
852
+ generateDocument,
853
+ isPaperDisabled,
854
+ isElectronicDisabled,
855
+ isScansDisabled,
856
+ isQrDisabled,
857
+ isQrXmlDisabled,
858
+ isSignatureDisabled,
859
+ choosePayActions,
860
+ consentGiven,
282
861
  };
283
862
  },
284
863
  });
@@ -288,16 +867,19 @@ export default defineComponent({
288
867
  .v-expansion-panel-title__overlay {
289
868
  background: #ffffff;
290
869
  }
870
+
291
871
  .v-expansion-panel-title {
292
872
  height: 70px !important;
293
873
  padding: 10px 20px !important;
294
874
  }
875
+
295
876
  .v-expansion-panels--variant-accordion > :last-child {
296
877
  border-top-left-radius: 0.5rem !important;
297
878
  border-top-right-radius: 0.5rem !important;
298
879
  border-top-left-radius: 0.5rem !important;
299
880
  border-radius: 0.5rem !important;
300
881
  }
882
+
301
883
  .v-expansion-panel-text__wrapper {
302
884
  padding: 10px 20px !important;
303
885
  }