[fix] negodata: 협상카드 성공률에 회사 스코프 누락 — 타사 견적 이력이 섞이던 문제
card_success_map 이 quotations 조인 없이 DB 전체 chats 를 카드별로 집계해, 다른 회사 견적에서 쓰인 이력이 내 카드 목록의 used_count/success_rate 로 잡혔다. 통계 화면 '협상카드 성공률 TOP 5' 와 견적 생성 시 카드 추천 순위가 모두 이 값을 쓴다. - quotations 조인 + 작성자 회사(users.company_id) 스코프 추가 - 소프트 삭제분 제외(sessions.deleted / quotations.deleted 필터 누락분 보강)
This commit is contained in:
parent
8112394aef
commit
69e4240039
@ -5,7 +5,7 @@ from sqlalchemy import select, func, and_, or_, update, case
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from common.database.db_session_manager import DB_SESSION_MNG
|
||||
from common.database.model.models import users, chats, sessions
|
||||
from common.database.model.models import users, chats, sessions, quotations
|
||||
from common.enums import ErrorType, SessionStatus
|
||||
from common.logger import LOG
|
||||
from common.utils.gtime import GTime
|
||||
@ -38,7 +38,7 @@ class ICardCRUD(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def card_success_map(self, cdb: AsyncSession) -> Tuple[ErrorType, dict]:
|
||||
async def card_success_map(self, cdb: AsyncSession, company_id) -> Tuple[ErrorType, dict]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
@ -83,9 +83,10 @@ class CardCRUD(ICardCRUD):
|
||||
LOG.e_no_callstack(ex)
|
||||
return ErrorType.DB_RUN_FAILED, [], 0
|
||||
|
||||
async def card_success_map(self, cdb: AsyncSession) -> Tuple[ErrorType, dict]:
|
||||
async def card_success_map(self, cdb: AsyncSession, company_id) -> Tuple[ErrorType, dict]:
|
||||
# 카드별 성공률: 카드 사용(card_used_yn) 채팅이 속한 세션의 타결(DONE) 비율.
|
||||
# {card_id(UUID): (used_sessions, won_sessions)}. 성공=세션 DONE(협상완료).
|
||||
# 집계 범위는 내 회사 견적에서 쓰인 이력만 — quotations 까지 조인해 작성자 회사로 좁힌다.
|
||||
try:
|
||||
stmt = (
|
||||
select(
|
||||
@ -94,7 +95,15 @@ class CardCRUD(ICardCRUD):
|
||||
func.count(func.distinct(case((sessions.status == SessionStatus.DONE.value, chats.session_id)))).label("won"),
|
||||
)
|
||||
.join(sessions, sessions.session_id == chats.session_id)
|
||||
.where(chats.card_used_yn == True, chats.card_id.isnot(None), chats.deleted == False) # noqa: E712
|
||||
.join(quotations, quotations.qt_id == sessions.quotation_id)
|
||||
.where(
|
||||
chats.card_used_yn == True, # noqa: E712
|
||||
chats.card_id.isnot(None),
|
||||
chats.deleted == False, # noqa: E712
|
||||
sessions.deleted == False, # noqa: E712
|
||||
quotations.deleted == False, # noqa: E712
|
||||
quotations.user_id.in_(select(users.user_id).where(users.company_id == company_id)),
|
||||
)
|
||||
.group_by(chats.card_id)
|
||||
)
|
||||
err, rows = await DB_SESSION_MNG.execute(cdb, stmt)
|
||||
|
||||
@ -142,7 +142,7 @@ class CardService:
|
||||
# 카드 성공률(#12) — 카드 사용→타결 집계를 page 카드에 매핑.
|
||||
_e, success_map = await DB_SESSION_MNG.execute_lambda(
|
||||
nego_cards.DBType(), DBWRType.DB_READ.value,
|
||||
lambda s: self.card_crud.card_success_map(s),
|
||||
lambda s: self.card_crud.card_success_map(s, company_uuid),
|
||||
)
|
||||
success_map = success_map or {}
|
||||
for c in page:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user