feat(시간 표시): 화면 시각 = 보는 사람 PC 시간대 · 서버 응답 UTC Z · 서버가 만드는 파일 글 = 한국 시각 (PLAN 593-1 · 요구 456)
- 공용 `common_util_time.ts`(날짜 · 시각 · 오늘/어제/n 일 전 · Z 없는 옛 글 = UTC) · `common_util_time.py`(UTC Z 글 · 한국 시각) - 화면 바꿈: 대시보드(프로젝트 · 휴지통 · 시스템 로그 · 보관함 · 홈 카드) · B09 굳힘 · E03 · E05 · E07 · M02 호표 이력 · 목록 고친 날 · 지난 판 - 서버: 응답 datetime = UTC + Z(main.py) · 로컬 시각 저장 → UTC · 대시보드 경과일 = UTC 기준 · 엑셀 날짜 · 파일 이름 = 한국 시각 - 시험: test_593_time(서울 · 뉴욕 · Z 없는 옛 글 · 서버 글) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -24,10 +24,10 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import date
|
||||
from typing import Any
|
||||
|
||||
from B09_Estimation.B09_Estimation_Calc_Base import num, rounddown, roundup, total
|
||||
from common_util.common_util_time import kst_today
|
||||
|
||||
#: 제비율 줄 (키, 이름, M01 요율 후보 키, 산식 글) — 엑셀 총괄 49~58 차례 · 나.소계에 듦
|
||||
RATE_LINES: tuple[tuple[str, str, str, str], ...] = (
|
||||
@@ -155,7 +155,7 @@ def compute_total(
|
||||
"target": target,
|
||||
"price": num(est.get("estimated_price")),
|
||||
"days": num(est.get("duration_days")),
|
||||
"year": year or date.today().year,
|
||||
"year": year or kst_today().year,
|
||||
"env": est.get("environment_kind"),
|
||||
},
|
||||
)
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
from typing import Any
|
||||
|
||||
from B08_Quantity.B08_Quantity_Material_Calc import DEDUCT_KEY
|
||||
from common_util.common_util_time import utc_now_text
|
||||
from M01_MasterData import M01_MasterData_Store as m01
|
||||
|
||||
#: 운전사 시간 노임 계수 표(건설품셈 공통 8-1-3 · 건협기술-2230)
|
||||
@@ -194,7 +194,7 @@ def refresh_book(keys: list[str], book: dict[str, Any] | None = None) -> dict[st
|
||||
old = (book or {}).get("rows") or {}
|
||||
rows.update({key: old[key] for key in want["missing"] if key in old})
|
||||
return {
|
||||
"made": datetime.now().isoformat(timespec="seconds"),
|
||||
"made": utc_now_text(),
|
||||
"rows": rows,
|
||||
"driver_factor": driver_factor(master),
|
||||
"fx": fx_inputs(master),
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from uuid import UUID
|
||||
@@ -23,6 +22,7 @@ from fastapi.responses import FileResponse
|
||||
from B03_FileInput.B03_FileInput_Engine import save_upload_stream
|
||||
from B08_Quantity.B08_Quantity_Router_Hydro import _project_root
|
||||
from B09_Estimation import B09_Estimation_Store as store
|
||||
from common_util.common_util_time import utc_from_timestamp
|
||||
|
||||
router = APIRouter()
|
||||
PATH = "/{project_id}/estimation/quotes"
|
||||
@@ -33,7 +33,7 @@ def _listing(folder: Path) -> list[dict[str, Any]]:
|
||||
{
|
||||
"name": f.name,
|
||||
"size": f.stat().st_size,
|
||||
"at": datetime.fromtimestamp(f.stat().st_mtime).isoformat(timespec="seconds"),
|
||||
"at": utc_from_timestamp(f.stat().st_mtime),
|
||||
}
|
||||
for f in store.quote_files(folder)
|
||||
]
|
||||
|
||||
@@ -11,6 +11,7 @@ import { attachHoverInfo } from "@ui/ui_template_hover_info";
|
||||
import { createBadge } from "@ui/ui_template_badge";
|
||||
import { createText } from "@ui/ui_template_text";
|
||||
import type { Row } from "./B09_Estimation_Calc_Base";
|
||||
import { dateTimeText } from "../common_util/common_util_time";
|
||||
import { tabName, type Link, type TabId } from "./B09_Estimation_UI_Tabs";
|
||||
|
||||
export interface CheckItem {
|
||||
@@ -38,7 +39,7 @@ export function checkItems(sheets: Row, payload: Row): { items: CheckItem[]; not
|
||||
/** [업데이트] 호버 글 — 굳힌 시각 + 낡은 까닭 */
|
||||
export function refreshTip(payload: Row | null): string {
|
||||
const made = payload?.book?.made;
|
||||
const when = made ? `단가 굳힘 ${String(made).replace("T", " ")}` : "단가 아직 안 굳힘";
|
||||
const when = made ? `단가 굳힘 ${dateTimeText(String(made))}` : "단가 아직 안 굳힘";
|
||||
const stale = payload?.stale;
|
||||
return `${when} · 누르면 지금 M01 값으로 새로 굳힘${stale ? ` · 업데이트 필요 — ${stale}` : ""}`;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
import type { MapContextMenuItem } from "@ui/ui_template_context_menu";
|
||||
import type { DataRow } from "@ui/ui_template_data_table";
|
||||
import { SOURCES, type Row } from "./B09_Estimation_Calc_Base";
|
||||
import { dateText } from "../common_util/common_util_time";
|
||||
import { openQuotes } from "./B09_Estimation_UI_Tabs_Base_Quote";
|
||||
import {
|
||||
blockLevel,
|
||||
@@ -64,7 +65,7 @@ export const buildExpense: TabBuild = ({ sheets, payload }) =>
|
||||
);
|
||||
|
||||
function madeText(payload: Row): string {
|
||||
return payload.book?.made ? `${String(payload.book.made).slice(0, 10)} 굳힘` : "아직 안 굳힘";
|
||||
return payload.book?.made ? `${dateText(String(payload.book.made))} 굳힘` : "아직 안 굳힘";
|
||||
}
|
||||
|
||||
export const buildBasis: TabBuild = ({ sheets }): TabTable => {
|
||||
|
||||
@@ -25,6 +25,7 @@ from typing import Any
|
||||
from B09_Estimation.B09_Estimation_Calc_Base import num
|
||||
from B09_Estimation.B09_Estimation_Summary import expand, hopyo_lines
|
||||
from B09_Estimation.draft.B09_Draft_Schedule_Calc import HOLIDAY_KINDS, compute_schedule
|
||||
from common_util.common_util_time import kst_today
|
||||
|
||||
HOLIDAYS = Path(__file__).with_name("B09_Draft_Schedule_Holidays.json")
|
||||
CLIMATE = {
|
||||
@@ -116,7 +117,7 @@ def holiday_table() -> dict[str, list[list[str]]]:
|
||||
|
||||
|
||||
def schedule_inputs(sheets: dict[str, Any], today: datetime.date | None = None) -> dict[str, Any]:
|
||||
today = today or datetime.date.today()
|
||||
today = today or kst_today()
|
||||
return {
|
||||
"units": unit_resources(sheets),
|
||||
"holidays": holiday_table(),
|
||||
|
||||
Reference in New Issue
Block a user