contract additional methods

This commit is contained in:
merelendor 2021-11-28 09:28:21 +03:00
parent 56ef282173
commit fa0af100bc
25 changed files with 3580 additions and 91 deletions

View File

@ -38,7 +38,175 @@ export const getContract = ({ dispatch, number, }) =>
console.log("response.data");
console.log(response.data);
dispatch({ type: actionTypes.CONTRACT, data: response.data });
dispatch({ type: actionTypes.CONTRACT_PAYMENTS, data: { payments: response.data } });
resolve();
})
.catch((error) =>
{
console.error(error);
reject();
});
});
}
export const getContractInfo = ({ dispatch, number, }) =>
{
return new Promise((resolve, reject) =>
{
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/info`, {
number: number
},
{
withCredentials: true,
})
.then((response) =>
{
dispatch({ type: actionTypes.CONTRACT_DATE, data: { date: response.data.dl_date } });
resolve();
})
.catch((error) =>
{
console.error(error);
reject();
});
});
}
export const getContractInsurance = ({ dispatch, number, }) =>
{
return new Promise((resolve, reject) =>
{
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/insurance`, {
number: number
},
{
withCredentials: true,
})
.then((response) =>
{
dispatch({ type: actionTypes.CONTRACT_INSURANCE, data: { insurance: response.data } });
resolve();
})
.catch((error) =>
{
console.error(error);
reject();
});
});
}
export const getContractHelpCard = ({ dispatch, number, }) =>
{
return new Promise((resolve, reject) =>
{
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/helpcard`, {
number: number
},
{
withCredentials: true,
})
.then((response) =>
{
dispatch({ type: actionTypes.CONTRACT_HELPCARD, data: { helpcard: response.data } });
resolve();
})
.catch((error) =>
{
console.error(error);
reject();
});
});
}
export const getContractRegistration = ({ dispatch, number, }) =>
{
return new Promise((resolve, reject) =>
{
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/registration`, {
number: number
},
{
withCredentials: true,
})
.then((response) =>
{
dispatch({ type: actionTypes.CONTRACT_HELPCARD, data: { registration: response.data } });
resolve();
})
.catch((error) =>
{
console.error(error);
reject();
});
});
}
export const getContractTelematic = ({ dispatch, number, }) =>
{
return new Promise((resolve, reject) =>
{
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/telematic`, {
number: number
},
{
withCredentials: true,
})
.then((response) =>
{
dispatch({ type: actionTypes.CONTRACT_TELEMATIC, data: { telematic: response.data } });
resolve();
})
.catch((error) =>
{
console.error(error);
reject();
});
});
}
export const getContractAgreement = ({ dispatch, number, }) =>
{
return new Promise((resolve, reject) =>
{
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/agreement`, {
number: number
},
{
withCredentials: true,
})
.then((response) =>
{
dispatch({ type: actionTypes.CONTRACT_AGREEMENT, data: { agreement: response.data } });
resolve();
})
.catch((error) =>
{
console.error(error);
reject();
});
});
}
export const getContractDocuments = ({ dispatch, number, }) =>
{
return new Promise((resolve, reject) =>
{
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/documents`, {
number: number
},
{
withCredentials: true,
})
.then((response) =>
{
dispatch({ type: actionTypes.CONTRACT_DOCUMENTS, data: { documents: response.data } });
resolve();
})

View File

@ -3,4 +3,12 @@ export const USER = 'USER';
export const COMPANY = 'COMPANY';
export const CONTRACTS = 'CONTRACTS';
export const CONTRACT = 'CONTRACT';
export const CONTRACT_PAYMENTS = 'CONTRACT_PAYMENTS';
export const CONTRACT_DATE = 'CONTRACT_DATE';
export const CONTRACT_INSURANCE = 'CONTRACT_INSURANCE';
export const CONTRACT_HELPCARD = 'CONTRACT_HELPCARD';
export const CONTRACT_REGISTRATION = 'CONTRACT_REGISTRATION';
export const CONTRACT_TELEMATIC = 'CONTRACT_TELEMATIC';
export const CONTRACT_AGREEMENT = 'CONTRACT_AGREEMENT';
export const CONTRACT_DOCUMENTS = 'CONTRACT_DOCUMENTS';
export const CALENDAR = 'CALENDAR';

File diff suppressed because one or more lines are too long

View File

@ -2490,6 +2490,10 @@ main {
}
}
&[data-status="notpaid"] {
background: rgb(168 2 107 / 10%);
}
&[data-status="overpayment-2"] {
background: rgb(28 1 169 / 10%);
}

View File

@ -4,7 +4,7 @@ const withLess = require("next-with-less");
module.exports = withImages(withFonts(withLess({
images: {
domains: [ 'evo-lk.quickcode.ru', 'www.evolesing.ru', 'evolesing.ru', 'localhost', 'localhost:3000'],
domains: [ 'evo-lk.quickcode.ru', 'wow.evoleasing.ru', 'www.evoleasing.ru', 'lk.evoleasing.ru', 'evoleasing.ru', 'localhost', 'localhost:3000'],
},
reactStrictMode: true,
/*

View File

@ -32,7 +32,7 @@
"redux-persist": "^6.0.0"
},
"devDependencies": {
"eslint": "8.0.0",
"eslint": "^8.3.0",
"eslint-config-next": "11.1.2"
}
}

View File

@ -85,7 +85,7 @@ export default function ActsPage()
</div>
<button className="button button-blue">Скачать</button>
<button className="button button-blue">Отправить в ЭДО</button>
{/*<button className="button button-blue">Отправить в ЭДО</button>*/}
</div>
</div>
</article>

View File

@ -0,0 +1,49 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import axios from 'axios';
import { Cookies } from 'react-cookie';
import cookie from 'cookie';
import moment from 'moment';
import jwt from 'jsonwebtoken';
import { cors } from '../../../lib/cors';
export default async function handler(req, res)
{
await cors(req, res);
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(client_jwt_decoded, process.env.JWT_SECRET_CRM, { noTimestamp: true });
try
{
await axios.get(`${ process.env.CRM_API_HOST }/lk/Contract/GetDocumentList`, {
params: { ...client_jwt_decoded, contract_number: req.body.number },
headers: { "Authorization": `Bearer ${ crm_jwt }`, },
withCredentials: true,
})
.then((crm_response) =>
{
res.status(200).json(crm_response.data);
})
.catch((error) =>
{
console.error(error);
res.status(500);
});
}
catch(e)
{
console.error(e);
res.status(500);
}
}
else
{
res.status(403);
}
}
}

View File

@ -0,0 +1,49 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import axios from 'axios';
import { Cookies } from 'react-cookie';
import cookie from 'cookie';
import moment from 'moment';
import jwt from 'jsonwebtoken';
import { cors } from '../../../lib/cors';
export default async function handler(req, res)
{
await cors(req, res);
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(client_jwt_decoded, process.env.JWT_SECRET_CRM, { noTimestamp: true });
try
{
await axios.get(`${ process.env.CRM_API_HOST }/lk/Contract/GetUPDListByContract`, {
params: { ...client_jwt_decoded, contract_number: req.body.number },
headers: { "Authorization": `Bearer ${ crm_jwt }`, },
withCredentials: true,
})
.then((crm_response) =>
{
res.status(200).json(crm_response.data);
})
.catch((error) =>
{
console.error(error);
res.status(500);
});
}
catch(e)
{
console.error(e);
res.status(500);
}
}
else
{
res.status(403);
}
}
}

View File

@ -0,0 +1,46 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import axios from 'axios';
import { Cookies } from 'react-cookie';
import cookie from 'cookie';
import moment from 'moment';
import jwt from 'jsonwebtoken';
import { cors } from '../../../lib/cors';
export default async function handler(req, res)
{
await cors(req, res);
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(client_jwt_decoded, process.env.JWT_SECRET_CRM, { noTimestamp: true });
const response = await new Promise((resolve) =>
{
axios.get(`${ process.env.CRM_API_HOST }/lk/Contract/GetHelpCard`, {
params: { ...client_jwt_decoded, contract_number: req.body.number },
headers: { "Authorization": `Bearer ${ crm_jwt }`, },
withCredentials: true,
})
.then((crm_response) =>
{
resolve(crm_response.data);
})
.catch((error) =>
{
console.error(error);
resolve(error);
});
});
res.status(200).json(response);
}
else
{
res.status(403);
}
}
}

View File

@ -32,7 +32,7 @@ export default async function handler(req, res)
try
{
axios.get(`${ process.env.CRM_API_HOST }/lk/Contract/GetSchedulePayments`, {
await axios.get(`${ process.env.CRM_API_HOST }/lk/Contract/GetSchedulePayments`, {
params: { ...client_jwt_decoded, contract_number: req.body.number },
headers: {
"Authorization": `Bearer ${ crm_jwt }`,

View File

@ -0,0 +1,49 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import axios from 'axios';
import { Cookies } from 'react-cookie';
import cookie from 'cookie';
import moment from 'moment';
import jwt from 'jsonwebtoken';
import { cors } from '../../../lib/cors';
export default async function handler(req, res)
{
await cors(req, res);
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(client_jwt_decoded, process.env.JWT_SECRET_CRM, { noTimestamp: true });
try
{
await axios.get(`${ process.env.CRM_API_HOST }/lk/Contract/GetAddInfoForContract`, {
params: { ...client_jwt_decoded, contract_number: req.body.number },
headers: { "Authorization": `Bearer ${ crm_jwt }`, },
withCredentials: true,
})
.then((crm_response) =>
{
res.status(200).json(crm_response.data);
})
.catch((error) =>
{
console.error(error);
res.status(500);
});
}
catch(e)
{
console.error(e);
res.status(500);
}
}
else
{
res.status(403);
}
}
}

View File

@ -36,7 +36,7 @@ export default async function handler(req, res)
nsib: null,
};
Promise.all([
await Promise.all([
new Promise((resolve) => {
axios.get(`${ process.env.CRM_API_HOST }/lk/Contract/GetOsago`, {
params: client_jwt_decoded,

View File

@ -0,0 +1,28 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import axios from 'axios';
import { Cookies } from 'react-cookie';
import cookie from 'cookie';
import moment from 'moment';
import jwt from 'jsonwebtoken';
import { cors } from '../../../lib/cors';
export default async function handler(req, res)
{
await cors(req, res);
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(client_jwt_decoded, process.env.JWT_SECRET_CRM, { noTimestamp: true });
res.status(200).json(null);
}
else
{
res.status(403);
}
}
}

View File

@ -0,0 +1,28 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import axios from 'axios';
import { Cookies } from 'react-cookie';
import cookie from 'cookie';
import moment from 'moment';
import jwt from 'jsonwebtoken';
import { cors } from '../../../lib/cors';
export default async function handler(req, res)
{
await cors(req, res);
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(client_jwt_decoded, process.env.JWT_SECRET_CRM, { noTimestamp: true });
res.status(200).json(null);
}
else
{
res.status(403);
}
}
}

View File

@ -1,6 +1,7 @@
import React, { Component } from "react";
import Link from "next/link";
import numeral from "numeral";
import moment from "moment";
class CalendarCellModal extends Component
{
@ -47,7 +48,7 @@ class CalendarCellModal extends Component
<div className="table_row" key={ index }>
<div className="table_cell">
<Link href={`/contract/${ payment.contract.number }/payments`}>
<a>{ payment.contract.number } от { payment.contract.date }</a>
<a>{ payment.contract.number } от { moment(payment.contract.date, "DD-MM-YYYY").format("DD.MM.YYYY") }</a>
</Link>
</div>
<div className="table_cell">

View File

@ -3,6 +3,8 @@ import Head from 'next/head';
import Image from 'next/image';
import { connect } from "react-redux";
import { withRouter } from 'next/router';
import moment from "moment";
import { reduxWrapper } from '../../store';
import Header from '../components/Header';
@ -10,15 +12,45 @@ import Footer from '../components/Footer';
import Company from "../components/Company";
import InnerMenu from "./components/InnerMenu";
import { getContractInfo, getContractAgreement } from "../../actions";
class ContractPage extends React.Component
{
constructor(props)
{
super(props);
this.state = {
contract_date: null,
agreement: null,
}
}
static getDerivedStateFromProps(nextProps, prevState)
{
return {
contract_date: nextProps.contract_date,
agreement: nextProps.agreement,
};
}
componentDidMount()
{
if(!this.state.loading && this.props.number !== undefined)
{
this.setState({ loading: true }, () =>
{
getContractInfo({ dispatch: this.props.dispatch, number: this.props.number });
getContractAgreement({ dispatch: this.props.dispatch, number: this.props.number }).then(() => {
this.setState({ loading: false });
}).catch(() => {});
});
}
}
render()
{
const { contract_date } = this.state;
const { number } = this.props;
return (
@ -37,7 +69,7 @@ class ContractPage extends React.Component
<div className="container">
<div className="title_wrapper">
<div className="left">
<h1 className="section_title">Договор { number.replace("_", "/") } от 10.01.2021</h1>
<h1 className="section_title">Договор { number.replace("_", "/") }{ contract_date !== null && (<> от { moment(contract_date).format("DD.MM.YYYY") }</>)}</h1>
</div>
<Company/>
</div>
@ -102,6 +134,8 @@ function mapStateToProps(state, ownProps)
return {
company: state.company,
schedule: state.payments,
contract_date: state.contract.date,
agreement: state.contract.agreement,
}
}

View File

@ -3,6 +3,8 @@ import Head from 'next/head';
import Image from 'next/image';
import { connect } from "react-redux";
import { withRouter } from 'next/router';
import moment from "moment";
import { reduxWrapper } from '../../store';
import Header from '../components/Header';
@ -10,15 +12,45 @@ import Footer from '../components/Footer';
import InnerMenu from "./components/InnerMenu";
import Company from "../components/Company";
import { getContractInfo, getContractDocuments } from "../../actions";
class ContractDocumentsPage extends React.Component
{
constructor(props)
{
super(props);
this.state = {
contract_date: null,
documents: null,
}
}
static getDerivedStateFromProps(nextProps, prevState)
{
return {
contract_date: nextProps.contract_date,
documents: nextProps.documents,
};
}
componentDidMount()
{
if(!this.state.loading && this.props.number !== undefined)
{
this.setState({ loading: true }, () =>
{
getContractInfo({ dispatch: this.props.dispatch, number: this.props.number });
getContractDocuments({ dispatch: this.props.dispatch, number: this.props.number }).then(() => {
this.setState({ loading: false });
}).catch(() => {});
});
}
}
render()
{
const { contract_date } = this.state;
const { number } = this.props;
return (
@ -37,7 +69,7 @@ class ContractDocumentsPage extends React.Component
<div className="container">
<div className="title_wrapper">
<div className="left">
<h1 className="section_title">Договор { number.replace("_", "/") } от 10.01.2021</h1>
<h1 className="section_title">Договор { number.replace("_", "/") }{ contract_date !== null && (<> от { moment(contract_date).format("DD.MM.YYYY") }</>)}</h1>
</div>
<Company />
</div>
@ -56,7 +88,7 @@ class ContractDocumentsPage extends React.Component
</div>
<div className="form_group">
<button className="button button-blue">Скачать</button>
<button className="button button-blue">Отправить в ЭДО</button>
{/*<button className="button button-blue">Отправить в ЭДО</button>*/}
</div>
</div>
@ -127,6 +159,8 @@ function mapStateToProps(state, ownProps)
return {
company: state.company,
schedule: state.payments,
contract_date: state.contract.date,
documents: state.contract.documents,
}
}

View File

@ -10,7 +10,7 @@ import Footer from '../components/Footer';
import Company from "../components/Company";
import InnerMenu from "./components/InnerMenu";
import { getContract } from './../../actions';
import { getContract, getContractInfo } from './../../actions';
import numeral from "numeral";
import moment from "moment";
@ -21,7 +21,8 @@ class ContractSchedulePage extends React.Component
super(props);
this.state = {
loading: false,
contract: null,
payments: null,
contract_date: null,
full: false,
opened: [],
}
@ -30,7 +31,8 @@ class ContractSchedulePage extends React.Component
static getDerivedStateFromProps(nextProps, prevState)
{
return {
contract: nextProps.contract,
payments: nextProps.payments,
contract_date: nextProps.contract_date,
};
}
@ -45,6 +47,8 @@ class ContractSchedulePage extends React.Component
this.setState({ loading: true }, () =>
{
getContractInfo({ dispatch: this.props.dispatch, number: this.props.number });
getContract({ dispatch: this.props.dispatch, number: this.props.number }).then(() => {
this.setState({ loading: false });
}).catch(() => {});
@ -71,11 +75,11 @@ class ContractSchedulePage extends React.Component
render()
{
const { contract, full, opened } = this.state;
const { payments, contract_date, full, opened } = this.state;
const { number } = this.props;
console.log("RENDER", "contact");
console.log(contract);
console.log("RENDER", "payments");
console.log(payments);
const statuses = {
"NotPaid": "",
@ -101,7 +105,7 @@ class ContractSchedulePage extends React.Component
<div className="container">
<div className="title_wrapper">
<div className="left">
<h1 className="section_title">Договор { number.replace("_", "/") }{/* от 10.01.2021*/}</h1>
<h1 className="section_title">Договор { number.replace("_", "/") }{ contract_date !== null && (<> от { moment(contract_date).format("DD.MM.YYYY") }</>)}</h1>
</div>
<Company/>
</div>
@ -120,35 +124,37 @@ class ContractSchedulePage extends React.Component
{ !full && (
<button className="show_more primary" onClick={ this._handle_onSetFull }>Показать прошедшие платежи</button>
) }
{ contract !== null && Object.values(contract).map((payment, index) =>
{ payments !== null && Object.values(payments).map((payment, index) =>
{
let pd = moment(payment.date, "DD-MM-YYYY");
if(!full && today > pd) { return null; }
return (
<div className={ `table_row ${ opened.indexOf(payment.number) > -1 ? "opened" : "" }` } data-status={ statuses[payment.status] } key={ index }>
<div className="table_cell" data-title="Платеж №">{ payment.number }</div>
<div className="table_cell" data-title="от">{ moment(payment.date, "DD-MM-YYYY").format("DD.MM.YYYY") }</div>
<div className="table_cell" data-title="На сумму">{ numeral(payment.total_amount).format('') }</div>
<div className="table_cell" data-title="НДС, 20% ₽">{ numeral(payment.vat_amount).format('') }</div>
{ payment.status === "NotPaid" && (
<div className="table_cell">Не оплачено</div>
) }
{ payment.status === "HalfPaid" && (
<div className="table_cell">Частично оплачено</div>
) }
{ payment.status === "OverPaid" && (
<div className="table_cell"><span>Переплата</span> <span>{ numeral(payment.total_amount).format('') } </span></div>
) }
<div className="table_cell">
{ payment.invoices.map((invoice, invoice_index) =>
(
<span key={ invoice_index }>{ invoice.number } от { moment(invoice.date, "DD-MM-YYYY").format("DD.MM.YYYY") } на сумму { numeral(invoice.total_amount).format('') } </span>
)) }
<div className={ `table_row ${ opened.indexOf(payment.number) > -1 ? "opened" : "" }` } data-status={ payment.status === "NotPaid" && pd < today ? "notpaid" : statuses[payment.status] } key={ index }>
<div className="table_cell" data-title="Платеж №">{ payment.number }</div>
<div className="table_cell" data-title="от">{ moment(payment.date, "DD-MM-YYYY").format("DD.MM.YYYY") }</div>
<div className="table_cell" data-title="На сумму">{ numeral(payment.total_amount).format('') }</div>
<div className="table_cell" data-title="НДС, 20% ₽">{ numeral(payment.vat_amount).format('') }</div>
<div className="table_cell">
{ payment.status === "Paid" && "Оплачено" }
{ payment.status === "NotPaid" && "Не оплачено" }
{ payment.status === "HalfPaid" && "Частично оплачено" }
{ payment.status === "OverPaid" && (
<div className="table_cell"><span>Переплата</span> <span>{ numeral(payment.total_amount).format('') } </span></div>
) }
</div>
<div className="table_cell">
{ payment.invoices.map((invoice, invoice_index) =>
(
<React.Fragment key={invoice_index}>
<p style={{ paddingBottom: "15px", lineHeight: "18px" }}>{ invoice.number } от { moment(invoice.date, "DD-MM-YYYY").format("DD.MM.YYYY") } на сумму { numeral(invoice.total_amount).format('') } </p>
</React.Fragment>
)) }
</div>
<button className="toggle_cell" onClick={ () => this._handle_onSetOpen(payment.number) }></button>
</div>
<button className="toggle_cell" onClick={ () => this._handle_onSetOpen(payment.number) }></button>
</div>
)})}
)
}) }
{/*}
<div className="table_row" data-status="overpayment-2">
<div className="table_cell" data-title="Платеж №">11</div>
@ -208,7 +214,8 @@ function mapStateToProps(state, ownProps)
{
return {
company: state.company,
contract: state.contract,
payments: state.contract.payments,
contract_date: state.contract.date,
//schedule: state.payments,
}
}

View File

@ -3,6 +3,8 @@ import Head from 'next/head';
import Image from 'next/image';
import { connect } from "react-redux";
import { withRouter } from 'next/router';
import moment from "moment";
import { reduxWrapper } from '../../store';
import Header from '../components/Header';
@ -10,6 +12,8 @@ import Footer from '../components/Footer';
import Company from "../components/Company";
import InnerMenu from "./components/InnerMenu";
import { getContractInfo, getContractHelpCard, getContractInsurance, getContractRegistration, getContractTelematic } from './../../actions';
class ContractServicesPage extends React.Component
{
constructor(props)
@ -17,9 +21,38 @@ class ContractServicesPage extends React.Component
super(props);
this.state = {
opened: [],
contract_date: null,
loading: false,
};
}
static getDerivedStateFromProps(nextProps, prevState)
{
return {
contract_date: nextProps.contract_date,
};
}
componentDidMount()
{
if(!this.state.loading && this.props.number !== undefined)
{
this.setState({ loading: true }, () =>
{
getContractInfo({ dispatch: this.props.dispatch, number: this.props.number });
Promise.all([
new Promise((resolve) => { getContractHelpCard({ dispatch: this.props.dispatch, number: this.props.number }).then(resolve())}),
new Promise((resolve) => { getContractInsurance({ dispatch: this.props.dispatch, number: this.props.number }).then(resolve())}),
new Promise((resolve) => { getContractRegistration({ dispatch: this.props.dispatch, number: this.props.number }).then(resolve())}),
new Promise((resolve) => { getContractTelematic({ dispatch: this.props.dispatch, number: this.props.number }).then(resolve())}),
])
.then(() => {
this.setState({ loading: false });
});
});
}
}
_handle_onCard = (card) =>
{
const opened = [ ...this.state.opened ];
@ -37,7 +70,7 @@ class ContractServicesPage extends React.Component
render()
{
const { opened } = this.state;
const { opened, contract_date } = this.state;
const { number } = this.props;
return (
@ -56,7 +89,7 @@ class ContractServicesPage extends React.Component
<div className="container">
<div className="title_wrapper">
<div className="left">
<h1 className="section_title">Договор { number.replace("_", "/") } от 10.01.2021</h1>
<h1 className="section_title">Договор { number.replace("_", "/") }{ contract_date !== null && (<> от { moment(contract_date).format("DD.MM.YYYY") }</>)}</h1>
</div>
<Company/>
</div>
@ -158,6 +191,7 @@ function mapStateToProps(state, ownProps)
return {
company: state.company,
schedule: state.payments,
contract_date: state.contract.date,
}
}

View File

@ -71,7 +71,7 @@ class ReconciliationsPage extends React.Component
<input type="text" className="date_input" value="" placeholder="Дата окончания договора" onFocus={ () => { /*(this.type='date')*/} } onBlur={ () => {/*(this.value == '' ? this.type='text' : this.type='date')*/} } />
</div>
<button className="button button-blue">Скачать</button>
<button className="button button-blue">Отправить в ЭДО</button>
{/*<button className="button button-blue">Отправить в ЭДО</button>*/}
</div>
</div>
</article>

View File

@ -5,6 +5,7 @@ import Link from "next/link";
import cookie from 'cookie';
import { connect } from "react-redux";
import numeral from "numeral";
import moment from 'moment';
import { withRouter } from 'next/router';
import { reduxWrapper } from '../store';
@ -190,14 +191,14 @@ class IndexPage extends React.Component
{ contracts.length > 0 ? contracts.map((contract, index) => (
<div className="table_row" key={ index }>
<div className="table_cell"><Link href={`/contract/${ contract.number }/payments`}><a>Договор { contract.number }</a></Link></div>
<div className="table_cell">{ contract.date }</div>
<div className="table_cell">{ moment(contract.date).format("DD.MM.YYYY") }</div>
<div className="table_cell">{ contract.car?.brand?.name } { contract.car?.model?.name }</div>
<div className="table_cell">{ contract.car?.reg_number !== null ? contract.car?.reg_number : "Без рег. номера" }</div>
<div className="table_cell">{ contract.car?.vin_number }</div>
<div className="table_cell"><p className={ contract_status[contract.status] }>{ contract.status }</p></div>
<div className="table_cell">
{ contract.current_payment_amount !== null ? (
<>{ contract.current_payment_date }<b className="price">{ numeral(contract.current_payment_amount).format('') } р.</b></>
<>{ moment(contract.current_payment_date).format("DD.MM.YYYY") }<b className="price">{ numeral(contract.current_payment_amount).format('') } р.</b></>
) : "-" }
</div>
</div>

View File

@ -23,6 +23,70 @@ const contractReducer = (state = initialState.contract, action) =>
};
}
case actionTypes.CONTRACT_PAYMENTS:
{
return {
...state,
payments: action.data.payments,
};
}
case actionTypes.CONTRACT_DATE:
{
return {
...state,
date: action.data.date,
};
}
case actionTypes.CONTRACT_INSURANCE:
{
return {
...state,
insurance: action.data.insurance,
};
}
case actionTypes.CONTRACT_HELPCARD:
{
return {
...state,
helpcard: action.data.helpcard,
};
}
case actionTypes.CONTRACT_REGISTRATION:
{
return {
...state,
registration: action.data.registration,
};
}
case actionTypes.CONTRACT_TELEMATIC:
{
return {
...state,
telematic: action.data.telematic,
};
}
case actionTypes.CONTRACT_AGREEMENT:
{
return {
...state,
agreement: action.data.agreement,
};
}
case actionTypes.CONTRACT_DOCUMENTS:
{
return {
...state,
documents: action.data.documents,
};
}
default: {
return state;
}

View File

@ -20,7 +20,16 @@ export const defaultState = {
page: 1,
pages: 1,
},
contract: null,
contract: {
payments: null,
date: null,
insurance: null,
helpcard: null,
registration: null,
telematic: null,
agreement: null,
documents: null,
},
calendar: {
payments: null,
periods: null,

View File

@ -72,10 +72,10 @@
"@babel/helper-validator-identifier" "^7.14.9"
to-fast-properties "^2.0.0"
"@eslint/eslintrc@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.0.2.tgz#6044884f7f93c4ecc2d1694c7486cce91ef8f746"
integrity sha512-x1ZXdEFsvTcnbTZgqcWUL9w2ybgZCw/qbKTPQnab+XnYA2bMQpJCh+/bBzCRfDJaJdlrrQlOk49jNtru9gL/6Q==
"@eslint/eslintrc@^1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.0.4.tgz#dfe0ff7ba270848d10c5add0715e04964c034b31"
integrity sha512-h8Vx6MdxwWI2WM8/zREHMoqdgLNXEL4QX3MWSVMdyNJGvXVOs+6lp+m2hc3FnuMHDc4poxFNI20vCk0OmI4G0Q==
dependencies:
ajv "^6.12.4"
debug "^4.3.2"
@ -83,7 +83,7 @@
globals "^13.9.0"
ignore "^4.0.6"
import-fresh "^3.2.1"
js-yaml "^3.13.1"
js-yaml "^4.1.0"
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
@ -373,6 +373,11 @@ acorn@^8.5.0:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.5.0.tgz#4512ccb99b3698c752591e9bb4472e38ad43cee2"
integrity sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==
acorn@^8.6.0:
version "8.6.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.6.0.tgz#e3692ba0eb1a0c83eaa4f37f5fa7368dd7142895"
integrity sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==
ajv-keywords@^3.5.2:
version "3.5.2"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
@ -425,13 +430,6 @@ anymatch@~3.1.1, anymatch@~3.1.2:
normalize-path "^3.0.0"
picomatch "^2.0.4"
argparse@^1.0.7:
version "1.0.10"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
dependencies:
sprintf-js "~1.0.2"
argparse@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
@ -1305,10 +1303,10 @@ eslint-plugin-react@^7.23.1:
semver "^6.3.0"
string.prototype.matchall "^4.0.5"
eslint-scope@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-6.0.0.tgz#9cf45b13c5ac8f3d4c50f46a5121f61b3e318978"
integrity sha512-uRDL9MWmQCkaFus8RF5K9/L/2fn+80yoW3jkD53l4shjCh26fCtvJGasxjUqP5OT87SYTxCVA3BwTUzuELx9kA==
eslint-scope@^7.1.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.0.tgz#c1f6ea30ac583031f203d65c73e723b01298f153"
integrity sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==
dependencies:
esrecurse "^4.3.0"
estraverse "^5.2.0"
@ -1330,12 +1328,17 @@ eslint-visitor-keys@^3.0.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz#e32e99c6cdc2eb063f204eda5db67bfe58bb4186"
integrity sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==
eslint@8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.0.0.tgz#2c2d0ac6353755667ac90c9ff4a9c1315e43fcff"
integrity sha512-03spzPzMAO4pElm44m60Nj08nYonPGQXmw6Ceai/S4QK82IgwWO1EXx1s9namKzVlbVu3Jf81hb+N+8+v21/HQ==
eslint-visitor-keys@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz#eee4acea891814cda67a7d8812d9647dd0179af2"
integrity sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==
eslint@^8.3.0:
version "8.3.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.3.0.tgz#a3c2409507403c1c7f6c42926111d6cbefbc3e85"
integrity sha512-aIay56Ph6RxOTC7xyr59Kt3ewX185SaGnAr8eWukoPLeriCrvGjvAubxuvaXOfsxhtwV5g0uBOsyhAom4qJdww==
dependencies:
"@eslint/eslintrc" "^1.0.2"
"@eslint/eslintrc" "^1.0.4"
"@humanwhocodes/config-array" "^0.6.0"
ajv "^6.10.0"
chalk "^4.0.0"
@ -1344,10 +1347,10 @@ eslint@8.0.0:
doctrine "^3.0.0"
enquirer "^2.3.5"
escape-string-regexp "^4.0.0"
eslint-scope "^6.0.0"
eslint-scope "^7.1.0"
eslint-utils "^3.0.0"
eslint-visitor-keys "^3.0.0"
espree "^9.0.0"
eslint-visitor-keys "^3.1.0"
espree "^9.1.0"
esquery "^1.4.0"
esutils "^2.0.2"
fast-deep-equal "^3.1.3"
@ -1369,7 +1372,7 @@ eslint@8.0.0:
progress "^2.0.0"
regexpp "^3.2.0"
semver "^7.2.1"
strip-ansi "^6.0.0"
strip-ansi "^6.0.1"
strip-json-comments "^3.1.0"
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
@ -1383,10 +1386,14 @@ espree@^9.0.0:
acorn-jsx "^5.3.1"
eslint-visitor-keys "^3.0.0"
esprima@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
espree@^9.1.0:
version "9.1.0"
resolved "https://registry.yarnpkg.com/espree/-/espree-9.1.0.tgz#ba9d3c9b34eeae205724124e31de4543d59fbf74"
integrity sha512-ZgYLvCS1wxOczBYGcQT9DDWgicXwJ4dbocr9uYN+/eresBAUuBu+O4WzB21ufQ/JqQT8gyp7hJ3z8SHii32mTQ==
dependencies:
acorn "^8.6.0"
acorn-jsx "^5.3.1"
eslint-visitor-keys "^3.1.0"
esquery@^1.4.0:
version "1.4.0"
@ -2005,14 +2012,6 @@ jest-worker@27.0.0-next.5:
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
js-yaml@^3.13.1:
version "3.14.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
dependencies:
argparse "^1.0.7"
esprima "^4.0.0"
js-yaml@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
@ -3174,11 +3173,6 @@ source-map@^0.6.1:
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
sprintf-js@~1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
stacktrace-parser@0.1.10:
version "0.1.10"
resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a"
@ -3291,7 +3285,7 @@ strip-ansi@6.0.0:
dependencies:
ansi-regex "^5.0.0"
strip-ansi@^6.0.0:
strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==