diff --git a/actions/questionnaireActions.js b/actions/questionnaireActions.js index 315da7a..b2d377e 100644 --- a/actions/questionnaireActions.js +++ b/actions/questionnaireActions.js @@ -257,6 +257,15 @@ export const resetQuestionnaire = ({ dispatch, id }) => }); } +export const defaultQuestionnaire = ({ dispatch }) => +{ + console.log("defaultQuestionnaire"); + + const template = JSON.parse(JSON.stringify(questionnaire_template)); + dispatch({ type: actionTypes.QUESTIONNAIRE_UPDATE, data: { questionnaire: template, } }); +} + + export const uploadAttachmentFile = (file) => { console.log("ACTION", "questionnaireActions", "uploadAttachmentFile()", { file }); diff --git a/components/questionnaire/SuggestsInput.js b/components/questionnaire/SuggestsInput.js index cec1065..a30c23b 100644 --- a/components/questionnaire/SuggestsInput.js +++ b/components/questionnaire/SuggestsInput.js @@ -69,22 +69,21 @@ export default class SuggestsInput extends React.Component const { onChange } = this.props; onChange(value); - this._getValue(value); - - setTimeout(() => + this.setState({ focused: true }, () => { - this.setState({ focused: false }); - }, 100); + this._getValue(value); + }); } _handle_onSelect = (value) => { const { onChange } = this.props; - this.setState({ focused: false }, () => + onChange(value); + setTimeout(() => { - onChange(value); - }); + this.setState({ focused: false }); + }, 100); } _handle_onFocus = (event) => diff --git a/components/questionnaire/forms/DigitalSignaturesList.js b/components/questionnaire/forms/DigitalSignaturesList.js index 0301d94..a2bc2e0 100644 --- a/components/questionnaire/forms/DigitalSignaturesList.js +++ b/components/questionnaire/forms/DigitalSignaturesList.js @@ -16,6 +16,7 @@ export default class DigitalSignaturesList extends React.Component loading: true, certificates_error: null, certificate_selected: undefined, + signing: false, }; } @@ -41,16 +42,17 @@ export default class DigitalSignaturesList extends React.Component if(certificate?.info?.subjectFields['ИНН ЮЛ'] !== null || certificate?.info?.subjectFields['ИНН'] !== null) { - let today = moment(); - if(today < moment(certificate.info.validToDate)) - { - certificate.info.validToDate = moment(certificate.info.validToDate).format('DD.MM.YYYY'); - certificates_list.push(certificate); + if(certificate?.info?.subjectFields['ОГРНИП'] !== null || certificate?.info?.subjectFields['ОГРН'] !== null) + { + let today = moment(); + if(today < moment(certificate.info.validToDate)) + { + certificate.info.validToDate = moment(certificate.info.validToDate).format('DD.MM.YYYY'); + certificates_list.push(certificate); + } } } } - - this.setState({ certificates: certificates_list, certificates_error: certificates_list.length > 0 ? null : "ISSUED", loading: false }); }) @@ -79,69 +81,64 @@ export default class DigitalSignaturesList extends React.Component _sign = () => { - const { company, main, onSignDigital } = this.props; - const filename = `${ main.inn }_questionnaire_${ moment().format("DDMMYYYY_HHmmss") }.pdf`; - - downloadQuestionnaire({ filename, download: false }) - .then(({ file }) => + this.setState({ signing: true }, () => { - //let created_at = moment().format('DD-MM-yyyy'); - //let filename = `Коммерческое предложение №${this.props.proposal.proposalId} от ${createAt}.docx` - let file_to_sign = new File([ file ], filename); - - console.log("this.state", this.state); - console.log("file"); - console.log(file); - - console.log("file_to_sign"); - console.log(file_to_sign); - - const now = moment().format("DDMMYYYY_HHmmss"); - generateSignature(file_to_sign, this.state.certificate_selected.certificate) - .then(signature => + const { company, main, onSignDigital } = this.props; + const filename = `${ main.inn }_questionnaire_${ moment().format("DDMMYYYY_HHmmss") }.pdf`; + + downloadQuestionnaire({ filename, download: false }) + .then(({ file }) => { - console.log("signature"); - console.log(signature); - - uploadSignedFile(signature, company.questionnaire_id) - .then(() => + let file_to_sign = new File([ file ], filename); + + const now = moment().format("DDMMYYYY_HHmmss"); + generateSignature(file_to_sign, this.state.certificate_selected.certificate) + .then(signature => { - onSignDigital(); + console.log("signature"); + console.log(signature); + + uploadSignedFile(signature, company.questionnaire_id, true) + .then(() => + { + onSignDigital(); + }) + .catch(() => + { + this.setState({ signing: false }); + }); }) .catch(() => { - }); - - //fileDownload(signature, `${ now }_${ filename }.sig`); - //fileDownload(file, `${ now }_${ filename }`); - //alert("Подписание ЭЦП прошло успешно."); - }); - }) - .catch((e) => - { - console.error("exception on sign"); - console.error(e); - - let errorsText = { - 'The action was cancelled by the user. (0x8010006E)': 'Подписание было отменено', - 'Key does not exist. (0x8009000D)': 'Сертификата не существует', - 'Keyset does not exist (0x80090016)': 'Набор ключей не существует', - 'File upload error': 'Ошибка загрузки файла', - 'Invalid algorithm specified. (0x80090008)': 'На вашем компьютере не установлена программа «КриптоПро CSP»', - 'The card cannot be accessed because the wrong PIN was presented. (0x8010006B)': 'Указанный пароль неверный' - } - - if(e !== undefined) + this.setState({ signing: false }); + }) + }) + .catch((e) => { - let errorText = errorsText[e.message] || 'Ошибка подписания файла'; - alert(errorText); - } + console.error("exception on sign"); + console.error(e); + + let errorsText = { + 'The action was cancelled by the user. (0x8010006E)': 'Подписание было отменено', + 'Key does not exist. (0x8009000D)': 'Сертификата не существует', + 'Keyset does not exist (0x80090016)': 'Набор ключей не существует', + 'File upload error': 'Ошибка загрузки файла', + 'Invalid algorithm specified. (0x80090008)': 'На вашем компьютере не установлена программа «КриптоПро CSP»', + 'The card cannot be accessed because the wrong PIN was presented. (0x8010006B)': 'Указанный пароль неверный' + } + + if(e !== undefined) + { + let errorText = errorsText[e.message] || 'Ошибка подписания файла'; + alert(errorText); + } + }); }); } render() { - const { certificates, certificates_error, certificate_selected, loading } = this.state; + const { certificates, certificates_error, certificate_selected, loading, signing } = this.state; console.log(certificates); if(loading) @@ -175,16 +172,16 @@ export default class DigitalSignaturesList extends React.Component
-

{ certificate?.info?.subjectName.replace(/\""/g, '@').replace(/"/g, '').replace(/@/g, '"') }

+

{ certificate?.info?.subjectName.replace(/"/g, '') }

- { certificate.info.subjectFields['SN'] || certificate.info.subjectFields['SN'] ? ({ certificate.info.subjectFields['SN'] } { certificate.info.subjectFields['G'] }) : null } + { certificate.info.subjectFields['SN'] ? ({ certificate.info.subjectFields['SN'] } { certificate.info.subjectFields['G'] }) : null }

ИНН { certificate?.info?.subjectFields['ИНН ЮЛ'] !== null ? certificate?.info?.subjectFields['ИНН ЮЛ'] : certificate.info.subjectFields['ИНН'] }

{ certificate?.info?.subjectFields['ОГРНИП'] && (ОГРНИП { certificate.info.subjectFields['ОГРНИП'] }) } - { certificate?.info?.subjectFields['ОГРН'] && (ОГРНИП { certificate.info.subjectFields['ОГРН'] }) } + { certificate?.info?.subjectFields['ОГРН'] && (ОГРН { certificate.info.subjectFields['ОГРН'] }) }

Подпись действительна до { certificate?.info?.validToDate } @@ -204,8 +201,11 @@ export default class DigitalSignaturesList extends React.Component className="button button-blue" disabled={ certificate_selected !== undefined ? false : true } onClick={ this._sign } + style={{ minWidth: "250px" }} > - Подписать выбранной подписью + { signing ? ( + + ) : "Подписать выбранной подписью" }

diff --git a/components/questionnaire/forms/Form_3_Signer/index.js b/components/questionnaire/forms/Form_3_Signer/index.js index 2a2b437..f000d16 100644 --- a/components/questionnaire/forms/Form_3_Signer/index.js +++ b/components/questionnaire/forms/Form_3_Signer/index.js @@ -1391,7 +1391,7 @@ class Form_3_Signer extends QuestionnaireForm
+ { error && ( + + )} { !sign_digital && (
@@ -157,7 +173,11 @@ class Form_8_Signing extends QuestionnaireForm { filename } Анкета клиента

- Скачать + + { downloading ? ( + + ) : "Скачать" } +
) } diff --git a/components/questionnaire/forms/Form_9_Status/index.js b/components/questionnaire/forms/Form_9_Status/index.js index 2827c13..5210d87 100644 --- a/components/questionnaire/forms/Form_9_Status/index.js +++ b/components/questionnaire/forms/Form_9_Status/index.js @@ -72,7 +72,10 @@ class Form_9_Status extends QuestionnaireForm uploadSignedFile(file, company.questionnaire_id) .then(() => { - this.setState({ sent: true }); + this.setState({ sent: true }, () => + { + this.props.onSuccess(); + }); }) .catch(() => { @@ -88,18 +91,23 @@ class Form_9_Status extends QuestionnaireForm return ( { sign.digital && ( -
- - - - -

- Анкета заполнена и подписана - Вы заполнили и подписали анкету лизингополучателя посредством - ЭЦП. Анкета передана в обрабатывающий центр. Если у - сотрудников возникнут вопросы мы свяжемся с Вами. Спасибо! -

-
+ +
+ + + + +

+ Анкета заполнена и подписана + Вы заполнили и подписали анкету лизингополучателя посредством + ЭЦП. Анкета передана в обрабатывающий центр. Если у + сотрудников возникнут вопросы мы свяжемся с Вами. Спасибо! +

+
+
+ +
+
) } { sign.print && ( @@ -167,6 +175,9 @@ class Form_9_Status extends QuestionnaireForm Спасибо!

+
+ +
) }
diff --git a/pages/api/questionnaire/download.js b/pages/api/questionnaire/download.js index 75122cd..9144302 100644 --- a/pages/api/questionnaire/download.js +++ b/pages/api/questionnaire/download.js @@ -141,11 +141,7 @@ export default async function handler(req, res) pdfDoc.registerFontkit(fontkit); const formFont = await pdfDoc.embedFont(fontBytes); - // Embed the Mario and emblem images - - // Get the form containing all the fields const form = pdfDoc.getForm(); - //form.registerFontkit(fontkit); for(let group in fields) { @@ -319,6 +315,11 @@ export default async function handler(req, res) form.updateFieldAppearances(formFont); form.flatten(); + if(!questionnaire.main.nko) + { + pdfDoc.removePage(2); + } + const pdfBytes = await pdfDoc.save(); //responseType: 'blob', fs.writeFileSync(`${ __dirname }/../../../../../uploads/${ client_jwt_decoded.acc_number }_questionnaire.pdf`, pdfBytes); diff --git a/pages/api/questionnaire/send.js b/pages/api/questionnaire/send.js index 659773c..9cfc7a7 100644 --- a/pages/api/questionnaire/send.js +++ b/pages/api/questionnaire/send.js @@ -298,33 +298,47 @@ export default async function handler(req, res) eachSeries(files_to_send, (file_entry, callback) => { - const file_to_send_data = fs.readFileSync(`${ uploads }${ file_entry.filename }`); - const data = new FormData(); - data.append("file", file_to_send_data, file_entry.name); - - console.log({ data }); - - const file_upload_url = `${ process.env.CRM_API_HOST }/lk/document/upload/?entity=evo_client_questionnaire&documentTypeNumber=${ file_entry.number }&name=${ id }`; - console.log({ file_upload_url }); - - axios.post(file_upload_url, data, + if(fs.existsSync(`${ uploads }${ file_entry.filename }`)) { - headers: { - "Content-Type": `multipart/form-data; boundary=${ data._boundary }`, - "Authorization": `Bearer ${ crm_jwt }`, - }, - withCredentials: true, - }) - .then(() => + const file_to_send_data = fs.readFileSync(`${ uploads }${ file_entry.filename }`); + const data = new FormData(); + data.append("file", file_to_send_data, file_entry.name); + + console.log({ data }); + + const file_upload_url = `${ process.env.CRM_API_HOST }/lk/document/upload/?entity=evo_client_questionnaire&documentTypeNumber=${ file_entry.number }&name=${ id }`; + console.log({ file_upload_url }); + + axios.post(file_upload_url, data, + { + headers: { + "Content-Type": `multipart/form-data; boundary=${ data._boundary }`, + "Authorization": `Bearer ${ crm_jwt }`, + }, + withCredentials: true, + }) + .then(() => + { + console.log("FILE", file_entry.filename, "SENT"); + callback(); + }) + .catch((crm_file_upload_error) => + { + if(crm_file_upload_error.response !== undefined) + { + console.error("crm_file_upload_error", { status: crm_file_upload_error.response.status, data: crm_file_upload_error.response.data }); + } + else + { + console.error({ crm_file_upload_error }); + } + callback(); + }); + } + else { - console.log("FILE", file_entry.filename, "SENT"); callback(); - }) - .catch((crm_file_upload_error) => - { - console.error("crm_file_upload_error", { status: crm_file_upload_error.response.status, data: crm_file_upload_error.response.data }); - callback(); - }); + } }, async () => { const existed_files = fs.readdirSync(uploads); @@ -343,7 +357,14 @@ export default async function handler(req, res) }) .catch((crm_send_error) => { - console.error("crm_send_error", { status: crm_send_error.response.status, data: crm_send_error.response.data }); + if(crm_send_error.response !== undefined) + { + console.error("crm_send_error", { status: crm_send_error.response.status, data: crm_send_error.response.data }); + } + else + { + console.error({ crm_send_error }); + } res.status(500).json({ payload, id, digital }); resolve(); diff --git a/pages/questionnaire/index.js b/pages/questionnaire/index.js index 2e4ae0c..4b5b6b2 100644 --- a/pages/questionnaire/index.js +++ b/pages/questionnaire/index.js @@ -16,7 +16,7 @@ import InnerMenu from "../../components/questionnaire/InnerMenu"; import Header from '../components/Header'; import Footer from '../components/Footer'; -import { sendPhoneChangeNumber, sendPhoneChangeNumberSmsCode, setUserPhone, getQuestionnaire, getContractGraphicChangeSignatories, } from '../../actions'; +import { sendPhoneChangeNumber, sendPhoneChangeNumberSmsCode, setUserPhone, getQuestionnaire, getContractGraphicChangeSignatories, getCompanyInfo, defaultQuestionnaire, } from '../../actions'; import AccountLayout from "../components/Layout/Account"; import Form_1_Main from "../../components/questionnaire/forms/Form_1_Main"; import Form_2_Contacts from "../../components/questionnaire/forms/Form_2_Contacts"; @@ -103,6 +103,12 @@ class QuestionnairePage extends React.Component this.props.router.push(`/questionnaire#${ path }`); } + _handle_onSuccess = () => + { + getCompanyInfo({ dispatch: this.props.dispatch }); + defaultQuestionnaire({ dispatch: this.props.dispatch }); + } + _renderForm = () => { const { signatories, company } = this.state; @@ -115,8 +121,8 @@ class QuestionnairePage extends React.Component if (route.indexOf("#regulatory") > -1) return (); if (route.indexOf("#non-profit") > -1) return (); if (route.indexOf("#check") > -1) return (); - if (route.indexOf("#signing") > -1) return (); - if (route.indexOf("#status") > -1) return (); + if (route.indexOf("#signing") > -1) return (); + if (route.indexOf("#status") > -1) return (); return (); } diff --git a/utils/digital_signature/index.js b/utils/digital_signature/index.js index 2ef1070..723a5c3 100644 --- a/utils/digital_signature/index.js +++ b/utils/digital_signature/index.js @@ -188,67 +188,65 @@ function parseSubjectNameToArray(string) function parseSubjectNameToObj(string) { - console.log("parseSubjectNameToObj", string); - const marks = [ { r: new RegExp(/CN\=\"{0,}(.*?)\"{0,},\s{0,}/gm), field: "CN", }, { - r: new RegExp(/\sSN\=(.*?)[,\s]|[$]/gm), + r: new RegExp(/\s{0,}SN\=(.*?)[,\s]|[$]/gm), field: "SN", }, { - r: new RegExp(/\sG\=(.*?)[,\s]|[$]/gm), + r: new RegExp(/\s{0,}G\=(.*?),\s{0,}/gm), field: "G", }, { - r: new RegExp(/\sC\=(.*?)[,\s]|[$]/gm), + r: new RegExp(/\s{0,}C\=(.*?)[,\s]|[$]/gm), field: "C", }, { - r: new RegExp(/\sS\=(.*?)[,\s]|[$]/gm), + r: new RegExp(/\s{0,}S\=(.*?)[,\s]|[$]/gm), field: "S", }, { - r: new RegExp(/\sL\=(.*?)[,\s]|[$]/gm), + r: new RegExp(/\s{0,}L\=(.*?)[,\s]|[$]/gm), field: "L", }, { - r: new RegExp(/\sSTREET\=\"(.*?)\"[,\s]|[$]/gm), + r: new RegExp(/\s{0,}STREET\=\"(.*?)\"[,\s]|[$]/gm), field: "STREET", }, { - r: new RegExp(/\sO\=\"(.*?)\"[,\s]|[$]/gm), + r: new RegExp(/\s{0,}O\=\"(.*?)\"[,\s]|[$]/gm), field: "O", }, { - r: new RegExp(/\sT\=(.*?)[,\s]|[$]/gm), + r: new RegExp(/\s{0,}T\=(.*?)[,\s]|[$]/gm), field: "T", }, { - r: new RegExp(/\sОГРН\=(\d+)[,\s]|[$]/gm), + r: new RegExp(/\s{0,}ОГРН\=(\d+)[,\s]|[$]/gm), field: "ОГРН", }, { - r: new RegExp(/\sОГРНИП\=(\d+)[,\s]|[$]/gm), + r: new RegExp(/\s{0,}ОГРНИП\=(\d+)[,\s]|[$]/gm), field: "ОГРНИП", }, { - r: new RegExp(/\sСНИЛС\=(\d+)[,\s]|[$]/gm), + r: new RegExp(/\s{0,}СНИЛС\=(\d+)[,\s]|[$]/gm), field: "СНИЛС", }, { - r: new RegExp(/\sИНН\=(\d+)[,\s]|[$]/gm), + r: new RegExp(/\s{0,}ИНН\=(\d+)[,\s]|[$]/gm), field: "ИНН", }, { - r: new RegExp(/\sE\=(.*?)[,\s]|[$]/gm), + r: new RegExp(/\s{0,}E\=(.*?)[,\s]|[$]/gm), field: "E", }, { - r: new RegExp(/\sИНН ЮЛ\=(\d+)[,\s]|[$]/gm), + r: new RegExp(/\s{0,}ИНН ЮЛ\=(\d+)[,\s]|[$]/gm), field: "ИНН ЮЛ", }, ];