StocKing / models.py
adoomy's picture
feat: ์‚ฌ์šฉ์ž ํ”ผ๋“œ๋ฐฑ ๋Œ“๊ธ€ ์‹œ์Šคํ…œ ์ถ”๊ฐ€ ๋ฐ DB ์—ฐ๊ฒฐ ๋ฒ„๊ทธ ์ˆ˜์ •
ffd99f4
from datetime import datetime, timedelta
from sqlalchemy import Column, String, Integer, Float, Boolean, DateTime, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import declarative_base
Base = declarative_base()
class Company(Base):
"""์ƒ์žฅ์‚ฌ ๊ธฐ๋ณธ ์ •๋ณด. ์šฐ์„ ์ฃผ๋Š” ์ˆ˜์ง‘ ์‹œ skip."""
__tablename__ = "company"
ticker = Column(String, primary_key=True)
corp_code = Column(String) # DART corp_code (8์ž๋ฆฌ)
name = Column(String, nullable=False)
market = Column(String) # KOSPI / KOSDAQ
fiscal_year_end = Column(Integer, default=12) # ๊ฒฐ์‚ฐ์›” (12=12์›” ๊ฒฐ์‚ฐ)
class PriceSnapshot(Base):
"""ํ˜„์žฌ ์ฃผ๊ฐ€ + ์‹œ๊ฐ€์ด์•ก. ๋„ค์ด๋ฒ„ ์ปจ์„ผ์„œ์Šค ์ˆ˜์ง‘ ์‹œ ํ•จ๊ป˜ ์ €์žฅ."""
__tablename__ = "price_snapshot"
ticker = Column(String, ForeignKey("company.ticker"), primary_key=True)
current_price = Column(Float)
market_cap = Column(Float) # ์–ต์›
updated_at = Column(DateTime)
class AnnualData(Base):
"""์—ฐ๊ฐ„ ์žฌ๋ฌด ๋ฐ์ดํ„ฐ. ํ™•์ •์‹ค์ (is_estimate=False)๊ณผ ์ปจ์„ผ์„œ์Šค(is_estimate=True) ํ†ตํ•ฉ."""
__tablename__ = "annual_data"
id = Column(Integer, primary_key=True, autoincrement=True)
ticker = Column(String, ForeignKey("company.ticker"), nullable=False)
year = Column(Integer, nullable=False)
is_estimate = Column(Boolean, nullable=False, default=False)
# ์‹ค์ 
revenue = Column(Float) # ๋งค์ถœ์•ก (์–ต์›)
op_income = Column(Float) # ์˜์—…์ด์ต (์–ต์›)
net_income = Column(Float) # ๋‹น๊ธฐ์ˆœ์ด์ต (์–ต์›) โ€” ํ™•์ •๋งŒ
# ์ฃผ๋‹น ์ง€ํ‘œ
eps = Column(Float) # EPS (์›)
bps = Column(Float) # BPS (์›)
dividend_per_share = Column(Float) # ์ฃผ๋‹น๋ฐฐ๋‹น๊ธˆ (์›)
dividend_yield = Column(Float) # ๋ฐฐ๋‹น์ˆ˜์ต๋ฅ  (%)
# ์žฌ๋ฌด์ƒํƒœ
equity = Column(Float) # ์ž๋ณธ์ด๊ณ„ (์–ต์›)
total_assets = Column(Float) # ์ž์‚ฐ์ด๊ณ„ (์–ต์›)
shares_outstanding = Column(Float)
# ์•ˆ์ •์„ฑ ๋น„์œจ โ€” ํ™•์ •์—ฐ๋„๋งŒ (์ถ”์ •์—ฐ๋„๋Š” NULL)
roe = Column(Float) # ROE (%)
roa = Column(Float) # ROA (%)
debt_ratio = Column(Float) # ๋ถ€์ฑ„๋น„์œจ (%)
interest_bearing_debt = Column(Float) # ์ด์ž๋ฐœ์ƒ๋ถ€์ฑ„ (์–ต์›)
# ๋ฉ”ํƒ€
is_stale = Column(Boolean, default=False)
updated_at = Column(DateTime)
__table_args__ = (
Index("ix_annual_data_ticker_year_is_estimate", "ticker", "year", "is_estimate"),
Index("ix_annual_data_ticker_is_estimate", "ticker", "is_estimate"),
)
class User(Base):
"""Google OAuth ๋กœ๊ทธ์ธ ์‚ฌ์šฉ์ž."""
__tablename__ = "user"
id = Column(Integer, primary_key=True, autoincrement=True)
google_id = Column(String, unique=True, nullable=False)
email = Column(String, nullable=False)
name = Column(String)
is_admin = Column(Boolean, default=False)
created_at = Column(DateTime, default=lambda: datetime.utcnow() + timedelta(hours=9))
class Watchlist(Base):
"""๊ด€์‹ฌ์ข…๋ชฉ. ์‚ฌ์šฉ์ž๋ณ„ ๊ฒฉ๋ฆฌ."""
__tablename__ = "watchlist"
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("user.id"), nullable=False)
ticker = Column(String, ForeignKey("company.ticker"), nullable=False)
added_at = Column(DateTime, default=lambda: datetime.utcnow() + timedelta(hours=9))
memo = Column(String, default="")
__table_args__ = (UniqueConstraint("user_id", "ticker"),)
class BondRate(Base):
"""๊ตญ์ฑ„ 10๋…„๋ฌผ ๊ธˆ๋ฆฌ. ๋‹จ์ผ row (id=1) upsert."""
__tablename__ = "bond_rate"
id = Column(Integer, primary_key=True, default=1)
rate = Column(Float, nullable=False) # % (์˜ˆ: 3.2)
fetched_at = Column(DateTime)
class Feedback(Base):
"""์‚ฌ์šฉ์ž ํ”ผ๋“œ๋ฐฑ/๋Œ“๊ธ€."""
__tablename__ = "feedback"
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("user.id"), nullable=False)
content = Column(String, nullable=False)
created_at = Column(DateTime, default=lambda: datetime.utcnow() + timedelta(hours=9))