224 lines
7.3 KiB
Python
224 lines
7.3 KiB
Python
from typing import Literal
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class TicketCreateRequest(BaseModel):
|
|
workspace_code: str = Field(default="", max_length=50)
|
|
requester_id: str = Field(..., min_length=1, max_length=100)
|
|
requester_tenant_id: str = Field(..., min_length=1, max_length=100)
|
|
requester_contact: str | None = Field(default=None, max_length=100)
|
|
requester_email: str | None = Field(default=None, max_length=320)
|
|
requester_name: str | None = Field(default=None, max_length=100)
|
|
requester_department: str | None = Field(default=None, max_length=100)
|
|
requester_phone_number: str | None = Field(default=None, max_length=50)
|
|
title: str = Field(..., min_length=1, max_length=255)
|
|
description: str = Field(..., min_length=1)
|
|
category_code: str | None = Field(default=None, max_length=20)
|
|
ticket_type: str = Field(default="GENERAL")
|
|
is_secret: bool = False
|
|
requires_approval: bool = False
|
|
extra_fields: dict[str, str] = Field(default_factory=dict)
|
|
|
|
|
|
class TicketUpdateRequest(BaseModel):
|
|
title: str | None = Field(default=None, min_length=1, max_length=255)
|
|
description: str | None = Field(default=None, min_length=1)
|
|
requester_contact: str | None = Field(default=None, max_length=100)
|
|
is_secret: bool | None = None
|
|
extra_fields: dict[str, str] | None = None
|
|
|
|
|
|
class TicketCreateResponse(BaseModel):
|
|
ticket_id: int
|
|
workspace_code: str
|
|
status_code: str
|
|
feedback_status: str
|
|
sync_status: str
|
|
message: str
|
|
|
|
|
|
FeedbackStatus = Literal["INIT", "ON_REVIEW", "DETAILED_REVIEW", "IN_PROGRESS", "RESOLVED", "PENDING"]
|
|
|
|
|
|
class FeedbackStatusUpdateRequest(BaseModel):
|
|
feedback_status: FeedbackStatus
|
|
|
|
|
|
class SupportFeedbackStatusRecord(BaseModel):
|
|
feedback_id: int
|
|
feedback_status: FeedbackStatus
|
|
updated_at: str
|
|
|
|
|
|
class SupportFeedbackMetrics(BaseModel):
|
|
project_id: int
|
|
channel_id: int | None = None
|
|
today_first_count: int
|
|
answer_waiting_count: int
|
|
issue_linked_count: int
|
|
issue_link_rate: float
|
|
average_processing_minutes: float | None = None
|
|
|
|
|
|
class WorkspaceSummary(BaseModel):
|
|
workspace_code: str
|
|
workspace_name: str
|
|
workspace_type: str
|
|
|
|
|
|
class WorkspaceFormField(BaseModel):
|
|
field_code: str
|
|
label: str
|
|
field_type: str
|
|
required: bool = False
|
|
options: list[dict[str, str | int]] = Field(default_factory=list)
|
|
|
|
|
|
class WorkspaceFormTemplateResponse(BaseModel):
|
|
workspace_code: str
|
|
workspace_name: str
|
|
requires_approval: bool
|
|
fields: list[WorkspaceFormField]
|
|
|
|
|
|
class SupportActivityItem(BaseModel):
|
|
id: str
|
|
label: str
|
|
detail: str
|
|
timestamp: str
|
|
|
|
|
|
class SupportAttachmentRecord(BaseModel):
|
|
attachment_id: int = Field(description="첨부파일 식별자")
|
|
original_file_name: str = Field(description="사용자가 업로드한 원본 파일명")
|
|
mime_type: str | None = Field(default=None, description="MIME 타입")
|
|
file_size: int | None = Field(default=None, description="파일 크기(bytes)")
|
|
created_at: str = Field(description="첨부파일 생성 시각")
|
|
|
|
|
|
class TicketCommentCreateRequest(BaseModel):
|
|
requester_id: str = Field(
|
|
...,
|
|
min_length=1,
|
|
max_length=100,
|
|
description="인증된 작성자 식별자. API 서버가 로그인 사용자 정보로 덮어쓴다.",
|
|
)
|
|
requester_tenant_id: str = Field(
|
|
...,
|
|
min_length=1,
|
|
max_length=100,
|
|
description="인증된 작성자 테넌트 식별자. API 서버가 로그인 사용자 정보로 덮어쓴다.",
|
|
)
|
|
author_name: str | None = Field(
|
|
default=None,
|
|
max_length=100,
|
|
description="작성자 표시명. 인증 사용자 정보로 서버가 결정한다.",
|
|
)
|
|
content: str = Field(default="", description="댓글 본문")
|
|
is_internal: bool = Field(
|
|
default=False,
|
|
description="서버 내부용 필드. 일반 댓글 API에서는 무시되며 내부 메모 API가 true로 설정한다.",
|
|
)
|
|
|
|
|
|
class TicketCommentUpdateRequest(BaseModel):
|
|
requester_id: str = Field(..., min_length=1, max_length=100)
|
|
requester_tenant_id: str = Field(..., min_length=1, max_length=100)
|
|
content: str = Field(..., min_length=1)
|
|
|
|
|
|
class InternalMemoCreateRequest(BaseModel):
|
|
content: str = Field(..., min_length=1, description="관리자만 조회할 내부 메모 본문")
|
|
|
|
|
|
class InternalMemoUpdateRequest(BaseModel):
|
|
content: str = Field(..., min_length=1, description="수정할 내부 메모 본문")
|
|
|
|
|
|
class TicketIssueLinkStatusSyncRequest(BaseModel):
|
|
linked: bool
|
|
|
|
|
|
class TicketAssigneeCandidate(BaseModel):
|
|
user_id: str
|
|
tenant_id: str
|
|
name: str | None = None
|
|
email: str | None = None
|
|
department: str | None = None
|
|
phone_number: str | None = None
|
|
role_code: str
|
|
|
|
|
|
class TicketAssigneeUpdateRequest(BaseModel):
|
|
assignee_id: str | None = None
|
|
assignee_tenant_id: str | None = None
|
|
|
|
|
|
class SupportTicketCommentRecord(BaseModel):
|
|
comment_id: int = Field(description="댓글 또는 내부 메모 식별자")
|
|
ticket_id: int = Field(description="지원 요청 식별자")
|
|
author_id: str = Field(description="작성자 식별자")
|
|
author_tenant_id: str = Field(description="작성자 테넌트 식별자")
|
|
author_name: str = Field(description="작성자 표시명")
|
|
content: str = Field(description="댓글 또는 내부 메모 본문")
|
|
is_internal: bool = Field(description="관리자 전용 내부 메모 여부")
|
|
comment_type: str = Field(default="COMMENT", description="COMMENT 또는 INTERNAL_MEMO")
|
|
created_at: str = Field(description="작성 시각")
|
|
updated_at: str = Field(description="수정 시각")
|
|
edited_at: str | None = Field(default=None, description="마지막 수정 시각")
|
|
attachments: list[SupportAttachmentRecord] = Field(default_factory=list)
|
|
can_edit: bool = False
|
|
can_delete: bool = False
|
|
|
|
|
|
class TicketDeleteResponse(BaseModel):
|
|
deleted: bool = Field(description="삭제 처리 여부")
|
|
ticket_id: int = Field(description="지원 요청 식별자")
|
|
comment_id: int | None = Field(default=None, description="삭제된 댓글 또는 내부 메모 식별자")
|
|
feedback_id: int | None = Field(default=None, description="연결된 ABC 피드백 식별자")
|
|
|
|
|
|
class SupportTicketRecord(BaseModel):
|
|
ticket_id: int
|
|
workspace_code: str
|
|
workspace_name: str
|
|
title: str
|
|
description: str
|
|
requester_id: str
|
|
requester_tenant_id: str
|
|
requester_contact: str
|
|
requester_email: str | None
|
|
requester_name: str | None
|
|
requester_department: str | None
|
|
requester_phone_number: str | None
|
|
category_code: str
|
|
ticket_type: str
|
|
requires_approval: bool
|
|
status_code: str
|
|
feedback_status: str
|
|
approval_status: str
|
|
sync_status: str
|
|
issue_link_status: str
|
|
external_issue_status: str | None = None
|
|
assignee_id: str | None = None
|
|
assignee_tenant_id: str | None = None
|
|
assignee_name: str | None = None
|
|
assignee_email: str | None = None
|
|
is_secret: bool
|
|
created_at: str
|
|
updated_at: str
|
|
extra_fields: dict[str, str]
|
|
attachments: list[SupportAttachmentRecord] = Field(default_factory=list)
|
|
activity: list[SupportActivityItem]
|
|
|
|
|
|
class TicketMutationResponse(BaseModel):
|
|
ticket_id: int
|
|
status_code: str
|
|
feedback_status: str
|
|
approval_status: str
|
|
issue_link_status: str
|
|
external_issue_status: str | None = None
|
|
updated_at: str
|