From 0c6a002e298524209f1a46624b031bab6e40f82f Mon Sep 17 00:00:00 2001 From: Mina Choi Date: Fri, 26 Jun 2026 15:06:37 +0900 Subject: [PATCH] =?UTF-8?q?[fix]=20negodata/backend:=20=EC=8B=9C=EA=B0=81?= =?UTF-8?q?=20=EC=BB=AC=EB=9F=BC=20timestamptz=20=EC=A0=84=ED=99=98=20+=20?= =?UTF-8?q?naive=20=EB=B3=80=ED=99=98=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - models.py: created_at/updated_at/last_accessed_at/start_time/end_time/bid_at DateTime → DateTime(timezone=True) - quotation_service: tz-aware 입력을 naive 로 깎던 _naive_utc 제거(컬럼이 tz-aware라 불필요), start_time/end_time 직접 사용. negosium_db 는 UTC 고정. Co-Authored-By: Claude Opus 4.8 (1M context) --- negodata/backend/common/database/model/models.py | 14 +++++++------- negodata/backend/services/quotation_service.py | 13 ++----------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/negodata/backend/common/database/model/models.py b/negodata/backend/common/database/model/models.py index c3c9e31..d0cf970 100644 --- a/negodata/backend/common/database/model/models.py +++ b/negodata/backend/common/database/model/models.py @@ -27,8 +27,8 @@ class _DBTypeMixin: # ERD 공통 컬럼 class MainTableMixin(_DBTypeMixin): - created_at = Column(DateTime, nullable=False, server_default=_utc_now_sql()) - updated_at = Column(DateTime, nullable=False, server_default=_utc_now_sql(), onupdate=_utc_now_sql()) + created_at = Column(DateTime(timezone=True), nullable=False, server_default=_utc_now_sql()) + updated_at = Column(DateTime(timezone=True), nullable=False, server_default=_utc_now_sql(), onupdate=_utc_now_sql()) deleted = Column(Boolean, nullable=False, server_default=text("false"), default=False) @@ -60,7 +60,7 @@ class users(MainTableMixin, MAIN_BASE): name = Column(String(50), nullable=True) email = Column(String(255), nullable=True) contact_number = Column(String(20), nullable=True) - last_accessed_at = Column(DateTime, nullable=False, server_default=_utc_now_sql()) + last_accessed_at = Column(DateTime(timezone=True), nullable=False, server_default=_utc_now_sql()) status = Column(SmallInteger, nullable=False, default=UserStatus.ACTIVE.value) role = Column(SmallInteger, nullable=False, default=UserRole.USER.value) @@ -191,8 +191,8 @@ class quotations(MainTableMixin, MAIN_BASE): type = Column(SmallInteger, nullable=False) # QuotationType: 1=renego(1:1) / 2=requote(1:N) round = Column(Integer, nullable=False, default=1) # 재견적 진행 시 증가 status = Column(SmallInteger, nullable=False) # 진행 상태 코드 - start_time = Column(DateTime, nullable=False) - end_time = Column(DateTime, nullable=False) + start_time = Column(DateTime(timezone=True), nullable=False) + end_time = Column(DateTime(timezone=True), nullable=False) manager_name = Column(String(50), nullable=True) manager_email = Column(String(255), nullable=True) @@ -222,8 +222,8 @@ class sessions(MainTableMixin, MAIN_BASE): target_price = Column(BigInteger, nullable=False) # 목표가(원) status = Column(SmallInteger, nullable=False) # SessionStatus 코드 bid_price = Column(BigInteger, nullable=True) # 입찰가(원) - bid_at = Column(DateTime, nullable=True) # 입찰 시각 - end_time = Column(DateTime, nullable=False) # 세션 종료 시각 + bid_at = Column(DateTime(timezone=True), nullable=True) # 입찰 시각 + end_time = Column(DateTime(timezone=True), nullable=False) # 세션 종료 시각 reject_reason = Column(String(255), nullable=True) reject_price = Column(BigInteger, nullable=True) reject_delivery_type = Column(SmallInteger, nullable=True) # DeliveryType 코드 diff --git a/negodata/backend/services/quotation_service.py b/negodata/backend/services/quotation_service.py index d733d01..d5aa41d 100644 --- a/negodata/backend/services/quotation_service.py +++ b/negodata/backend/services/quotation_service.py @@ -68,15 +68,6 @@ class QuotationService: return int(int(price) / (1 + margin)) return int(price) - @staticmethod - def _naive_utc(dt): - """DB 컬럼이 naive(TIMESTAMP WITHOUT TIME ZONE)라, tz-aware 입력(프론트 toISOString 등)은 UTC naive 로 변환.""" - if dt is None: - return dt - if getattr(dt, "tzinfo", None) is not None: - return dt.astimezone(timezone.utc).replace(tzinfo=None) - return dt - @staticmethod def _gen_number() -> str: """견적번호 자동 생성(미지정 시). EST-YYYYMM-XXXX.""" @@ -156,8 +147,8 @@ class QuotationService: type_=req.type, status=req.status or QuotationStatus.CREATED.value, round_=req.round or 1, - start_time=self._naive_utc(req.start_time or GTime.UTC()), - end_time=self._naive_utc(req.end_time), + start_time=req.start_time or GTime.UTC(), + end_time=req.end_time, manager_name=req.manager_name, manager_email=req.manager_email, manager_contact_number=req.manager_contact_number,