fix: aggregate allocation formula lines by year

This commit is contained in:
2026-05-04 16:41:11 +09:00
parent bf7bf93179
commit 5f4834de10

View File

@@ -5478,18 +5478,39 @@
<div className="subtle" style={{ marginTop: 6, lineHeight: 1.5 }}> <div className="subtle" style={{ marginTop: 6, lineHeight: 1.5 }}>
<div>본사관리비 배부원천 x (프로젝트 기준값 / 전체 기준값)</div> <div>본사관리비 배부원천 x (프로젝트 기준값 / 전체 기준값)</div>
<div>기준값: {allocationMode === "income_ratio" ? "프로젝트 입금 / 전체입금" : "프로젝트 지출 / 전체지출"}</div> <div>기준값: {allocationMode === "income_ratio" ? "프로젝트 입금 / 전체입금" : "프로젝트 지출 / 전체지출"}</div>
{(sharedAllocationDetails.length ? sharedAllocationDetails : [{ year_month: "", source_amount: 0, display_project_basis_amount: 0, display_total_basis_amount: 0, allocated_amount: item.amount || 0 }]) {(() => {
.map((row, idx) => { const baseRows = sharedAllocationDetails.length
? sharedAllocationDetails
: [{ year_month: "", source_amount: 0, display_project_basis_amount: 0, display_total_basis_amount: 0, allocated_amount: item.amount || 0 }];
const yearlyMap = {};
baseRows.forEach((row) => {
const year = ((row.year_month || "").slice(0, 4) || "-");
if (!yearlyMap[year]) {
yearlyMap[year] = {
year,
source_amount: 0,
display_project_basis_amount: 0,
display_total_basis_amount: 0,
allocated_amount: 0,
};
}
yearlyMap[year].source_amount += Number(row.source_amount || 0);
yearlyMap[year].display_project_basis_amount += Number(row.display_project_basis_amount ?? row.project_basis_amount ?? 0);
yearlyMap[year].display_total_basis_amount += Number(row.display_total_basis_amount ?? row.total_basis_amount ?? 0);
yearlyMap[year].allocated_amount += Number(row.allocated_amount || 0);
});
return Object.values(yearlyMap).sort((a, b) => String(a.year).localeCompare(String(b.year))).map((row, idx) => {
const sourceAmount = Number(row.source_amount || 0); const sourceAmount = Number(row.source_amount || 0);
const allocatedAmount = Number(row.allocated_amount || 0); const allocatedAmount = Number(row.allocated_amount || 0);
const projectBasisAmount = Number(row.display_project_basis_amount ?? row.project_basis_amount ?? 0); const projectBasisAmount = Number(row.display_project_basis_amount ?? row.project_basis_amount ?? 0);
const totalBasisAmount = Number(row.display_total_basis_amount ?? row.total_basis_amount ?? 0); const totalBasisAmount = Number(row.display_total_basis_amount ?? row.total_basis_amount ?? 0);
return ( return (
<div key={`shared-inline-alloc-${idx}`}> <div key={`shared-inline-alloc-${idx}`}>
{((row.year_month || "").slice(0, 4) || "-")} · {fmt(sourceAmount)} x ({fmt(projectBasisAmount)} / {fmt(totalBasisAmount)}) = {fmt(allocatedAmount)} {(row.year || "-")} · {fmt(sourceAmount)} x ({fmt(projectBasisAmount)} / {fmt(totalBasisAmount)}) = {fmt(allocatedAmount)}
</div> </div>
); );
})} });
})()}
</div> </div>
)} )}
</div> </div>
@@ -5574,15 +5595,33 @@
<br /> <br />
기준값: {item.allocation_mode === "income_ratio" ? "프로젝트 입금 / 전체입금" : "프로젝트 지출 / 전체지출"} 기준값: {item.allocation_mode === "income_ratio" ? "프로젝트 입금 / 전체입금" : "프로젝트 지출 / 전체지출"}
<br /> <br />
{(Array.isArray(item.allocation_details) && item.allocation_details.length {(() => {
? item.allocation_details const baseRows = (Array.isArray(item.allocation_details) && item.allocation_details.length)
: [{ ? item.allocation_details
: [{
source_amount: item.allocation_source_amount || 0, source_amount: item.allocation_source_amount || 0,
project_basis_amount: item.allocation_project_basis_amount || 0, project_basis_amount: item.allocation_project_basis_amount || 0,
total_basis_amount: item.allocation_total_basis_amount || 0, total_basis_amount: item.allocation_total_basis_amount || 0,
allocated_amount: item.expense_supply || 0, allocated_amount: item.expense_supply || 0,
}] }];
).map((row, idx) => { const yearlyMap = {};
baseRows.forEach((row) => {
const year = ((row.year_month || "").slice(0, 4) || "-");
if (!yearlyMap[year]) {
yearlyMap[year] = {
year,
source_amount: 0,
display_project_basis_amount: 0,
display_total_basis_amount: 0,
allocated_amount: 0,
};
}
yearlyMap[year].source_amount += Number(row.source_amount || 0);
yearlyMap[year].display_project_basis_amount += Number(row.display_project_basis_amount ?? row.project_basis_amount ?? 0);
yearlyMap[year].display_total_basis_amount += Number(row.display_total_basis_amount ?? row.total_basis_amount ?? 0);
yearlyMap[year].allocated_amount += Number(row.allocated_amount || 0);
});
return Object.values(yearlyMap).sort((a, b) => String(a.year).localeCompare(String(b.year))).map((row, idx) => {
const sourceAmount = Number(row.source_amount || 0); const sourceAmount = Number(row.source_amount || 0);
const allocatedAmount = Number(row.allocated_amount || 0); const allocatedAmount = Number(row.allocated_amount || 0);
const projectBasisAmount = Number( const projectBasisAmount = Number(
@@ -5593,10 +5632,11 @@
); );
return ( return (
<span key={`alloc-line-${item.account_code}-${idx}`} style={{ display: "block" }}> <span key={`alloc-line-${item.account_code}-${idx}`} style={{ display: "block" }}>
{((row.year_month || "").slice(0, 4) || "-")} · {fmt(sourceAmount)} x ({fmt(projectBasisAmount)} / {fmt(totalBasisAmount)}) = {fmt(allocatedAmount)} {(row.year || "-")} · {fmt(sourceAmount)} x ({fmt(projectBasisAmount)} / {fmt(totalBasisAmount)}) = {fmt(allocatedAmount)}
</span> </span>
); );
})} });
})()}
</div> </div>
)} )}
</div> </div>
@@ -6979,14 +7019,31 @@
if (!list.length || (list.length === 1 && Number(list[0].source_amount || 0) === 0 && Number(list[0].allocated_amount || 0) === 0)) { if (!list.length || (list.length === 1 && Number(list[0].source_amount || 0) === 0 && Number(list[0].allocated_amount || 0) === 0)) {
return <div key="alloc-empty">해당 계정의 배부 원천 금액이 없어 계산식이 없습니다.</div>; return <div key="alloc-empty">해당 계정의 배부 원천 금액이 없어 계산식이 없습니다.</div>;
} }
return list.map((row, idx) => { const yearlyMap = {};
list.forEach((row) => {
const year = ((row.year_month || "").slice(0, 4) || "-");
if (!yearlyMap[year]) {
yearlyMap[year] = {
year,
source_amount: 0,
display_project_basis_amount: 0,
display_total_basis_amount: 0,
allocated_amount: 0,
};
}
yearlyMap[year].source_amount += Number(row.source_amount || 0);
yearlyMap[year].display_project_basis_amount += Number(row.display_project_basis_amount ?? row.project_basis_amount ?? 0);
yearlyMap[year].display_total_basis_amount += Number(row.display_total_basis_amount ?? row.total_basis_amount ?? 0);
yearlyMap[year].allocated_amount += Number(row.allocated_amount || 0);
});
return Object.values(yearlyMap).sort((a, b) => String(a.year).localeCompare(String(b.year))).map((row, idx) => {
const sourceAmount = Number(row.source_amount || 0); const sourceAmount = Number(row.source_amount || 0);
const allocatedAmount = Number(row.allocated_amount || 0); const allocatedAmount = Number(row.allocated_amount || 0);
const projectBasisAmount = Number(row.display_project_basis_amount ?? row.project_basis_amount ?? 0); const projectBasisAmount = Number(row.display_project_basis_amount ?? row.project_basis_amount ?? 0);
const totalBasisAmount = Number(row.display_total_basis_amount ?? row.total_basis_amount ?? 0); const totalBasisAmount = Number(row.display_total_basis_amount ?? row.total_basis_amount ?? 0);
return ( return (
<div key={`alloc-restore-${idx}`}> <div key={`alloc-restore-${idx}`}>
{((row.year_month || "").slice(0, 4) || "-")} · {fmt(sourceAmount)} x ({fmt(projectBasisAmount)} / {fmt(totalBasisAmount)}) = {fmt(allocatedAmount)} {(row.year || "-")} · {fmt(sourceAmount)} x ({fmt(projectBasisAmount)} / {fmt(totalBasisAmount)}) = {fmt(allocatedAmount)}
</div> </div>
); );
}); });
@@ -7109,20 +7166,39 @@
기준값: {(lifecycleProjectTotalModal.allocation_mode || "") === "income_ratio" ? "프로젝트 입금 / 전체입금" : "프로젝트 지출 / 전체지출"} 기준값: {(lifecycleProjectTotalModal.allocation_mode || "") === "income_ratio" ? "프로젝트 입금 / 전체입금" : "프로젝트 지출 / 전체지출"}
</div> </div>
<div className="subtle" style={{ marginTop: 8, lineHeight: 1.55 }}> <div className="subtle" style={{ marginTop: 8, lineHeight: 1.55 }}>
{(Array.isArray(lifecycleProjectTotalModal.allocation_details) && lifecycleProjectTotalModal.allocation_details.length {(() => {
? lifecycleProjectTotalModal.allocation_details const rows = (Array.isArray(lifecycleProjectTotalModal.allocation_details) && lifecycleProjectTotalModal.allocation_details.length)
: [] ? lifecycleProjectTotalModal.allocation_details
).map((row, idx) => { : [];
const sourceAmount = Number(row.source_amount || 0); const yearlyMap = {};
const allocatedAmount = Number(row.allocated_amount || 0); rows.forEach((row) => {
const projectBasisAmount = Number(row.display_project_basis_amount ?? row.project_basis_amount ?? 0); const year = ((row.year_month || "").slice(0, 4) || "-");
const totalBasisAmount = Number(row.display_total_basis_amount ?? row.total_basis_amount ?? 0); if (!yearlyMap[year]) {
return ( yearlyMap[year] = {
<div key={`lifecycle-total-alloc-${idx}`}> year,
{((row.year_month || "").slice(0, 4) || "-")} · {fmt(sourceAmount)} x ({fmt(projectBasisAmount)} / {fmt(totalBasisAmount)}) = {fmt(allocatedAmount)} source_amount: 0,
</div> display_project_basis_amount: 0,
); display_total_basis_amount: 0,
})} allocated_amount: 0,
};
}
yearlyMap[year].source_amount += Number(row.source_amount || 0);
yearlyMap[year].display_project_basis_amount += Number(row.display_project_basis_amount ?? row.project_basis_amount ?? 0);
yearlyMap[year].display_total_basis_amount += Number(row.display_total_basis_amount ?? row.total_basis_amount ?? 0);
yearlyMap[year].allocated_amount += Number(row.allocated_amount || 0);
});
return Object.values(yearlyMap).sort((a, b) => String(a.year).localeCompare(String(b.year))).map((row, idx) => {
const sourceAmount = Number(row.source_amount || 0);
const allocatedAmount = Number(row.allocated_amount || 0);
const projectBasisAmount = Number(row.display_project_basis_amount ?? row.project_basis_amount ?? 0);
const totalBasisAmount = Number(row.display_total_basis_amount ?? row.total_basis_amount ?? 0);
return (
<div key={`lifecycle-total-alloc-${idx}`}>
{(row.year || "-")} · {fmt(sourceAmount)} x ({fmt(projectBasisAmount)} / {fmt(totalBasisAmount)}) = {fmt(allocatedAmount)}
</div>
);
});
})()}
{!((lifecycleProjectTotalModal.allocation_details || []).length) && ( {!((lifecycleProjectTotalModal.allocation_details || []).length) && (
<div>표시할 배부 계산식이 없습니다.</div> <div>표시할 배부 계산식이 없습니다.</div>
)} )}