feat: Excel batch registration (equipment + employees)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package com.srsystem.controller;
|
||||
|
||||
import com.srsystem.dto.ApiResponse;
|
||||
import com.srsystem.dto.BatchResult;
|
||||
import com.srsystem.dto.CreateEquipmentRequest;
|
||||
import com.srsystem.dto.CreateMaintenanceRequest;
|
||||
import com.srsystem.dto.EquipmentSummary;
|
||||
@@ -11,6 +12,7 @@ import com.srsystem.entity.EquipmentMaintenance;
|
||||
import com.srsystem.entity.enums.EquipmentStatus;
|
||||
import com.srsystem.entity.enums.EquipmentType;
|
||||
import com.srsystem.service.EquipmentService;
|
||||
import com.srsystem.util.ExcelParser;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@@ -19,11 +21,15 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -158,4 +164,75 @@ public class EquipmentController {
|
||||
Equipment equipment = equipmentService.removeImage(equipmentId, imageIndex);
|
||||
return ResponseEntity.ok(ApiResponse.ok("이미지가 삭제되었습니다", equipment));
|
||||
}
|
||||
|
||||
// ---- Batch ----
|
||||
|
||||
@Operation(summary = "장비 일괄 등록", description = "엑셀 파일로 장비를 일괄 등록합니다")
|
||||
@PreAuthorize("hasAnyRole('MANAGER', 'ADMIN')")
|
||||
@Transactional
|
||||
@PostMapping("/batch")
|
||||
public ResponseEntity<ApiResponse<BatchResult<Equipment>>> batchCreate(@RequestParam("file") MultipartFile file) {
|
||||
try {
|
||||
ExcelParser.ParseResult<CreateEquipmentRequest> parsed = ExcelParser.parse(
|
||||
file,
|
||||
(row) -> new CreateEquipmentRequest(
|
||||
EquipmentType.valueOf(row.getOrDefault("장비유형", "LAPTOP").toUpperCase()),
|
||||
row.getOrDefault("제조사", ""),
|
||||
row.getOrDefault("모델명", ""),
|
||||
row.getOrDefault("시리얼번호", ""),
|
||||
row.getOrDefault("자산코드", ""),
|
||||
row.getOrDefault("제원정보", ""),
|
||||
EquipmentStatus.AVAILABLE,
|
||||
row.containsKey("구매일") ? java.time.LocalDate.parse(row.get("구매일")) : java.time.LocalDate.now(),
|
||||
null
|
||||
),
|
||||
List.of()
|
||||
);
|
||||
|
||||
List<BatchResult.Failure> failures = new ArrayList<>();
|
||||
List<Equipment> success = new ArrayList<>();
|
||||
var parseFailures = parsed.failures();
|
||||
for (var pf : parseFailures) {
|
||||
failures.add(new BatchResult.Failure(pf.row(), pf.reason()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < parsed.data().size(); i++) {
|
||||
try {
|
||||
Equipment eq = equipmentService.createEquipment(parsed.data().get(i));
|
||||
success.add(eq);
|
||||
} catch (Exception e) {
|
||||
failures.add(new BatchResult.Failure(i + 2, e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
BatchResult<Equipment> result = new BatchResult<>(
|
||||
parsed.data().size() + parseFailures.size(),
|
||||
success.size(),
|
||||
failures.size(),
|
||||
failures,
|
||||
success
|
||||
);
|
||||
return ResponseEntity.ok(ApiResponse.ok(
|
||||
String.format("%d건 중 %d건 성공, %d건 실패", result.totalCount(), result.successCount(), result.failCount()),
|
||||
result
|
||||
));
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.badRequest().body(ApiResponse.error("엑셀 파싱 실패: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "장비 일괄 등록 템플릿 다운로드")
|
||||
@PreAuthorize("hasAnyRole('MANAGER', 'ADMIN')")
|
||||
@GetMapping("/batch/template")
|
||||
public ResponseEntity<byte[]> downloadTemplate() throws Exception {
|
||||
String[] headers = {"장비유형", "제조사", "모델명", "시리얼번호", "자산코드", "제원정보", "구매일"};
|
||||
Map<Integer, String[]> dropdowns = Map.of(
|
||||
0, new String[]{"LAPTOP", "MONITOR", "TEST_DEVICE", "ACCESSORY"}
|
||||
);
|
||||
byte[] data = ExcelParser.generateTemplate(headers, "장비 일괄등록", dropdowns);
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=equipment_batch_template.xlsx")
|
||||
.contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
|
||||
.body(data);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user