diff --git a/backend/src/main/java/com/srsystem/dto/CreateTicketRequest.java b/backend/src/main/java/com/srsystem/dto/CreateTicketRequest.java index 88f87d3..71bca91 100644 --- a/backend/src/main/java/com/srsystem/dto/CreateTicketRequest.java +++ b/backend/src/main/java/com/srsystem/dto/CreateTicketRequest.java @@ -11,6 +11,8 @@ public record CreateTicketRequest( @NotNull TicketCategory category, @NotNull TicketPriority priority, @NotBlank String title, - @NotBlank String description + @NotBlank String description, + @Nullable String attachmentUrl, + @Nullable String attachmentName ) { } diff --git a/backend/src/main/java/com/srsystem/dto/IssueTicket.java b/backend/src/main/java/com/srsystem/dto/IssueTicket.java index 7a4f54e..8ba7f32 100644 --- a/backend/src/main/java/com/srsystem/dto/IssueTicket.java +++ b/backend/src/main/java/com/srsystem/dto/IssueTicket.java @@ -20,6 +20,8 @@ public record IssueTicket( LocalDateTime resolvedAt, String resolutionNote, boolean slaWarnFlag, - LocalDateTime createdAt + LocalDateTime createdAt, + String attachmentUrl, + String attachmentName ) { } diff --git a/backend/src/main/java/com/srsystem/entity/Ticket.java b/backend/src/main/java/com/srsystem/entity/Ticket.java index 03207bd..d15adb5 100644 --- a/backend/src/main/java/com/srsystem/entity/Ticket.java +++ b/backend/src/main/java/com/srsystem/entity/Ticket.java @@ -66,6 +66,12 @@ public class Ticket extends BaseEntity { @Column(name = "resolution_note", columnDefinition = "TEXT") private String resolutionNote; + @Column(name = "attachment_url", length = 500) + private String attachmentUrl; + + @Column(name = "attachment_name", length = 255) + private String attachmentName; + @Column(name = "sla_warn_flag", nullable = false, length = 1) private char slaWarnFlag = 'N'; } diff --git a/backend/src/main/java/com/srsystem/service/TicketService.java b/backend/src/main/java/com/srsystem/service/TicketService.java index 2cdd188..6970449 100644 --- a/backend/src/main/java/com/srsystem/service/TicketService.java +++ b/backend/src/main/java/com/srsystem/service/TicketService.java @@ -66,7 +66,9 @@ public class TicketService { .title(request.title()) .description(request.description()) .status(TicketStatus.OPEN) - .slaWarnFlag('N'); + .slaWarnFlag('N') + .attachmentUrl(request.attachmentUrl()) + .attachmentName(request.attachmentName()); if (request.projectId() != null) { Project project = projectRepository.findById(request.projectId()) @@ -186,7 +188,7 @@ public class TicketService { private IssueTicket toIssueTicket(Ticket ticket) { return new IssueTicket( ticket.getTicketId(), - ticket.getProject().getProjectName(), + ticket.getProject() != null ? ticket.getProject().getProjectName() : null, ticket.getRequester().getName(), ticket.getAssignee() != null ? ticket.getAssignee().getName() : null, ticket.getCategory(), @@ -198,7 +200,9 @@ public class TicketService { ticket.getResolvedAt(), ticket.getResolutionNote(), ticket.getSlaWarnFlag() == 'Y', - ticket.getCreatedAt() + ticket.getCreatedAt(), + ticket.getAttachmentUrl(), + ticket.getAttachmentName() ); } } diff --git a/backend/src/main/resources/db/migration/V19__add_ticket_attachment.sql b/backend/src/main/resources/db/migration/V19__add_ticket_attachment.sql new file mode 100644 index 0000000..6a872f5 --- /dev/null +++ b/backend/src/main/resources/db/migration/V19__add_ticket_attachment.sql @@ -0,0 +1,2 @@ +ALTER TABLE tb_ticket ADD COLUMN IF NOT EXISTS attachment_url VARCHAR(500); +ALTER TABLE tb_ticket ADD COLUMN IF NOT EXISTS attachment_name VARCHAR(255); diff --git a/src/app/(main)/issues/[id]/page.tsx b/src/app/(main)/issues/[id]/page.tsx index 55b8520..cb8849b 100644 --- a/src/app/(main)/issues/[id]/page.tsx +++ b/src/app/(main)/issues/[id]/page.tsx @@ -119,20 +119,36 @@ export default function IssueDetailPage({ params }: { params: Promise<{ id: stri

{ticket.description}

+ {ticket.attachmentUrl && ( +
+ +
+

첨부 파일

+

{ticket.attachmentName || ticket.attachmentUrl.split('/').pop()}

+
+ + 다운로드 + +
+ )} + {ticket.category === 'VACATION' && (

휴가 신청

-

세부 일정은 description을 확인하세요.

+

해당 티켓은 휴가 신청 건입니다. 휴가 기간 등 세부 내용은 description을 확인하세요.

)} {ticket.category === 'EXPENSE' && (

비용 청구

+

비용 청구 건입니다. 금액 및 영수증은 description과 첨부파일을 확인하세요.

)} {ticket.category === 'EQUIPMENT_REQUEST' && (

장비 요청

+

장비 요청 건입니다. 요청 장비 및 긴급도는 description을 확인하세요.

)} diff --git a/src/app/(main)/issues/page.tsx b/src/app/(main)/issues/page.tsx index 977c42d..e553c58 100644 --- a/src/app/(main)/issues/page.tsx +++ b/src/app/(main)/issues/page.tsx @@ -93,7 +93,7 @@ function CreateTicketModal({ onClose, onSuccess }: { onClose: () => void; onSucc extras.push(`\n\n[휴가 신청]\n시작일: ${extraFields.startDate}\n종료일: ${extraFields.endDate}`); } if (formData.category === 'EXPENSE') { - extras.push(`\n\n[비용 청구]\n금액: ${extraFields.amount}원`); + extras.push(`\n\n[비용 청구]\n금액: ${extraFields.amount}원${extraFields.receiptUrl ? `\n영수증: ${extraFields.receiptUrl}` : ''}`); } if (formData.category === 'EQUIPMENT_REQUEST') { extras.push(`\n\n[장비 요청]\n장비 유형: ${extraFields.equipmentType}\n긴급도: ${extraFields.urgency}`); @@ -109,6 +109,8 @@ function CreateTicketModal({ onClose, onSuccess }: { onClose: () => void; onSucc category: formData.category as TicketCategory, priority: formData.priority as TicketPriority, projectId: formData.projectId ? parseInt(formData.projectId) : undefined, + attachmentUrl: extraFields.receiptUrl || undefined, + attachmentName: extraFields.receiptName || undefined, }); onSuccess(); onClose(); @@ -158,22 +160,6 @@ function CreateTicketModal({ onClose, onSuccess }: { onClose: () => void; onSucc {renderFieldError('title')} -
- -