diff --git a/PTC/management_dashboard_preview.html b/PTC/management_dashboard_preview.html index 60e9aa5..3c0cd08 100644 --- a/PTC/management_dashboard_preview.html +++ b/PTC/management_dashboard_preview.html @@ -1921,6 +1921,7 @@ const [companyAccountDetailModalLoading, setCompanyAccountDetailModalLoading] = useState(false); const [lifecycleBreakdownModal, setLifecycleBreakdownModal] = useState(null); const [lifecycleProjectTotalModal, setLifecycleProjectTotalModal] = useState(null); + const [lifecycleProjectTotalGroup, setLifecycleProjectTotalGroup] = useState("공통배분분"); const [lifecycleAccountDetailModal, setLifecycleAccountDetailModal] = useState(null); const [lifecycleAccountDetailModalLoading, setLifecycleAccountDetailModalLoading] = useState(false); const [lifecycleAllocationModal, setLifecycleAllocationModal] = useState(null); @@ -5397,16 +5398,48 @@ className="button-muted" style={{ height: 30, padding: "0 10px", borderRadius: 9, fontSize: 12 }} onClick={() => { - const allocationAccount = (lifecycleBreakdownModal.accounts || []).find( - (acc) => Array.isArray(acc.allocation_details) && acc.allocation_details.length - ) || (lifecycleBreakdownModal.accounts || [])[0] || {}; + const accounts = Array.isArray(lifecycleBreakdownModal.accounts) ? lifecycleBreakdownModal.accounts : []; + const allocationMode = + (accounts.find((acc) => (acc.allocation_mode || "").trim()) || {}).allocation_mode || ""; + const aggregatedByYearMonth = {}; + accounts.forEach((acc) => { + const rows = Array.isArray(acc.allocation_details) ? acc.allocation_details : []; + rows.forEach((row) => { + const key = String(row.year_month || ""); + if (!aggregatedByYearMonth[key]) { + aggregatedByYearMonth[key] = { + year_month: key, + source_amount: 0, + project_basis_amount: Number(row.project_basis_amount || 0), + total_basis_amount: Number(row.total_basis_amount || 0), + display_project_basis_amount: Number(row.display_project_basis_amount ?? row.project_basis_amount ?? 0), + display_total_basis_amount: Number(row.display_total_basis_amount ?? row.total_basis_amount ?? 0), + allocated_amount: 0, + }; + } + aggregatedByYearMonth[key].source_amount += Number(row.source_amount || 0); + aggregatedByYearMonth[key].allocated_amount += Number(row.allocated_amount || 0); + }); + }); + const aggregatedAllocationDetails = Object.values(aggregatedByYearMonth).sort((a, b) => + String(a.year_month || "").localeCompare(String(b.year_month || "")) + ); + const sharedProjects = (Array.isArray(lifecycleBreakdownModal.projects) ? lifecycleBreakdownModal.projects : []) + .map((project) => ({ ...project })) + .filter((project) => Number(project.shared_expense_supply || 0) > 0); + const directTotal = sharedProjects.reduce((sum, project) => sum + Number(project.direct_expense_supply || 0), 0); + const sharedTotal = sharedProjects.reduce((sum, project) => sum + Number(project.shared_expense_supply || 0), 0); setLifecycleProjectTotalModal({ label: lifecycleBreakdownModal.label || "", - total_amount: Number(lifecycleBreakdownModal.expense_supply || 0), - projects: Array.isArray(lifecycleBreakdownModal.projects) ? lifecycleBreakdownModal.projects.map((project) => ({ ...project })) : [], - allocation_mode: allocationAccount.allocation_mode || "", - allocation_details: Array.isArray(allocationAccount.allocation_details) ? allocationAccount.allocation_details.map((row) => ({ ...row })) : [], + total_amount: directTotal + sharedTotal, + direct_total: directTotal, + shared_total: sharedTotal, + projects: sharedProjects, + accounts: Array.isArray(lifecycleBreakdownModal.accounts) ? lifecycleBreakdownModal.accounts.map((account) => ({ ...account })) : [], + allocation_mode: allocationMode, + allocation_details: aggregatedAllocationDetails, }); + setLifecycleProjectTotalGroup("공통배분분"); }} > 상세보기 @@ -5415,31 +5448,66 @@
연결된 프로젝트들 중 이 항목에 반영된 지출 금액입니다.
{(lifecycleBreakdownModal.projects || []).length ? ( - (lifecycleBreakdownModal.projects || []).map((item) => ( -
{ + const projects = Array.isArray(lifecycleBreakdownModal.projects) ? lifecycleBreakdownModal.projects : []; + const roleAmount = { + 영업: 0, + 설계: 0, + 시공: 0, + }; + const roleCodes = { + 영업: new Set(), + 설계: new Set(), + 시공: new Set(), + }; + let sharedAmount = 0; + projects.forEach((project) => { + const role = (project.project_type || "").trim(); + const direct = Number(project.direct_expense_supply || 0); + const shared = Number(project.shared_expense_supply || 0); + const projectCode = (project.project_code || "").trim(); + if (roleAmount[role] !== undefined) { + roleAmount[role] += direct; + if (projectCode) roleCodes[role].add(projectCode); + } + sharedAmount += shared; + }); + const groupedRows = [ + { key: "영업", label: "영업", amount: roleAmount.영업, showWhenZero: false, codes: Array.from(roleCodes.영업) }, + { key: "설계", label: "설계", amount: roleAmount.설계, showWhenZero: false, codes: Array.from(roleCodes.설계) }, + { key: "시공", label: "시공", amount: roleAmount.시공, showWhenZero: true, codes: Array.from(roleCodes.시공) }, + { key: "공통배분분", label: "공통배분분", amount: sharedAmount, showWhenZero: true, codes: [] }, + ].filter((row) => row.showWhenZero || row.amount > 0); + return groupedRows.map((item) => ( +
- )) +
+ {fmt(item.amount || 0)}원 +
+ + )); + })() ) : (
표시할 프로젝트가 없습니다.
)} @@ -5448,10 +5516,28 @@
계정별 금액
-
이 항목에 포함된 계정 기준 합계입니다.
+
+ {lifecycleProjectTotalGroup === "설계" || lifecycleProjectTotalGroup === "시공" + ? `${lifecycleProjectTotalGroup} 직접분 계정 기준 합계입니다.` + : lifecycleProjectTotalGroup === "공통배분분" + ? "공통배분분 계정 기준 합계입니다." + : "이 항목에 포함된 계정 기준 합계입니다."} +
{(lifecycleBreakdownModal.accounts || []).length ? ( - (lifecycleBreakdownModal.accounts || []).map((item) => ( + (() => { + const roleField = + lifecycleProjectTotalGroup === "설계" ? "direct_design_expense_supply" + : lifecycleProjectTotalGroup === "시공" ? "direct_construction_expense_supply" + : lifecycleProjectTotalGroup === "영업" ? "direct_sales_expense_supply" + : "shared_expense_supply"; + const filtered = (lifecycleBreakdownModal.accounts || []) + .map((item) => ({ ...item, __role_amount: Number(item?.[roleField] || 0) })) + .filter((item) => item.__role_amount > 0); + if (!filtered.length) { + return
표시할 계정이 없습니다.
; + } + return filtered.map((item) => (
)}
-
{fmt(item.expense_supply || 0)}원
+
{fmt(item.__role_amount || 0)}원
- )) + )); + })() ) : (
표시할 계정이 없습니다.
)} @@ -6843,20 +6932,22 @@
계정 상세를 불러오는 중입니다.
) : lifecycleAccountDetailModal.detail?.summary ? ( <> + {(() => { + const summaryAmount = Number(lifecycleAccountDetailModal.detail?.summary?.expense_supply_sum || 0); + const selectedAmount = Number(lifecycleAccountDetailModal.allocation_result_amount || 0); + const effectiveAccountAmount = selectedAmount > 0 ? selectedAmount : summaryAmount; + const effectiveTxnCount = Number(lifecycleAccountDetailModal.detail?.summary?.txn_count || 0); + return (
지출 합계
- {fmt( - Number(lifecycleAccountDetailModal.allocation_result_amount || 0) > 0 - ? Number(lifecycleAccountDetailModal.allocation_result_amount || 0) - : Number(lifecycleAccountDetailModal.detail.summary.expense_supply_sum || 0) - )}원 + {fmt(effectiveAccountAmount)}원
거래 건수
-
{fmt(lifecycleAccountDetailModal.detail.summary.txn_count || 0)}건
+
{fmt(effectiveTxnCount)}건
기간
@@ -6867,8 +6958,10 @@
+ ); + })()}
- {((lifecycleAccountDetailModal.bucket_label || "") === "인건비" || (lifecycleAccountDetailModal.bucket_label || "") === "관리비") && ( + {Boolean(lifecycleAccountDetailModal.show_allocation_formula) && (
배부 계산식
@@ -7011,9 +7104,11 @@
{fmt( - (lifecycleAccountDetailModal.account_code || "").startsWith("SHARED_") - ? Number(lifecycleAccountDetailModal.allocation_result_amount || 0) - : Number(lifecycleAccountDetailModal.detail?.summary?.expense_supply_sum || 0) + (() => { + const summaryAmount = Number(lifecycleAccountDetailModal.detail?.summary?.expense_supply_sum || 0); + const selectedAmount = Number(lifecycleAccountDetailModal.allocation_result_amount || 0); + return selectedAmount > 0 ? selectedAmount : summaryAmount; + })() )}원
@@ -7038,13 +7133,16 @@
{lifecycleProjectTotalModal.label || "전체"} 프로젝트별 상세
-
연결 프로젝트 기준 전체 금액 내역입니다.
+
연결 프로젝트 기준 공통배분분 내역입니다.
- +
합계 금액
{fmt(lifecycleProjectTotalModal.total_amount || 0)}원
+
+ 직접분 {fmt(lifecycleProjectTotalModal.direct_total || 0)}원 · 공통배분분 {fmt(lifecycleProjectTotalModal.shared_total || 0)}원 +
배부 계산식
@@ -7095,11 +7193,16 @@ {item.project_code || "-"} · {item.project_type || "미지정"} · {item.construction_family || "종류미지정"} · {item.construction_method || "공법미지정"} -
{fmt(item.expense_supply || 0)}원
+
+
{fmt(item.expense_supply || 0)}원
+
+ 직접분 {fmt(item.direct_expense_supply || 0)}원 · 공통배분분 {fmt(item.shared_expense_supply || 0)}원 +
+
)) ) : ( -
표시할 프로젝트가 없습니다.
+
표시할 공통배분 프로젝트가 없습니다.
)}