diff --git a/ga-api/src/main/java/com/ga/api/controller/product/ProductController.java b/ga-api/src/main/java/com/ga/api/controller/product/ProductController.java index b66ceb7..1462591 100644 --- a/ga-api/src/main/java/com/ga/api/controller/product/ProductController.java +++ b/ga-api/src/main/java/com/ga/api/controller/product/ProductController.java @@ -4,14 +4,13 @@ import com.ga.api.service.product.ProductService; import com.ga.common.annotation.DataChangeLog; import com.ga.common.annotation.RequirePermission; import com.ga.common.model.ApiResponse; +import com.ga.common.model.PageResponse; import com.ga.core.vo.product.ProductResp; import com.ga.core.vo.product.ProductVO; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; -import java.util.List; - @Tag(name = "상품 관리") @RestController @RequestMapping("/api/products") @@ -22,11 +21,13 @@ public class ProductController { @GetMapping @RequirePermission(menu = "PRODUCT", perm = "READ") - public ApiResponse> list(@RequestParam(required = false) Long companyId, - @RequestParam(required = false) String insuranceType, - @RequestParam(required = false) String keyword, - @RequestParam(required = false) String isActive) { - return ApiResponse.ok(productService.list(companyId, insuranceType, keyword, isActive)); + public ApiResponse> list(@RequestParam(defaultValue = "1") int pageNum, + @RequestParam(defaultValue = "10") int pageSize, + @RequestParam(required = false) Long companyId, + @RequestParam(required = false) String insuranceType, + @RequestParam(required = false) String keyword, + @RequestParam(required = false) String isActive) { + return ApiResponse.ok(productService.list(pageNum, pageSize, companyId, insuranceType, keyword, isActive)); } @GetMapping("/{productId}") diff --git a/ga-api/src/main/java/com/ga/api/service/product/ProductService.java b/ga-api/src/main/java/com/ga/api/service/product/ProductService.java index 092cb5b..7f150f3 100644 --- a/ga-api/src/main/java/com/ga/api/service/product/ProductService.java +++ b/ga-api/src/main/java/com/ga/api/service/product/ProductService.java @@ -2,15 +2,15 @@ package com.ga.api.service.product; import com.ga.common.exception.BizException; import com.ga.common.exception.ErrorCode; +import com.ga.common.model.PageResponse; import com.ga.core.mapper.product.ProductMapper; import com.ga.core.vo.product.ProductResp; import com.ga.core.vo.product.ProductVO; +import com.github.pagehelper.PageHelper; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.List; - @Service @RequiredArgsConstructor public class ProductService { @@ -18,8 +18,9 @@ public class ProductService { private final ProductMapper mapper; @Transactional(readOnly = true) - public List list(Long companyId, String insuranceType, String keyword, String isActive) { - return mapper.selectList(companyId, insuranceType, keyword, isActive); + public PageResponse list(int pageNum, int pageSize, Long companyId, String insuranceType, String keyword, String isActive) { + PageHelper.startPage(pageNum, pageSize); + return PageResponse.of(mapper.selectList(companyId, insuranceType, keyword, isActive)); } @Transactional(readOnly = true) diff --git a/ga-frontend/src/api/batch.ts b/ga-frontend/src/api/batch.ts index 7f0b9d6..fbec59f 100644 --- a/ga-frontend/src/api/batch.ts +++ b/ga-frontend/src/api/batch.ts @@ -29,19 +29,60 @@ export interface BatchHistoryResp { errorMessage?: string; } +/** 백엔드 batch_job_log VO (실제 응답 형태) */ +interface BatchJobVO { + jobId: number; + jobName: string; + status: string; // REQUESTED | STARTED | COMPLETED | FAILED + currentStep?: string; + totalCount?: number; + processedCount?: number; + errorCount?: number; + errorMessage?: string; + startedAt?: number[] | string; + finishedAt?: number[] | string; + durationSec?: number; +} + +/** LocalDateTime 배열([y,M,d,h,m,s,..]) → 'YYYY-MM-DD HH:mm:ss' */ +function fmtTs(v?: number[] | string): string | undefined { + if (v == null) return undefined; + if (typeof v === 'string') return v; + const [y, mo, d, h = 0, mi = 0, s = 0] = v; + const p = (n: number) => String(n).padStart(2, '0'); + return `${y}-${p(mo)}-${p(d)} ${p(h)}:${p(mi)}:${p(s)}`; +} + +function mapStatus(s: string): BatchJobLogResp['status'] { + if (s === 'STARTED') return 'RUNNING'; + if (s === 'REQUESTED' || s === 'RUNNING' || s === 'COMPLETED' || s === 'FAILED') return s; + return 'RUNNING'; +} + +/** 백엔드 VO → 프론트 BatchJobLogResp 어댑터 */ +function toJobLog(v: BatchJobVO): BatchJobLogResp { + return { + jobLogId: v.jobId, + jobName: v.jobName, + status: mapStatus(v.status), + stepName: v.currentStep, + totalCount: v.totalCount, + successCount: v.processedCount, + errorCount: v.errorCount, + startedAt: fmtTs(v.startedAt), + endedAt: fmtTs(v.finishedAt), + durationMs: v.durationSec != null ? v.durationSec * 1000 : undefined, + errorMessage: v.errorMessage, + }; +} + export const batchRunApi = { run: (settleMonth: string, companyCode?: string) => - unwrap( - api.post('/api/batch/settlement/run', null, { - params: { settleMonth, companyCode }, - }), - ), + unwrap(api.post('/api/batch/settlement/run', { settleMonth, companyCode })), status: (jobLogId: number) => - unwrap( - api.get('/api/batch/settlement/status', { params: { jobLogId } }), - ), + unwrap(api.get(`/api/batch/jobs/${jobLogId}`)).then(toJobLog), history: (size = 10) => - unwrap( - api.get('/api/batch/settlement/history', { params: { size } }), + unwrap(api.get('/api/batch/jobs')).then((rows) => + rows.slice(0, size).map(toJobLog) as BatchHistoryResp[], ), }; diff --git a/ga-frontend/src/api/operation.ts b/ga-frontend/src/api/operation.ts index ad0a54f..9ea389f 100644 --- a/ga-frontend/src/api/operation.ts +++ b/ga-frontend/src/api/operation.ts @@ -153,9 +153,9 @@ export const operationApi = { hqSettleDelete: (id: number) => unwrap(api.delete(`/api/hq-settles/${id}`)), - // GradeEval Rules + // GradeEval Rules — 백엔드는 PageResponse({list}) 반환이므로 .list 추출 gradeEvalRules: () => - unwrap(api.get('/api/grade-evaluations/rules')), + unwrap<{ list: GradeEvalRuleRow[] }>(api.get('/api/grade-evaluations/rules')).then((r) => r.list ?? []), gradeEvalRuleGet: (id: number) => unwrap(api.get(`/api/grade-evaluations/rules/${id}`)), gradeEvalRuleCreate: (body: Partial) =>