fix(enhance-v4): APK QR 버그 수정 + 웹메일 라우터 수정

This commit is contained in:
DESKTOP-TKLFCPR\ython 2026-06-02 20:21:07 +09:00
parent 1057915729
commit f00388b066
3 changed files with 16 additions and 20 deletions

View File

@ -5457,7 +5457,8 @@ class AppVersion(Base):
android_url = Column(String(1000), nullable=True)
ios_url = Column(String(1000), nullable=True)
qr_image_path = Column(String(500), nullable=True)
landing_token = Column(String(36), nullable=True, unique=True)
qr_data = Column(Text, nullable=True) # base64 PNG
landing_token = Column(String(64), nullable=True, unique=True)
download_count = Column(Integer, default=0)
is_latest = Column(Boolean, default=False)
release_notes = Column(Text, nullable=True)

View File

@ -97,9 +97,10 @@ async def upload_apk(
file_path.write_bytes(file_bytes)
# 기존 latest 해제
from sqlalchemy import update as sa_update
await db.execute(
__import__('sqlalchemy', fromlist=['update']).update(AppVersion)
.where(AppVersion.tenant_id == user.tenant_id, AppVersion.is_latest == True)
sa_update(AppVersion)
.where(AppVersion.is_latest == True)
.values(is_latest=False)
)
@ -110,11 +111,10 @@ async def upload_apk(
qr_b64 = base64.b64encode(qr_bytes).decode()
app_ver = AppVersion(
tenant_id=user.tenant_id,
version=version,
platform="ANDROID",
file_path=str(file_path),
file_size=len(file_bytes),
file_size_mb=round(len(file_bytes) / 1024 / 1024, 2),
android_url=f"{BASE_URL}/api/app/download?token={token}",
ios_url=ios_url or None,
landing_token=token,
@ -147,9 +147,10 @@ async def set_app_url(
user: User = Depends(require_admin_role),
):
"""외부 URL(EAS 빌드 등)로 QR 코드 생성."""
from sqlalchemy import update as sa_update
await db.execute(
__import__('sqlalchemy', fromlist=['update']).update(AppVersion)
.where(AppVersion.tenant_id == user.tenant_id, AppVersion.is_latest == True)
sa_update(AppVersion)
.where(AppVersion.is_latest == True)
.values(is_latest=False)
)
@ -158,7 +159,6 @@ async def set_app_url(
qr_bytes = _generate_qr(landing_url)
app_ver = AppVersion(
tenant_id=user.tenant_id,
version=req.version,
platform="BOTH" if req.ios_url else "ANDROID",
android_url=req.android_url,
@ -190,10 +190,7 @@ async def get_latest(
):
"""최신 버전 정보 조회."""
row = await db.execute(
select(AppVersion).where(
AppVersion.tenant_id == user.tenant_id,
AppVersion.is_latest == True,
)
select(AppVersion).where(AppVersion.is_latest == True)
)
ver = row.scalar_one_or_none()
if not ver:
@ -303,8 +300,7 @@ async def app_landing(
version_id=ver.id,
platform="IOS" if is_ios else "ANDROID",
user_agent=request.headers.get("User-Agent", "")[:200],
ip_addr=request.client.host if request.client else "",
accessed_at=datetime.utcnow(),
downloaded_at=datetime.utcnow(),
)
db.add(log)
await db.commit()
@ -343,8 +339,7 @@ async def list_versions(
user: User = Depends(get_current_user),
):
rows = await db.execute(
select(AppVersion).where(AppVersion.tenant_id == user.tenant_id)
.order_by(desc(AppVersion.created_at)).limit(20)
select(AppVersion).order_by(desc(AppVersion.created_at)).limit(20)
)
versions = rows.scalars().all()
return [
@ -353,7 +348,7 @@ async def list_versions(
"download_count": v.download_count, "is_latest": v.is_latest,
"qr_url": f"{BASE_URL}/api/app/qr?token={v.landing_token}",
"landing_url": f"{BASE_URL}/api/app/landing?token={v.landing_token}",
"file_size_mb": round((v.file_size or 0) / 1024 / 1024, 1),
"file_size_mb": round((v.file_size_mb or 0), 1),
"release_notes": v.release_notes,
"created_at": v.created_at,
}
@ -368,7 +363,7 @@ async def delete_version(
user: User = Depends(require_admin_role),
):
row = await db.execute(
select(AppVersion).where(AppVersion.id == version_id, AppVersion.tenant_id == user.tenant_id)
select(AppVersion).where(AppVersion.id == version_id)
)
ver = row.scalar_one_or_none()
if not ver:
@ -388,7 +383,7 @@ async def app_stats(
user: User = Depends(get_current_user),
):
total = (await db.execute(
select(func.sum(AppVersion.download_count)).where(AppVersion.tenant_id == user.tenant_id)
select(func.sum(AppVersion.download_count))
)).scalar() or 0
android = (await db.execute(
select(func.count(AppDownloadLog.id)).where(AppDownloadLog.platform == "ANDROID")

View File

@ -42,7 +42,7 @@ class NotifyRuleCreate(BaseModel):
name: str = Field(..., max_length=200)
trigger_type: str = Field(..., description="SR_CREATED|SR_UPDATED|INCIDENT|DRIFT|KPI_BREACH|CUSTOM")
conditions: dict = Field(default_factory=dict)
channels: List[str] = Field(default_factory=list, description=["messenger","email","slack","kakao"])
channels: List[str] = Field(default_factory=list, description="messenger|email|slack|kakao")
priority_filter: str = Field("ALL", description="HIGH|MEDIUM|ALL")
silence_hours: Optional[List[int]] = Field(None, description="무음 시간 목록 [22,23,0,1,...,7]")
digest_mode: bool = Field(False, description="묶음 발송 모드")