Upgrade to v5.5 (Professional Settlement Engine)
This commit is contained in:
@@ -281,9 +281,9 @@
|
||||
const t = String(teamRaw || '').trim();
|
||||
if (!t) return '공통';
|
||||
if (t.includes('관리')) return '관리팀';
|
||||
if (t.includes('공무')) return '공무팀';
|
||||
if (t.includes('제작')) return '제작팀';
|
||||
if (t.includes('철근')) return '철근팀';
|
||||
if (t.includes('공무')) return '공무';
|
||||
if (t.includes('제작')) return '제작';
|
||||
if (t.includes('철근')) return '철근';
|
||||
if (t.includes('공통')) return '공통';
|
||||
if (t.includes('일용')) return '공통';
|
||||
return '공통';
|
||||
@@ -406,9 +406,9 @@
|
||||
const n = String(name || '').trim();
|
||||
const r = String(regularType || '').trim();
|
||||
if (r.includes('일용')) return '공통';
|
||||
if (teamMfg.has(n)) return '제작팀';
|
||||
if (teamAdmin.has(n)) return '공무팀';
|
||||
return '철근팀';
|
||||
if (teamMfg.has(n)) return '제작';
|
||||
if (teamAdmin.has(n)) return '공무';
|
||||
return '철근';
|
||||
};
|
||||
const toNum = (v) => {
|
||||
const n = parseFloat(String(v || '').replace(/[^0-9.-]/g, ''));
|
||||
@@ -474,9 +474,9 @@
|
||||
rate: w.rate,
|
||||
team: String(w.regularType || '').includes('일용')
|
||||
? '공통'
|
||||
: teamMfg.has(w.name) ? '제작팀'
|
||||
: teamAdmin.has(w.name) ? '공무팀'
|
||||
: '철근팀'
|
||||
: teamMfg.has(w.name) ? '제작'
|
||||
: teamAdmin.has(name) ? '공무'
|
||||
: '철근'
|
||||
}));
|
||||
setFactoryWorkers(fallbackWorkers);
|
||||
applyFactoryDefaults(fallbackWorkers);
|
||||
@@ -751,13 +751,7 @@
|
||||
});
|
||||
|
||||
const ensureTeam = (name) => {
|
||||
if (!tmMap[name]) tmMap[name] = {
|
||||
name, direct: 0, allocA: 0, allocB: 0, final: 0, hours: 0, breakdown: {}, allocTrace: [],
|
||||
allocBucket: {
|
||||
A: { '지급임차료': 0, '전력비': 0, '일반경비': 0 },
|
||||
B: { '지급임차료': 0, '전력비': 0, '일반경비': 0 }
|
||||
}
|
||||
};
|
||||
if (!tmMap[name]) tmMap[name] = { name, direct: 0, allocA: 0, allocB: 0, final: 0, hours: 0, breakdown: {}, allocTrace: [] };
|
||||
return tmMap[name];
|
||||
};
|
||||
|
||||
@@ -797,7 +791,7 @@
|
||||
const ratios = TEAM_RATIOS[bucket] || TEAM_RATIOS['일반경비'];
|
||||
Object.entries(ratios).forEach(([team, ratio]) => {
|
||||
const share = amount * ratio;
|
||||
const row = ensureTeam(normalizeTeamName(team));
|
||||
const row = ensureTeam(team);
|
||||
row[allocKey] += share;
|
||||
row.allocBucket[allocKey === 'allocA' ? 'A' : 'B'][bucket] += share;
|
||||
row.allocTrace.push({
|
||||
@@ -855,14 +849,14 @@
|
||||
if (dailyWorkers.has(name) || String(name).includes('일용')) {
|
||||
map[name] = '공통';
|
||||
} else {
|
||||
map[name] = teamMfg.has(name) ? '제작팀' : teamAdmin.has(name) ? '공무팀' : '철근팀';
|
||||
map[name] = teamMfg.has(name) ? '제작' : teamAdmin.has(name) ? '공무' : '철근';
|
||||
}
|
||||
});
|
||||
return map;
|
||||
}, [factoryWorkers, wageSettings, laborRows]);
|
||||
|
||||
const factoryTeamCounts = useMemo(() => {
|
||||
const base = { '철근팀': 0, '제작팀': 0, '공무팀': 0, '공통': 0, '관리팀': 0 };
|
||||
const base = { '철근': 0, '제작': 0, '공무': 0, '공통': 0, '관리팀': 0 };
|
||||
Object.values(workerTeamMap || {}).forEach(team => {
|
||||
if (base[team] !== undefined) base[team] += 1;
|
||||
});
|
||||
@@ -1154,13 +1148,29 @@
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 text-xs">
|
||||
<div className="bg-blue-50 border border-blue-100 rounded-xl p-4 space-y-2">
|
||||
<div className="font-black text-blue-800">운영비 (A)</div>
|
||||
<div className="text-slate-700">운영/공통 성격 비용을 수익 프로젝트 공수 비율로 배분하는 풀입니다.</div>
|
||||
<div className="text-slate-500">기본 프로젝트: {POOL_A_PROJECTS.join(', ') || '-'}</div>
|
||||
<div className="text-slate-700">
|
||||
{viewMode === 'team'
|
||||
? '팀별에서는 공수 대신 지급임차료/전력비/일반경비 계정을 팀별 고정 비율로 배분해 A 금액을 계산합니다.'
|
||||
: '운영/공통 성격 비용을 수익 프로젝트 공수 비율로 배분하는 풀입니다.'}
|
||||
</div>
|
||||
<div className="text-slate-500">
|
||||
{viewMode === 'team'
|
||||
? '팀별 기준: 철근/제작/공무 비율표 적용 (공수 미사용)'
|
||||
: `기본 프로젝트: ${POOL_A_PROJECTS.join(', ') || '-'}`}
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-orange-50 border border-orange-100 rounded-xl p-4 space-y-2">
|
||||
<div className="font-black text-orange-800">관리비 (B)</div>
|
||||
<div className="text-slate-700">관리/간접 성격 비용을 수익 프로젝트 공수 비율로 배분하는 풀입니다.</div>
|
||||
<div className="text-slate-500">기본 프로젝트: {POOL_B_PROJECTS.join(', ') || '-'}</div>
|
||||
<div className="text-slate-700">
|
||||
{viewMode === 'team'
|
||||
? '팀별에서는 공수 대신 지급임차료/전력비/일반경비 계정을 팀별 고정 비율로 배분해 B 금액을 계산합니다.'
|
||||
: '관리/간접 성격 비용을 수익 프로젝트 공수 비율로 배분하는 풀입니다.'}
|
||||
</div>
|
||||
<div className="text-slate-500">
|
||||
{viewMode === 'team'
|
||||
? '팀별 기준: 철근/제작/공무 비율표 적용 (공수 미사용)'
|
||||
: `기본 프로젝트: ${POOL_B_PROJECTS.join(', ') || '-'}`}
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-violet-50 border border-violet-100 rounded-xl p-4 space-y-2">
|
||||
<div className="font-black text-violet-800">형식배분 (C)</div>
|
||||
|
||||
Reference in New Issue
Block a user