diff --git a/components/questionnaire/forms/DigitalCertificates.js b/components/questionnaire/forms/DigitalCertificates.js
index 96aa769..9dfff54 100644
--- a/components/questionnaire/forms/DigitalCertificates.js
+++ b/components/questionnaire/forms/DigitalCertificates.js
@@ -24,6 +24,7 @@ export default class DigitalCertificates extends React.Component
certificates_error: null,
certificate_selected: undefined,
signing: false,
+ show_all: false,
};
this.cryptopro = null;
}
@@ -41,11 +42,17 @@ export default class DigitalCertificates extends React.Component
.then((info) =>
{
//console.log('Initialized', info);
+// console.log('-'.repeat(20));
+// for(let i in this.cryptopro)
+// {
+// console.log(i);
+// }
+// console.log('-'.repeat(20));
this.cryptopro.listCertificates()
.then((certificates_list) =>
{
- //console.log({ certificates_list });
+ console.log({ certificates_list });
console.log("all certificates", JSON.stringify(certificates_list));
Sentry.captureMessage("Client digital sign step, list of all digital certificates");
@@ -57,63 +64,70 @@ export default class DigitalCertificates extends React.Component
this.cryptopro.certificateInfo(certificate.id)
.then((cert) =>
{
+ const errors = [];
+ let apply = true;
+
console.log("certificate", JSON.stringify(cert));
console.log("company", JSON.stringify(company));
//console.log({ cert });
- if(cert.IsValid)
+ if(cert.Subject['OGRNIP'] !== undefined && cert.Subject['OGRNIP'] !== null && cert.Subject['OGRNIP'] !== "")
{
- if(cert.Subject['OGRNIP'] !== undefined && cert.Subject['OGRNIP'] !== null && cert.Subject['OGRNIP'] !== "")
+ if(cert.Subject['INN'] !== undefined && cert.Subject['INN'] !== null && cert.Subject['INN'] !== "")
{
- if(cert.Subject['INN'] !== undefined && cert.Subject['INN'] !== null && cert.Subject['INN'] !== "")
+ if(main.inn !== cert.Subject['INN'])
{
- if(main.inn === cert.Subject['INN'])
- {
- callback(null, [ { id: certificate.id, fields: cert.Subject, valid_to_date: moment(cert.ValidToDate).format("DD.MM.YYYY") } ]);
- }
- else
- {
- callback(null, []);
- }
- }
- else
- {
- callback(null, []);
+ errors.push('inn');
}
}
else
{
- if(cert.Subject['INNLE'] !== undefined && cert.Subject['INNLE'] !== null && cert.Subject['INNLE'] !== "")
+ apply = false;
+ }
+ }
+ else
+ {
+ if(cert.Subject['INNLE'] !== undefined && cert.Subject['INNLE'] !== null && cert.Subject['INNLE'] !== "")
+ {
+ if(main.inn !== cert.Subject['INN'])
{
- let owner_valid = true;
- const fields = [ "lastname", "firstname", "middlename", ];
- const cert_owner = `${ cert.Subject['SN']} ${ cert.Subject['G']}`.toUpperCase();
-
- for(let i in fields)
- {
- if(head_person[fields[i]] !== null && head_person[fields[i]] !== "")
- {
- if(cert_owner.indexOf(head_person[fields[i]].toUpperCase().trim()) < 0)
- {
- owner_valid = false;
- }
- }
- }
-
- if(owner_valid)
- {
- callback(null, [ { id: certificate.id, fields: cert.Subject, valid_to_date: moment(cert.ValidToDate).format("DD.MM.YYYY") } ]);
- }
- else
- {
- callback(null, []);
- }
- }
- else
- {
- callback(null, []);
+ errors.push('inn');
}
}
+ else
+ {
+ apply = false;
+ }
+ }
+
+ let owner_valid = true;
+ const fields = [ "lastname", "firstname", "middlename", ];
+ const cert_owner = `${ cert.Subject['SN']} ${ cert.Subject['G']}`.toUpperCase();
+
+ for(let i in fields)
+ {
+ if(head_person[fields[i]] !== null && head_person[fields[i]] !== "")
+ {
+ if(cert_owner.indexOf(head_person[fields[i]].toUpperCase().trim()) < 0)
+ {
+ owner_valid = false;
+ }
+ }
+ }
+
+ if(!owner_valid)
+ {
+ errors.push('name');
+ }
+
+ if(!cert.IsValid)
+ {
+ errors.push('date');
+ }
+
+ if(apply)
+ {
+ callback(null, [ { id: certificate.id, fields: cert.Subject, valid_to_date: moment(cert.ValidToDate).format("DD.MM.YYYY"), errors } ]);
}
else
{
@@ -131,14 +145,34 @@ export default class DigitalCertificates extends React.Component
{
console.log("applicable certificates", JSON.stringify(certificates));
Sentry.captureMessage("Client digital sign step, list of applicable digital certificates");
-
+
if(certificates.length === 0)
{
- this.setState({ loading: false, certificates_error: "ISSUED" });
+ this.setState({ loading: false, certificates_error: "INVALID" });
}
else
{
- this.setState({ loading: false, certificates });
+ const list = [];
+ let valid_certificate_exists = false;
+
+ for(let i in certificates) { if(certificates[i].errors.length === 0) { list.push(certificates[i]); valid_certificate_exists = true; } }
+ for(let i in certificates) { if(certificates[i].errors.length !== 0) { list.push(certificates[i]); } }
+
+ const update = { loading: false, certificates: list, certificates_error: null };
+ if(list[0] !== undefined)
+ {
+ if(list[0].errors.length === 0)
+ {
+ update.certificate_selected = list[0];
+ }
+ }
+
+ if(!valid_certificate_exists)
+ {
+ update.certificates_error = "INVALID";
+ }
+
+ this.setState(update);
}
});
})
@@ -201,7 +235,7 @@ export default class DigitalCertificates extends React.Component
render()
{
const { company, main, head_person } = this.props;
- const { loading, certificates, certificates_error, certificate_selected, signing } = this.state;
+ const { loading, certificates, certificates_error, certificate_selected, signing, show_all } = this.state;
//console.log("render()", { certificates });
if(loading)
@@ -214,88 +248,104 @@ export default class DigitalCertificates extends React.Component
}
else
{
- if(certificates_error === null)
- {
- console.log({ certificates });
-
- return (
-
-
-
Выберите подписанта
-
-
- { certificates.map((certificate, index) => (
-
-
{ this.setState({ certificate_selected: certificate }) } }
- />
-
-
- )) }
-
-
-
-
-
-
-
-
- )
- }
- else
- {
- return (
-
- { certificates_error === "NOT_INSTALLED" && (
- Плагин КриптоПРО не установлен, посмотрите инструкцию как установить плагин КриптоПРО.> }/>
+ return (
+ <>
+ { (certificates_error !== null) &&
+ <>
+ { certificates_error === "NOT_INSTALLED" || certificates_error === "CERTIFICATES" && (
+
+ Плагин КриптоПРО не установлен или не активирован. Посмотите инструкцию как установить, активировать и проверить работу плагина КриптоПро.
+ > }/>
) }
- { certificates_error === "CERTIFICATES" && (
- Плагин КриптоПРО не активирован, пожалуйста, обновите страницу и подтвердите разрешение для сайта на доступ к списку сертификатов.> }/>
- ) }
- { certificates_error === "ISSUED" && (
- Анкету необходимо подписать по ЭЦП сертификатом юридического лица с ИНН: { main.inn }, выданного: { head_person.lastname } { head_person.firstname } { head_person.middlename }. Такой сертификат не найден.> }/>
+ { certificates_error === "INVALID" && (
+
+ Анкету необходимо подписать по ЭЦП сертификатом юридического лица с ИНН:
+ { main.inn }, выданного: { head_person.lastname } { head_person.firstname } { head_person.middlename }.
+ Такой сертификат не найден!
+ Если Вы уверены в наличии такого сертификата:
+
+ - Проверьте, вставлен ли ключ с этим сертификатом.
+ - Проверьте возможность подписания этим сертификатом с помощью средства проверки КриптоПро.
+ - Возможно, сертификат нужно установить. Воспользуйтесь инструкцией.
+
+ > }/>
) }
{ certificates_error === "MISMATCH" && (
- Подписант не соответствует указанному подписанту в анкете.> }/>
+ Подписант не соответствует указанному подписанту в анкете.> }/>
) }
-
+ >
+ }
+ { certificates.length > 0 && (
+ <>
+
+
Выберите подписанта
+
- )
- }
+ { certificates.slice(0, show_all ? certificates.length : 2).map((certificate, index) => (
+
0 ? "error" : "" } ${ certificates.length > 1 && !show_all && index === 1 ? "show_all_holder" : ""}`} key={ index }>
+
{ this.setState({ certificate_selected: certificate }) } }
+ />
+
+ { certificates.length > 1 && !show_all && index === 1 && (
+
this.setState({ show_all: true }) }>Посмотреть все
+ ) }
+
+ )) }
+
+
+
+
+
+
+
+ >
+ ) }
+ >
+ )
}
}
}
\ No newline at end of file
diff --git a/components/questionnaire/forms/Form_4_Shareholders/index.js b/components/questionnaire/forms/Form_4_Shareholders/index.js
index 0ff4f9b..93f4caa 100644
--- a/components/questionnaire/forms/Form_4_Shareholders/index.js
+++ b/components/questionnaire/forms/Form_4_Shareholders/index.js
@@ -359,7 +359,7 @@ class ShareholderForm extends React.Component
) }
-
+
{/*}
-1 ? "error" : "" }
@@ -791,6 +791,11 @@ class Form_4_Shareholders extends QuestionnaireForm
if(v !== "" && v !== null && !isNaN(parseFloat(v)))
{
total_parts = total_parts + parseFloat(v)
+
+ if(parseFloat(v) < 25)
+ {
+ errors[f].push(`founder_part`);
+ }
}
else
{
diff --git a/components/questionnaire/forms/QuestionnaireForm.js b/components/questionnaire/forms/QuestionnaireForm.js
index 112009b..719432c 100644
--- a/components/questionnaire/forms/QuestionnaireForm.js
+++ b/components/questionnaire/forms/QuestionnaireForm.js
@@ -114,7 +114,6 @@ export default class QuestionnaireForm extends React.Component
{
//console.log("QuestionnaireForm", "_handle_onCheckboxFieldChange", { name, value });
-
const update = { ...this.state };
_set(update, name, value);
this._updateQuestionnaire(update);
diff --git a/css/forms/style.css b/css/forms/style.css
index 70861ec..dc3c0cc 100644
--- a/css/forms/style.css
+++ b/css/forms/style.css
@@ -1663,3 +1663,44 @@
.deal_offers_table {
width: 100%;
}
+.digital_certificates_status {
+ position: relative;
+}
+.digital_certificates_status.error {
+ border: none !important;
+}
+.digital_certificates_status.error label {
+ pointer-events: none;
+ cursor: unset;
+}
+.digital_certificates_status.error label::before {
+ border: none !important;
+ width: 16px;
+ height: 16px;
+ background: url("/assets/images/icons/delete_red.svg") no-repeat center;
+ z-index: 2;
+ transform: scale(1.3);
+ margin-right: 12px;
+}
+.digital_certificates_status.show_all_holder {
+ margin-bottom: 40px !important;
+}
+.digital_certificates_status .show_all {
+ position: absolute;
+ left: 0px;
+ top: 10px;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: flex-end;
+ justify-content: flex-start;
+ background: linear-gradient(0deg, #ffffff 0%, rgba(255, 255, 255, 0) 100%);
+}
+.digital_certificates_status .show_all span {
+ color: var(--blue);
+ text-decoration: underline;
+ cursor: pointer;
+}
+.digital_certificates_status .show_all span:hover {
+ text-decoration: none;
+}
diff --git a/css/forms/style.less b/css/forms/style.less
index 018372b..1d6a071 100644
--- a/css/forms/style.less
+++ b/css/forms/style.less
@@ -1947,4 +1947,51 @@
.deal_offers_table {
width: 100%;
+}
+
+.digital_certificates_status {
+ position: relative;
+
+ &.error {
+ border: none !important;
+ label {
+ pointer-events: none;
+ cursor: unset;
+ &::before {
+ border: none !important;
+ width: 16px;
+ height: 16px;
+ background: url("/assets/images/icons/delete_red.svg") no-repeat center;
+ z-index: 2;
+ transform: scale(1.3);
+ margin-right: 12px;
+ }
+ }
+ }
+
+ &.show_all_holder {
+ margin-bottom: 40px !important;
+ }
+
+ .show_all {
+ position: absolute;
+ left: 0px;
+ top: 10px;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: flex-end;
+ justify-content: flex-start;
+ background: linear-gradient(0deg, rgba(255,255,255,1) 0%, rgba(255,255,255,0) 100%);
+
+ span {
+ color: var(--blue);
+ text-decoration: underline;
+ cursor: pointer;
+
+ &:hover {
+ text-decoration: none;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/css/main/style.css b/css/main/style.css
index ad283ae..acd0c04 100644
--- a/css/main/style.css
+++ b/css/main/style.css
@@ -114,7 +114,7 @@ main .title_wrapper .right {
}
main .title_wrapper .company-dropdown {
position: relative;
- z-index: 100;
+ z-index: 90;
}
main .title_wrapper .company-dropdown .arrow {
cursor: pointer;
@@ -3598,7 +3598,7 @@ main .dropdown_blocks_list .dropdown_block .block_body .fines_detail ul li {
bottom: -30px;
right: 0;
pointer-events: none;
- z-index: 98;
+ z-index: 80;
margin: 0 auto;
max-width: 1310px;
}
diff --git a/css/main/style.less b/css/main/style.less
index 775d6f6..0f6ca84 100644
--- a/css/main/style.less
+++ b/css/main/style.less
@@ -121,7 +121,7 @@ main {
.company-dropdown {
position: relative;
- z-index: 100;
+ z-index: 90;
.arrow {
cursor: pointer;
@@ -4019,7 +4019,7 @@ main .dropdown_blocks_list .dropdown_block .block_body {
bottom: -30px;
right: 0;
pointer-events: none;
- z-index: 98;
+ z-index: 80;
margin: 0 auto;
max-width: 1310px;
diff --git a/pages/api/suggests/document/check.js b/pages/api/suggests/document/check.js
index dc6602c..218a695 100644
--- a/pages/api/suggests/document/check.js
+++ b/pages/api/suggests/document/check.js
@@ -23,36 +23,44 @@ export default async function handler(req, res)
{
if(jwt.verify(cookies.jwt, process.env.JWT_SECRET_CLIENT))
{
- try
+ if(parseInt(process.env.DADATA_API_CHECK_DOCUMENT_ENABLED, 10) === 1)
{
- const { seria, number } = req.body;
+ try
+ {
+ const { seria, number } = req.body;
- axios.post(`https://cleaner.dadata.ru/api/v1/clean/passport`, [ `${ seria } ${ number }` ], {
- httpAgent: keepAliveAgent,
- headers: {
- "Content-Type": "application/json",
- "Authorization": `Token ${ process.env.DADATA_API_KEY }`,
- "X-Secret": process.env.DADATA_SECRET_KEY
- },
- })
- .then((api_response) =>
+ axios.post(`https://cleaner.dadata.ru/api/v1/clean/passport`, [ `${ seria } ${ number }` ], {
+ httpAgent: keepAliveAgent,
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": `Token ${ process.env.DADATA_API_KEY }`,
+ "X-Secret": process.env.DADATA_SECRET_KEY
+ },
+ })
+ .then((api_response) =>
+ {
+ res.status(200).send(api_response.data);
+ resolve();
+ })
+ .catch((error) =>
+ {
+ console.log("error");
+ console.error(error);
+
+ res.status(500).send();
+ resolve();
+ });
+ }
+ catch(e)
{
- res.status(200).send(api_response.data);
- resolve();
- })
- .catch((error) =>
- {
- console.log("error");
- console.error(error);
-
+ console.error(e);
res.status(500).send();
resolve();
- });
+ }
}
- catch(e)
+ else
{
- console.error(e);
- res.status(500).send();
+ res.status(200).json([{ qc: 0 }]);
resolve();
}
}
diff --git a/pages/recovery.js b/pages/recovery.js
index 5bc17f2..7f33814 100644
--- a/pages/recovery.js
+++ b/pages/recovery.js
@@ -29,7 +29,7 @@ export default class RecoveryPage extends React.Component
email_error: false,
recovery_form_step: 1,
email_code_error: false,
- email_send_disabled: false,
+ email_send_disabled: true,
set_password_disabled: true,
email_code_submit_disabled: true,
email_code_resend_disabled: true,
@@ -137,17 +137,26 @@ export default class RecoveryPage extends React.Component
_handle_onEmailChange = (value) =>
{
- this.setState({ email: value, email_send_disabled: this._check_fields_disabled([ value, this.state.email ]), email_error: false });
+ this.setState({ email: value, email_error: false }, () =>
+ {
+ this.setState({ email_send_disabled: this._check_fields_disabled([ value, this.state.email ]) });
+ });
}
_handle_onPasswordChange = (value) =>
{
- this.setState({ password: value, set_password_disabled: this._check_fields_disabled([ value, this.state.password ]), password_error: false });
+ this.setState({ password: value, password_error: false }, () =>
+ {
+ this.setState({ set_password_disabled: this._check_fields_disabled([ value, this.state.password ]) });
+ });
}
_handle_onPasswordCheckChange = (value) =>
{
- this.setState({ password_repeat: value, set_password_disabled: this._check_fields_disabled([ value, this.state.password_repeat ]), password_error: false });
+ this.setState({ password_repeat: value, password_error: false }, () =>
+ {
+ this.setState({ set_password_disabled: this._check_fields_disabled([ value, this.state.password_repeat ]) });
+ });
}
_handle_onEmailCodeChange = (value) =>
diff --git a/public/assets/images/icons/delete_red.svg b/public/assets/images/icons/delete_red.svg
new file mode 100644
index 0000000..14b7c74
--- /dev/null
+++ b/public/assets/images/icons/delete_red.svg
@@ -0,0 +1,3 @@
+