411 lines
24 KiB
TypeScript
411 lines
24 KiB
TypeScript
|
|
import React from 'react';
|
|||
|
|
import { ResidentReportContent } from '../../types';
|
|||
|
|
import { Download, Printer } from 'lucide-react';
|
|||
|
|
|
|||
|
|
interface ResidentReportViewProps {
|
|||
|
|
content: ResidentReportContent;
|
|||
|
|
buildingAddress?: string;
|
|||
|
|
period?: string;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export const ResidentReportView: React.FC<ResidentReportViewProps> = ({
|
|||
|
|
content,
|
|||
|
|
buildingAddress,
|
|||
|
|
period
|
|||
|
|
}) => {
|
|||
|
|
const formatCurrency = (amount: number) => {
|
|||
|
|
return new Intl.NumberFormat('ru-RU', {
|
|||
|
|
style: 'currency',
|
|||
|
|
currency: 'RUB',
|
|||
|
|
minimumFractionDigits: 2,
|
|||
|
|
maximumFractionDigits: 2
|
|||
|
|
}).format(amount);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const formatNumber = (num: number) => {
|
|||
|
|
return new Intl.NumberFormat('ru-RU', {
|
|||
|
|
minimumFractionDigits: 2,
|
|||
|
|
maximumFractionDigits: 2
|
|||
|
|
}).format(num);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const handleDownloadCSV = () => {
|
|||
|
|
// TODO: Реализовать экспорт в CSV
|
|||
|
|
alert('Экспорт в CSV будет реализован');
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const handlePrint = () => {
|
|||
|
|
window.print();
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div className="space-y-6 animate-fade-in print:space-y-4">
|
|||
|
|
{/* Кнопки действий */}
|
|||
|
|
<div className="flex justify-end gap-3 print:hidden">
|
|||
|
|
<button
|
|||
|
|
onClick={handleDownloadCSV}
|
|||
|
|
className="bg-primary-600 text-white px-4 py-2 rounded-lg flex items-center gap-2 hover:bg-primary-700 transition-colors"
|
|||
|
|
>
|
|||
|
|
<Download className="w-4 h-4" />
|
|||
|
|
Скачать CSV
|
|||
|
|
</button>
|
|||
|
|
<button
|
|||
|
|
onClick={handlePrint}
|
|||
|
|
className="bg-slate-100 text-slate-700 px-4 py-2 rounded-lg flex items-center gap-2 hover:bg-slate-200 transition-colors"
|
|||
|
|
>
|
|||
|
|
<Printer className="w-4 h-4" />
|
|||
|
|
Печать
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Параметры */}
|
|||
|
|
{content.parameters && (
|
|||
|
|
<div className="bg-white rounded-2xl border border-slate-200 shadow-sm p-6 print:border-0 print:shadow-none">
|
|||
|
|
<h3 className="text-lg font-bold text-slate-800 mb-4">Параметры:</h3>
|
|||
|
|
<div className="space-y-3">
|
|||
|
|
<div>
|
|||
|
|
<p className="text-sm text-slate-600 mb-1">Период: {content.parameters.periodStart && content.parameters.periodEnd
|
|||
|
|
? `${new Date(content.parameters.periodStart).toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit', year: 'numeric' })} - ${new Date(content.parameters.periodEnd).toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit', year: 'numeric' })}`
|
|||
|
|
: period || 'Не указан'}
|
|||
|
|
</p>
|
|||
|
|
<p className="text-sm text-slate-600 mb-1">Начало периода:</p>
|
|||
|
|
<p className="text-sm text-slate-600 mb-1">Конец периода:</p>
|
|||
|
|
<p className="text-sm text-slate-600 mb-1">Дом: {content.parameters.building || buildingAddress || 'Не указан'}</p>
|
|||
|
|
</div>
|
|||
|
|
<div className="grid grid-cols-2 md:grid-cols-5 gap-4 pt-2 border-t border-slate-200">
|
|||
|
|
{content.parameters.residentialArea && (
|
|||
|
|
<div>
|
|||
|
|
<p className="text-sm text-slate-600 mb-1">Ж (кв.м)</p>
|
|||
|
|
<p className="font-bold text-slate-800">{formatNumber(content.parameters.residentialArea)}</p>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
{content.parameters.nonResidentialArea && (
|
|||
|
|
<div>
|
|||
|
|
<p className="text-sm text-slate-600 mb-1">НЖ (кв.м) в т.ч.:</p>
|
|||
|
|
<p className="font-bold text-slate-800">{formatNumber(content.parameters.nonResidentialArea)}</p>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
{content.parameters.parkingArea && (
|
|||
|
|
<div>
|
|||
|
|
<p className="text-sm text-slate-600 mb-1">Парковка</p>
|
|||
|
|
<p className="font-bold text-slate-800">{formatNumber(content.parameters.parkingArea)}</p>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
{content.parameters.totalArea && (
|
|||
|
|
<div>
|
|||
|
|
<p className="text-sm text-slate-600 mb-1">Итого (кв.м)</p>
|
|||
|
|
<p className="font-bold text-slate-800">{formatNumber(content.parameters.totalArea)}</p>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
</div>
|
|||
|
|
{content.tariffs && (
|
|||
|
|
<div className="grid grid-cols-2 gap-4 pt-2 border-t border-slate-200">
|
|||
|
|
<div>
|
|||
|
|
<p className="text-sm text-slate-600 mb-1">Тариф</p>
|
|||
|
|
<p className="font-bold text-slate-800">{formatNumber(content.tariffs.tariff)}</p>
|
|||
|
|
</div>
|
|||
|
|
<div>
|
|||
|
|
<p className="text-sm text-slate-600 mb-1">Резервный фонд</p>
|
|||
|
|
<p className="font-bold text-slate-800">{formatNumber(content.tariffs.reserveFund)}</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
|
|||
|
|
{/* Тарифы */}
|
|||
|
|
{content.tariffs && (
|
|||
|
|
<div className="bg-white rounded-2xl border border-slate-200 shadow-sm p-6 print:border-0 print:shadow-none">
|
|||
|
|
<div className="grid grid-cols-2 gap-4">
|
|||
|
|
<div>
|
|||
|
|
<p className="text-sm text-slate-600 mb-1">Тариф</p>
|
|||
|
|
<p className="font-bold text-slate-800">{formatNumber(content.tariffs.tariff)}</p>
|
|||
|
|
</div>
|
|||
|
|
<div>
|
|||
|
|
<p className="text-sm text-slate-600 mb-1">Резервный фонд</p>
|
|||
|
|
<p className="font-bold text-slate-800">{formatNumber(content.tariffs.reserveFund)}</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
|
|||
|
|
{/* Услуги */}
|
|||
|
|
{content.services && content.services.length > 0 && (
|
|||
|
|
<div className="bg-white rounded-2xl border border-slate-200 shadow-sm p-6 print:border-0 print:shadow-none overflow-x-auto">
|
|||
|
|
<h3 className="text-lg font-bold text-slate-800 mb-4">Услуги</h3>
|
|||
|
|
<table className="w-full border-collapse">
|
|||
|
|
<thead>
|
|||
|
|
<tr className="border-b border-slate-200">
|
|||
|
|
<th className="text-left py-2 px-3 text-sm font-bold text-slate-700">Услуга</th>
|
|||
|
|
<th className="text-right py-2 px-3 text-sm font-bold text-slate-700">Долг</th>
|
|||
|
|
<th className="text-right py-2 px-3 text-sm font-bold text-slate-700">Начислено</th>
|
|||
|
|
<th className="text-right py-2 px-3 text-sm font-bold text-slate-700">Оплачено</th>
|
|||
|
|
<th className="text-right py-2 px-3 text-sm font-bold text-slate-700">% от плана</th>
|
|||
|
|
<th className="text-right py-2 px-3 text-sm font-bold text-slate-700">Порядок</th>
|
|||
|
|
</tr>
|
|||
|
|
</thead>
|
|||
|
|
<tbody>
|
|||
|
|
{content.services
|
|||
|
|
.sort((a, b) => a.order - b.order)
|
|||
|
|
.map((service, index) => (
|
|||
|
|
<tr
|
|||
|
|
key={index}
|
|||
|
|
className={`border-b border-slate-100 hover:bg-slate-50 ${
|
|||
|
|
service.name === 'СОДЕРЖАНИЕ ВСЕГО' ? 'bg-emerald-50 font-bold' : ''
|
|||
|
|
}`}
|
|||
|
|
>
|
|||
|
|
<td className={`py-2 px-3 text-sm ${service.name === 'СОДЕРЖАНИЕ ВСЕГО' ? 'font-bold text-slate-900' : 'text-slate-800'}`}>
|
|||
|
|
{service.name}
|
|||
|
|
</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-700">{formatCurrency(service.debt)}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-700">{formatCurrency(service.accrued)}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-700">{formatCurrency(service.paid)}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-700">{formatNumber(service.percentOfPlan)}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-500">{formatNumber(service.order)}</td>
|
|||
|
|
</tr>
|
|||
|
|
))}
|
|||
|
|
</tbody>
|
|||
|
|
</table>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
|
|||
|
|
{/* Сальдо */}
|
|||
|
|
{content.balance && (
|
|||
|
|
<div className="bg-white rounded-2xl border border-slate-200 shadow-sm p-6 print:border-0 print:shadow-none overflow-x-auto">
|
|||
|
|
<h3 className="text-lg font-bold text-slate-800 mb-4">Сальдо</h3>
|
|||
|
|
<table className="w-full border-collapse">
|
|||
|
|
<thead>
|
|||
|
|
<tr className="border-b border-slate-200">
|
|||
|
|
<th className="text-left py-2 px-3 text-sm font-bold text-slate-700">Сальдо</th>
|
|||
|
|
<th className="text-right py-2 px-3 text-sm font-bold text-slate-700">Сумма</th>
|
|||
|
|
</tr>
|
|||
|
|
</thead>
|
|||
|
|
<tbody>
|
|||
|
|
<tr className="border-b border-slate-100">
|
|||
|
|
<td className="py-2 px-3 text-sm text-slate-700">Исходя из начисленных</td>
|
|||
|
|
<td className={`py-2 px-3 text-sm text-right font-bold ${
|
|||
|
|
(content.balance.fromAccrued || 0) < 0 ? 'text-red-600' : 'text-slate-800'
|
|||
|
|
}`}>
|
|||
|
|
{formatCurrency(content.balance.fromAccrued || 0)}
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
<tr className="border-b border-slate-100">
|
|||
|
|
<td className="py-2 px-3 text-sm text-slate-700">Исходя из поступивших средств</td>
|
|||
|
|
<td className={`py-2 px-3 text-sm text-right font-bold ${
|
|||
|
|
(content.balance.fromReceived || 0) < 0 ? 'text-red-600' : 'text-slate-800'
|
|||
|
|
}`}>
|
|||
|
|
{formatCurrency(content.balance.fromReceived || 0)}
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
{content.balance.reserveFundFromAccrued !== undefined && (
|
|||
|
|
<tr className="border-b border-slate-100">
|
|||
|
|
<td className="py-2 px-3 text-sm text-slate-700">Сальдо Резервного фонда на начало периода исходя из Начисленых средств</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right font-bold text-slate-800">
|
|||
|
|
{formatCurrency(content.balance.reserveFundFromAccrued)}
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
)}
|
|||
|
|
{content.balance.reserveFundFromReceived !== undefined && (
|
|||
|
|
<tr>
|
|||
|
|
<td className="py-2 px-3 text-sm text-slate-700">Сальдо Резервного фонда на начало периода исходя из Поступивших средств</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right font-bold text-slate-800">
|
|||
|
|
{formatCurrency(content.balance.reserveFundFromReceived)}
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
)}
|
|||
|
|
</tbody>
|
|||
|
|
</table>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
|
|||
|
|
{/* Статьи затрат */}
|
|||
|
|
{content.expenseItems && content.expenseItems.length > 0 && (
|
|||
|
|
<div className="bg-white rounded-2xl border border-slate-200 shadow-sm p-6 print:border-0 print:shadow-none overflow-x-auto">
|
|||
|
|
<h3 className="text-lg font-bold text-slate-800 mb-4">Статьи затрат</h3>
|
|||
|
|
<table className="w-full border-collapse">
|
|||
|
|
<thead>
|
|||
|
|
<tr className="border-b border-slate-200">
|
|||
|
|
<th className="text-left py-2 px-3 text-sm font-bold text-slate-700">№ п/п</th>
|
|||
|
|
<th className="text-left py-2 px-3 text-sm font-bold text-slate-700">Статья затрат</th>
|
|||
|
|
<th className="text-right py-2 px-3 text-sm font-bold text-slate-700">В месяц</th>
|
|||
|
|
<th className="text-right py-2 px-3 text-sm font-bold text-slate-700">Сумма</th>
|
|||
|
|
<th className="text-right py-2 px-3 text-sm font-bold text-slate-700">руб/кв.м в месяц</th>
|
|||
|
|
</tr>
|
|||
|
|
</thead>
|
|||
|
|
<tbody>
|
|||
|
|
{content.expenseItems.map((item, index) => (
|
|||
|
|
<React.Fragment key={index}>
|
|||
|
|
<tr className="border-b border-slate-100">
|
|||
|
|
<td className="py-2 px-3 text-sm text-slate-800 font-medium">{item.number}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-slate-800 font-bold">{item.name}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-700">{formatCurrency(item.perMonth)}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-700 font-bold">{formatCurrency(item.total)}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-700">{formatNumber(item.perSquareMeter)}</td>
|
|||
|
|
</tr>
|
|||
|
|
{item.children && item.children.map((child, childIndex) => (
|
|||
|
|
<React.Fragment key={`${index}-${childIndex}`}>
|
|||
|
|
<tr className="border-b border-slate-50 bg-slate-50/50">
|
|||
|
|
<td className="py-2 px-3 text-sm text-slate-700 pl-8">{child.number}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-slate-700">{child.name}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-600">{formatCurrency(child.perMonth)}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-600">{formatCurrency(child.total)}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-600">{formatNumber(child.perSquareMeter)}</td>
|
|||
|
|
</tr>
|
|||
|
|
{child.children && child.children.map((grandchild, grandchildIndex) => (
|
|||
|
|
<tr key={`${index}-${childIndex}-${grandchildIndex}`} className="border-b border-slate-50 bg-slate-50/30">
|
|||
|
|
<td className="py-2 px-3 text-sm text-slate-600 pl-12">{grandchild.number}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-slate-600">{grandchild.name}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-500">{formatCurrency(grandchild.perMonth)}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-500">{formatCurrency(grandchild.total)}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-500">{formatNumber(grandchild.perSquareMeter)}</td>
|
|||
|
|
</tr>
|
|||
|
|
))}
|
|||
|
|
</React.Fragment>
|
|||
|
|
))}
|
|||
|
|
</React.Fragment>
|
|||
|
|
))}
|
|||
|
|
</tbody>
|
|||
|
|
</table>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
|
|||
|
|
{/* Итоги */}
|
|||
|
|
{content.totals && (
|
|||
|
|
<div className="bg-white rounded-2xl border border-slate-200 shadow-sm p-6 print:border-0 print:shadow-none overflow-x-auto">
|
|||
|
|
<h3 className="text-lg font-bold text-slate-800 mb-4">Итоги</h3>
|
|||
|
|
<table className="w-full border-collapse">
|
|||
|
|
<tbody>
|
|||
|
|
<tr className="border-b border-slate-200">
|
|||
|
|
<td className="py-2 px-3 text-sm font-bold text-slate-800">Итого</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-700">{formatCurrency(content.totals.totalExpenses / (content.parameters?.totalArea ? (new Date(content.parameters.periodEnd).getTime() - new Date(content.parameters.periodStart).getTime()) / (1000 * 60 * 60 * 24 * 30) : 1))}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right font-bold text-slate-800">{formatCurrency(content.totals.totalExpenses)}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-700">{formatNumber(content.parameters?.totalArea ? (content.totals.totalExpenses / (content.parameters.totalArea * ((new Date(content.parameters.periodEnd).getTime() - new Date(content.parameters.periodStart).getTime()) / (1000 * 60 * 60 * 24 * 30)))) : 0)}</td>
|
|||
|
|
</tr>
|
|||
|
|
<tr>
|
|||
|
|
<td colSpan={4} className="py-2"></td>
|
|||
|
|
</tr>
|
|||
|
|
<tr>
|
|||
|
|
<td className="py-2 px-3 text-sm text-slate-700">НДС</td>
|
|||
|
|
<td colSpan={2} className="py-2 px-3 text-sm text-right text-slate-700">{formatCurrency(content.totals.vat)}</td>
|
|||
|
|
<td></td>
|
|||
|
|
</tr>
|
|||
|
|
{content.totals.recalculation > 0 && (
|
|||
|
|
<tr>
|
|||
|
|
<td className="py-2 px-3 text-sm text-slate-700">Перерасчет (механизированная уборка, резервный фонд)</td>
|
|||
|
|
<td colSpan={2} className="py-2 px-3 text-sm text-right text-slate-700">{formatCurrency(content.totals.recalculation)}</td>
|
|||
|
|
<td></td>
|
|||
|
|
</tr>
|
|||
|
|
)}
|
|||
|
|
<tr>
|
|||
|
|
<td className="py-2 px-3 text-sm font-medium text-slate-700">Итого расходов с учетом перерасчета (без НДС)</td>
|
|||
|
|
<td colSpan={2} className="py-2 px-3 text-sm text-right font-bold text-slate-800">{formatCurrency(content.totals.totalWithRecalculation)}</td>
|
|||
|
|
<td></td>
|
|||
|
|
</tr>
|
|||
|
|
<tr>
|
|||
|
|
<td className="py-2 px-3 text-sm font-medium text-slate-700">Итого расходов с учетом перерасчета</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-700">{formatCurrency(content.totals.totalWithRecalculationWithVAT / (content.parameters?.totalArea ? (new Date(content.parameters.periodEnd).getTime() - new Date(content.parameters.periodStart).getTime()) / (1000 * 60 * 60 * 24 * 30) : 1))}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right font-bold text-slate-800">{formatCurrency(content.totals.totalWithRecalculationWithVAT)}</td>
|
|||
|
|
<td></td>
|
|||
|
|
</tr>
|
|||
|
|
<tr>
|
|||
|
|
<td className="py-2 px-3 text-sm text-slate-700">Возврат долга</td>
|
|||
|
|
<td colSpan={2} className="py-2 px-3 text-sm text-right text-slate-700">{content.totals.debtReturn > 0 ? formatCurrency(content.totals.debtReturn) : ''}</td>
|
|||
|
|
<td></td>
|
|||
|
|
</tr>
|
|||
|
|
<tr>
|
|||
|
|
<td className="py-2 px-3 text-sm font-bold text-slate-800">Итого тариф</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-700">{formatCurrency(content.totals.totalTariff / (content.parameters?.totalArea ? (new Date(content.parameters.periodEnd).getTime() - new Date(content.parameters.periodStart).getTime()) / (1000 * 60 * 60 * 24 * 30) : 1))}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right font-bold text-slate-800">{formatCurrency(content.totals.totalTariff)}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-700">{formatNumber(content.parameters?.totalArea ? (content.totals.totalTariff / (content.parameters.totalArea * ((new Date(content.parameters.periodEnd).getTime() - new Date(content.parameters.periodStart).getTime()) / (1000 * 60 * 60 * 24 * 30)))) : 0)}</td>
|
|||
|
|
</tr>
|
|||
|
|
{content.totals.otherIncome > 0 && (() => {
|
|||
|
|
const periodMonths = content.parameters?.totalArea
|
|||
|
|
? (new Date(content.parameters.periodEnd).getTime() - new Date(content.parameters.periodStart).getTime()) / (1000 * 60 * 60 * 24 * 30)
|
|||
|
|
: 1;
|
|||
|
|
const otherIncomePerM2 = content.parameters?.totalArea
|
|||
|
|
? content.totals.otherIncome / (content.parameters.totalArea * periodMonths)
|
|||
|
|
: 0;
|
|||
|
|
return (
|
|||
|
|
<tr>
|
|||
|
|
<td className="py-2 px-3 text-sm text-slate-700">Прочие доходы</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-700">{formatCurrency(content.totals.otherIncome / periodMonths)}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-700">{formatCurrency(content.totals.otherIncome)}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right text-slate-700">{formatNumber(otherIncomePerM2)}</td>
|
|||
|
|
</tr>
|
|||
|
|
);
|
|||
|
|
})()}
|
|||
|
|
</tbody>
|
|||
|
|
</table>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
|
|||
|
|
{/* Финансовые результаты */}
|
|||
|
|
{content.financialResults && (
|
|||
|
|
<div className="bg-white rounded-2xl border border-slate-200 shadow-sm p-6 print:border-0 print:shadow-none overflow-x-auto">
|
|||
|
|
<h3 className="text-lg font-bold text-slate-800 mb-4">Финансовый результат</h3>
|
|||
|
|
<table className="w-full border-collapse">
|
|||
|
|
<tbody>
|
|||
|
|
<tr>
|
|||
|
|
<td colSpan={4} className="py-2 px-3 text-sm font-bold text-slate-800">Финансовый результат по содержанию</td>
|
|||
|
|
</tr>
|
|||
|
|
<tr>
|
|||
|
|
<td colSpan={2} className="py-2 px-3 text-sm text-slate-700">исходя из начисленых</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right font-bold text-slate-800">{formatCurrency(content.financialResults.maintenanceFromAccrued || 0)}</td>
|
|||
|
|
<td className={`py-2 px-3 text-sm text-right font-bold ${
|
|||
|
|
(content.financialResults.maintenanceFromAccrued || 0) < 0 ? 'text-red-600' : 'text-slate-800'
|
|||
|
|
}`}>
|
|||
|
|
{formatNumber(content.parameters?.totalArea ? ((content.financialResults.maintenanceFromAccrued || 0) / content.parameters.totalArea) : 0)}
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
<tr>
|
|||
|
|
<td colSpan={2} className="py-2 px-3 text-sm text-slate-700">исходя из поступивших средств</td>
|
|||
|
|
<td className={`py-2 px-3 text-sm text-right font-bold ${
|
|||
|
|
(content.financialResults.maintenanceFromReceived || 0) < 0 ? 'text-red-600' : 'text-slate-800'
|
|||
|
|
}`}>
|
|||
|
|
{formatCurrency(content.financialResults.maintenanceFromReceived || 0)}
|
|||
|
|
</td>
|
|||
|
|
<td className={`py-2 px-3 text-sm text-right font-bold ${
|
|||
|
|
(content.financialResults.maintenanceFromReceived || 0) < 0 ? 'text-red-600' : 'text-slate-800'
|
|||
|
|
}`}>
|
|||
|
|
{formatNumber(content.parameters?.totalArea ? ((content.financialResults.maintenanceFromReceived || 0) / content.parameters.totalArea) : 0)}
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
<tr>
|
|||
|
|
<td colSpan={4} className="py-2"></td>
|
|||
|
|
</tr>
|
|||
|
|
<tr>
|
|||
|
|
<td colSpan={4} className="py-2 px-3 text-sm font-bold text-slate-800">Финансовый результат по резервному фонду</td>
|
|||
|
|
</tr>
|
|||
|
|
<tr>
|
|||
|
|
<td colSpan={2} className="py-2 px-3 text-sm text-slate-700">исходя из начисленых</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right font-bold text-slate-800">{formatCurrency(content.financialResults.reserveFundFromAccrued || 0)}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right font-bold text-slate-800">
|
|||
|
|
{formatNumber(content.parameters?.totalArea ? ((content.financialResults.reserveFundFromAccrued || 0) / content.parameters.totalArea) : 0)}
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
<tr>
|
|||
|
|
<td colSpan={2} className="py-2 px-3 text-sm text-slate-700">исходя из поступивших средств</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right font-bold text-slate-800">{formatCurrency(content.financialResults.reserveFundFromReceived || 0)}</td>
|
|||
|
|
<td className="py-2 px-3 text-sm text-right font-bold text-slate-800">
|
|||
|
|
{formatNumber(content.parameters?.totalArea ? ((content.financialResults.reserveFundFromReceived || 0) / content.parameters.totalArea) : 0)}
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
</tbody>
|
|||
|
|
</table>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
|
|||
|
|
{/* Подпись директора */}
|
|||
|
|
<div className="bg-white rounded-2xl border border-slate-200 shadow-sm p-6 print:border-0 print:shadow-none">
|
|||
|
|
<div className="flex justify-end">
|
|||
|
|
<div className="text-right">
|
|||
|
|
<p className="text-sm font-bold text-slate-800 mb-1">Директор</p>
|
|||
|
|
<p className="text-sm text-slate-600">_________________</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
};
|