# W5 — 파트너가 회원 거래를 중지/재개

작성 2026-08-19 · repo `cryptoments`(core, partner-api) + `cryptoments-admin`(partner-ui)
제품 결정 (2026-08-19): **파트너가 회원 거래를 대신 중지할 수 있다.**

---

## 범위 — 거래중지만. 입금방식은 열지 않는다

```
✅ 거래중지 / 재개      trading_paused — 신규 매칭만 차단
✘ 입금방식(AUTO/MANUAL) 회원 본인만
```

**입금방식을 제외하는 이유**: `AUTO` 는 회원의 스크래핑 인증 계좌가 있어야 성립한다
(없으면 서비스가 409). `MANUAL` 로 바꾸면 이후 모든 확인이 **회원의 수동 작업**이 된다.
남의 작업 부담과 인증 상태에 얽힌 값이라 본인 결정으로 남긴다.
**열어야 한다는 판단이 서면 그때 별도로 하라.**

## ⚠️ 이미 있는 '접근 차단'과 다른 기능이다

파트너 콘솔에 **접근 차단(suspend)** 이 이미 있다. 둘을 혼동하면 운영 사고가 난다.

```
접근 차단(suspend)   status = SUSPENDED. 회원의 서비스 접근 자체를 막는다
거래 중지(pause)     trading_paused = 1. 매칭 후보 쿼리에서만 빠진다
                     → 진행 중인 매칭·정산·출금은 그대로 계속된다
```

**화면에서 이 차이를 반드시 설명하라.** "중지하면 새 매칭만 안 잡히고,
이미 진행 중인 거래는 그대로 진행됩니다" 수준의 문구가 있어야 한다.

---

# A. 백엔드 (partner-api + core)

## A1. 엔드포인트

기존 `suspend`/`activate` 패턴을 그대로 따른다.

```
POST /api/partner/p2p/members/{token}/trading/pause
POST /api/partner/p2p/members/{token}/trading/resume
→ P2pMemberResponse (기존 응답 재사용)
```

**소유 검증은 `verifyMemberOwnership(token)`** — 기존 회원 조작 API 가 전부 쓰는 헬퍼다.
**새 검증을 만들지 마라.**

## A2. ⚠️ core 의 `setTradingPaused` 는 소유 검증이 없다

```java
public P2pMember setTradingPaused(Long memberId, boolean paused)
```

`memberId` 를 그대로 받는다. 회원 페이지는 세션의 `memberId` 를 넘기므로 안전했지만,
**파트너 경로는 컨트롤러가 반드시 소유를 검증한 뒤에 불러야 한다.**

토큰 기반 오버로드를 추가하든 컨트롤러에서 검증 후 id 를 넘기든 좋다.
**단 기존 시그니처를 깨지 마라** — 회원 페이지가 쓰고 있다.

## A3. 회원에게 알린다 ★

**자기 거래가 멈췄는데 모르면 안 된다.** 회원은 "왜 매칭이 안 잡히지?" 를 알 방법이 없다.

- `P2pMemberEvent` 에 값 추가 (예: `TRADING_PAUSED` / `TRADING_RESUMED`)
- `P2pMemberNotifier` 포맷터 추가 — 기존 이벤트들의 톤을 따른다
- **`afterCommit` 발송** — 기존 회원 알림 패턴을 그대로 따라라. 트랜잭션 안에서 보내지 마라
- 문구에 **누가 했는지**를 담아라 — "파트너가 거래를 일시 중지했습니다" 여야
  회원이 자기가 한 게 아님을 안다
- 회원 본인이 바꾼 경우(회원 페이지 경로)에는 **에코하지 마라.** 본인이 방금 누른 걸
  다시 알리는 건 소음이다 (분쟁 제기 알림이 제기자에게 에코되는 기존 결함과 같은 유형)

> 텔레그램 연결률이 52명 중 5명이라 도달은 10%다. 그래도 넣는다 —
> 연결한 회원에겐 이게 유일한 통지 경로다.

## A4. 감사 기록

partner-api 에는 **감사 로그 인프라가 없다**(admin-api 에만 있다).
새로 만들지 말고 **구조화된 로그**를 남겨라 — 파트너 ID·회원 토큰·이전/이후 값.

> 파트너의 회원 설정 변경을 정식 감사 대상으로 삼을지는 별도 결정이다. **여기서 정하지 마라.**

---

# B. 프론트 (partner-ui)

**파일** `views/partner/p2p/P2pMemberDetailView.vue`

- 현재 `depositMethod` 를 읽기 전용으로 표시하는 자리 근처에 **거래 상태 토글**
- 기존 핀 리셋·접근 차단 버튼들과 같은 영역에 두되, **접근 차단과 시각적으로 구분**하라
- 중지 전 확인 다이얼로그 — 위의 "새 매칭만 안 잡힌다" 설명을 여기 넣어라
- 성공 후 목록/상세 갱신
- `P2pMembersView` 목록에도 거래중지 상태를 보여줄지 판단하라
  (중지된 회원이 목록에서 안 보이면 재개를 못 한다 — **최소한 상세로 갈 수 있어야 한다**)

**입금방식은 읽기 전용 그대로 둔다.** 바꾸는 UI 를 만들지 마라.

---

## 코딩 규칙

- Java 17 · Lombok(`@Data` 금지) · DTO 멤버 JavaDoc 필수
- 소유 검증은 기존 헬퍼 재사용. 새로 만들지 마라
- 알림은 `afterCommit`. **알림 실패가 트랜잭션을 깨면 안 된다** — try/catch
- **DDL 금지. DB 접속 금지** (`trading_paused` 컬럼은 이미 있다)
- Vue 는 기존 스타일. 새 라이브러리 금지

## 완료 기준

```
1  ./gradlew :core:compileJava :partner-api:compileJava :open-api:compileJava 통과
2  partner-ui 빌드 통과
3  남의 회원 토큰으로 호출하면 막힌다 (기존 verifyMemberOwnership 경유)
4  파트너가 중지하면 회원에게 알림이 가고, 문구에 '파트너가' 라는 주체가 담긴다
5  회원 본인이 바꾼 경우엔 에코하지 않는다
6  화면이 '접근 차단'과 '거래 중지'의 차이를 설명한다
7  중지된 회원을 다시 찾아 재개할 수 있다
8  입금방식 변경 UI 는 만들지 않았다
```

## 보고 형식

- 작업별 수정 파일:라인 + 한 줄
- **A2 를 어떻게 처리했는지** (오버로드 / 컨트롤러 검증) 와 기존 시그니처 보존 여부
- A3 에서 본인 변경 에코를 어떻게 막았는지
- B 의 목록 노출 판단과 근거
- 지침이 실제 코드와 어긋난 지점 — **고치지 말고 먼저 보고**
- 빌드 결과

## 착수 전 필수 확인

```
partner-api/.../controller/P2pMemberController.java   (suspend/activate 패턴 · verifyMemberOwnership)
core/.../p2p/P2pMemberService.java                     (setTradingPaused · suspend · getByToken)
open-api/.../controller/p2p/P2pMemberSettingsController.java  (회원 본인 경로 — 에코 방지 판단)
core/.../notification/P2pMemberNotifier.java           (알림 패턴 · afterCommit)
common/.../enums/P2pMemberEvent.java
partner-ui/src/views/partner/p2p/P2pMemberDetailView.vue · P2pMembersView.vue
common/.../mapper/P2pMatchingMapper.java 약 :113        (trading_paused 게이트 — 읽기만)
```

지침과 다르면 **멈추고 보고하라.**
