529 lines
18 KiB
Markdown
529 lines
18 KiB
Markdown
# 피드백 작성 페이지와 관리페이지 데이터 흐름
|
|
|
|
## 1. 전체 구조
|
|
|
|
현재 구조는 피드백 작성 웹과 관리 콘솔이 분리되어 있습니다. 작성 웹은 직접 ABC API나 DB에 접근하지 않고, Next.js 서버 Proxy를 통해 외부 관리 콘솔 API에 요청합니다.
|
|
|
|
```text
|
|
피드백 작성 페이지
|
|
/support/{workspaceCode}/new
|
|
│
|
|
│ POST /api/support/workspaces/{workspaceCode}/submit
|
|
▼
|
|
apps/web의 Next.js API Proxy
|
|
│
|
|
│ POST /api/support/workspaces/{workspaceCode}/tickets
|
|
▼
|
|
외부 관리 콘솔 API
|
|
https://feedback.hmac.kr/api/support
|
|
│
|
|
├─ Secretary DB: support_tickets 저장
|
|
├─ ABC API: feedbacks 저장
|
|
├─ abc_feedback_mappings: 두 ID 연결
|
|
└─ 첨부파일: Secretary Local/R2 저장
|
|
▼
|
|
관리 콘솔에서 조회·처리
|
|
```
|
|
|
|
피드백 전용 배포에서는 브라우저 요청을 same-origin으로 유지하고, 외부 관리 콘솔 주소는 서버 환경변수로만 사용합니다.
|
|
|
|
관련 설정:
|
|
|
|
- `NEXT_PUBLIC_FEEDBACK_ONLY=true`
|
|
- `SUPPORT_CONSOLE_API_BASE_URL=https://feedback.hmac.kr/api/support`
|
|
- `NEXT_PUBLIC_API_BASE_URL`은 빈 값으로 설정
|
|
|
|
## 1.1 전체 데이터 흐름도
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
U[사용자] --> W[피드백 작성 페이지<br/>/support/{workspaceCode}/new]
|
|
W -->|FormData<br/>제목·내용·필드·첨부파일| P[Next.js 서버 Proxy]
|
|
P -->|POST /api/support/workspaces/{workspaceCode}/tickets| S[외부 관리 콘솔 API<br/>Secretary]
|
|
|
|
S -->|1. 내부 티켓 저장| T[(Secretary DB<br/>baron_support)]
|
|
S -->|2. ABC 피드백 생성| A[ABC API]
|
|
A --> F[(ABC MySQL<br/>feedbacks)]
|
|
S --> M[(abc_feedback_mappings)]
|
|
M -. ticket_id ↔ feedback_id .-> T
|
|
M -. ticket_id ↔ feedback_id .-> F
|
|
S -->|첨부파일 저장| X[(Secretary Local/R2<br/>+ attachments 메타데이터)]
|
|
|
|
T --> C[관리 콘솔 목록·상세 화면]
|
|
F --> C
|
|
X --> C
|
|
```
|
|
|
|
### 핵심 저장 위치
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
D[피드백 등록 데이터]
|
|
D --> D1[ABC MySQL<br/>feedbacks.data JSON<br/>원본 피드백 본문]
|
|
D --> D2[Secretary DB<br/>support_tickets<br/>관리용 티켓·상태·권한]
|
|
D --> D3[Secretary DB<br/>abc_feedback_mappings<br/>두 시스템 ID 연결]
|
|
D --> D4[Secretary Local/R2<br/>첨부파일 바이너리]
|
|
D --> D5[Secretary DB<br/>attachments<br/>첨부파일 메타데이터]
|
|
D1 -. 검색 활성화 시 .-> D6[OpenSearch<br/>검색용 색인]
|
|
```
|
|
|
|
### ID 연결 구조
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
W[workspace_code<br/>예: EGBIM_DEMO]
|
|
W --> ST[Secretary ticket_id]
|
|
ST --> MAP[abc_feedback_mappings]
|
|
MAP --> AF[ABC feedback_id]
|
|
AF --> CH[ABC project_id / channel_id]
|
|
```
|
|
|
|
`ticket_id`와 `feedback_id`는 서로 다른 시스템에서 생성되는 별도 ID입니다. 관리 콘솔은 `abc_feedback_mappings` 또는 응답의 `extra_fields.abc_feedback_id`를 이용해 두 데이터를 결합합니다.
|
|
|
|
## 1.2 네이버웍스 알림 흐름도
|
|
|
|
피드백 등록 자체는 먼저 ABC와 Secretary에 저장되고, 저장 완료 후 ABC 백엔드 이벤트를 통해 네이버웍스 알림이 발송됩니다.
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant User as 사용자
|
|
participant Web as 작성 웹
|
|
participant Secretary as Secretary API
|
|
participant ABC as ABC API
|
|
participant ABCDB as ABC MySQL
|
|
participant Notify as 알림 서비스
|
|
participant NW as 네이버웍스 API
|
|
participant Log as notification_deliveries
|
|
|
|
User->>Web: 피드백 등록
|
|
Web->>Secretary: POST /workspaces/{code}/tickets
|
|
Secretary->>Secretary: support_tickets 저장
|
|
Secretary->>ABC: feedback 생성 요청
|
|
ABC->>ABCDB: feedbacks 저장
|
|
ABC-->>Notify: FEEDBACK_CREATION 이벤트
|
|
Notify->>Notify: 담당자·프로젝트 관리자·작성자 계산
|
|
Notify->>NW: 이메일로 사용자 ID 조회
|
|
NW-->>Notify: 네이버웍스 userId
|
|
Notify->>NW: Bot 개인 메시지 발송
|
|
Notify->>Log: SENT / FAILED / SKIPPED 기록
|
|
ABC-->>Secretary: abc_feedback_id 반환
|
|
Secretary-->>Web: ticket_id·동기화 상태 반환
|
|
```
|
|
|
|
## 2. 피드백 작성 페이지
|
|
|
|
작성 페이지는 다음 파일입니다.
|
|
|
|
`apps/web/src/pages/support/[workspaceCode]/new.tsx`
|
|
|
|
### 양식 조회
|
|
|
|
페이지 진입 시 workspace별 양식을 조회합니다.
|
|
|
|
```text
|
|
GET /api/support/workspaces/{workspaceCode}/form-template
|
|
```
|
|
|
|
Next.js API Proxy는 이를 외부 관리 콘솔 API로 전달합니다.
|
|
|
|
```text
|
|
GET {SUPPORT_CONSOLE_API_BASE_URL}/workspaces/{workspaceCode}/form-template
|
|
```
|
|
|
|
양식의 workspace code는 프로젝트와 ABC 프로젝트·채널을 연결하는 식별자입니다.
|
|
|
|
### 등록 요청
|
|
|
|
사용자가 등록하면 브라우저는 `FormData`를 생성합니다.
|
|
|
|
주요 필드는 다음과 같습니다.
|
|
|
|
- `title`
|
|
- `description`
|
|
- `category_code`
|
|
- `is_secret`
|
|
- `ticket_type`
|
|
- `requires_approval`
|
|
- `extra_fields`
|
|
- `attachments`
|
|
|
|
작성 페이지는 다음 내부 API를 호출합니다.
|
|
|
|
```text
|
|
POST /api/support/workspaces/{workspaceCode}/submit
|
|
```
|
|
|
|
관련 파일:
|
|
|
|
`apps/web/src/pages/api/support/workspaces/[workspaceCode]/submit.ts`
|
|
|
|
이 API는 multipart 요청을 파싱한 후 외부 관리 콘솔로 다시 전달합니다.
|
|
|
|
```text
|
|
POST {SUPPORT_CONSOLE_API_BASE_URL}/workspaces/{workspaceCode}/tickets
|
|
```
|
|
|
|
인증 정보는 브라우저에서 별도 입력받지 않고, 현재 로그인된 BARON-SSO 세션의 Authorization 헤더를 Proxy가 전달합니다.
|
|
|
|
## 3. Secretary API에서의 저장
|
|
|
|
Secretary API의 티켓 생성 로직은 다음 파일에 있습니다.
|
|
|
|
`apps/secretary-api/app/services/ticket_service.py`
|
|
|
|
티켓 등록 시 다음 순서로 처리됩니다.
|
|
|
|
1. `support_tickets`에 내부 관리 티켓을 생성합니다.
|
|
2. workspace에 매핑된 ABC 프로젝트와 채널을 확인합니다.
|
|
3. ABC API에 피드백을 생성합니다.
|
|
4. `abc_feedback_mappings`에 Secretary 티켓과 ABC 피드백의 연결 정보를 저장합니다.
|
|
5. 첨부파일을 Secretary 저장소에 저장합니다.
|
|
6. 동기화 상태를 `SYNCED`로 변경합니다.
|
|
7. 티켓 ID와 동기화 상태를 작성 웹에 반환합니다.
|
|
|
|
API 라우트:
|
|
|
|
```text
|
|
POST /api/workspaces/{workspaceCode}/tickets
|
|
```
|
|
|
|
구현 파일:
|
|
|
|
`apps/secretary-api/app/api/routes/tickets.py`
|
|
|
|
## 4. 데이터베이스 구조
|
|
|
|
### Secretary DB
|
|
|
|
Secretary 쪽에는 관리 업무용 데이터가 저장됩니다.
|
|
|
|
| 테이블 | 역할 |
|
|
| --- | --- |
|
|
| `support_tickets` | 내부 관리 티켓 본체 |
|
|
| `abc_feedback_mappings` | Secretary 티켓 ID와 ABC 피드백 ID 연결 |
|
|
| `ticket_comments` | 사용자 댓글 및 내부 메모 |
|
|
| `attachments` | 첨부파일 메타데이터 |
|
|
| `user_workspace_access` | 사용자별 workspace 권한 |
|
|
|
|
주요 모델은 다음 파일에 정의되어 있습니다.
|
|
|
|
`apps/secretary-api/app/db/models.py`
|
|
|
|
### ABC DB
|
|
|
|
ABC 쪽에는 기존 피드백 데이터가 저장됩니다.
|
|
|
|
| 테이블 | 역할 |
|
|
| --- | --- |
|
|
| `feedbacks` | 피드백 본문과 동적 필드를 `data` JSON으로 저장 |
|
|
| `channels` | 피드백이 소속된 채널 |
|
|
| `feedbacks_issues_issues` | 피드백과 이슈의 다대다 연결 |
|
|
|
|
ABC 피드백 엔티티:
|
|
|
|
`apps/api/src/domains/admin/feedback/feedback.entity.ts`
|
|
|
|
## 5. 티켓 ID와 피드백 ID
|
|
|
|
Secretary 티켓 ID와 ABC 피드백 ID는 서로 다른 식별자입니다.
|
|
|
|
```text
|
|
Secretary ticket_id = 관리 티켓 식별자
|
|
ABC feedback_id = ABC 피드백 식별자
|
|
abc_feedback_mappings = 두 식별자를 연결하는 매핑
|
|
```
|
|
|
|
관리 API 응답에서는 보통 다음과 같이 ABC ID가 함께 노출됩니다.
|
|
|
|
```json
|
|
{
|
|
"ticket_id": 101,
|
|
"extra_fields": {
|
|
"abc_feedback_id": "345"
|
|
}
|
|
}
|
|
```
|
|
|
|
이 매핑을 이용해 관리 콘솔은 티켓 정보와 ABC 피드백 정보, 이슈 연결 정보를 함께 처리합니다.
|
|
|
|
## 6. 관리페이지 조회 흐름
|
|
|
|
실제 운영 관리 콘솔은 Secretary API를 기준으로 티켓 목록을 조회합니다.
|
|
|
|
```text
|
|
GET /api/support/workspaces/{workspaceCode}/tickets
|
|
│
|
|
├─ support_tickets 조회
|
|
├─ abc_feedback_mappings 확인
|
|
├─ 담당자·권한 정보 결합
|
|
├─ 댓글·첨부파일 정보 결합
|
|
└─ ABC 피드백과 상태 동기화
|
|
```
|
|
|
|
피드백 전용 모드에서 이 저장소의 목록 Proxy는 외부 관리 콘솔 API를 그대로 호출합니다.
|
|
|
|
관련 파일:
|
|
|
|
`apps/web/src/pages/api/support/workspaces/[workspaceCode]/tickets.ts`
|
|
|
|
관리 콘솔에서 처리하는 주요 데이터는 다음과 같습니다.
|
|
|
|
- 피드백 목록과 상세 내용
|
|
- 피드백 처리 상태
|
|
- 담당자 지정
|
|
- 사용자 댓글
|
|
- 내부 메모
|
|
- 첨부파일
|
|
- ABC 이슈 연결 상태
|
|
|
|
## 7. 이 저장소에 있는 기존 ABC 관리자 화면
|
|
|
|
이 저장소에는 기존 ABC 관리자 화면도 남아 있습니다.
|
|
|
|
```text
|
|
/main/project/{projectId}/feedback
|
|
```
|
|
|
|
페이지:
|
|
|
|
`apps/web/src/pages/main/project/[projectId]/feedback.tsx`
|
|
|
|
이 화면은 Secretary 티켓 목록이 아니라 ABC 관리자 API를 직접 조회합니다.
|
|
|
|
```text
|
|
POST /api/admin/projects/{projectId}/channels/{channelId}/feedbacks/search
|
|
```
|
|
|
|
ABC API의 검색 요청은 다음 서버 로직으로 처리됩니다.
|
|
|
|
`apps/api/src/domains/admin/feedback/feedback.service.ts`
|
|
|
|
검색 데이터는 설정에 따라 다음 중 하나에서 조회됩니다.
|
|
|
|
- ABC MySQL의 `feedbacks` 테이블
|
|
- OpenSearch의 피드백 인덱스
|
|
|
|
따라서 이 화면은 실제 외부 관리 콘솔의 Secretary 기반 관리 화면과 데이터 조회 기준이 다를 수 있습니다.
|
|
|
|
## 8. 화면별 역할 비교
|
|
|
|
| 화면 | 주요 데이터 원천 | 역할 |
|
|
| --- | --- | --- |
|
|
| `/support/{workspaceCode}/new` | 외부 관리 콘솔 등록 API | 피드백 작성 |
|
|
| 외부 관리 콘솔 `feedback.hmac.kr` | Secretary + ABC | 실제 운영 관리 |
|
|
| `/main/project/{projectId}/feedback` | ABC API 직접 조회 | 기존 ABC 관리자 화면 |
|
|
| `/admin/issues` | Secretary 티켓 API 또는 스텁 | 데모·보조 관리 화면 |
|
|
| `/ops` | Secretary 티켓 API 또는 스텁 | 승인 큐 데모 화면 |
|
|
|
|
피드백 전용 전환 문서의 목표는 이 저장소에서 작성 화면만 제공하고, 목록·상세·관리 기능은 외부 관리 콘솔에서 유지하는 것입니다.
|
|
|
|
## 9. 첨부파일 흐름
|
|
|
|
작성 페이지에서 첨부파일을 선택하면 브라우저의 `FormData`에 포함됩니다.
|
|
|
|
```text
|
|
브라우저
|
|
→ Next.js Proxy
|
|
→ 외부 관리 콘솔/Secretary API
|
|
→ Secretary Local 또는 R2 저장소
|
|
→ attachments 테이블에 메타데이터 저장
|
|
```
|
|
|
|
현재 작성 화면의 제한은 다음과 같습니다.
|
|
|
|
- 파일당 최대 30MB
|
|
- 전체 최대 30MB
|
|
- 최대 10개
|
|
- 이미지 외 일반 파일도 업로드 가능
|
|
|
|
첨부파일은 피드백 본문 JSON에 직접 저장되지 않고 별도 저장소와 `attachments` 메타데이터로 관리됩니다.
|
|
|
|
## 10. 네이버웍스 알림 흐름
|
|
|
|
피드백 작성 웹은 네이버웍스 API를 직접 호출하지 않습니다. 피드백 등록 후 ABC API와 기존 관리 콘솔의 백엔드 알림 파이프라인에서 네이버웍스 알림을 처리합니다.
|
|
|
|
```text
|
|
피드백 작성
|
|
→ Secretary가 내부 티켓 저장
|
|
→ ABC API가 feedbacks 저장
|
|
→ FEEDBACK_CREATION 이벤트 발생
|
|
→ 알림 수신자 계산
|
|
→ 네이버웍스 사용자 ID 조회
|
|
→ 네이버웍스 Bot 메시지 발송
|
|
→ notification_deliveries에 결과 저장
|
|
```
|
|
|
|
### 10.1 알림 이벤트 발생
|
|
|
|
ABC의 [`FeedbackService.create`](apps/api/src/domains/admin/feedback/feedback.service.ts)는 피드백 저장 후 `FEEDBACK_CREATION` 이벤트를 발생시킵니다.
|
|
|
|
```text
|
|
apps/api/src/domains/admin/feedback/feedback.service.ts
|
|
│
|
|
│ EventTypeEnum.FEEDBACK_CREATION
|
|
▼
|
|
apps/api/src/domains/admin/project/webhook/notification-internal.listener.ts
|
|
```
|
|
|
|
트랜잭션 커밋 전에 알림이 조회되지 않도록, 생성 이벤트 처리 시 저장 완료 후 피드백을 다시 조회합니다.
|
|
|
|
알림 이벤트에는 다음 정보가 포함됩니다.
|
|
|
|
- `projectId`
|
|
- `channelId`
|
|
- `feedbackId`
|
|
- 피드백 제목
|
|
- 작성자 이메일
|
|
- 담당자 이메일
|
|
- 현재 피드백 상태
|
|
- 비밀글 여부
|
|
|
|
### 10.2 알림 대상
|
|
|
|
수신자 계산은 [`notification-recipient.router.ts`](apps/api/src/domains/admin/project/webhook/notification-recipient.router.ts)에서 수행합니다.
|
|
|
|
신규 피드백과 상태 변경 시 대상은 다음과 같습니다.
|
|
|
|
- 해당 피드백의 담당자
|
|
- 해당 프로젝트의 `PROJECT_MANAGER` 또는 `Admin` 역할 사용자
|
|
- 피드백 작성자
|
|
|
|
관리자 댓글 등록 시에는 해당 피드백 작성자에게만 보냅니다.
|
|
|
|
같은 사용자가 여러 역할에 해당하면 이메일 기준으로 중복 제거하여 한 번만 발송합니다. 프로젝트 관리자는 ABC의 프로젝트 멤버와 Secretary의 관리자 조회 결과를 함께 사용합니다.
|
|
|
|
```text
|
|
ABC project/channel
|
|
│
|
|
├─ ABC DB의 프로젝트 관리자 조회
|
|
├─ Secretary API의 프로젝트 관리자 조회
|
|
├─ 피드백 담당자 추가
|
|
└─ 피드백 작성자 추가
|
|
│
|
|
▼
|
|
이메일 기준 중복 제거
|
|
```
|
|
|
|
수신자 이메일은 네이버웍스 API에서 실제 사용자 ID로 변환됩니다. 이메일 또는 사용자 매핑이 확인되지 않으면 임의 사용자나 전체 방으로 대체 발송하지 않습니다.
|
|
|
|
### 10.3 네이버웍스 발송
|
|
|
|
실제 발송은 [`NaverWorksClient`](apps/api/src/domains/admin/project/webhook/naver-works.client.ts)에서 수행합니다.
|
|
|
|
1. 네이버웍스 Access Token을 확인합니다.
|
|
2. 설정된 이메일로 네이버웍스 사용자 ID를 조회합니다.
|
|
3. Bot ID와 사용자 ID를 사용해 개인 메시지를 발송합니다.
|
|
4. 발송 성공·실패 결과를 저장합니다.
|
|
|
|
인증 방식은 두 가지를 지원합니다.
|
|
|
|
- `NAVER_WORKS_ACCESS_TOKEN` 직접 사용
|
|
- Client ID, Client Secret, Service Account, Private Key를 이용한 JWT Bearer 인증
|
|
|
|
관련 환경변수는 API 서버에만 설정해야 합니다.
|
|
|
|
```text
|
|
NAVER_WORKS_ENABLED
|
|
NAVER_WORKS_API_BASE_URL
|
|
NAVER_WORKS_AUTH_URL
|
|
NAVER_WORKS_ACCESS_TOKEN
|
|
NAVER_WORKS_BOT_ID
|
|
NAVER_WORKS_DEFAULT_ROOM_ID
|
|
NAVER_WORKS_CLIENT_ID
|
|
NAVER_WORKS_CLIENT_SECRET
|
|
NAVER_WORKS_SERVICE_ACCOUNT
|
|
NAVER_WORKS_PRIVATE_KEY
|
|
```
|
|
|
|
피드백 전용 작성 웹에는 이 값들을 넣지 않습니다.
|
|
|
|
### 10.4 메시지 구성
|
|
|
|
메시지는 [`notification-message.builder.ts`](apps/api/src/domains/admin/project/webhook/notification-message.builder.ts)에서 생성합니다.
|
|
|
|
기본 메시지에는 다음 정보가 포함됩니다.
|
|
|
|
- 이벤트 종류
|
|
- 피드백 ID
|
|
- 피드백 제목
|
|
- 상태 변경 전·후 상태
|
|
- 관리자 공개 댓글 내용
|
|
- 기존 관리자 상세 페이지 링크
|
|
|
|
비밀글 작성자에게 보내는 메시지는 제목·본문·댓글 원문을 노출하지 않고 피드백 ID 중심으로 최소화합니다. 전화번호, IP 주소, MAC 주소는 기본 알림에 포함하지 않습니다.
|
|
|
|
### 10.5 알림 대상 이벤트
|
|
|
|
| 이벤트 | 기본 수신자 | 조건 |
|
|
| --- | --- | --- |
|
|
| `FEEDBACK_CREATION` | 담당자, 프로젝트 관리자, 작성자 | 신규 피드백 등록 |
|
|
| `FEEDBACK_STATUS_CHANGE` | 담당자, 프로젝트 관리자, 작성자 | 이전 상태와 현재 상태가 다름 |
|
|
| `FEEDBACK_COMMENT_CREATION` | 작성자 | 관리자의 공개 댓글 등록 |
|
|
|
|
다음 이벤트는 현재 네이버웍스 피드백 알림 대상이 아닙니다.
|
|
|
|
- 내부 메모 등록·수정·삭제
|
|
- 관리자 공개 댓글 수정·삭제
|
|
- 이슈 상태 변경
|
|
- Gitea 상태 변경
|
|
- 같은 상태로 다시 저장한 상태 변경
|
|
|
|
### 10.6 중복 및 실패 처리
|
|
|
|
알림 서비스는 `notification_deliveries` 테이블에 이벤트별 발송 결과를 기록합니다.
|
|
|
|
주요 상태:
|
|
|
|
- `RECEIVED`: 발송 처리 대상 등록
|
|
- `SENT`: 발송 성공
|
|
- `SKIPPED`: 대상 없음 또는 알림 제외
|
|
- `FAILED`: 발송 실패
|
|
|
|
이벤트와 수신자 조합으로 Idempotency Key를 생성하므로 동일 이벤트가 반복 수신되어도 같은 사용자에게 중복 발송하지 않습니다.
|
|
|
|
네이버웍스 발송은 네트워크 오류, `408`, `429`, `5xx` 응답에 대해 제한적으로 재시도합니다. `400`, `403`, 사용자 매핑 실패와 같은 영구 오류는 반복하지 않고 실패 이력으로 남깁니다.
|
|
|
|
발송 실패는 피드백 등록 실패와 분리됩니다. 즉, 피드백이 ABC와 Secretary에 정상 저장된 뒤 네이버웍스 알림만 실패할 수 있습니다.
|
|
|
|
## 11. 현재 운영 기준 요약
|
|
|
|
```text
|
|
사용자 입력
|
|
→ /support/{workspaceCode}/new
|
|
→ /api/support/workspaces/{workspaceCode}/submit
|
|
→ 외부 관리 콘솔 API
|
|
→ Secretary support_tickets 저장
|
|
→ ABC feedbacks 저장
|
|
→ abc_feedback_mappings로 연결
|
|
→ 외부 관리 콘솔에서 조회·상태변경·댓글·이슈처리
|
|
```
|
|
|
|
정리하면 작성 페이지와 관리페이지는 프론트엔드 상태를 직접 공유하지 않습니다. 두 시스템은 다음 정보를 기준으로 서버 데이터에서 연결됩니다.
|
|
|
|
```text
|
|
workspace_code
|
|
→ Secretary ticket_id
|
|
→ abc_feedback_id
|
|
→ ABC project/channel
|
|
```
|
|
|
|
## 참고 파일
|
|
|
|
- `FEEDBACK_ONLY_TASKS.md`
|
|
- `apps/web/src/pages/support/[workspaceCode]/new.tsx`
|
|
- `apps/web/src/pages/api/support/workspaces/[workspaceCode]/submit.ts`
|
|
- `apps/web/src/pages/api/support/workspaces/[workspaceCode]/tickets.ts`
|
|
- `apps/web/src/server/support-external.ts`
|
|
- `apps/web/src/server/support-auth.ts`
|
|
- `apps/secretary-api/app/api/routes/tickets.py`
|
|
- `apps/secretary-api/app/services/ticket_service.py`
|
|
- `apps/secretary-api/app/db/models.py`
|
|
- `apps/api/src/domains/admin/feedback/feedback.entity.ts`
|
|
- `apps/api/src/domains/admin/feedback/feedback.service.ts`
|
|
- `apps/api/src/domains/admin/project/webhook/notification-internal.listener.ts`
|
|
- `apps/api/src/domains/admin/project/webhook/notification-recipient.router.ts`
|
|
- `apps/api/src/domains/admin/project/webhook/webhook-notification.service.ts`
|
|
- `apps/api/src/domains/admin/project/webhook/notification-message.builder.ts`
|
|
- `apps/api/src/domains/admin/project/webhook/naver-works.client.ts`
|
|
- `apps/api/src/domains/admin/project/webhook/notification-delivery.entity.ts`
|