diff --git a/actions/signActions.js b/actions/signActions.js index c928854..811a268 100644 --- a/actions/signActions.js +++ b/actions/signActions.js @@ -185,6 +185,31 @@ export const signGetFileContractProject = (payload) => }); } +export const signCheckDownloadContractProject = (payload) => +{ + const url = `${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/sign/document/check`; + + return new Promise((resolve, reject) => + { + axios.post(url, payload, { + withCredentials: true, + }) + .then((response) => + { + if(parseInt(process.env.LOG, 10) === 1) { console.log("ACTION", "sign", "signCheckDownloadContractProject()", "response", response.data); } + + resolve(response.data); + }) + .catch((error) => + { + console.error("ACTION", "sign", "signCheckDownloadContractProject()", "ERROR"); + console.error(error); + + reject(error.data); + }); + }); +} + export const signUploadPaperDocument = (contract_number, deal_id, files) => { console.log({ contract_number, files }); diff --git a/components/DealsStatus/components/DealContractsSignEDO.js b/components/DealsStatus/components/DealContractsSignEDO.js new file mode 100644 index 0000000..e8e3fe5 --- /dev/null +++ b/components/DealsStatus/components/DealContractsSignEDO.js @@ -0,0 +1,611 @@ +import React from "react"; +import { connect } from "react-redux"; +import moment from "moment"; +import { SpinnerCircular } from "spinners-react"; +import { concatSeries } from "async"; +import { eachSeries } from 'async'; +import Select from 'react-select'; + +import { createEDOProject, docEDOCancel, signCheckCreatePrintForm, signCheckPowerAttorneyClient, signDownloadFile, signGetGUIDEntity, signGetPowerAttorneyClient, signGetWMDoc, docEDOSign, docEDOStatus, docEDOConnect, getFile, signGetFileContractProject } from "../../../actions"; + +class DealContractsSignEDO extends React.Component +{ + constructor(props) + { + super(props) + this.state = { + finished: false, + operators: null, + edo_message: null, + loading: false, + disabled: false, + documents: [], + operator_selected: {}, + statuses: {}, + step: 0, + } + } + + static getDerivedStateFromProps(nextProps, prevState) + { + console.log("DealContractsSignEDO", "getDerivedStateFromProps", { nextProps }); + return { + operators: nextProps.operators, + edo_message: nextProps.edo_message, + } + } + + componentDidMount() + { + const docs = []; + for(let i in this.props.documents) + { + docs.push({ ...this.props.documents[i], ...{ index: i, loading: true, ready: false, attorney: false } }); + } + this.setState({ documents: docs }); + + if(this.state.operator_selected.box_id === undefined) + { + this.setState({ operator_selected: this.state.operators !== null && this.state.operators[0] !== undefined ? this.state.operators[0] : {} }); + } + } + + _updateDocs = (id, update) => + { + return new Promise((resolve) => + { + const docs = [ ...this.state.documents ]; + docs[ id ] = { ...docs[id], ...update }; + + this.setState({ documents: docs }, () => + { + resolve(); + }); + }); + } + + _checkDocumentsCompleted = () => + { + const { documents } = this.state; + let completed = true; + + for(let i in documents) + { + console.log({ fin: documents[i] }); + if(!documents[i].completed) + completed = false; + break; + } + + return completed; + } + + _sign = () => + { + //const { documents } = this.props; + const { operator_selected, step } = this.state; + const documents = [ ...this.state.documents ]; + + console.log("_handle_onFormSubmit"); + console.log({ documents, operator_selected }); + + this.setState({ loading: true }, () => + { + eachSeries(documents, async (document, callback) => + { + if(document.completed) + { + callback(); + } + else if(document.signing) + { + await this._updateDocs(document.index, { loading: true, }); + + const status_result = await docEDOStatus({ contract_number: document.id }); + if(status_result.status === 3) + { + await this._updateDocs(document.index, { loading: false, signing: false, ready: false, completed: true, }); + } + else + { + await this._updateDocs(document.index, { loading: false, signing: true, ready: false, }); + } + + callback(); + } + else if(document.ready) + { + console.log({ document }) + await this._updateDocs(document.index, { loading: true, }); + + const status_result = await docEDOStatus({ contract_number: document.id }); + console.log({ status_result }); + + if(status_result.status > 0) + { + const sign_result = await docEDOSign({ edoid: status_result.edoid }); + } + + await this._updateDocs(document.index, { loading: false, signing: true, ready: false, error: false, }); + callback(); + } + else + { + console.log({ document }) + await this._updateDocs(document.index, { loading: true }); + + if(document.attorney && document.attorney_selected !== undefined) + { + const create_edo_project_result = await createEDOProject({ + contract_number: document.id, + power_attorney: document.attorney_selected.value, + power_attorney_number: document.attorney_selected.label, + edo_box: operator_selected.edo_box, + }); + + console.log("\n\nIMPORTANT !!!!!!!!!!\n\n"); + console.log({ create_edo_project_result }); + + const get_guid_entity_result = await signGetGUIDEntity({ + contract_number: document.id, + }); + + console.log("\n\nENTITY !!!!!!!!!!\n\n"); + console.log({ get_guid_entity_result }); + + const wmdoc_result = await signGetWMDoc({ + entity_name: "evo_contract", + entity_id: get_guid_entity_result.entityid, + sign_type: "EDO", + evo_id: "144", + }); + console.log({ wmdoc_result }); + + const connect_result = await docEDOConnect({ contract_number: document.id }); + + await this._updateDocs(document.index, { + entity_id: get_guid_entity_result.entityid, + ready: true, + loading: false, + attorney: false, + }); + + callback(); + } + else + { + const create_print_form_result = await signCheckCreatePrintForm({ contract_number: document.id, sign_type: "EDO" }); + console.log({ create_print_form_result }); + + const docs = { status: create_print_form_result.status }; + + if(create_print_form_result.status !== "success") + { + docs.loading = false; + docs.error = true; + docs.ready = true; + docs.message = create_print_form_result.message; + } + + await this._updateDocs(document.index, docs); + + if(create_print_form_result.status === "success") + { + const check_attorney_client_result = await signCheckPowerAttorneyClient({ contract_number: document.id }) + console.log({ check_attorney_client_result }); + + await this._updateDocs(document.index, { attorney: check_attorney_client_result.power_attorney_required, }); + + if(check_attorney_client_result.power_attorney_required) + { + const get_attorney_client_result = await signGetPowerAttorneyClient({ contract_number: document.id }); + console.log({ get_attorney_client_result }); + + if(get_attorney_client_result === null) + { + await this._updateDocs(document.index, { loading: false, error: true, ready: true, message: "Возникла ошибка при создании документа для подписания." }); + callback(); + } + else + { + if(get_attorney_client_result.length === null) + { + await this._updateDocs(document.index, { loading: false, error: true, ready: true, message: "Не обнаружена доверенность на подписанта. Для продолжения подписания обратитесь к своему персональному менеджеру" }); + callback(); + } + else + { + const attorneys = []; + for(let i in get_attorney_client_result) + { + attorneys.push({ + value: get_attorney_client_result[i].power_attorney, + label: get_attorney_client_result[i].power_attorney_number, + }); + } + + await this._updateDocs(document.index, { loading: false, error: false, attorneys, attorney_selected: undefined }); + + callback(); + } + } + } + else + { + const create_edo_project_result = await createEDOProject({ + contract_number: document.id, + edo_box: operator_selected.edo_box, + }); + + const get_guid_entity_result = await signGetGUIDEntity({ + contract_number: document.id, + }); + + const wmdoc_result = await signGetWMDoc({ + entity_name: "evo_contract", + entity_id: get_guid_entity_result.entityid, + sign_type: "EDO", + evo_id: "144", + }); + console.log({ wmdoc_result }); + + const connect_result = await docEDOConnect({ contract_number: document.id }); + + await this._updateDocs(document.index, { + entity_id: get_guid_entity_result.entityid, + ready: true, + loading: false, + attorney: false, + }); + + callback(); + } + } + else + { + await this._updateDocs(document.index, { + loading: false, + error: true, + ready: true, + message: create_print_form_result.message !== undefined && create_print_form_result.message !== null ? create_print_form_result.message : "Возникла ошибка при создании документа для подписания.", + }); + callback(); + } + } + } + }, () => + { + if(this._checkDocumentsCompleted()) + { + this.setState({ loading: false, disabled: false, finished: true, }); + } + else + { + this.setState({ loading: false, disabled: false, finished: false, }); + } + }); + }); + } + + _handle_onFormSubmit = (event) => + { + event.preventDefault(); + + const { onFinish, onGoToEDOInvites } = this.props; + const { operators, operator_selected, step, finished } = this.state; + const documents = [ ...this.state.documents ]; + + console.log("_handle_onFormSubmit"); + console.log({ documents, operator_selected }); + + if(operators !== null && operators.length === 0) + { + onGoToEDOInvites(); + } + else + { + if(finished) + { + onFinish(); + } + else + { + switch(step) + { + case 0: + { + this.setState({ step: 1 }, () => + { + this._sign(); + }); + } + break; + + case 1: + { + this._sign(); + } + break; + } + } + } + } + + _handle_onSelectOperator = (operator) => + { + this.setState({ operator_selected: operator }); + } + + _handle_onAttorneyChange = (index, attorney) => + { + console.log("_handle_onAttorneyChange", { index, attorney }); + this._updateDocs(index, { attorney_selected: attorney }); + } + + _handle_onDownloadFile = (index) => + { + const { documents } = this.state; + + this.setState({ loading: true, disabled: true, }, async () => + { + await this._updateDocs(index, { loading: true }); + + const link_result = await signGetFileContractProject({ + contract_number: documents[index].id, + }); + + console.log("_handle_onDownloadFile", { link_result }); + await getFile({ id: link_result.url, filename: `ЛК ЭВОЛЮЦИЯ ${ documents[index].id }.${ link_result.extension }` }); + + await this._updateDocs(index, { loading: false, disabled: false, }); + this.setState({ loading: false, disabled: false, }); + }); + } + + _handle_onCancelFile = async (index) => + { + const { onCancel } = this.props; + const { documents } = this.state; + await this._updateDocs(index, { loading: true }); + + this.setState({ loading: true, disabled: true }, async () => + { + await docEDOCancel({ contract_number: documents[index].id, doc_type_id: "144" }); + const docs = [ ...this.state.documents ]; + docs.splice(index, 1); + + if(docs.length > 0) + { + this.setState({ documents: docs, loading: false, disabled: false, }); + } + else + { + onCancel(true); + } + }); + } + + _handle_onCancel = () => + { + const { onCancel } = this.props; + const { documents } = this.state; + + console.log("documents", documents, "LEN", documents.length); + + var clean = false; + if(documents.length === 0) + { + clean = true; + } + + onCancel(clean); + } + + _handle_onCheckEDOStatus = async (index) => + { + const { documents } = this.state; + + await this._updateDocs(index, { loading: true }); + + this.setState({ loading: true, disabled: true }, async () => + { + const status_result = await docEDOStatus({ contract_number: documents[index].id }); + console.log({ status_result }); + + if(status_result.status >= 2) + { + await this._updateDocs(index, { loading: false, disabled: false, signing: false, completed: true, url: status_result.url_edo, }); + } + else + { + await this._updateDocs(index, { loading: false, disabled: false, signing: true, completed: false, url: status_result.url_edo, }); + } + + if(this._checkDocumentsCompleted()) + { + this.setState({ loading: false, disabled: false, finished: true, }); + } + else + { + this.setState({ loading: false, disabled: false, finished: false, }); + } + }); + } + + _handle_onGoToEDO = (index) => + { + const { documents } = this.state; + + if(documents[index].url !== undefined && documents[index].url !== null) + { + window.open(documents[index].url, "_blank"); + } + } + + render() + { + const { step, operators, edo_message, documents, loading, disabled, finished, operator_selected } = this.state; + const { onCancel, } = this.props; + console.log({ operators, documents }); + + return ( +
+
+

Подписание через ЭДО

+
+ { step === 0 && ( +
+ +
+ { operators !== undefined && operators !== null && ( + <> + { operators.length === 0 ? ( +
+
+
+ { edo_message } +
+
+ ) : ( + operators.map((operator, index) => ( +
+ this._handle_onSelectOperator(operator) } + disabled={ false } + /> + +
+ ) ) + )} + + ) } +
+
+ ) } + { step === 1 && ( +
+ { documents.map((document, index) => + { + console.log({ document }); + return ( +
+
+

+ { document.name } от { moment(document.date).format("DD.MM.YYYY") } + { document.type !== undefined && ({ document.type }) } +

+
+
+ { document.loading ? ( + <> + { loading && ( + + ) } + + ) : ( + <> + { document.error ? ( + <> +
+ { document.message !== undefined && document.message !== null ? document.message : "" } + + ) : ( + <> + { document.attorney && ( + <> +
+
+ +
+ ) } + + ) : ( + + ) } +
+ ) } + ) } - { status === 1 && ( - - )} - { status === 1 && ( - + { contract.sign_type === "EDO" && ( +
+ { status === 1 && ( + + ) } + { status === 1 && ( + + )} + { status === 1 && ( + + ) } + { status >= 2 && ( + + ) } +
) } - { status >= 2 && ( - - ) } -
+ ) } ) } diff --git a/components/DealsStatus/components/SignedContract.js b/components/DealsStatus/components/SignedContract.js new file mode 100644 index 0000000..7a808a1 --- /dev/null +++ b/components/DealsStatus/components/SignedContract.js @@ -0,0 +1,86 @@ +import React from "react"; +import moment from "moment"; +import { SpinnerCircular } from "spinners-react"; + +import { signCheckDownloadContractProject, signGetFileContractProject, getFile, } from "../../../actions"; + +export default class SignedContract extends React.Component +{ + constructor(props) + { + super(props); + this.state = { + loading: false, + url: undefined, + error: false, + message: undefined, + }; + } + + async componentDidMount() + { + } + + _handle_downloadFile = () => + { + console.log("_handle_downloadFile"); + + const { contract } = this.props; + + this.setState({ loading: true, error: false, }, async () => + { + const check_result = await signCheckDownloadContractProject({ contract_number: contract.name }); + if(check_result.status === "success") + { + console.log("_handle_downloadFile", { check_result }); + + const link_result = await signGetFileContractProject({ + contract_number: contract.name + }); + + console.log("_handle_downloadFile", { link_result }); + await getFile({ id: link_result.url, filename: `ЛК ЭВОЛЮЦИЯ ${ contract.name }.${ link_result.extension }` }); + this.setState({ loading: false, error: false, }); + } + else + { + this.setState({ loading: false, error: true, message: check_result.message !== undefined && check_result.message !== null ? check_result.message : "Возникла ошибка обработки документа" }) + } + }); + } + + render() + { + const { index, contract, } = this.props; + const { loading, error, message, } = this.state; + + return ( +
+
+ PDF +
+
+

{ contract.name }

+
+ { moment(contract.date).format("DD.MM.YYYY") } + { contract.brand_name } + { contract.model_name } +
+
+
+
+
+ { contract.statuscode_name } +
+ { loading ? ( +
+ +
+ ) : ( + + ) } +
+
+ ) + } +} \ No newline at end of file diff --git a/css/main/style.css b/css/main/style.css index d26751f..e67209b 100644 --- a/css/main/style.css +++ b/css/main/style.css @@ -2689,6 +2689,11 @@ main #order .container { display: flex; width: 100%; } +@media (max-width: 1280px) { + .contract_table .table_row { + padding-bottom: 0px !important; + } +} .contract_table .table_row .table_cell { padding: 16px 8px; border: 1px solid #EDEFF5; @@ -2717,6 +2722,12 @@ main #order .container { .contract_table .table_row .table_cell p.opened { color: var(--green); } +@media (max-width: 1280px) { + .contract_table .table_row .table_cell p { + width: 100%; + margin-top: 40px; + } +} .contract_table .table_row .table_cell b { display: block; } @@ -6943,6 +6954,39 @@ main .dropdown_blocks_list.zero-margin.gibdd .dropdown_block .block_body .fines_ .deal_contract_sign_item .actions { width: 65%; justify-content: space-between; + justify-content: flex-start !important; +} +.deal_contract_sign_item .actions .status_icon { + width: 24px; + min-width: 24px; + height: 24px; + min-height: 24px; + background-repeat: no-repeat; + background-position: center; + background-position-y: -1px; + background-position-x: -1px; +} +.deal_contract_sign_item .actions .status_icon.success { + background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z' stroke='%235FB158' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M16.125 9.75L10.625 15L7.875 12.375' stroke='%235FB158' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E%0A"); + border: none !important; +} +.deal_contract_sign_item .actions .status_icon.error { + background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z' stroke='%23ED0A34' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M13 16C13 16.5523 12.5523 17 12 17C11.4477 17 11 16.5523 11 16C11 15.4477 11.4477 15 12 15C12.5523 15 13 15.4477 13 16Z' fill='%23ED0A34'/%3E%3Cpath d='M12 8L12 12' stroke='%23ED0A34' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); + border: none !important; +} +.deal_contract_sign_item .actions .status_icon.await { + background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z' stroke='%238E94A7' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M12 8L12 12' stroke='%238E94A7' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M16 12L12 12' stroke='%238E94A7' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); + border: none !important; +} +.deal_contract_sign_item .actions .status_title { + padding: 0px 10px; +} +.deal_contract_sign_item .actions .status_title i { + display: contents; +} +.deal_contract_sign_item .actions.actions_with_status { + justify-content: flex-start !important; + margin-left: 15px; } .deal_contract_sign_item:first-child { border: none; diff --git a/css/main/style.less b/css/main/style.less index 60554d6..7c6466e 100644 --- a/css/main/style.less +++ b/css/main/style.less @@ -2925,6 +2925,10 @@ main { display: flex; width: 100%; + @media (max-width: 1280px) { + padding-bottom: 0px !important; + } + .table_cell { padding: 16px 8px; border: 1px solid #EDEFF5; @@ -2957,6 +2961,11 @@ main { &.opened { color: var(--green); } + + @media (max-width: 1280px) { + width: 100%; + margin-top: 40px; + } } b { @@ -7945,6 +7954,46 @@ main .dropdown_blocks_list.zero-margin.gibdd .dropdown_block { .actions { width: 65%; justify-content: space-between; + justify-content: flex-start !important; + + .status_icon { + width: 24px; + min-width: 24px; + height: 24px; + min-height: 24px; + background-repeat: no-repeat; + background-position: center; + background-position-y: -1px; + background-position-x: -1px; + + &.success { + background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z' stroke='%235FB158' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M16.125 9.75L10.625 15L7.875 12.375' stroke='%235FB158' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E%0A"); + border: none !important; + } + + &.error { + background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z' stroke='%23ED0A34' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M13 16C13 16.5523 12.5523 17 12 17C11.4477 17 11 16.5523 11 16C11 15.4477 11.4477 15 12 15C12.5523 15 13 15.4477 13 16Z' fill='%23ED0A34'/%3E%3Cpath d='M12 8L12 12' stroke='%23ED0A34' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); + border: none !important; + } + + &.await { + background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z' stroke='%238E94A7' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M12 8L12 12' stroke='%238E94A7' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M16 12L12 12' stroke='%238E94A7' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); + border: none !important; + } + } + + .status_title { + padding: 0px 10px; + + i { + display: contents; + } + } + + &.actions_with_status { + justify-content: flex-start !important; + margin-left: 15px; + } } &:first-child { diff --git a/pages/api/contract/sign/document/check.js b/pages/api/contract/sign/document/check.js new file mode 100644 index 0000000..c9a6bde --- /dev/null +++ b/pages/api/contract/sign/document/check.js @@ -0,0 +1,19 @@ +import CRMRequestGet from '../../../../../lib/CRMRequestGet'; + +export default async function handler(req, res) +{ + console.log("\n\n", "API", "SIGN", "/document/check"); + + const { contract_number } = req.body; + const payload = { + contract_number + }; + + console.log({ payload }); + + await CRMRequestGet({ req, res, + path: `${ process.env.CRM_API_HOST }/lk/Contract/CheckDownloadContractProject`, + params: payload, + log: true, + }); +} \ No newline at end of file diff --git a/pages/api/contract/sign/document/upload.js b/pages/api/contract/sign/document/upload.js index cda1a7b..ecccefc 100644 --- a/pages/api/contract/sign/document/upload.js +++ b/pages/api/contract/sign/document/upload.js @@ -87,7 +87,8 @@ export default async function handler(req, res) }) .catch((crm_error) => { - console.error({ crm_error: crm_error.data }); + console.error("\n\n", "API", "SIGN", "/document/upload"); + console.error(crm_error); res.status(500).send(); resolve();