feat: update manage dashboard flows

This commit is contained in:
2026-04-17 10:32:12 +09:00
parent 01a6e197ce
commit 6e8f606591
6 changed files with 626 additions and 193 deletions

View File

@@ -14,7 +14,7 @@ from zipfile import ZipFile
BASE_DIR = Path("/home/hyein/project")
DEFAULT_XLSX_PATH = BASE_DIR / "PTC(2023-2026.02).xlsx"
DEFAULT_XLSX_PATH = BASE_DIR / "PTC 입출금내역(2015~).xlsx"
XLSX_SOURCE_CONFIG_PATH = BASE_DIR / "server" / "ptc_source_path.txt"
METHOD_XLSX_PATH = BASE_DIR / "PTC공법.xlsx"
DB_PATH = BASE_DIR / "db" / "ptc_local.sqlite3"
@@ -375,6 +375,24 @@ def normalize_transaction_type(in_out: str, account_name: str) -> str:
return "unknown"
def correct_transaction_date(
transaction_date: str,
raw_value: str,
project_code: str,
account_code: str,
description: str,
) -> str:
if (
transaction_date == "2106-10-31"
and raw_value == "75545"
and project_code == "15-시공-25"
and account_code == "711"
and (description or "").strip() == "강관말뚝"
):
return "2016-10-31"
return transaction_date
def read_xlsx_rows(path: Path) -> list[dict]:
with ZipFile(path) as book:
shared_strings = []
@@ -405,36 +423,72 @@ def read_xlsx_rows(path: Path) -> list[dict]:
if not rows:
return []
headers = rows[0]
data_rows = rows[1:]
header_row_index = 0
headers = rows[0] if rows else []
for idx, candidate in enumerate(rows):
normalized = [str(cell).strip() for cell in candidate if str(cell).strip()]
if "거래일" in normalized and "입/출금" in normalized and "계정코드" in normalized:
header_row_index = idx
headers = candidate
break
data_rows = rows[header_row_index + 1 :]
width = len(headers)
items = []
for source_row_no, row in enumerate(data_rows, start=2):
def payload_get(payload: dict, *keys: str) -> str:
for key in keys:
if key in payload and payload.get(key) not in (None, ""):
return payload.get(key, "")
return ""
for source_row_no, row in enumerate(data_rows, start=header_row_index + 2):
current = row + [""] * (width - len(row)) if len(row) < width else row[:width]
payload = dict(zip(headers, current))
transaction_date_raw = payload_get(payload, "거래일")
in_out = payload_get(payload, "입/출금")
account_code = payload_get(payload, "계정코드")
account_name = payload_get(payload, "구분", "계정과목")
department_name = payload_get(payload, "부서")
vendor_name = payload_get(payload, "거래처")
project_code = payload_get(payload, "프로젝트코드")
raw_project_type = payload_get(payload, "프로젝트 구분(안)")
project_name = payload_get(payload, "프로젝트명")
description = payload_get(payload, "적요")
supply_amount_raw = payload_get(payload, "공급가액")
vat_amount_raw = payload_get(payload, "부가세")
total_amount_raw = payload_get(payload, "합계금액")
remarks = payload_get(payload, "비고")
transaction_date = correct_transaction_date(
excel_serial_to_date(transaction_date_raw),
transaction_date_raw,
project_code,
account_code,
description,
)
items.append(
{
"source_row_no": source_row_no,
"transaction_date_raw": payload.get("거래일", ""),
"transaction_date": excel_serial_to_date(payload.get("거래일", "")),
"in_out": payload.get("입/출금", ""),
"account_code": payload.get("계정코드", ""),
"account_name": payload.get("구분", ""),
"department_name": payload.get("부서", ""),
"vendor_name": payload.get("거래처", ""),
"project_code": payload.get("프로젝트코드", ""),
"project_type": payload.get("프로젝트 구분(안)", ""),
"project_name": payload.get("프로젝트명", ""),
"description": payload.get("적요", ""),
"supply_amount_raw": payload.get("공급가액", ""),
"vat_amount_raw": payload.get("부가세", ""),
"total_amount_raw": payload.get("합계금액", ""),
"remarks": payload.get("비고", ""),
"supply_amount": parse_amount(payload.get("공급가액", "")),
"vat_amount": parse_amount(payload.get("부가세", "")),
"total_amount": parse_amount(payload.get("합계금액", "")),
"transaction_date_raw": transaction_date_raw,
"transaction_date": transaction_date,
"in_out": in_out,
"account_code": account_code,
"account_name": account_name,
"department_name": department_name,
"vendor_name": vendor_name,
"project_code": project_code,
"project_type": raw_project_type or infer_project_type_from_code(project_code),
"project_name": project_name,
"description": description,
"supply_amount_raw": supply_amount_raw,
"vat_amount_raw": vat_amount_raw,
"total_amount_raw": total_amount_raw,
"remarks": remarks,
"supply_amount": parse_amount(supply_amount_raw),
"vat_amount": parse_amount(vat_amount_raw),
"total_amount": parse_amount(total_amount_raw),
"normalized_type": normalize_transaction_type(
payload.get("입/출금", ""), payload.get("구분", "")
in_out, account_name
),
}
)