|
|
import { useState, useEffect, useCallback } from 'react';
|
|
|
import Messages from './Messages.jsx';
|
|
|
import './Form.css';
|
|
|
|
|
|
function Form() {
|
|
|
const [firstRender, setFirstRender] = useState(true);
|
|
|
const [payerName, setPayerName] = useState('');
|
|
|
const [payerINN, setPayerINN] = useState('');
|
|
|
const [payerPhoneEmail, setPayerPhoneEmail] = useState('');
|
|
|
const [payerAddress, setPayerAddress] = useState('');
|
|
|
const [clientId, setClientId] = useState('');
|
|
|
const [payerBankAccount, setPayerBankAccount] = useState('');
|
|
|
const [amount, setAmount] = useState('0-00');
|
|
|
const [payerAccounts, setPayerAccounts] = useState([]);
|
|
|
const [payerAccount, setPayerAccount] = useState('');
|
|
|
const [chargesDetails, setChargesDetails] = useState('OUR');
|
|
|
const [bnfAccount, setBNFAccount] = useState('');
|
|
|
const [bnfBankBic, setBNFBankBic] = useState('');
|
|
|
const [bnfINN, setBNFINN] = useState('');
|
|
|
const [bnfKPP, setBNFKPP] = useState('');
|
|
|
const [bnfName, setBNFName] = useState('');
|
|
|
const [bnfBankName, setBNFBankName] = useState('');
|
|
|
const [bnfBankAccounts, setBNFBankAccounts] = useState([
|
|
|
'Выберите значение...',
|
|
|
]);
|
|
|
const [bnfBankAccount, setBNFBankAccount] = useState('Выберите значение...');
|
|
|
const [paymentDetails, setPaymentDetails] = useState('');
|
|
|
const [codePurpose, setCodePurpose] = useState('1');
|
|
|
const [taxUINCode, setTaxUINCode] = useState('');
|
|
|
|
|
|
const [messages, setMessages] = useState([]);
|
|
|
|
|
|
const fields = [
|
|
|
{
|
|
|
name: 'payer_name',
|
|
|
value: payerName,
|
|
|
status: 'OK',
|
|
|
message: '',
|
|
|
values: [],
|
|
|
},
|
|
|
{
|
|
|
name: 'client_id',
|
|
|
value: clientId,
|
|
|
status: 'OK',
|
|
|
message: '',
|
|
|
values: [],
|
|
|
},
|
|
|
{
|
|
|
name: 'payer_inn',
|
|
|
value: payerINN,
|
|
|
status: 'OK',
|
|
|
message: '',
|
|
|
values: [],
|
|
|
},
|
|
|
{
|
|
|
name: 'payer_phone_email',
|
|
|
value: payerPhoneEmail,
|
|
|
status: 'OK',
|
|
|
message: '',
|
|
|
values: [],
|
|
|
},
|
|
|
{
|
|
|
name: 'payer_address',
|
|
|
value: payerAddress,
|
|
|
status: 'OK',
|
|
|
message: '',
|
|
|
values: [],
|
|
|
},
|
|
|
{ name: 'amount', value: amount, status: 'OK', message: '', values: [] },
|
|
|
{
|
|
|
name: 'payer_account',
|
|
|
value: payerAccount?.split('|')[0],
|
|
|
status: 'OK',
|
|
|
message: '',
|
|
|
values: [],
|
|
|
},
|
|
|
{
|
|
|
name: 'details_of_charges',
|
|
|
value: chargesDetails,
|
|
|
status: 'OK',
|
|
|
message: '',
|
|
|
values: [],
|
|
|
},
|
|
|
{
|
|
|
name: 'bnf_account',
|
|
|
value: bnfAccount,
|
|
|
status: 'OK',
|
|
|
message: '',
|
|
|
values: [],
|
|
|
},
|
|
|
{
|
|
|
name: 'bnf_bank_bic',
|
|
|
value: bnfBankBic,
|
|
|
status: 'OK',
|
|
|
message: '',
|
|
|
values: [],
|
|
|
},
|
|
|
{ name: 'bnf_inn', value: bnfINN, status: 'OK', message: '', values: [] },
|
|
|
{ name: 'bnf_kpp', value: bnfKPP, status: 'OK', message: '', values: [] },
|
|
|
{ name: 'bnf_name', value: bnfName, status: 'OK', message: '', values: [] },
|
|
|
{
|
|
|
name: 'bnf_bank_name',
|
|
|
value: bnfBankName,
|
|
|
status: 'OK',
|
|
|
message: '',
|
|
|
values: [],
|
|
|
},
|
|
|
{
|
|
|
name: 'bnf_bank_account',
|
|
|
value: bnfBankAccount,
|
|
|
status: 'OK',
|
|
|
message: '',
|
|
|
values: bnfBankAccounts,
|
|
|
},
|
|
|
{
|
|
|
name: 'payment_details',
|
|
|
value: paymentDetails,
|
|
|
status: 'OK',
|
|
|
message: '',
|
|
|
values: [],
|
|
|
},
|
|
|
{
|
|
|
name: 'code_purpose',
|
|
|
value: codePurpose,
|
|
|
status: 'OK',
|
|
|
message: '',
|
|
|
values: [],
|
|
|
},
|
|
|
{
|
|
|
name: 'tax_uin_code',
|
|
|
value: taxUINCode,
|
|
|
status: 'OK',
|
|
|
message: '',
|
|
|
values: [],
|
|
|
},
|
|
|
{
|
|
|
name: 'form_type',
|
|
|
value: 'EXT-RUB',
|
|
|
status: 'OK',
|
|
|
message: '',
|
|
|
values: [],
|
|
|
},
|
|
|
{
|
|
|
name: 'payment_type',
|
|
|
values: [],
|
|
|
value: 'regular_payment',
|
|
|
status: 'OK',
|
|
|
message: null,
|
|
|
},
|
|
|
];
|
|
|
|
|
|
const handlePressEnter = (e, field = null) => {
|
|
|
if (e.key === 'Enter') {
|
|
|
handleBlur(field);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
const focusField = (fieldName) => {
|
|
|
document.getElementById(fieldName).focus();
|
|
|
};
|
|
|
|
|
|
const getBorderColor = (fieldName) => {
|
|
|
try {
|
|
|
switch (messages[fieldName].status) {
|
|
|
case 'ERROR':
|
|
|
return 'red';
|
|
|
case 'WARNING':
|
|
|
return 'orange';
|
|
|
default:
|
|
|
return 'black';
|
|
|
}
|
|
|
} catch {
|
|
|
return 'black';
|
|
|
}
|
|
|
};
|
|
|
|
|
|
const handleBlur = (field) => {
|
|
|
setFirstRender(false);
|
|
|
(async () => {
|
|
|
const data = await requestPMTValidationAsyncAwait(fields, 'validate');
|
|
|
setMessages(
|
|
|
data.fields?.reduce((acc, item) => {
|
|
|
acc[item.name] = { status: item.status, message: item.message };
|
|
|
return acc;
|
|
|
}, {})
|
|
|
);
|
|
|
})();
|
|
|
if (['bnf_account', 'bnf_bank_bic', 'bnf_inn'].includes(field)) {
|
|
|
(async () => {
|
|
|
const data = await requestPMTValidationAsyncAwait(
|
|
|
fields,
|
|
|
'doActionForField',
|
|
|
field
|
|
|
);
|
|
|
setBNFBankName(data.fields[13].value);
|
|
|
setBNFBankAccounts(data.fields[14].values);
|
|
|
setBNFBankAccount(data.fields[14].values[0]);
|
|
|
})();
|
|
|
}
|
|
|
};
|
|
|
|
|
|
const requestPMTValidationAsyncAwait = async (
|
|
|
fields,
|
|
|
action,
|
|
|
currentField = null
|
|
|
) => {
|
|
|
const response = await fetch('/pmtvalidation/validate/', {
|
|
|
method: 'POST',
|
|
|
headers: {
|
|
|
Accept: 'application/json',
|
|
|
'Content-Type': 'application/json',
|
|
|
},
|
|
|
body: JSON.stringify({
|
|
|
fields: fields,
|
|
|
action: action,
|
|
|
currentField: currentField,
|
|
|
}),
|
|
|
});
|
|
|
const data = await response.json();
|
|
|
console.log(data);
|
|
|
return data;
|
|
|
};
|
|
|
|
|
|
useEffect(() => {
|
|
|
if (firstRender) {
|
|
|
setFirstRender(false);
|
|
|
return;
|
|
|
}
|
|
|
handleBlur();
|
|
|
}, [firstRender, bnfBankAccount, payerAccount]);
|
|
|
|
|
|
useEffect(() => {
|
|
|
const URLParams = new URLSearchParams(window.location.search);
|
|
|
const cnum = URLParams.get('cnum');
|
|
|
const ftype = URLParams.get('type');
|
|
|
|
|
|
(async () => {
|
|
|
const data = await requestPMTValidationAsyncAwait(
|
|
|
[
|
|
|
{ name: 'payer_account' },
|
|
|
{ name: 'client_id', value: cnum },
|
|
|
{ name: 'form_type', value: ftype },
|
|
|
],
|
|
|
'getClientInfo'
|
|
|
);
|
|
|
setPayerName(data.fields[3].value);
|
|
|
setPayerINN(data.fields[4].value);
|
|
|
setPayerPhoneEmail(data.fields[6].value);
|
|
|
setPayerAddress(data.fields[7].value);
|
|
|
setClientId(data.fields[1].value);
|
|
|
setPayerBankAccount(data.fields[12].value);
|
|
|
setPayerAccounts(data.accounts);
|
|
|
setPayerAccount(data.accounts[0]?.cbAccountNumber);
|
|
|
})();
|
|
|
}, []);
|
|
|
|
|
|
return (
|
|
|
<div className="payment_container">
|
|
|
<div
|
|
|
className="payment_form"
|
|
|
style={{
|
|
|
width:
|
|
|
Object.keys(messages)?.filter(
|
|
|
(item) => messages[item]?.status != 'OK'
|
|
|
).length > 0
|
|
|
? '75%'
|
|
|
: '100%',
|
|
|
}}
|
|
|
>
|
|
|
<div className="payment">
|
|
|
<div className="title_wrapper">
|
|
|
<div className="title">
|
|
|
Рублевый перевод на счета других клиентов или в другие банки,
|
|
|
включая налоговые платежи
|
|
|
</div>
|
|
|
<div className="title">№2 от 03.07.2024</div>
|
|
|
</div>
|
|
|
<div className="section_wrapper">
|
|
|
<div className="section_header">Плательщик</div>
|
|
|
<div className="section_line"></div>
|
|
|
</div>
|
|
|
<div className="payer">
|
|
|
<div className="child label">Плательщик:</div>
|
|
|
<div className="child">{`${payerName} ${clientId}`}</div>
|
|
|
<div className="child label">Номер счета:</div>
|
|
|
<div className="child">
|
|
|
<select
|
|
|
value={payerAccount}
|
|
|
style={{ width: '40ch' }}
|
|
|
onChange={(e) => {
|
|
|
setPayerAccount(e.target.value);
|
|
|
handleBlur();
|
|
|
}}
|
|
|
>
|
|
|
{payerAccounts.map((item, ind) => (
|
|
|
<option key={`cbAccountNumber_${ind}`}>
|
|
|
{item.description
|
|
|
? `${item.cbAccountNumber}|${item.description}`
|
|
|
: item.cbAccountNumber}
|
|
|
</option>
|
|
|
))}
|
|
|
</select>
|
|
|
</div>
|
|
|
<div className="child label">ИНН:</div>
|
|
|
<div className="child">{payerINN}</div>
|
|
|
<div className="child label">Сумма:</div>
|
|
|
<div className="child">
|
|
|
<span>
|
|
|
<input
|
|
|
id="amount"
|
|
|
value={amount}
|
|
|
onChange={(e) => setAmount(e.target.value)}
|
|
|
onKeyDown={(e) => handlePressEnter(e)}
|
|
|
onBlur={handleBlur}
|
|
|
style={{ borderColor: getBorderColor('amount') }}
|
|
|
/>
|
|
|
RUB
|
|
|
</span>
|
|
|
</div>
|
|
|
<div className="child label">Телефон или электронный адрес:</div>
|
|
|
<div className="child">{payerPhoneEmail}</div>
|
|
|
<div className="child"></div>
|
|
|
<div className="child"></div>
|
|
|
<div className="child label">Адрес места жительства:</div>
|
|
|
<div className="child">{payerAddress}</div>
|
|
|
<div className="child label">Комиссии и расходы:</div>
|
|
|
<div className="child">
|
|
|
<select
|
|
|
value={chargesDetails}
|
|
|
onChange={(e) => {
|
|
|
setChargesDetails(e.target.value);
|
|
|
handleBlur();
|
|
|
}}
|
|
|
>
|
|
|
<option>BEN</option>
|
|
|
<option>OUR</option>
|
|
|
<option>SHA</option>
|
|
|
</select>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div className="section_wrapper_1">
|
|
|
<div className="section_header">Получатель</div>
|
|
|
<div className="section_line"></div>
|
|
|
</div>
|
|
|
<div className="receiver_1">
|
|
|
<div className="child"></div>
|
|
|
<div className="child"></div>
|
|
|
<div className="child label">БИК:</div>
|
|
|
<div className="child">
|
|
|
<input
|
|
|
id="bnf_bank_bic"
|
|
|
value={bnfBankBic}
|
|
|
onChange={(e) => setBNFBankBic(e.target.value)}
|
|
|
onBlur={(e) => handleBlur('bnf_bank_bic')}
|
|
|
onKeyDown={(e) => handlePressEnter(e, 'bnf_bank_bic')}
|
|
|
style={{
|
|
|
maxWidth: '32ch',
|
|
|
borderColor: getBorderColor('bnf_bank_bic'),
|
|
|
}}
|
|
|
/>
|
|
|
</div>
|
|
|
<div className="child label">№ Корр. счета:</div>
|
|
|
<div className="child">
|
|
|
<select
|
|
|
onChange={(e) => {
|
|
|
setBNFBankAccount(e.target.value);
|
|
|
}}
|
|
|
value={bnfBankAccount}
|
|
|
style={{ width: '28ch' }}
|
|
|
>
|
|
|
{bnfBankAccounts.map((item, ind) => (
|
|
|
<option key={`bnfBankAccount_${ind}`}>{item}</option>
|
|
|
))}
|
|
|
</select>
|
|
|
</div>
|
|
|
<div className="child label">Номер счета:</div>
|
|
|
<div className="child">
|
|
|
<input
|
|
|
id="bnf_account"
|
|
|
value={bnfAccount}
|
|
|
onChange={(e) => setBNFAccount(e.target.value)}
|
|
|
onBlur={(e) => handleBlur('bnf_account')}
|
|
|
onKeyDown={(e) => handlePressEnter(e, 'bnf_account')}
|
|
|
style={{
|
|
|
maxWidth: '32ch',
|
|
|
borderColor: getBorderColor('bnf_account'),
|
|
|
}}
|
|
|
/>
|
|
|
</div>
|
|
|
<div className="child label">ИНН:</div>
|
|
|
<div className="child">
|
|
|
<input
|
|
|
id="bnf_inn"
|
|
|
value={bnfINN}
|
|
|
onChange={(e) => setBNFINN(e.target.value)}
|
|
|
onBlur={(e) => handleBlur('bnf_inn')}
|
|
|
onKeyDown={(e) => handlePressEnter(e, 'bnf_inn')}
|
|
|
style={{
|
|
|
maxWidth: '32ch',
|
|
|
borderColor: getBorderColor('bnf_inn'),
|
|
|
}}
|
|
|
/>
|
|
|
</div>
|
|
|
<div className="child label">КПП (103):</div>
|
|
|
<div className="child">
|
|
|
<input
|
|
|
id="bnf_kpp"
|
|
|
value={bnfKPP}
|
|
|
onChange={(e) => setBNFKPP(e.target.value)}
|
|
|
onBlur={handleBlur}
|
|
|
onKeyDown={(e) => handlePressEnter(e)}
|
|
|
style={{
|
|
|
maxWidth: '32ch',
|
|
|
borderColor: getBorderColor('bnf_kpp'),
|
|
|
}}
|
|
|
/>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div className="receiver_2">
|
|
|
<div className="child label">Наименование:</div>
|
|
|
<div className="child">
|
|
|
<input
|
|
|
id="bnf_name"
|
|
|
value={bnfName}
|
|
|
onChange={(e) => setBNFName(e.target.value)}
|
|
|
onBlur={handleBlur}
|
|
|
onKeyDown={(e) => handlePressEnter(e)}
|
|
|
style={{
|
|
|
width: '91%',
|
|
|
borderColor: getBorderColor('bnf_name'),
|
|
|
}}
|
|
|
/>
|
|
|
</div>
|
|
|
<div className="child label">Банк получателя:</div>
|
|
|
<div className="child">{bnfBankName}</div>
|
|
|
<div className="child label">Назначение платежа:</div>
|
|
|
<div className="child">
|
|
|
<textarea
|
|
|
id="payment_details"
|
|
|
value={paymentDetails}
|
|
|
onChange={(e) => setPaymentDetails(e.target.value)}
|
|
|
onBlur={handleBlur}
|
|
|
onKeyDown={(e) => handlePressEnter(e)}
|
|
|
style={{
|
|
|
height: '60px',
|
|
|
borderColor: getBorderColor('payment_details'),
|
|
|
}}
|
|
|
/>
|
|
|
</div>
|
|
|
<div className="child label">Код вида дохода:</div>
|
|
|
<div className="child">
|
|
|
<select
|
|
|
style={{ width: '60ch' }}
|
|
|
value={codePurpose}
|
|
|
onChange={(e) => {
|
|
|
setCodePurpose(e.target.value);
|
|
|
handleBlur();
|
|
|
}}
|
|
|
>
|
|
|
<option>1 - напр., заработная плата</option>
|
|
|
<option>2 - алименты (периодические выплаты)</option>
|
|
|
<option>
|
|
|
3 - возмещение вреда здоровью (периодические выплаты)
|
|
|
</option>
|
|
|
<option>
|
|
|
4 - мат. помощь на рождение ребенка (единовременная выплата)
|
|
|
</option>
|
|
|
<option>
|
|
|
5 - возмещение вреда здоровью (единовременная выплата)
|
|
|
</option>
|
|
|
</select>
|
|
|
</div>
|
|
|
<div className="child label">Код (УИП) (22):</div>
|
|
|
<div className="child">
|
|
|
<input
|
|
|
value={taxUINCode}
|
|
|
onChange={(e) => setTaxUINCode(e.target.value)}
|
|
|
onBlur={handleBlur}
|
|
|
onKeyDown={(e) => handlePressEnter(e)}
|
|
|
style={{ maxWidth: '32ch' }}
|
|
|
/>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
{Object.keys(messages)?.filter((item) => messages[item]?.status != 'OK')
|
|
|
.length > 0 ? (
|
|
|
<div className="payment_messages">
|
|
|
<Messages messages={messages} focusField={focusField} />
|
|
|
</div>
|
|
|
) : null}
|
|
|
</div>
|
|
|
);
|
|
|
}
|
|
|
|
|
|
export default Form;
|