Refine project navigation and balance calculation behavior
This commit is contained in:
@@ -3836,7 +3836,11 @@ def merge_project_external_fields(
|
|||||||
item["hanmac_contract_amount"] = normalize_amount(contract_info.get("hanmac_contract_amount"))
|
item["hanmac_contract_amount"] = normalize_amount(contract_info.get("hanmac_contract_amount"))
|
||||||
item["billing_contract_amount"] = normalize_amount(billing_summary.get("contract_amount"))
|
item["billing_contract_amount"] = normalize_amount(billing_summary.get("contract_amount"))
|
||||||
item["billed_amount"] = normalize_amount(billing_summary.get("billed_amount"))
|
item["billed_amount"] = normalize_amount(billing_summary.get("billed_amount"))
|
||||||
item["collection_balance_amount"] = normalize_amount(billing_summary.get("balance_amount"))
|
# 수금잔액은 원천 balance 합계 대신 계약금액 대비 수금액 차이로 통일 계산한다.
|
||||||
|
computed_collection_balance = contract_amount - collection_amount
|
||||||
|
if abs(computed_collection_balance) < 1:
|
||||||
|
computed_collection_balance = 0.0
|
||||||
|
item["collection_balance_amount"] = computed_collection_balance
|
||||||
item["latest_billing_date"] = normalize_text(billing_summary.get("latest_billing_date"))
|
item["latest_billing_date"] = normalize_text(billing_summary.get("latest_billing_date"))
|
||||||
item["changed_contract_amount"] = latest_changed_contract_amount
|
item["changed_contract_amount"] = latest_changed_contract_amount
|
||||||
item["changed_contract_date"] = normalize_text(latest_summary_change.get("change_date")) or normalize_text(latest_round_change.get("change_date"))
|
item["changed_contract_date"] = normalize_text(latest_summary_change.get("change_date")) or normalize_text(latest_round_change.get("change_date"))
|
||||||
|
|||||||
@@ -511,6 +511,34 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pc-related-head {
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pc-related-head-main {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-width: 0;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pc-related-form.pc-related-form--inline {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
flex: 1 1 460px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pc-related-form.pc-related-form--inline input[type="text"] {
|
||||||
|
flex: 1 1 260px;
|
||||||
|
min-width: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
.pc-related-list {
|
.pc-related-list {
|
||||||
border: 1px solid var(--line);
|
border: 1px solid var(--line);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
@@ -884,8 +912,15 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section class="pc-collapse is-first" id="pcRelatedSection">
|
<section class="pc-collapse is-first" id="pcRelatedSection">
|
||||||
<div class="pc-collapse-head">
|
<div class="pc-collapse-head pc-related-head">
|
||||||
<h3>연계 프로젝트</h3>
|
<div class="pc-related-head-main">
|
||||||
|
<h3>연계 프로젝트</h3>
|
||||||
|
<div class="pc-related-form pc-related-form--inline">
|
||||||
|
<input type="text" id="relatedSearchInput" placeholder="추가할 프로젝트 코드/명 검색" {% if not process_cost_selected_code %}disabled{% endif %}>
|
||||||
|
<button type="button" class="button-secondary" id="relatedSaveButton" {% if not process_cost_selected_code %}disabled{% endif %}>저장</button>
|
||||||
|
<button type="button" class="button-secondary" id="relatedResetButton" {% if not process_cost_selected_code %}disabled{% endif %}>초기화</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<button type="button" class="pc-collapse-toggle" data-collapse-target="pcRelatedSection" aria-label="연계 프로젝트 접기">
|
<button type="button" class="pc-collapse-toggle" data-collapse-target="pcRelatedSection" aria-label="연계 프로젝트 접기">
|
||||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
<path d="M6 15l6-6 6 6"></path>
|
<path d="M6 15l6-6 6 6"></path>
|
||||||
@@ -904,11 +939,6 @@
|
|||||||
</span>
|
</span>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
<div class="pc-related-form">
|
|
||||||
<input type="text" id="relatedSearchInput" placeholder="추가할 프로젝트 코드/명 검색" {% if not process_cost_selected_code %}disabled{% endif %}>
|
|
||||||
<button type="button" class="button-secondary" id="relatedSaveButton" {% if not process_cost_selected_code %}disabled{% endif %}>저장</button>
|
|
||||||
<button type="button" class="button-secondary" id="relatedResetButton" {% if not process_cost_selected_code %}disabled{% endif %}>초기화</button>
|
|
||||||
</div>
|
|
||||||
<div class="pc-related-list" id="relatedSuggestList"></div>
|
<div class="pc-related-list" id="relatedSuggestList"></div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
+32
-3
@@ -567,7 +567,21 @@
|
|||||||
opacity: 0.72;
|
opacity: 0.72;
|
||||||
}
|
}
|
||||||
|
|
||||||
.related-project-tag button {
|
.related-project-open {
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 800;
|
||||||
|
line-height: 1.1;
|
||||||
|
padding: 0;
|
||||||
|
text-decoration: underline;
|
||||||
|
text-underline-offset: 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.related-project-tag .related-project-toggle,
|
||||||
|
.related-project-tag [data-remove-related] {
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
min-width: 14px;
|
min-width: 14px;
|
||||||
@@ -589,7 +603,8 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.related-project-tag button:hover {
|
.related-project-tag .related-project-toggle:hover,
|
||||||
|
.related-project-tag [data-remove-related]:hover {
|
||||||
transform: none;
|
transform: none;
|
||||||
background: rgba(41, 72, 95, 0.14);
|
background: rgba(41, 72, 95, 0.14);
|
||||||
}
|
}
|
||||||
@@ -7269,7 +7284,10 @@
|
|||||||
const isInactive = inactiveCodes.has(item.support_dept_code);
|
const isInactive = inactiveCodes.has(item.support_dept_code);
|
||||||
return `
|
return `
|
||||||
<span class="related-project-tag${isInactive ? " is-muted" : ""}">
|
<span class="related-project-tag${isInactive ? " is-muted" : ""}">
|
||||||
${escapeHtml(item.support_dept_code)} · ${escapeHtml(item.support_dept_name)}
|
<button type="button" class="related-project-open" data-open-related-project="${escapeHtml(item.support_dept_code)}" title="${escapeHtml(item.support_dept_name)}">
|
||||||
|
${escapeHtml(item.support_dept_code)}
|
||||||
|
</button>
|
||||||
|
· ${escapeHtml(item.support_dept_name)}
|
||||||
<button type="button" class="related-project-toggle" data-toggle-related="${escapeHtml(item.support_dept_code)}" title="${isInactive ? "상세 반영 다시 켜기" : "상세 반영 끄기"}" aria-label="${isInactive ? "상세 반영 다시 켜기" : "상세 반영 끄기"}">${isInactive ? "+" : "-"}</button>
|
<button type="button" class="related-project-toggle" data-toggle-related="${escapeHtml(item.support_dept_code)}" title="${isInactive ? "상세 반영 다시 켜기" : "상세 반영 끄기"}" aria-label="${isInactive ? "상세 반영 다시 켜기" : "상세 반영 끄기"}">${isInactive ? "+" : "-"}</button>
|
||||||
<button type="button" data-remove-related="${escapeHtml(item.support_dept_code)}" title="연관 프로젝트 제거" aria-label="연관 프로젝트 제거">×</button>
|
<button type="button" data-remove-related="${escapeHtml(item.support_dept_code)}" title="연관 프로젝트 제거" aria-label="연관 프로젝트 제거">×</button>
|
||||||
</span>
|
</span>
|
||||||
@@ -8671,6 +8689,17 @@
|
|||||||
relatedBarBox.querySelectorAll("[data-remove-related]").forEach((button) => {
|
relatedBarBox.querySelectorAll("[data-remove-related]").forEach((button) => {
|
||||||
button.addEventListener("click", () => removeRelatedProject(button.dataset.removeRelated || ""));
|
button.addEventListener("click", () => removeRelatedProject(button.dataset.removeRelated || ""));
|
||||||
});
|
});
|
||||||
|
relatedBarBox.querySelectorAll("[data-open-related-project]").forEach((button) => {
|
||||||
|
button.addEventListener("click", (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
const code = String(button.dataset.openRelatedProject || "").trim();
|
||||||
|
if (!code) return;
|
||||||
|
const targetItem = getAnalysisItem(code);
|
||||||
|
if (!targetItem) return;
|
||||||
|
renderAnalysis(targetItem);
|
||||||
|
});
|
||||||
|
});
|
||||||
relatedBarBox.querySelectorAll("[data-analysis-detail-note]").forEach((inputEl) => {
|
relatedBarBox.querySelectorAll("[data-analysis-detail-note]").forEach((inputEl) => {
|
||||||
inputEl.addEventListener("focusout", async () => {
|
inputEl.addEventListener("focusout", async () => {
|
||||||
const baseCode = String(inputEl.dataset.analysisDetailNote || "").trim();
|
const baseCode = String(inputEl.dataset.analysisDetailNote || "").trim();
|
||||||
|
|||||||
Reference in New Issue
Block a user