update for errors checking, digital certs list

This commit is contained in:
merelendor 2023-04-14 14:56:46 +03:00
parent 1cfbd39e1a
commit d725c01ad6
11 changed files with 213 additions and 148 deletions

View File

@ -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 });

View File

@ -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) =>

View File

@ -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
<div className="feed_item user">
<img src="/assets/images/icons/avatar.svg" alt="" />
<div>
<p className="item_title">{ certificate?.info?.subjectName.replace(/\""/g, '@').replace(/"/g, '').replace(/@/g, '"') }</p>
<p className="item_title">{ certificate?.info?.subjectName.replace(/"/g, '') }</p>
<p className="item_desc">
{ certificate.info.subjectFields['SN'] || certificate.info.subjectFields['SN'] ? (<span>{ certificate.info.subjectFields['SN'] } { certificate.info.subjectFields['G'] }</span>) : null }
{ certificate.info.subjectFields['SN'] ? (<span>{ certificate.info.subjectFields['SN'] } { certificate.info.subjectFields['G'] }</span>) : null }
</p>
<p className="item_desc">
<span>ИНН { certificate?.info?.subjectFields['ИНН ЮЛ'] !== null ? certificate?.info?.subjectFields['ИНН ЮЛ'] : certificate.info.subjectFields['ИНН'] }</span>
</p>
<p className="item_desc">
{ certificate?.info?.subjectFields['ОГРНИП'] && (<span>ОГРНИП { certificate.info.subjectFields['ОГРНИП'] }</span>) }
{ certificate?.info?.subjectFields['ОГРН'] && (<span>ОГРНИП { certificate.info.subjectFields['ОГРН'] }</span>) }
{ certificate?.info?.subjectFields['ОГРН'] && (<span>ОГРН { certificate.info.subjectFields['ОГРН'] }</span>) }
</p>
<p className="item_desc">
<span>Подпись действительна до { certificate?.info?.validToDate }</span>
@ -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 ? (
<SpinnerCircular size={24} thickness={100} speed={100} color="rgba(255, 255, 255, 1)" secondaryColor="rgba(255, 255, 255, 0.5)" style={{ marginTop: "4px" }}/>
) : "Подписать выбранной подписью" }
</button>
</div>
</React.Fragment>

View File

@ -1391,7 +1391,7 @@ class Form_3_Signer extends QuestionnaireForm
<button type="button" className="button button-blue" onClick={ this._handle_onNextPage }>
{ loading ? (
<SpinnerCircular size={24} thickness={100} speed={100} color="rgba(255, 255, 255, 1)" secondaryColor="rgba(255, 255, 255, 0.5)" style={{ marginTop: "4px" }}/>
) : "Продолжить" }
) : "Продолжить" }
</button>
<button ref={ this.ref_submit } type="submit" style={{ display: "none" }}/>
{ status !== "empty" && (

View File

@ -702,7 +702,7 @@ class Form_4_Shareholders extends QuestionnaireForm
}
else if(check[i] === "founder_part")
{
if(v !== "" || v !== null || !isNaN(parseInt(v, 10)))
if(v !== "" && v !== null && !isNaN(parseInt(v, 10)))
{
total_parts = total_parts + parseInt(v, 10)
}

View File

@ -15,6 +15,7 @@ import { MatchMedia } from '../../../../utils/mediaqueries';
import { reduxWrapper } from '../../../../store';
import DigitalSignaturesList from "../DigitalSignaturesList";
import { downloadQuestionnaire } from "../../../../actions";
import FormMessage from "../FormMessage";
class Form_8_Signing extends QuestionnaireForm
{
@ -32,6 +33,8 @@ class Form_8_Signing extends QuestionnaireForm
filename: null,
mobile: MatchMedia() === "mobile" ? true : false,
company: {},
downloading: false,
error: false,
};
}
@ -68,22 +71,32 @@ class Form_8_Signing extends QuestionnaireForm
return false;
};
_download = () =>
_handle_onDownload = () =>
{
const { filename } = this.state;
downloadQuestionnaire({ filename, download: true })
.then(() =>
const { filename, downloading } = this.state;
if(!downloading)
{
this._handle_onCheckboxFieldChange("step", 9);
setTimeout(() =>
this.setState({ downloading: true }, () =>
{
this.props.onNextStep("status");
}, 10);
});
downloadQuestionnaire({ filename, download: true })
.then(() =>
{
this._handle_onCheckboxFieldChange("step", 9);
setTimeout(() =>
{
this.props.onNextStep("status");
this.props.onSuccess();
}, 10);
})
.catch(() =>
{
this.setState({ downloading: false, error: true, })
})
});
}
}
_handle_onChangeSignMehod = () =>
_handle_onChangeSignMethod = () =>
{
const { sign_digital } = this.state;
this.setState({ sign_digital: sign_digital ? false : true }, () =>
@ -94,7 +107,7 @@ class Form_8_Signing extends QuestionnaireForm
render()
{
const { filename, sign_digital, mobile, company, main } = this.state;
const { filename, sign_digital, mobile, company, main, downloading, error } = this.state;
return (
<React.Fragment>
@ -108,7 +121,7 @@ class Form_8_Signing extends QuestionnaireForm
id="sign_digital"
name="sign_digital"
checked={ sign_digital }
onChange={ this._handle_onChangeSignMehod }
onChange={ this._handle_onChangeSignMethod }
/>
<label htmlFor="sign_digital">
<b>Подписать онлайн используя ЭЦП</b>
@ -141,7 +154,7 @@ class Form_8_Signing extends QuestionnaireForm
id="sign_print"
name="sign_print"
checked={ !sign_digital }
onChange={ this._handle_onChangeSignMehod }
onChange={ this._handle_onChangeSignMethod }
/>
<label htmlFor="sign_print">
<b>Подписать в бумажном виде</b>
@ -150,6 +163,9 @@ class Form_8_Signing extends QuestionnaireForm
</div>
</div>
{ error && (
<FormMessage type="error" title="Ошибка" message="К сожалению в процессе создания документа возникла ошибка. Пожалуйста, обратитесь к сотруднику Отдела по работе с клиентами или попробуйте еще раз."/>
)}
{ !sign_digital && (
<div className="dosc_list medium-icon">
<div className="row">
@ -157,7 +173,11 @@ class Form_8_Signing extends QuestionnaireForm
{ filename }
<span style={{ width: "100%" }}>Анкета клиента</span>
</p>
<a className="button button-blue " onClick={ this._download }>Скачать</a>
<a className="button button-blue " onClick={ this._handle_onDownload }>
{ downloading ? (
<SpinnerCircular size={ 24 } thickness={ 50 } speed={ 100 } color="rgba(28, 1, 169, 1)" secondaryColor="rgba(236, 239, 244, 1)" />
) : "Скачать" }
</a>
</div>
</div>
) }

View File

@ -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 (
<React.Fragment>
{ sign.digital && (
<div className="questionnaire message success">
<svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M22 38.5C31.1127 38.5 38.5 31.1127 38.5 22C38.5 12.8873 31.1127 5.5 22 5.5C12.8873 5.5 5.5 12.8873 5.5 22C5.5 31.1127 12.8873 38.5 22 38.5Z" fill="white"/>
<path d="M29.5625 17.875L19.4791 27.5L14.4375 22.6875" stroke="#5FB158" strokeWidth="4" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
<p>
<b>Анкета заполнена и подписана</b>
Вы заполнили и подписали анкету лизингополучателя посредством
ЭЦП. Анкета передана в обрабатывающий центр. Если у
сотрудников возникнут вопросы мы свяжемся с Вами. Спасибо!
</p>
</div>
<React.Fragment>
<div className="questionnaire message success">
<svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M22 38.5C31.1127 38.5 38.5 31.1127 38.5 22C38.5 12.8873 31.1127 5.5 22 5.5C12.8873 5.5 5.5 12.8873 5.5 22C5.5 31.1127 12.8873 38.5 22 38.5Z" fill="white"/>
<path d="M29.5625 17.875L19.4791 27.5L14.4375 22.6875" stroke="#5FB158" strokeWidth="4" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
<p>
<b>Анкета заполнена и подписана</b>
Вы заполнили и подписали анкету лизингополучателя посредством
ЭЦП. Анкета передана в обрабатывающий центр. Если у
сотрудников возникнут вопросы мы свяжемся с Вами. Спасибо!
</p>
</div>
<div className="questionnaire status_action">
<button className="button button-blue" style={{ width: "100%", minWidth: "255px" }} onClick={ () => this.props.router.push("/") }>Перейти на главную страницу </button>
</div>
</React.Fragment>
) }
{ sign.print && (
<React.Fragment>
@ -167,6 +175,9 @@ class Form_9_Status extends QuestionnaireForm
Спасибо!
</p>
</div>
<div className="questionnaire status_action">
<button className="button button-blue" style={{ width: "100%", minWidth: "255px" }} onClick={ () => this.props.router.push("/") }>Перейти на главную страницу </button>
</div>
</React.Fragment>
) }
</React.Fragment>

View File

@ -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);

View File

@ -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();

View File

@ -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 (<Form_5_Regulatory company={ company } onNextStep={ this._handle_onNextStep } checking={ false }/>);
if (route.indexOf("#non-profit") > -1) return (<Form_6_NonProfit company={ company } onNextStep={ this._handle_onNextStep } checking={ false }/>);
if (route.indexOf("#check") > -1) return (<Form_7_Check company={ company } signatories={ signatories } onNextStep={ this._handle_onNextStep } checking={ true }/>);
if (route.indexOf("#signing") > -1) return (<Form_8_Signing onNextStep={ this._handle_onNextStep }/>);
if (route.indexOf("#status") > -1) return (<Form_9_Status/>);
if (route.indexOf("#signing") > -1) return (<Form_8_Signing onSuccess={ this._handle_onSuccess } onNextStep={ this._handle_onNextStep }/>);
if (route.indexOf("#status") > -1) return (<Form_9_Status onSuccess={ this._handle_onSuccess } router={ this.props.router }/>);
return (<Form_1_Main company={ company } onNextStep={ this._handle_onNextStep } checking={ false }/>);
}

View File

@ -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: "ИНН ЮЛ",
},
];