update for deal documents

This commit is contained in:
merelendor 2023-10-13 13:14:06 +03:00
parent 2fe3547666
commit 2fefacbce1
13 changed files with 486 additions and 146 deletions

View File

@ -4,6 +4,7 @@ import Router from 'next/router';
import moment from 'moment'; import moment from 'moment';
import { nSQL } from "@nano-sql/core"; import { nSQL } from "@nano-sql/core";
import { eachSeries } from 'async'; import { eachSeries } from 'async';
import fileDownload from 'js-file-download';
import * as actionTypes from '../constants/actionTypes'; import * as actionTypes from '../constants/actionTypes';
import * as currentState from '../reducers/initialState'; import * as currentState from '../reducers/initialState';
@ -80,7 +81,7 @@ export const getDeals = ({ dispatch, update = false }) =>
export const getDealOffers = ({ dispatch, deal_id }) => export const getDealOffers = ({ dispatch, deal_id }) =>
{ {
const url = `${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/deals/offers`; const url = `${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/deals/offer/list`;
console.log("ACTION", "deals", "getDealOffers()", { url }); console.log("ACTION", "deals", "getDealOffers()", { url });
console.log("ACTION", "deals", "getDealOffers()", { deal_id }); console.log("ACTION", "deals", "getDealOffers()", { deal_id });
@ -122,6 +123,31 @@ export const getDealOffers = ({ dispatch, deal_id }) =>
}); });
} }
export const downloadDealOffer = ({ quote_number, filename }) =>
{
return new Promise((resolve, reject) =>
{
const url = `${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/deals/offer/download`;
axios.get(url, {
params: { quote_number },
responseType: 'blob',
})
.then((response) =>
{
fileDownload(response.data, filename);
resolve();
})
.catch((error) =>
{
console.error("ACTION", "sign", "downloadDealOffer()", "ERROR");
console.error(error);
reject(error.data);
});
});
}
export const acceptDealOffers = ({ deal_id, offers }) => export const acceptDealOffers = ({ deal_id, offers }) =>
{ {
const url = `${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/deals/accept`; const url = `${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/deals/accept`;
@ -171,7 +197,7 @@ export const getDealDocuments = ({ dispatch, deal_id }) =>
data: { data: {
deal_id, deal_id,
documents: response.data.documents, documents: response.data.documents,
files: response.data.files, uploaded: response.data.uploaded,
} }
}); });
@ -187,7 +213,7 @@ export const getDealDocuments = ({ dispatch, deal_id }) =>
data: { data: {
deal_id, deal_id,
documents: [], documents: [],
files: {}, uploaded: {},
} }
}); });

View File

@ -1,13 +1,13 @@
import React from "react"; import React from "react";
import numeral from "numeral"; import numeral from "numeral";
import moment from "moment"; import moment from "moment";
import { eachLimit } from "async"; import { eachLimit, eachSeries } from "async";
import { SpinnerCircular } from "spinners-react"; import { SpinnerCircular } from "spinners-react";
import FileDropzoneDeals from "../FileDropzoneDeals"; import FileDropzoneDeals from "../FileDropzoneDeals";
import EDOSign from "../../components/EDOSign"; import EDOSign from "../../components/EDOSign";
import { acceptDealOffers, attachDealDocument, docEDOCancel, docEDOStatus, getFile, removeDealDocument, sendDealDocuments, signDownloadFile, signGetFileContractProject } from "../../actions"; import { acceptDealOffers, attachDealDocument, docEDOCancel, docEDOStatus, downloadDealOffer, getFile, removeDealDocument, sendDealDocuments, signDownloadFile, signGetFileContractProject } from "../../actions";
class Step extends React.Component class Step extends React.Component
{ {
@ -93,6 +93,13 @@ class Offers extends Step
this.setState({ checked }); this.setState({ checked });
} }
_handle_onOffer = (quote_number) =>
{
downloadDealOffer({ quote_number, filename: `ЛК Эволюция КП №${ quote_number }.pdf` })
.then(() => {})
.catch(() => {});
}
_handle_onSend = (event) => _handle_onSend = (event) =>
{ {
event.preventDefault(); event.preventDefault();
@ -202,7 +209,7 @@ class Offers extends Step
<td>{ offer.model_name }</td> <td>{ offer.model_name }</td>
<td>{ offer.object_count }</td> <td>{ offer.object_count }</td>
<td> <td>
<div className="docs_list"> <div className="docs_list" style={{ cursor: "pointer" }} onClick={ () => this._handle_onOffer(offer.quote_number) }>
<div className="row"> <div className="row">
<div className="small-icon"> <div className="small-icon">
<p className="doc_name i-pdf"> <p className="doc_name i-pdf">
@ -274,7 +281,7 @@ class DocumentsForm extends Step
super(props); super(props);
this.state = { this.state = {
open: false, open: false,
files: {}, uploaded: {},
uploading: false, uploading: false,
completed: false, completed: false,
loading: true, loading: true,
@ -282,6 +289,14 @@ class DocumentsForm extends Step
this.status = 102; this.status = 102;
} }
componentDidMount()
{
if(this.status === this.props.statuscode_id)
{
this.setState({ open: true, });
}
}
componentDidUpdate(prevProps, prevState) componentDidUpdate(prevProps, prevState)
{ {
if(this.props.statuscode_id !== prevProps.statuscode_id) if(this.props.statuscode_id !== prevProps.statuscode_id)
@ -296,11 +311,12 @@ class DocumentsForm extends Step
} }
} }
if(prevProps.files !== this.props.files) if(prevProps.uploaded !== this.props.uploaded)
{ {
this.setState({ files: this.props.files, loading: false }, () => this.setState({ uploaded: this.props.uploaded, loading: false }, () =>
{ {
this._checkFilesCompleted(); const completed = this._checkFilesCompleted();
this.setState({ completed });
}); });
} }
} }
@ -323,7 +339,7 @@ class DocumentsForm extends Step
}); });
}) })
/* /*
const { files } = this.state; const { files } = this.state;
const files_array = []; const files_array = [];
@ -332,7 +348,7 @@ class DocumentsForm extends Step
for(let f in files[g]) for(let f in files[g])
{ {
files_array.push(files[g][f]) files_array.push(files[g][f])
} }
} }
this.setState({ uploading: true }, () => this.setState({ uploading: true }, () =>
@ -362,24 +378,39 @@ class DocumentsForm extends Step
this._checkFilesCompleted(); this._checkFilesCompleted();
onDealsUpdate(); onDealsUpdate();
}); });
}); });
}); });
*/ */
} }
_onSendFileStats = (group, index) => _onSendFileStats = (group, index) =>
{ {
const files = { ...this.state.files }; return new Promise((resolve) =>
{
const uploaded = { ...this.state.uploaded };
files[group][index].sent = true; uploaded[group].files[index].sent = true;
this.setState({ files }); this.setState({ uploaded }, () =>
{
resolve();
});
})
} }
_handle_onAddFile = (document_id, files) => _handle_onAddFile = (document_id, files, update) =>
{ {
const existed_files = this.state.files; const existed_files = { ...this.state.uploaded };
const document_files = existed_files[ document_id ] === undefined ? [] : existed_files[ document_id ]; console.log("_handle_onAddFile", { existed_files });
const document_files = existed_files[ document_id ] === undefined ? [] : existed_files[ document_id ].files;
if(existed_files[ document_id ] === undefined)
{
existed_files[ document_id ] = {
sent: false,
files: [],
};
}
for(let nf in files) for(let nf in files)
{ {
@ -394,65 +425,77 @@ class DocumentsForm extends Step
files[nf].index = nf; files[nf].index = nf;
files[nf].group = document_id; files[nf].group = document_id;
files[nf].sent = false; files[nf].sent = false;
files[nf].update = update;
document_files.push(files[nf]); document_files.push(files[nf]);
} }
existed_files[ document_id ] = document_files; existed_files[ document_id ].sent = false;
existed_files[ document_id ].files = document_files;
}
this.setState({ files: existed_files }, () => this.setState({ uploaded: existed_files, uploading: true }, () =>
{
const { opp_number } = this.props;
eachSeries(files, (file, callback) =>
{ {
const { opp_number } = this.props;
const payload = { const payload = {
deal_id: opp_number, deal_id: opp_number,
document_id: files[0].group, document_id: file.group,
filename: files[0].name, filename: file.name,
index: files[0].index, index: file.index,
lastModified: files[0].lastModified, lastModified: file.lastModified,
file: files[0], type: file.type,
type: files[0].type, file,
update,
}; };
attachDealDocument(payload) attachDealDocument(payload)
.then(() => .then(async () =>
{ {
this._onSendFileStats(document_id, 0); await this._onSendFileStats(document_id, file.index);
this._checkFilesCompleted(); callback();
}, 1000) }, 1000)
//this._checkFilesCompleted(); }, () =>
{
const completed = this._checkFilesCompleted();
this.setState({ uploading: false, completed });
}); });
} });
} }
_handle_onDeleteFile = (document_id, file) => _handle_onDeleteFile = (document_id, file) =>
{ {
const files = { ...this.state.files }; const uploaded = { ...this.state.uploaded };
const { opp_number } = this.props; const { opp_number } = this.props;
const list = []; const list = [];
for(let i in files[document_id]) for(let i in uploaded[document_id].files)
{ {
if(files[document_id][i].name !== file.name) if(uploaded[document_id].files[i].name !== file.name)
{ {
list.push(files[document_id][i]); list.push(uploaded[document_id].files[i]);
} }
} }
if(list.length > 0) if(list.length > 0)
{ {
files[document_id] = list; uploaded[document_id].files = list;
} }
else else
{ {
delete files[document_id]; delete uploaded[document_id];
} }
this.setState({ files }, () => this.setState({ uploaded }, () =>
{ {
this._checkFilesCompleted(); const completed = this._checkFilesCompleted();
this.setState({ completed }, () =>
removeDealDocument({ deal_id: opp_number, document_id }); {
removeDealDocument({ deal_id: opp_number, document_id });
});
}); });
} }
@ -466,39 +509,44 @@ class DocumentsForm extends Step
_checkFilesCompleted = () => _checkFilesCompleted = () =>
{ {
const documents_length = this.props.documents.length; // const documents_length = this.props.documents.length;
const files_length = Object.keys(this.state.files).length; // const files_length = Object.keys(this.state.files).length;
// const c = files_length >= documents_length ? true : false;
const c = files_length >= documents_length ? true : false; const { uploaded } = this.state;
/*
const { files } = this.state;
const { documents } = this.props; const { documents } = this.props;
let c = true; let c = true;
for(let g in documents) if(documents !== undefined)
{ {
const group = documents[g].doc_id; for(let g in documents)
{
const group = documents[g].doc_id;
if(files[group] === undefined || files[group].length === 0) if(uploaded[group] === undefined || uploaded[group].files.length === 0)
{
c = false;
break;
}
else
{
for(let f in files[group])
{ {
if(!files[group][f].sent) c = false;
break;
}
else
{
for(let f in uploaded[group].files)
{ {
c = false; if(!uploaded[group].files[f].sent)
break; {
c = false;
break;
}
} }
} }
} }
} }
*/ else
{
c = false;
}
this.setState({ completed: c }); return c;
} }
_renderHeaderButtons = () => _renderHeaderButtons = () =>
@ -506,13 +554,13 @@ class DocumentsForm extends Step
const { open, uploading, completed, loading, } = this.state; const { open, uploading, completed, loading, } = this.state;
const { statuscode_id } = this.props; const { statuscode_id } = this.props;
if(open && !uploading && !loading && completed) if(open && !uploading && !loading)
{ {
if(this.status === statuscode_id) if(this.status === statuscode_id)
{ {
return ( return (
<div className="buttons"> <div className="buttons">
<button className="button button button-blue" onClick={ this._handle_onSendFiles }>Отправить документы</button> <button className="button button button-blue" onClick={ this._handle_onSendFiles } disabled={ completed ? false : true }>Отправить документы</button>
</div> </div>
) )
} }
@ -524,7 +572,7 @@ class DocumentsForm extends Step
render() render()
{ {
const { index, statuscode_id, dealSelected, documents, questionnaire_status, } = this.props; const { index, statuscode_id, dealSelected, documents, questionnaire_status, } = this.props;
const { open, files, uploading, loading } = this.state; const { open, uploaded, uploading, loading } = this.state;
return ( return (
<div className={`${ this.status === statuscode_id ? "current" : statuscode_id > this.status ? "done" : "" }`}> <div className={`${ this.status === statuscode_id ? "current" : statuscode_id > this.status ? "done" : "" }`}>
@ -580,8 +628,8 @@ class DocumentsForm extends Step
{ document.add ? ( { document.add ? (
<FileDropzoneDeals <FileDropzoneDeals
uploading={ uploading } uploading={ uploading }
files={ files[ document.doc_id ] !== undefined ? files[ document.doc_id ] : [] } uploaded={ uploaded[ document.doc_id ] !== undefined ? uploaded[ document.doc_id ] : { sent: false, files: [] } }
onAddFile={ (file) => { this._handle_onAddFile(document.doc_id, file) } } onAddFile={ (file, update) => { this._handle_onAddFile(document.doc_id, file, update) } }
onDeleteFile={ (file) => this._handle_onDeleteFile(document.doc_id, file) } onDeleteFile={ (file) => this._handle_onDeleteFile(document.doc_id, file) }
document={ document } document={ document }
/> />
@ -823,13 +871,13 @@ class SignPlannedContract extends React.Component
await getFile({ id: link_result.url, filename: `ЛК ЭВОЛЮЦИЯ ${ contract.name }.${ link_result.extension }` }); await getFile({ id: link_result.url, filename: `ЛК ЭВОЛЮЦИЯ ${ contract.name }.${ link_result.extension }` });
this.setState({ disabled: false, loading_download_file: false }); this.setState({ disabled: false, loading_download_file: false });
/* /*
const wmdoc_result = await signDownloadFile({ const wmdoc_result = await signDownloadFile({
payload: { entity_name: "evo_contract", entity_id: contract_entity_id, sign_type: edo ? "EDO" : "Paper", evo_id: "144", }, payload: { entity_name: "evo_contract", entity_id: contract_entity_id, sign_type: edo ? "EDO" : "Paper", evo_id: "144", },
filename: `ЛК ЭВОЛЮЦИЯ ${ contract.name }.pdf`, filename: `ЛК ЭВОЛЮЦИЯ ${ contract.name }.pdf`,
}); });
console.log({ wmdoc_result }); console.log({ wmdoc_result });
*/ */
}); });
} }
@ -843,7 +891,7 @@ class SignPlannedContract extends React.Component
await docEDOCancel({ contract_number: contract.name, doc_type_id: contract.sign_type === "EDO" ? "144" : "60" }); await docEDOCancel({ contract_number: contract.name, doc_type_id: contract.sign_type === "EDO" ? "144" : "60" });
setTimeout(() => { setTimeout(() => {
onDealContractsUpdate(); onDealContractsUpdate();
//this.setState({ disabled: false, loading_cancel_sign: false }); // this.setState({ disabled: false, loading_cancel_sign: false });
}, 1000); }, 1000);
}); });
} }
@ -1306,7 +1354,7 @@ export default class SingleDeal extends React.Component
const offers = deals.details[ dealSelected ] !== undefined ? deals.details[ dealSelected ].offers : undefined; const offers = deals.details[ dealSelected ] !== undefined ? deals.details[ dealSelected ].offers : undefined;
const documents = deals.details[ dealSelected ] !== undefined ? deals.details[ dealSelected ].documents : undefined; const documents = deals.details[ dealSelected ] !== undefined ? deals.details[ dealSelected ].documents : undefined;
const files = deals.details[ dealSelected ] !== undefined ? deals.details[ dealSelected ].files : undefined; const uploaded = deals.details[ dealSelected ] !== undefined ? deals.details[ dealSelected ].uploaded : undefined;
const contracts = deals.details[ dealSelected ] !== undefined ? deals.details[ dealSelected ].contracts : undefined; const contracts = deals.details[ dealSelected ] !== undefined ? deals.details[ dealSelected ].contracts : undefined;
return ( return (
@ -1320,7 +1368,7 @@ export default class SingleDeal extends React.Component
<div className="modal_body single_status"> <div className="modal_body single_status">
<Offers { ...this.props } offers={ offers }/> <Offers { ...this.props } offers={ offers }/>
<FinancialProgram { ...this.props }/> <FinancialProgram { ...this.props }/>
<DocumentsForm { ...this.props } documents={ documents } files={ files }/> <DocumentsForm { ...this.props } documents={ documents } uploaded={ uploaded }/>
<StatusDocumentsCheck { ...this.props }/> <StatusDocumentsCheck { ...this.props }/>
<StatusDecisionMaking { ...this.props }/> <StatusDecisionMaking { ...this.props }/>
<StatusDecisionRefuse { ...this.props }/> <StatusDecisionRefuse { ...this.props }/>

View File

@ -8,17 +8,30 @@ const LIMIT_FILES = 10;
export default class FileDropzoneDeals extends FileDropzone export default class FileDropzoneDeals extends FileDropzone
{ {
componentDidMount()
{
console.log("FileDropzoneDeals", "CDM");
}
render() render()
{ {
const { files, onAddFile, onDeleteFile, uploading, document, } = this.props; const { uploaded, onAddFile, onDeleteFile, uploading, document, } = this.props;
console.log("FileDropzoneDeals", { document }); console.log("FileDropzoneDeals", { uploaded, document });
return ( return (
<> <>
{ files.length > 0 && ( { uploaded.files.length > 0 && (
<div className="horizontal_dropzone_files_wrapper"> <div className="horizontal_dropzone_files_wrapper">
{ document.comment !== null && document.comment !== "" && (
<div className="horizontal_dropzone_files_item horizontal_dropzone_files_error">
<p className="horizontal_dropzone_files_comment">
<span>{ document.check }</span>
<span>{ document.comment }</span>
</p>
</div>
) }
<div className="horizontal_dropzone_files horizontal_dropzone_files_item"> <div className="horizontal_dropzone_files horizontal_dropzone_files_item">
{ files.map((file, index) => { uploaded.files.map((file, index) =>
{ {
return ( return (
<div className="file" key={ index }> <div className="file" key={ index }>
@ -42,20 +55,12 @@ export default class FileDropzoneDeals extends FileDropzone
) )
} ) } } ) }
</div> </div>
{ document.comment !== null && document.comment !== "" && (
<div className="horizontal_dropzone_files_item">
<p className="horizontal_dropzone_files_comment">
<span>{ document.check }</span>
<span>{ document.comment }</span>
</p>
</div>
)}
</div> </div>
) } ) }
{ !uploading && files.length < LIMIT_FILES && ( { uploaded.files.length < LIMIT_FILES && (
<Dropzone onDrop={ (acceptedFiles) => onAddFile(acceptedFiles) } maxFiles={ LIMIT_FILES } multiple={ false }> <Dropzone onDrop={ (acceptedFiles) => onAddFile(acceptedFiles, document.comment !== null && document.comment !== "" ? true : false) } maxFiles={ LIMIT_FILES } multiple={ true } disabled={ uploading }>
{ ({getRootProps, getInputProps}) => ( { ({getRootProps, getInputProps}) => (
<div className={`file_upload dropzone horizontal_dropzone_wrapper`} { ...getRootProps() }> <div className={`file_upload dropzone horizontal_dropzone_wrapper ${ uploading ? "disabled" : "" }`} { ...getRootProps() }>
<div className={`files`}></div> <div className={`files`}></div>
<div className={`horizontal_dropzone_inner`}> <div className={`horizontal_dropzone_inner`}>
<p data-sm-text="Выберите файлы"> <p data-sm-text="Выберите файлы">

View File

@ -6072,6 +6072,10 @@ main .dropdown_blocks_list.zero-margin.gibdd .dropdown_block .block_body .fines_
padding: 30px; padding: 30px;
height: 100px; height: 100px;
} }
.horizontal_dropzone_wrapper.disabled {
filter: grayscale(1);
opacity: 0.25;
}
.horizontal_dropzone_wrapper .horizontal_dropzone_inner { .horizontal_dropzone_wrapper .horizontal_dropzone_inner {
display: flex; display: flex;
width: 100%; width: 100%;
@ -6163,12 +6167,15 @@ main .dropdown_blocks_list.zero-margin.gibdd .dropdown_block .block_body .fines_
.horizontal_dropzone_files_wrapper { .horizontal_dropzone_files_wrapper {
width: 100%; width: 100%;
display: flex; display: flex;
flex-direction: row; flex-direction: column;
gap: 0px 20px; gap: 0px 20px;
padding-top: 15px; padding-top: 15px;
} }
.horizontal_dropzone_files_wrapper .horizontal_dropzone_files_item { .horizontal_dropzone_files_wrapper .horizontal_dropzone_files_item {
width: 50%; width: 100%;
}
.horizontal_dropzone_files_wrapper .horizontal_dropzone_files_error {
padding-bottom: 24px;
} }
.horizontal_dropzone_files_comment { .horizontal_dropzone_files_comment {
background: rgba(131, 3, 84, 0.1); background: rgba(131, 3, 84, 0.1);

View File

@ -6982,8 +6982,13 @@ main .dropdown_blocks_list.zero-margin.gibdd .dropdown_block {
.horizontal_dropzone_wrapper { .horizontal_dropzone_wrapper {
margin: 0px; margin: 0px;
padding: 30px; padding: 30px;
height: 100px; height: 100px;
&.disabled {
filter: grayscale(1);
opacity: 0.25;
}
.horizontal_dropzone_inner { .horizontal_dropzone_inner {
display: flex; display: flex;
@ -7092,12 +7097,16 @@ main .dropdown_blocks_list.zero-margin.gibdd .dropdown_block {
.horizontal_dropzone_files_wrapper { .horizontal_dropzone_files_wrapper {
width: 100%; width: 100%;
display: flex; display: flex;
flex-direction: row; flex-direction: column;
gap: 0px 20px; gap: 0px 20px;
padding-top: 15px; padding-top: 15px;
.horizontal_dropzone_files_item { .horizontal_dropzone_files_item {
width: 50%; width: 100%;
}
.horizontal_dropzone_files_error {
padding-bottom: 24px;
} }
} }

View File

@ -45,6 +45,7 @@ export default async function handler(req, res)
console.log({ key }) console.log({ key })
var files = {}; var files = {};
var uploaded = {};
if(deals !== null) if(deals !== null)
{ {
deals = JSON.parse(deals); deals = JSON.parse(deals);
@ -52,10 +53,11 @@ export default async function handler(req, res)
if(deals[ deal_id ] !== undefined) if(deals[ deal_id ] !== undefined)
{ {
files = deals[ deal_id ].files; files = deals[ deal_id ].files;
uploaded = deals[ deal_id ].uploaded;
} }
} }
res.status(200).send({ documents, files }); res.status(200).send({ documents, files, uploaded, });
resolve(); resolve();
}) })
.catch((error) => .catch((error) =>

View File

@ -34,9 +34,9 @@ export default async function handler(req, res)
upload.single("file")(req, {}, async (err) => upload.single("file")(req, {}, async (err) =>
{ {
const { file, } = req; const { file, } = req;
const { deal_id, document_id, type, index, lastModified } = req.query; const { deal_id, document_id, type, index, lastModified, } = req.query;
const local_filename = `${ client_jwt_decoded.acc_number }_${ deal_id }_${ document_id }`; const local_filename = `${ client_jwt_decoded.acc_number }_${ deal_id }_${ document_id }_${ index }`;
const file_payload = { const file_payload = {
name: Buffer.from(file.originalname, 'latin1').toString('utf8'), name: Buffer.from(file.originalname, 'latin1').toString('utf8'),
@ -57,14 +57,16 @@ export default async function handler(req, res)
const key = `deals_${ client_jwt_decoded.acc_number }`; const key = `deals_${ client_jwt_decoded.acc_number }`;
var deals = await RedisClient.get(key); var deals = await RedisClient.get(key);
var files = {}; var uploaded = {};
//var files = {};
if(deals !== null) if(deals !== null)
{ {
deals = JSON.parse(deals); deals = JSON.parse(deals);
if(deals[ deal_id ] !== undefined) if(deals[ deal_id ] !== undefined)
{ {
files = deals[ deal_id ].files; //files = deals[ deal_id ].files;
uploaded = deals[ deal_id ].uploaded;
} }
} }
else else
@ -72,6 +74,23 @@ export default async function handler(req, res)
deals = {}; deals = {};
} }
if(uploaded !== undefined)
{
if(uploaded[ document_id ] !== undefined)
{
uploaded[ document_id ].sent = false;
uploaded[ document_id ].files.push(file_payload);
}
else
{
uploaded[ document_id ] = {
sent: false,
files: [ file_payload ],
}
}
}
/*
if(files[ document_id ] !== undefined) if(files[ document_id ] !== undefined)
{ {
files[ document_id ].push(file_payload); files[ document_id ].push(file_payload);
@ -80,9 +99,10 @@ export default async function handler(req, res)
{ {
files[ document_id ] = [ file_payload ]; files[ document_id ] = [ file_payload ];
} }
*/
//files[ document_id ] = [ file_payload ]; //files[ document_id ] = [ file_payload ];
deals[ deal_id ] = { files }; deals[ deal_id ] = { uploaded };
await RedisClient.set(key, JSON.stringify(deals)); await RedisClient.set(key, JSON.stringify(deals));

View File

@ -46,6 +46,7 @@ export default async function handler(req, res)
const key = `deals_${ client_jwt_decoded.acc_number }`; const key = `deals_${ client_jwt_decoded.acc_number }`;
var deals = await RedisClient.get(key); var deals = await RedisClient.get(key);
var uploaded = {};
var files = {}; var files = {};
if(deals !== null) if(deals !== null)
{ {
@ -53,7 +54,8 @@ export default async function handler(req, res)
if(deals[ deal_id ] !== undefined) if(deals[ deal_id ] !== undefined)
{ {
files = deals[ deal_id ].files; //files = deals[ deal_id ].files;
uploaded = deals[ deal_id ].uploaded;
} }
} }
else else
@ -61,8 +63,19 @@ export default async function handler(req, res)
deals = {}; deals = {};
} }
files[ document_id ].splice(index, 1); if(uploaded !== undefined)
deals[ deal_id ] = { files }; {
if(uploaded[ document_id ] !== undefined)
{
if(uploaded[ document_id ].files !== undefined)
{
uploaded[ document_id ].sent = false;
uploaded[ document_id ].files.splice(index, 1);
}
}
}
deals[ deal_id ] = { uploaded };
await RedisClient.set(key, JSON.stringify(deals)); await RedisClient.set(key, JSON.stringify(deals));
} }

View File

@ -0,0 +1,82 @@
import fs from 'fs';
import axios from 'axios';
import { Cookies } from 'react-cookie';
import cookie from 'cookie';
import moment from 'moment';
import jwt from 'jsonwebtoken';
import { inspect } from 'util';
import { cors } from '../../../../lib/cors';
export default async function handler(req, res)
{
console.log("API", "DEALS", "/offer/download");
await cors(req, res);
const { quote_number, } = req.query;
return new Promise(async (resolve) =>
{
if(req.headers.cookie !== undefined)
{
const cookies = cookie.parse(req.headers?.cookie ? req.headers?.cookie : "");
if(cookies.jwt !== undefined && cookies.jwt !== null)
{
var client_jwt_decoded = jwt.verify(cookies.jwt, process.env.JWT_SECRET_CLIENT);
var crm_jwt = jwt.sign({ acc_number: client_jwt_decoded.acc_number }, process.env.JWT_SECRET_CRM, { noTimestamp: true });
const payload = {
quote_number,
acc_number: client_jwt_decoded.acc_number,
};
console.log({ payload });
try
{
axios.get(`${ process.env.CRM_API_HOST }/lk/ConsiderationOpportunity/quote/offerprintform`, {
params: payload,
responseType: 'arraybuffer',
headers: {
"Authorization": `Bearer ${ crm_jwt }`,
"Content-Type": "application/json",
},
})
.then((crm_response) =>
{
console.log("API", "DEALS", "/offer/download", "RESPONSE");
res.status(200).send(crm_response.data);
resolve();
})
.catch((error) =>
{
console.error("API", "DEALS", "/offer/download", "ERROR");
console.error(error);
console.error(error.data);
res.status(500).send(error.data);
resolve();
});
}
catch(e)
{
console.error(e);
res.status(500).send(e);
resolve();
}
}
else
{
res.status(403).send();
resolve();
}
}
else
{
res.status(403).send();
resolve();
}
});
}

View File

@ -0,0 +1,17 @@
/*
2.7.2 - Метод получения списка Предложений по Лизинговой сделке в CRM
GET /lk/ConsiderationOpportunity/quote
*/
import CRMRequestGet from '../../../../lib/CRMRequestGet';
export default async function handler(req, res)
{
console.log("API", "DEALS", "offers");
console.log(req.body);
console.log("-".repeat(50));
const { deal_id } = req.body;
await CRMRequestGet({ req, res, path: `${ process.env.CRM_API_HOST }/lk/ConsiderationOpportunity/quote`, params: { ...{ opp_number: deal_id } } });
}

View File

@ -11,7 +11,8 @@ import jwt from 'jsonwebtoken';
import { inspect } from 'util'; import { inspect } from 'util';
import FormData from 'form-data'; import FormData from 'form-data';
import multer from 'multer'; import multer from 'multer';
import { eachLimit } from 'async'; import { eachLimit, eachSeries } from 'async';
import archiver from 'archiver';
import { cors } from '../../../lib/cors'; import { cors } from '../../../lib/cors';
import RedisClient from '../../../lib/RedisClient'; import RedisClient from '../../../lib/RedisClient';
@ -25,6 +26,98 @@ function uploadFiles()
} }
*/ */
function createZipFile(zip_filename, files)
{
return new Promise(async (resolve) =>
{
const output = fs.createWriteStream(zip_filename);
const archive = archiver('zip', {
zlib: { level: 9 } // Sets the compression level.
});
output.on('end', function()
{
console.log('Data has been drained');
});
archive.on('warning', function(err)
{
if (err.code === 'ENOENT')
{
} else {
throw err;
}
});
archive.on('error', function(err)
{
throw err;
});
archive.pipe(output);
for(let i in files)
{
archive.append(fs.createReadStream(files[i].path), { name: files[i].name });
}
await archive.finalize();
resolve();
});
}
function uploadFile({ deal_id, filename, name, group, crm_jwt })
{
return new Promise((resolve) =>
{
if(fs.existsSync(`${ uploads }${ filename }`))
{
const path = `${ uploads }${ filename }`;
const file_to_send_data = fs.readFileSync(path);
console.log({ filename, len: file_to_send_data.length, path });
const data = new FormData();
data.append("file", file_to_send_data, name);
const payload = new URLSearchParams({
name: deal_id,
entity: "opportunity",
documentTypeNumber: group,
documentName: name,
});
const file_upload_url = `${ process.env.CRM_API_HOST }/lk/document/upload?${ payload.toString() }`;
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", filename, "SENT");
resolve();
})
.catch((error) =>
{
console.error("FILE", filename, "ERROR");
console.error(error);
resolve();
});
}
else
{
resolve();
}
});
}
export default async function handler(req, res) export default async function handler(req, res)
{ {
await cors(req, res); await cors(req, res);
@ -53,68 +146,86 @@ export default async function handler(req, res)
if(deals[ deal_id ] !== undefined) if(deals[ deal_id ] !== undefined)
{ {
for(let i in deals[ deal_id ].files) //for(let i in deals[ deal_id ].uploaded.files)
{ //{
files.push(deals[ deal_id ].files[i]); // files.push(deals[ deal_id ].uploaded.files[i]);
} //}
console.log({ files }); eachSeries(Object.keys(deals[ deal_id ].uploaded), (group, callback) =>
console.log(files[0])
eachLimit(files, 5, (file_entry, callback) =>
{ {
const file = file_entry[0]; const document = deals[ deal_id ].uploaded[ group ];
try console.log({ group, document });
if(document.files.length === 1)
{ {
if(fs.existsSync(`${ uploads }${ file.filename }`)) const file = document.files[0];
uploadFile({ deal_id, filename: file.filename, name: file.name, group, crm_jwt })
.then(() =>
{ {
const file_to_send_data = fs.readFileSync(`${ uploads }${ file.filename }`); callback();
const data = new FormData(); });
data.append("file", file_to_send_data, file.name); }
else
{
let files_to_zip = [];
for(let f in document.files)
{
const file = document.files[f];
const ext_regex = new RegExp("\.([0-9a-z]+)$", "i");
const ext = file.name.match(ext_regex);
const payload = new URLSearchParams({ files_to_zip.push({
name: deal_id, name: `${ file.name }`,
entity: "opportunity", path: `${ uploads }${ file.filename }`,
documentTypeNumber: file.group,
documentName: file.name,
}); });
}
const file_upload_url = `${ process.env.CRM_API_HOST }/lk/document/upload?${ payload.toString() }`; const zip_filename = `${ client_jwt_decoded.acc_number }_${ deal_id }_${ group }.zip`;
console.log( file_upload_url );
console.log({ files_to_zip });
axios.post(file_upload_url, data,
{ createZipFile(`${ uploads }${ zip_filename }`, files_to_zip)
headers: { .then(() =>
"Content-Type": `multipart/form-data; boundary=${ data._boundary }`, {
"Authorization": `Bearer ${ crm_jwt }`, uploadFile({ deal_id, filename: zip_filename, name: zip_filename, group, crm_jwt })
},
withCredentials: true,
})
.then(() => .then(() =>
{ {
console.log("FILE", file.filename, "SENT");
callback(); callback();
}) });
.catch(() => })
{ }
callback();
}); /*
try
{
if(fs.existsSync(`${ uploads }${ file.filename }`))
{
*/
/*
*/
/*
} }
else else
{ {
callback(); callback();
} }
*/
/* /*
console.log({ file_upload_url }); console.log({ file_upload_url });
*/ */
/*
} }
catch(e) catch(e)
{ {
console.error(e) console.error(e)
callback(); callback();
} }
*/
}, () => }, () =>
{ {
console.log("ALL FILES SENT"); console.log("ALL FILES SENT");

View File

@ -660,7 +660,7 @@ export default class Options extends React.Component
if(number_paydate !== null) { selected.number_paydate = moment(number_paydate).format(); } if(number_paydate !== null) { selected.number_paydate = moment(number_paydate).format(); }
if(period_new !== null) { selected.period_new = period_new; } if(period_new !== null) { selected.period_new = period_new; }
//if(fix_last_payment_available !== null) { selected.fix_last_payment_available = fix_last_payment_available; } if(fix_last_payment_available !== null) { selected.fix_last_payment_available = fix_last_payment_available; }
if(date_offset_type !== null) { selected.date_offset_type = date_offset_type; } if(date_offset_type !== null) { selected.date_offset_type = date_offset_type; }
if(sum !== null) { selected.sum = sum; } if(sum !== null) { selected.sum = sum; }
if(insurance_price_result !== null) { selected.insurance_price_result = insurance_price_result; } if(insurance_price_result !== null) { selected.insurance_price_result = insurance_price_result; }

View File

@ -55,7 +55,7 @@ const dealsReducer = (state = initialState.deals, action) =>
console.log("ACTION", actionTypes.DEAL_DOCUMENTS_LIST, { action }); console.log("ACTION", actionTypes.DEAL_DOCUMENTS_LIST, { action });
const details = state.details; const details = state.details;
details[action.data.deal_id] = { ...details[action.data.deal_id], ...{ documents: action.data.documents, files: action.data.files } }; details[action.data.deal_id] = { ...details[action.data.deal_id], ...{ documents: action.data.documents, uploaded: action.data.uploaded } };
return { return {
...state, ...state,