hl-core 0.0.9-beta.9 → 0.0.10-beta.2

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 +16 -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 +626 -49
  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 +558 -16
  58. package/nuxt.config.ts +11 -15
  59. package/package.json +37 -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>
62
123
  </div>
63
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" />
141
+ </div>
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,20 +229,32 @@
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
259
  emits: ['task'],
118
260
  setup(props, { emit }) {
@@ -121,11 +263,26 @@ export default defineComponent({
121
263
  const formStore = useFormStore();
122
264
  const actionCause = ref<string>('');
123
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
+
124
279
  const vForm = ref<any>();
125
280
  const isSendNumberOpen = ref<boolean>(false);
126
281
  const phoneNumber = ref<string | null>(formStore.policyholderForm.phoneNumber ?? '');
127
282
  const selectedClient = ref<SignUrlType>();
128
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));
129
286
  const affiliationDocument = computed(() => formStore.signedDocumentList.find((file: DocumentItem) => file.fileTypeName === 'Решение АС'));
130
287
  const affiliationData = ref<{
131
288
  processInstanceId: string | number;
@@ -138,6 +295,9 @@ export default defineComponent({
138
295
  fileTypeCode: documentDict.value ? documentDict.value.code : '',
139
296
  });
140
297
  const affiliationFormData = ref(new FormData());
298
+ const scansFormData = ref(new FormData());
299
+ const scansFiles = ref<any[]>([]);
300
+ const processCode = formStore.applicationData.processCode;
141
301
 
142
302
  const openSmsPanel = (signInfo: SignUrlType) => {
143
303
  if (signInfo) {
@@ -167,6 +327,92 @@ export default defineComponent({
167
327
  }
168
328
  };
169
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
+ };
170
416
  const submitForm = async () => {
171
417
  await vForm.value.validate().then(async (v: { valid: Boolean; errors: any }) => {
172
418
  if (v.valid) {
@@ -199,7 +445,13 @@ export default defineComponent({
199
445
 
200
446
  const handleTask = async () => {
201
447
  loading.value = true;
202
- if (dataStore.isAML || dataStore.isCheckContract || dataStore.isCheckContragent) {
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) {
203
455
  emit('task', [dataStore.panelAction, route.params.taskId as string, actionCause.value]);
204
456
  } else {
205
457
  await dataStore.handleTask(dataStore.panelAction, route.params.taskId as string, actionCause.value);
@@ -207,8 +459,24 @@ export default defineComponent({
207
459
  loading.value = false;
208
460
  };
209
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
+
210
477
  const buttonText = computed(() => {
211
478
  switch (dataStore.panelAction) {
479
+ case constants.actions.cancel:
212
480
  case constants.actions.reject:
213
481
  case constants.actions.rejectclient:
214
482
  return dataStore.t('buttons.rejectStatement');
@@ -224,6 +492,8 @@ export default defineComponent({
224
492
  return dataStore.t('buttons.register');
225
493
  case constants.actions.affiliate:
226
494
  return dataStore.t('buttons.send');
495
+ default:
496
+ return dataStore.t('buttons.send');
227
497
  }
228
498
  });
229
499
 
@@ -231,28 +501,296 @@ export default defineComponent({
231
501
  () => dataStore.panelAction,
232
502
  val => {
233
503
  if (!!val) {
234
- dataStore.panel.title = buttonText.value!;
504
+ dataStore.panel.title = buttonText.value;
235
505
  dataStore.panel.open = true;
236
506
  }
237
507
  },
238
508
  { immediate: true },
239
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
+ );
240
518
  const sendingActions = computed(
241
- () => 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,
242
524
  );
243
525
  const acceptAction = computed(() => dataStore.panelAction === constants.actions.accept);
244
526
  const signingActions = computed(() => dataStore.panelAction === constants.actions.sign);
245
527
  const payingActions = computed(() => dataStore.panelAction === constants.actions.pay);
246
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
+
247
532
  const paymentPeriod = computed(() => formStore.productConditionsForm.paymentPeriod.nameRu);
248
533
  const insurancePremiumPerMonth = computed(() => dataStore.getNumberWithSpaces(formStore.productConditionsForm.insurancePremiumPerMonth));
249
- 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);
250
542
  const hasConditionsInfo = computed(() => {
543
+ if (dataStore.isLifetrip || dataStore.isDas || dataStore.isUU || dataStore.isPrePension) {
544
+ return false;
545
+ }
251
546
  if (dataStore.isFinCenter()) {
252
547
  return false;
253
548
  }
254
549
  return true;
255
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
+ };
256
794
 
257
795
  return {
258
796
  // State
@@ -263,6 +801,18 @@ export default defineComponent({
263
801
  isSendNumberOpen,
264
802
  phoneNumber,
265
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,
266
816
 
267
817
  // Functions
268
818
  closePanel,
@@ -271,6 +821,16 @@ export default defineComponent({
271
821
  openSmsPanel,
272
822
  openEpayPanel,
273
823
  onFileChange,
824
+ downloadTemplate,
825
+ onFileChangeScans,
826
+ sendFiles,
827
+ onClearFile,
828
+ closeQrPanel,
829
+ handlePayAction,
830
+ payEpay,
831
+ convertQr,
832
+ sendInvoiceToEmail,
833
+ hasConditionsAction,
274
834
 
275
835
  // Computed
276
836
  buttonText,
@@ -279,11 +839,25 @@ export default defineComponent({
279
839
  payingActions,
280
840
  acceptAction,
281
841
  affiliateActions,
842
+ chooseSignActions,
282
843
  paymentPeriod,
283
844
  insurancePremiumPerMonth,
284
845
  requestedSumInsured,
285
846
  affiliationDocument,
286
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,
287
861
  };
288
862
  },
289
863
  });
@@ -293,16 +867,19 @@ export default defineComponent({
293
867
  .v-expansion-panel-title__overlay {
294
868
  background: #ffffff;
295
869
  }
870
+
296
871
  .v-expansion-panel-title {
297
872
  height: 70px !important;
298
873
  padding: 10px 20px !important;
299
874
  }
875
+
300
876
  .v-expansion-panels--variant-accordion > :last-child {
301
877
  border-top-left-radius: 0.5rem !important;
302
878
  border-top-right-radius: 0.5rem !important;
303
879
  border-top-left-radius: 0.5rem !important;
304
880
  border-radius: 0.5rem !important;
305
881
  }
882
+
306
883
  .v-expansion-panel-text__wrapper {
307
884
  padding: 10px 20px !important;
308
885
  }